--- a/.hgtags Thu Feb 02 05:26:20 2017 -0800
+++ b/.hgtags Thu Feb 09 23:15:52 2017 +0100
@@ -397,3 +397,5 @@
ab2c8b03c3284fcbdd157551a66f807e3a182d9b jdk-9+152
d7034ff7f8e257e81c9f95c7785dd4eaaa3c2afc jdk-9+153
8c70d170e62c0c58b5bc3ba666bd140399b98c9c jdk-10+0
+45b751afd11e6c05991cf4913c5a0ac3304fcc4e jdk-9+154
+f4aff695ffe05cfdb69d8af25a4ddc6a029754ea jdk-9+155
--- a/.hgtags-top-repo Thu Feb 02 05:26:20 2017 -0800
+++ b/.hgtags-top-repo Thu Feb 09 23:15:52 2017 +0100
@@ -396,3 +396,5 @@
71a766d4c18041a7f833ee22823125b02e1a7f1e jdk-9+151
ef056360ddf3977d7d2ddbeb456a4d612d19ea05 jdk-9+152
816a6d03a7c44edfbd8780110529f1bdc3964fb9 jdk-9+153
+8d26916eaa21b689835ffc1c0dbf12470aa9be61 jdk-9+154
+688a3863c00ebc089ab17ee1fc46272cbbd96815 jdk-9+155
--- a/common/autoconf/basics.m4 Thu Feb 02 05:26:20 2017 -0800
+++ b/common/autoconf/basics.m4 Thu Feb 09 23:15:52 2017 +0100
@@ -746,7 +746,8 @@
fi
# set SDKROOT too, Xcode tools will pick it up
- AC_SUBST(SDKROOT,$SYSROOT)
+ SDKROOT="$SYSROOT"
+ AC_SUBST(SDKROOT)
fi
# Prepend the extra path to the global path
@@ -831,9 +832,10 @@
CONFIGURESUPPORT_OUTPUTDIR="$OUTPUT_ROOT/configure-support"
$MKDIR -p "$CONFIGURESUPPORT_OUTPUTDIR"
- AC_SUBST(SPEC, $OUTPUT_ROOT/spec.gmk)
- AC_SUBST(CONF_NAME, $CONF_NAME)
- AC_SUBST(OUTPUT_ROOT, $OUTPUT_ROOT)
+ SPEC="$OUTPUT_ROOT/spec.gmk"
+ AC_SUBST(SPEC)
+ AC_SUBST(CONF_NAME)
+ AC_SUBST(OUTPUT_ROOT)
AC_SUBST(CONFIGURESUPPORT_OUTPUTDIR)
# The spec.gmk file contains all variables for the make system.
--- a/common/autoconf/boot-jdk.m4 Thu Feb 02 05:26:20 2017 -0800
+++ b/common/autoconf/boot-jdk.m4 Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, 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
@@ -325,7 +325,6 @@
fi
AC_MSG_CHECKING([if Boot JDK is 32 or 64 bits])
AC_MSG_RESULT([$BOOT_JDK_BITS])
- AC_SUBST(BOOT_JDK_BITS)
])
AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS],
--- a/common/autoconf/build-performance.m4 Thu Feb 02 05:26:20 2017 -0800
+++ b/common/autoconf/build-performance.m4 Thu Feb 09 23:15:52 2017 +0100
@@ -224,7 +224,7 @@
AC_MSG_ERROR([On macosx, ccache 3.2 or later is required, found $CCACHE_VERSION])
fi
fi
- if test "x$USE_PRECOMPILED_HEADER" = "x1"; then
+ if test "x$USE_PRECOMPILED_HEADER" = "xtrue"; then
HAS_BAD_CCACHE=[`$ECHO $CCACHE_VERSION | \
$GREP -e '^1.*' -e '^2.*' -e '^3\.0.*' -e '^3\.1\.[0123]$'`]
if test "x$HAS_BAD_CCACHE" != "x"; then
@@ -362,20 +362,20 @@
[disable using precompiled headers when compiling C++ @<:@enabled@:>@])],
[ENABLE_PRECOMPH=${enable_precompiled_headers}], [ENABLE_PRECOMPH=yes])
- USE_PRECOMPILED_HEADER=1
+ USE_PRECOMPILED_HEADER=true
AC_MSG_CHECKING([If precompiled header is enabled])
if test "x$ENABLE_PRECOMPH" = xno; then
AC_MSG_RESULT([no, forced])
- USE_PRECOMPILED_HEADER=0
+ USE_PRECOMPILED_HEADER=false
elif test "x$ICECC" != "x"; then
AC_MSG_RESULT([no, does not work effectively with icecc])
- USE_PRECOMPILED_HEADER=0
+ USE_PRECOMPILED_HEADER=false
elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then
AC_MSG_RESULT([no, does not work with Solaris Studio])
- USE_PRECOMPILED_HEADER=0
+ USE_PRECOMPILED_HEADER=false
elif test "x$TOOLCHAIN_TYPE" = xxlc; then
AC_MSG_RESULT([no, does not work with xlc])
- USE_PRECOMPILED_HEADER=0
+ USE_PRECOMPILED_HEADER=false
else
AC_MSG_RESULT([yes])
fi
@@ -387,7 +387,7 @@
echo "int alfa();" > conftest.h
$CXX -x c++-header conftest.h -o conftest.hpp.gch 2>&AS_MESSAGE_LOG_FD >&AS_MESSAGE_LOG_FD
if test ! -f conftest.hpp.gch; then
- USE_PRECOMPILED_HEADER=0
+ USE_PRECOMPILED_HEADER=false
AC_MSG_RESULT([no])
else
AC_MSG_RESULT([yes])
--- a/common/autoconf/flags.m4 Thu Feb 02 05:26:20 2017 -0800
+++ b/common/autoconf/flags.m4 Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, 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
@@ -808,7 +808,7 @@
IF_FALSE: [$2CXXSTD_CXXFLAG=""])
$2CXXFLAGS_JDK="${$2CXXFLAGS_JDK} ${$2CXXSTD_CXXFLAG}"
$2JVM_CFLAGS="${$2JVM_CFLAGS} ${$2CXXSTD_CXXFLAG}"
- AC_SUBST([$2CXXSTD_CXXFLAG])
+ AC_SUBST($2CXXSTD_CXXFLAG)
fi
if test "x$OPENJDK_TARGET_OS" = xsolaris; then
$2CFLAGS_JDK="${$2CFLAGS_JDK} -D__solaris__"
@@ -1440,18 +1440,6 @@
AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_MISC],
[
- # Some Zero and Shark settings.
- # ZERO_ARCHFLAG tells the compiler which mode to build for
- case "${OPENJDK_TARGET_CPU}" in
- s390)
- ZERO_ARCHFLAG="${COMPILER_TARGET_BITS_FLAG}31"
- ;;
- *)
- ZERO_ARCHFLAG="${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}"
- esac
- FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [$ZERO_ARCHFLAG], IF_FALSE: [ZERO_ARCHFLAG=""])
- AC_SUBST(ZERO_ARCHFLAG)
-
# Check that the compiler supports -mX (or -qX on AIX) flags
# Set COMPILER_SUPPORTS_TARGET_BITS_FLAG to 'true' if it does
FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}],
@@ -1476,15 +1464,7 @@
AC_MSG_ERROR([--enable-warnings-as-errors accepts no argument])
fi
- if test "x$WARNINGS_AS_ERRORS" = "xfalse"; then
- # Set legacy hotspot variable
- HOTSPOT_SET_WARNINGS_AS_ERRORS="WARNINGS_ARE_ERRORS="
- else
- HOTSPOT_SET_WARNINGS_AS_ERRORS=""
- fi
-
AC_SUBST(WARNINGS_AS_ERRORS)
- AC_SUBST(HOTSPOT_SET_WARNINGS_AS_ERRORS)
case "${TOOLCHAIN_TYPE}" in
microsoft)
--- a/common/autoconf/generated-configure.sh Thu Feb 02 05:26:20 2017 -0800
+++ b/common/autoconf/generated-configure.sh Thu Feb 09 23:15:52 2017 +0100
@@ -704,7 +704,6 @@
FIXPATH
BUILD_GTEST
ENABLE_AOT
-INCLUDE_DTRACE
GCOV_ENABLED
ZIP_EXTERNAL_DEBUG_SYMBOLS
COPY_DEBUG_SYMBOLS
@@ -712,10 +711,8 @@
CFLAGS_WARNINGS_ARE_ERRORS
BUILD_CC_DISABLE_WARNING_PREFIX
DISABLE_WARNING_PREFIX
-HOTSPOT_SET_WARNINGS_AS_ERRORS
WARNINGS_AS_ERRORS
COMPILER_SUPPORTS_TARGET_BITS_FLAG
-ZERO_ARCHFLAG
LDFLAGS_TESTEXE
LDFLAGS_TESTLIB
CXXFLAGS_TESTEXE
@@ -884,7 +881,6 @@
CREATE_BUILDJDK
JLINK
JMOD
-BOOT_JDK_BITS
JAVAC_FLAGS
BOOT_JDK_MODULAR
BOOT_JDK_SOURCETARGET
@@ -974,15 +970,12 @@
ORIGINAL_TOPDIR
TOPDIR
PATH_SEP
-ZERO_ARCHDEF
HOTSPOT_BUILD_CPU_DEFINE
HOTSPOT_BUILD_CPU_ARCH
HOTSPOT_BUILD_CPU
HOTSPOT_BUILD_OS_TYPE
HOTSPOT_BUILD_OS
OPENJDK_BUILD_BUNDLE_PLATFORM
-OPENJDK_BUILD_CPU_BUNDLE
-OPENJDK_BUILD_OS_BUNDLE
OPENJDK_BUILD_OS_EXPORT_DIR
OPENJDK_BUILD_CPU_OSARCH
OPENJDK_BUILD_CPU_ISADIR
@@ -994,10 +987,7 @@
HOTSPOT_TARGET_OS_TYPE
HOTSPOT_TARGET_OS
DEFINE_CROSS_COMPILE_ARCH
-LP64
OPENJDK_TARGET_BUNDLE_PLATFORM
-OPENJDK_TARGET_CPU_BUNDLE
-OPENJDK_TARGET_OS_BUNDLE
OPENJDK_TARGET_OS_EXPORT_DIR
OPENJDK_TARGET_CPU_OSARCH
OPENJDK_TARGET_CPU_ISADIR
@@ -3818,7 +3808,7 @@
# ... then the rest
#
-# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, 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
@@ -3998,7 +3988,7 @@
#
-# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, 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
@@ -4273,7 +4263,7 @@
#
-# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, 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
@@ -4561,7 +4551,7 @@
#
-# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, 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
@@ -4841,7 +4831,7 @@
#
-# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, 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
@@ -5180,7 +5170,7 @@
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1484571183
+DATE_WHEN_GENERATED=1486175373
###############################################################################
#
@@ -15936,18 +15926,14 @@
OPENJDK_TARGET_BUNDLE_PLATFORM="${OPENJDK_TARGET_OS_BUNDLE}-${OPENJDK_TARGET_CPU_BUNDLE}"
-
-
if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
- A_LP64="LP64:="
# -D_LP64=1 is only set on linux and mac. Setting on windows causes diff in
- # unpack200.exe
+ # unpack200.exe. This variable is used in
+ # FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER.
if test "x$OPENJDK_TARGET_OS" = xlinux || test "x$OPENJDK_TARGET_OS" = xmacosx; then
OPENJDK_TARGET_ADD_LP64="-D_LP64=1"
fi
fi
- LP64=$A_LP64
-
if test "x$COMPILE_TYPE" = "xcross"; then
# FIXME: ... or should this include reduced builds..?
@@ -16092,18 +16078,14 @@
OPENJDK_BUILD_BUNDLE_PLATFORM="${OPENJDK_BUILD_OS_BUNDLE}-${OPENJDK_BUILD_CPU_BUNDLE}"
-
-
if test "x$OPENJDK_BUILD_CPU_BITS" = x64; then
- A_LP64="LP64:="
# -D_LP64=1 is only set on linux and mac. Setting on windows causes diff in
- # unpack200.exe
+ # unpack200.exe. This variable is used in
+ # FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER.
if test "x$OPENJDK_BUILD_OS" = xlinux || test "x$OPENJDK_BUILD_OS" = xmacosx; then
OPENJDK_BUILD_ADD_LP64="-D_LP64=1"
fi
fi
- LP64=$A_LP64
-
if test "x$COMPILE_TYPE" = "xcross"; then
# FIXME: ... or should this include reduced builds..?
@@ -16173,12 +16155,6 @@
- # ZERO_ARCHDEF is used to enable architecture-specific code.
- # This is used in legacy hotspot build.
- ZERO_ARCHDEF="$HOTSPOT_TARGET_CPU_DEFINE"
-
-
-
# Continue setting up basic stuff. Most remaining code require fundamental tools.
@@ -17280,7 +17256,7 @@
fi
# set SDKROOT too, Xcode tools will pick it up
- SDKROOT=$SYSROOT
+ SDKROOT="$SYSROOT"
fi
@@ -17528,11 +17504,9 @@
CONFIGURESUPPORT_OUTPUTDIR="$OUTPUT_ROOT/configure-support"
$MKDIR -p "$CONFIGURESUPPORT_OUTPUTDIR"
- SPEC=$OUTPUT_ROOT/spec.gmk
-
- CONF_NAME=$CONF_NAME
-
- OUTPUT_ROOT=$OUTPUT_ROOT
+ SPEC="$OUTPUT_ROOT/spec.gmk"
+
+
@@ -30730,7 +30704,6 @@
-
# Check whether --with-build-jdk was given.
if test "${with_build_jdk+set}" = set; then :
withval=$with_build_jdk;
@@ -31283,12 +31256,6 @@
if test -d "$IMPORT_MODULES_TOPDIR/modules_src"; then
IMPORT_MODULES_SRC="$IMPORT_MODULES_TOPDIR/modules_src"
fi
- # Workaround for using different imported module-info.java in Jake due to a
- # change in format. Remove once new format is standard in JDK 9 and javafx
- # delivers just that.
- if test -d "$IMPORT_MODULES_TOPDIR/modules_src_jake"; then
- IMPORT_MODULES_SRC="$IMPORT_MODULES_TOPDIR/modules_src_jake $IMPORT_MODULES_SRC"
- fi
if test -d "$IMPORT_MODULES_TOPDIR/make"; then
IMPORT_MODULES_MAKE="$IMPORT_MODULES_TOPDIR/make"
fi
@@ -51486,282 +51453,6 @@
- # Some Zero and Shark settings.
- # ZERO_ARCHFLAG tells the compiler which mode to build for
- case "${OPENJDK_TARGET_CPU}" in
- s390)
- ZERO_ARCHFLAG="${COMPILER_TARGET_BITS_FLAG}31"
- ;;
- *)
- ZERO_ARCHFLAG="${COMPILER_TARGET_BITS_FLAG}${OPENJDK_TARGET_CPU_BITS}"
- esac
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- # Execute function body
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- # Execute function body
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the C compiler supports \"$ZERO_ARCHFLAG\"" >&5
-$as_echo_n "checking if the C compiler supports \"$ZERO_ARCHFLAG\"... " >&6; }
- supports=yes
-
- saved_cflags="$CFLAGS"
- CFLAGS="$CFLAGS $ZERO_ARCHFLAG"
- ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-int i;
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-else
- supports=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- ac_ext=cpp
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-
- CFLAGS="$saved_cflags"
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $supports" >&5
-$as_echo "$supports" >&6; }
- if test "x$supports" = "xyes" ; then
- :
- C_COMP_SUPPORTS="yes"
- else
- :
- C_COMP_SUPPORTS="no"
- fi
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- # Execute function body
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the C++ compiler supports \"$ZERO_ARCHFLAG\"" >&5
-$as_echo_n "checking if the C++ compiler supports \"$ZERO_ARCHFLAG\"... " >&6; }
- supports=yes
-
- saved_cxxflags="$CXXFLAGS"
- CXXFLAGS="$CXXFLAG $ZERO_ARCHFLAG"
- ac_ext=cpp
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-int i;
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
-
-else
- supports=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- ac_ext=cpp
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-
- CXXFLAGS="$saved_cxxflags"
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $supports" >&5
-$as_echo "$supports" >&6; }
- if test "x$supports" = "xyes" ; then
- :
- CXX_COMP_SUPPORTS="yes"
- else
- :
- CXX_COMP_SUPPORTS="no"
- fi
-
-
-
-
-
-
-
-
-
-
-
-
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if both compilers support \"$ZERO_ARCHFLAG\"" >&5
-$as_echo_n "checking if both compilers support \"$ZERO_ARCHFLAG\"... " >&6; }
- supports=no
- if test "x$C_COMP_SUPPORTS" = "xyes" -a "x$CXX_COMP_SUPPORTS" = "xyes"; then supports=yes; fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $supports" >&5
-$as_echo "$supports" >&6; }
- if test "x$supports" = "xyes" ; then
- :
-
- else
- :
- ZERO_ARCHFLAG=""
- fi
-
-
-
-
-
-
-
-
# Check that the compiler supports -mX (or -qX on AIX) flags
# Set COMPILER_SUPPORTS_TARGET_BITS_FLAG to 'true' if it does
@@ -52060,14 +51751,6 @@
as_fn_error $? "--enable-warnings-as-errors accepts no argument" "$LINENO" 5
fi
- if test "x$WARNINGS_AS_ERRORS" = "xfalse"; then
- # Set legacy hotspot variable
- HOTSPOT_SET_WARNINGS_AS_ERRORS="WARNINGS_ARE_ERRORS="
- else
- HOTSPOT_SET_WARNINGS_AS_ERRORS=""
- fi
-
-
case "${TOOLCHAIN_TYPE}" in
@@ -52922,7 +52605,6 @@
fi
-
# Check whether --enable-aot was given.
if test "${enable_aot+set}" = set; then :
enableval=$enable_aot;
@@ -63700,12 +63382,14 @@
DEFAULT_LIBPNG=bundled
# if user didn't specify, use DEFAULT_LIBPNG
if test "x${with_libpng}" = "x"; then
- with_libpng=${DEFAULT_LIBPNG}
+ with_libpng=${DEFAULT_LIBPNG}
fi
if test "x${with_libpng}" = "xbundled"; then
- USE_EXTERNAL_LIBPNG=false
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: bundled" >&5
+ USE_EXTERNAL_LIBPNG=false
+ PNG_CFLAGS=""
+ PNG_LIBS=""
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: bundled" >&5
$as_echo "bundled" >&6; }
elif test "x${with_libpng}" = "xsystem"; then
@@ -63765,28 +63449,31 @@
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
- LIBPNG_FOUND=no
+ LIBPNG_FOUND=no
elif test $pkg_failed = untried; then
- LIBPNG_FOUND=no
+ LIBPNG_FOUND=no
else
PNG_CFLAGS=$pkg_cv_PNG_CFLAGS
PNG_LIBS=$pkg_cv_PNG_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
- LIBPNG_FOUND=yes
-fi
- if test "x${LIBPNG_FOUND}" = "xyes"; then
- USE_EXTERNAL_LIBPNG=true
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: system" >&5
+ LIBPNG_FOUND=yes
+fi
+ if test "x${LIBPNG_FOUND}" = "xyes"; then
+ # PKG_CHECK_MODULES will set PNG_CFLAGS and PNG_LIBS
+ USE_EXTERNAL_LIBPNG=true
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: system" >&5
$as_echo "system" >&6; }
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: system not found" >&5
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: system not found" >&5
$as_echo "system not found" >&6; }
- as_fn_error $? "--with-libpng=system specified, but no libpng found!" "$LINENO" 5
- fi
- else
- as_fn_error $? "Invalid value of --with-libpng: ${with_libpng}, use 'system' or 'bundled'" "$LINENO" 5
- fi
+ as_fn_error $? "--with-libpng=system specified, but no libpng found!" "$LINENO" 5
+ fi
+ else
+ as_fn_error $? "Invalid value of --with-libpng: ${with_libpng}, use 'system' or 'bundled'" "$LINENO" 5
+ fi
+
+
@@ -63894,11 +63581,13 @@
DEFAULT_LCMS=bundled
# If user didn't specify, use DEFAULT_LCMS
if test "x${with_lcms}" = "x"; then
- with_lcms=${DEFAULT_LCMS}
+ with_lcms=${DEFAULT_LCMS}
fi
if test "x${with_lcms}" = "xbundled"; then
USE_EXTERNAL_LCMS=false
+ LCMS_CFLAGS=""
+ LCMS_LIBS=""
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: bundled" >&5
$as_echo "bundled" >&6; }
elif test "x${with_lcms}" = "xsystem"; then
@@ -63972,6 +63661,7 @@
LCMS_FOUND=yes
fi
if test "x${LCMS_FOUND}" = "xyes"; then
+ # PKG_CHECK_MODULES will set LCMS_CFLAGS and LCMS_LIBS
USE_EXTERNAL_LCMS=true
else
as_fn_error $? "--with-lcms=system specified, but no lcms found!" "$LINENO" 5
@@ -63990,6 +63680,8 @@
+
+
# Setup libm (the maths library)
if test "x$OPENJDK_TARGET_OS" != "xwindows"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5
@@ -64774,11 +64466,11 @@
$as_echo_n "checking if elliptic curve crypto implementation is present... " >&6; }
if test -d "${SRC_ROOT}/jdk/src/jdk.crypto.ec/share/native/libsunec/impl"; then
- ENABLE_INTREE_EC=yes
+ ENABLE_INTREE_EC=true
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
- ENABLE_INTREE_EC=no
+ ENABLE_INTREE_EC=false
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
@@ -66145,25 +65837,25 @@
fi
- USE_PRECOMPILED_HEADER=1
+ USE_PRECOMPILED_HEADER=true
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking If precompiled header is enabled" >&5
$as_echo_n "checking If precompiled header is enabled... " >&6; }
if test "x$ENABLE_PRECOMPH" = xno; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no, forced" >&5
$as_echo "no, forced" >&6; }
- USE_PRECOMPILED_HEADER=0
+ USE_PRECOMPILED_HEADER=false
elif test "x$ICECC" != "x"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no, does not work effectively with icecc" >&5
$as_echo "no, does not work effectively with icecc" >&6; }
- USE_PRECOMPILED_HEADER=0
+ USE_PRECOMPILED_HEADER=false
elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no, does not work with Solaris Studio" >&5
$as_echo "no, does not work with Solaris Studio" >&6; }
- USE_PRECOMPILED_HEADER=0
+ USE_PRECOMPILED_HEADER=false
elif test "x$TOOLCHAIN_TYPE" = xxlc; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no, does not work with xlc" >&5
$as_echo "no, does not work with xlc" >&6; }
- USE_PRECOMPILED_HEADER=0
+ USE_PRECOMPILED_HEADER=false
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
@@ -66177,7 +65869,7 @@
echo "int alfa();" > conftest.h
$CXX -x c++-header conftest.h -o conftest.hpp.gch 2>&5 >&5
if test ! -f conftest.hpp.gch; then
- USE_PRECOMPILED_HEADER=0
+ USE_PRECOMPILED_HEADER=false
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
else
@@ -66464,7 +66156,7 @@
as_fn_error $? "On macosx, ccache 3.2 or later is required, found $CCACHE_VERSION" "$LINENO" 5
fi
fi
- if test "x$USE_PRECOMPILED_HEADER" = "x1"; then
+ if test "x$USE_PRECOMPILED_HEADER" = "xtrue"; then
HAS_BAD_CCACHE=`$ECHO $CCACHE_VERSION | \
$GREP -e '^1.*' -e '^2.*' -e '^3\.0.*' -e '^3\.1\.[0123]$'`
if test "x$HAS_BAD_CCACHE" != "x"; then
--- a/common/autoconf/hotspot.m4 Thu Feb 02 05:26:20 2017 -0800
+++ b/common/autoconf/hotspot.m4 Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, 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
@@ -189,7 +189,6 @@
else
AC_MSG_ERROR([Invalid value for --enable-dtrace: $enable_dtrace])
fi
- AC_SUBST(INCLUDE_DTRACE)
])
################################################################################
--- a/common/autoconf/jdk-options.m4 Thu Feb 02 05:26:20 2017 -0800
+++ b/common/autoconf/jdk-options.m4 Thu Feb 09 23:15:52 2017 +0100
@@ -210,10 +210,10 @@
AC_MSG_CHECKING([if elliptic curve crypto implementation is present])
if test -d "${SRC_ROOT}/jdk/src/jdk.crypto.ec/share/native/libsunec/impl"; then
- ENABLE_INTREE_EC=yes
+ ENABLE_INTREE_EC=true
AC_MSG_RESULT([yes])
else
- ENABLE_INTREE_EC=no
+ ENABLE_INTREE_EC=false
AC_MSG_RESULT([no])
fi
@@ -479,5 +479,5 @@
AC_MSG_ERROR([Invalid value for --enable-generate-classlist: $enable_generate_classlist])
fi
- AC_SUBST([ENABLE_GENERATE_CLASSLIST])
+ AC_SUBST(ENABLE_GENERATE_CLASSLIST)
])
--- a/common/autoconf/lib-bundled.m4 Thu Feb 02 05:26:20 2017 -0800
+++ b/common/autoconf/lib-bundled.m4 Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, 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
@@ -119,28 +119,31 @@
DEFAULT_LIBPNG=bundled
# if user didn't specify, use DEFAULT_LIBPNG
if test "x${with_libpng}" = "x"; then
- with_libpng=${DEFAULT_LIBPNG}
+ with_libpng=${DEFAULT_LIBPNG}
fi
if test "x${with_libpng}" = "xbundled"; then
- USE_EXTERNAL_LIBPNG=false
- AC_MSG_RESULT([bundled])
+ USE_EXTERNAL_LIBPNG=false
+ PNG_CFLAGS=""
+ PNG_LIBS=""
+ AC_MSG_RESULT([bundled])
elif test "x${with_libpng}" = "xsystem"; then
- PKG_CHECK_MODULES(PNG, libpng,
- [ LIBPNG_FOUND=yes ],
- [ LIBPNG_FOUND=no ])
- if test "x${LIBPNG_FOUND}" = "xyes"; then
- USE_EXTERNAL_LIBPNG=true
- AC_MSG_RESULT([system])
- else
- AC_MSG_RESULT([system not found])
- AC_MSG_ERROR([--with-libpng=system specified, but no libpng found!])
- fi
+ PKG_CHECK_MODULES(PNG, libpng, [LIBPNG_FOUND=yes], [LIBPNG_FOUND=no])
+ if test "x${LIBPNG_FOUND}" = "xyes"; then
+ # PKG_CHECK_MODULES will set PNG_CFLAGS and PNG_LIBS
+ USE_EXTERNAL_LIBPNG=true
+ AC_MSG_RESULT([system])
+ else
+ AC_MSG_RESULT([system not found])
+ AC_MSG_ERROR([--with-libpng=system specified, but no libpng found!])
+ fi
else
- AC_MSG_ERROR([Invalid value of --with-libpng: ${with_libpng}, use 'system' or 'bundled'])
+ AC_MSG_ERROR([Invalid value of --with-libpng: ${with_libpng}, use 'system' or 'bundled'])
fi
AC_SUBST(USE_EXTERNAL_LIBPNG)
+ AC_SUBST(PNG_CFLAGS)
+ AC_SUBST(PNG_LIBS)
])
################################################################################
@@ -204,16 +207,19 @@
DEFAULT_LCMS=bundled
# If user didn't specify, use DEFAULT_LCMS
if test "x${with_lcms}" = "x"; then
- with_lcms=${DEFAULT_LCMS}
+ with_lcms=${DEFAULT_LCMS}
fi
if test "x${with_lcms}" = "xbundled"; then
USE_EXTERNAL_LCMS=false
+ LCMS_CFLAGS=""
+ LCMS_LIBS=""
AC_MSG_RESULT([bundled])
elif test "x${with_lcms}" = "xsystem"; then
AC_MSG_RESULT([system])
PKG_CHECK_MODULES([LCMS], [lcms2], [LCMS_FOUND=yes], [LCMS_FOUND=no])
if test "x${LCMS_FOUND}" = "xyes"; then
+ # PKG_CHECK_MODULES will set LCMS_CFLAGS and LCMS_LIBS
USE_EXTERNAL_LCMS=true
else
AC_MSG_ERROR([--with-lcms=system specified, but no lcms found!])
@@ -223,4 +229,6 @@
fi
AC_SUBST(USE_EXTERNAL_LCMS)
+ AC_SUBST(LCMS_CFLAGS)
+ AC_SUBST(LCMS_LIBS)
])
--- a/common/autoconf/platform.m4 Thu Feb 02 05:26:20 2017 -0800
+++ b/common/autoconf/platform.m4 Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, 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
@@ -276,12 +276,6 @@
[
PLATFORM_SETUP_LEGACY_VARS_HELPER([TARGET])
PLATFORM_SETUP_LEGACY_VARS_HELPER([BUILD])
-
- # ZERO_ARCHDEF is used to enable architecture-specific code.
- # This is used in legacy hotspot build.
- ZERO_ARCHDEF="$HOTSPOT_TARGET_CPU_DEFINE"
- AC_SUBST(ZERO_ARCHDEF)
-
])
# $1 - Either TARGET or BUILD to setup the variables for.
@@ -360,19 +354,16 @@
OPENJDK_$1_CPU_BUNDLE="$OPENJDK_$1_CPU"
fi
OPENJDK_$1_BUNDLE_PLATFORM="${OPENJDK_$1_OS_BUNDLE}-${OPENJDK_$1_CPU_BUNDLE}"
- AC_SUBST(OPENJDK_$1_OS_BUNDLE)
- AC_SUBST(OPENJDK_$1_CPU_BUNDLE)
AC_SUBST(OPENJDK_$1_BUNDLE_PLATFORM)
if test "x$OPENJDK_$1_CPU_BITS" = x64; then
- A_LP64="LP64:="
# -D_LP64=1 is only set on linux and mac. Setting on windows causes diff in
- # unpack200.exe
+ # unpack200.exe. This variable is used in
+ # FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER.
if test "x$OPENJDK_$1_OS" = xlinux || test "x$OPENJDK_$1_OS" = xmacosx; then
OPENJDK_$1_ADD_LP64="-D_LP64=1"
fi
fi
- AC_SUBST(LP64,$A_LP64)
if test "x$COMPILE_TYPE" = "xcross"; then
# FIXME: ... or should this include reduced builds..?
--- a/common/autoconf/source-dirs.m4 Thu Feb 02 05:26:20 2017 -0800
+++ b/common/autoconf/source-dirs.m4 Thu Feb 09 23:15:52 2017 +0100
@@ -114,12 +114,6 @@
if test -d "$IMPORT_MODULES_TOPDIR/modules_src"; then
IMPORT_MODULES_SRC="$IMPORT_MODULES_TOPDIR/modules_src"
fi
- # Workaround for using different imported module-info.java in Jake due to a
- # change in format. Remove once new format is standard in JDK 9 and javafx
- # delivers just that.
- if test -d "$IMPORT_MODULES_TOPDIR/modules_src_jake"; then
- IMPORT_MODULES_SRC="$IMPORT_MODULES_TOPDIR/modules_src_jake $IMPORT_MODULES_SRC"
- fi
if test -d "$IMPORT_MODULES_TOPDIR/make"; then
IMPORT_MODULES_MAKE="$IMPORT_MODULES_TOPDIR/make"
fi
--- a/common/autoconf/spec.gmk.in Thu Feb 02 05:26:20 2017 -0800
+++ b/common/autoconf/spec.gmk.in Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, 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
@@ -87,9 +87,8 @@
HOTSPOT_TARGET_CPU_ARCH := @HOTSPOT_TARGET_CPU_ARCH@
HOTSPOT_TARGET_CPU_DEFINE := @HOTSPOT_TARGET_CPU_DEFINE@
-OPENJDK_TARGET_CPU_BUNDLE:=@OPENJDK_TARGET_CPU_BUNDLE@
-OPENJDK_TARGET_OS_BUNDLE:=@OPENJDK_TARGET_OS_BUNDLE@
OPENJDK_TARGET_BUNDLE_PLATFORM:=@OPENJDK_TARGET_BUNDLE_PLATFORM@
+JDK_ARCH_ABI_PROP_NAME := @JDK_ARCH_ABI_PROP_NAME@
# We are building on this build system.
# When not cross-compiling, it is the same as the target.
@@ -683,8 +682,7 @@
# Build setup
ENABLE_AOT:=@ENABLE_AOT@
-ENABLE_JFR=@ENABLE_JFR@
-ENABLE_INTREE_EC=@ENABLE_INTREE_EC@
+ENABLE_INTREE_EC:=@ENABLE_INTREE_EC@
USE_EXTERNAL_LIBJPEG:=@USE_EXTERNAL_LIBJPEG@
USE_EXTERNAL_LIBGIF:=@USE_EXTERNAL_LIBGIF@
USE_EXTERNAL_LIBZ:=@USE_EXTERNAL_LIBZ@
--- a/common/bin/hgforest.sh Thu Feb 02 05:26:20 2017 -0800
+++ b/common/bin/hgforest.sh Thu Feb 09 23:15:52 2017 +0100
@@ -309,8 +309,8 @@
echo "serving root repo ${serving}" > ${status_output}
- echo "hg${global_opts} serve" > ${status_output}
- (PYTHONUNBUFFERED=true hg${global_opts} serve -A ${status_output} -E ${status_output} --pid-file ${tmp}/serve.pid --web-conf ${tmp}/serve.web-conf; echo "$?" > ${tmp}/serve.pid.rc ) 2>&1 &
+ echo "hg${global_opts} serve ${@}" > ${status_output}
+ (PYTHONUNBUFFERED=true hg${global_opts} serve -A ${status_output} -E ${status_output} --pid-file ${tmp}/serve.pid --web-conf ${tmp}/serve.web-conf "${@}"; echo "$?" > ${tmp}/serve.pid.rc ) 2>&1 &
) 2>&1 | sed -e "s@^@serve: @" > ${status_output}
) &
else
--- a/common/bin/unshuffle_list.txt Thu Feb 02 05:26:20 2017 -0800
+++ b/common/bin/unshuffle_list.txt Thu Feb 09 23:15:52 2017 +0100
@@ -60,7 +60,7 @@
jaxws/src/java.activation/share/classes/com/sun/activation/registries : jaxws/src/share/jaf_classes/com/sun/activation/registries
jaxws/src/java.activation/share/classes/javax/activation : jaxws/src/share/jaf_classes/javax/activation
jaxws/src/java.activation/share/classes/META-INF : jaxws/src/share/jaf_classes/META-INF
-jaxws/src/java.annotations.common/share/classes/javax/annotation : jaxws/src/share/jaxws_classes/javax/annotation
+jaxws/src/java.xml.ws.annotation/share/classes/javax/annotation : jaxws/src/share/jaxws_classes/javax/annotation
jaxws/src/java.xml.bind/share/classes/com/sun/istack/internal : jaxws/src/share/jaxws_classes/com/sun/istack/internal
jaxws/src/java.xml.bind/share/classes/com/sun/istack/internal/localization : jaxws/src/share/jaxws_classes/com/sun/istack/internal/localization
jaxws/src/java.xml.bind/share/classes/com/sun/istack/internal/logging/Logger.java : jaxws/src/share/jaxws_classes/com/sun/istack/internal/logging/Logger.java
@@ -1163,9 +1163,6 @@
jdk/src/java.management/share/classes/sun/management/counter : jdk/src/share/classes/sun/management/counter
jdk/src/java.management/share/classes/sun/management/counter/perf : jdk/src/share/classes/sun/management/counter/perf
jdk/src/java.management/share/classes/sun/management : jdk/src/share/classes/sun/management
-jdk/src/java.management/share/classes/sun/management/jdp : jdk/src/share/classes/sun/management/jdp
-jdk/src/java.management/share/classes/sun/management/jmxremote : jdk/src/share/classes/sun/management/jmxremote
-jdk/src/java.management/share/classes/sun/management/resources : jdk/src/share/classes/sun/management/resources
jdk/src/java.management/share/conf : jdk/src/share/lib/management
jdk/src/java.management/share/native/include/jmm.h : jdk/src/share/javavm/export/jmm.h
jdk/src/java.management/share/native/libmanagement : jdk/src/share/native/sun/management
@@ -1173,6 +1170,11 @@
jdk/src/java.management/unix/native/libmanagement : jdk/src/solaris/native/sun/management
jdk/src/java.management/windows/classes/sun/management : jdk/src/windows/classes/sun/management
jdk/src/java.management/windows/native/libmanagement : jdk/src/windows/native/sun/management
+jdk/src/java.management.rmi/share/classes/com/sun/jmx/remote/internal/rmi/ProxyRef.java : jdk/src/share/classes/com/sun/jmx/remote/internal/ProxyRef.java
+jdk/src/java.management.rmi/share/classes/com/sun/jmx/remote/internal/rmi/RMIExporter.java : jdk/src/share/classes/com/sun/jmx/remote/internal/RMIExporter.java
+jdk/src/java.management.rmi/share/classes/com/sun/jmx/remote/internal/rmi/Unmarshal.java : jdk/src/share/classes/com/sun/jmx/remote/internal/Unmarshal.java
+jdk/src/java.management.rmi/share/classes/com/sun/jmx/remote/protocol/rmi : jdk/src/share/classes/com/sun/jmx/remote/protocol/rmi
+jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi : jdk/src/share/classes/javax/management/remote/rmi
jdk/src/java.naming/share/classes/com/sun/jndi/ldap/ext : jdk/src/share/classes/com/sun/jndi/ldap/ext
jdk/src/java.naming/share/classes/com/sun/jndi/ldap : jdk/src/share/classes/com/sun/jndi/ldap
jdk/src/java.naming/share/classes/com/sun/jndi/ldap/pool : jdk/src/share/classes/com/sun/jndi/ldap/pool
@@ -1330,9 +1332,9 @@
jdk/src/jdk.jdwp.agent/unix/native/libjdwp : jdk/src/solaris/back
jdk/src/jdk.jdwp.agent/windows/native/libdt_socket : jdk/src/windows/transport/socket
jdk/src/jdk.jdwp.agent/windows/native/libjdwp : jdk/src/windows/back
-jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/monitor : jdk/src/share/classes/sun/jvmstat/monitor
-jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata : jdk/src/share/classes/sun/jvmstat/perfdata
-jdk/src/jdk.jvmstat/share/classes/sun/tools/jstatd : jdk/src/share/classes/sun/tools/jstatd
+jdk/src/jdk.internal.jvmstat/share/classes/sun/jvmstat/monitor : jdk/src/share/classes/sun/jvmstat/monitor
+jdk/src/jdk.internal.jvmstat/share/classes/sun/jvmstat/perfdata : jdk/src/share/classes/sun/jvmstat/perfdata
+jdk/src/jdk.internal.jvmstat/share/classes/sun/tools/jstatd : jdk/src/share/classes/sun/tools/jstatd
jdk/src/jdk.localedata/share/classes/sun/text/resources/ar : jdk/src/share/classes/sun/text/resources/ar
jdk/src/jdk.localedata/share/classes/sun/text/resources/be : jdk/src/share/classes/sun/text/resources/be
jdk/src/jdk.localedata/share/classes/sun/text/resources/bg : jdk/src/share/classes/sun/text/resources/bg
@@ -1421,6 +1423,9 @@
jdk/src/jdk.localedata/share/classes/sun/util/resources/vi : jdk/src/share/classes/sun/util/resources/vi
jdk/src/jdk.localedata/share/classes/sun/util/resources/zh : jdk/src/share/classes/sun/util/resources/zh
jdk/src/jdk.management/share/classes/com/sun/management : jdk/src/share/classes/com/sun/management
+jdk/src/jdk.management.agent/share/classes/jdk/internal/agent/resources : jdk/src/share/classes/sun/management/resources
+jdk/src/jdk.management.agent/share/classes/sun/management/jmxremote : jdk/src/share/classes/sun/management/jmxremote
+jdk/src/jdk.management.agent/share/classes/sun/management/jdp : jdk/src/share/classes/sun/management/jdp
jdk/src/jdk.naming.dns/share/classes/com/sun/jndi/dns : jdk/src/share/classes/com/sun/jndi/dns
jdk/src/jdk.naming.dns/share/classes/com/sun/jndi/url/dns : jdk/src/share/classes/com/sun/jndi/url/dns
jdk/src/jdk.naming.dns/share/classes/META-INF/services : jdk/src/share/classes/sun/net/spi/nameservice/dns/META-INF/services
--- a/common/conf/jib-profiles.js Thu Feb 02 05:26:20 2017 -0800
+++ b/common/conf/jib-profiles.js Thu Feb 09 23:15:52 2017 +0100
@@ -610,6 +610,19 @@
}
profiles = concatObjects(profiles, testOnlyProfilesPrebuilt);
+ // On macosx add the devkit bin dir to the path in all the run-test profiles.
+ // This gives us a guaranteed working version of lldb for the jtreg failure handler.
+ if (input.build_os == "macosx") {
+ macosxRunTestExtra = {
+ dependencies: [ "devkit" ],
+ environment_path: input.get("devkit", "install_path")
+ + "/Xcode.app/Contents/Developer/usr/bin"
+ }
+ profiles["run-test"] = concatObjects(profiles["run-test"], macosxRunTestExtra);
+ profiles["run-test-jprt"] = concatObjects(profiles["run-test-jprt"], macosxRunTestExtra);
+ profiles["run-test-prebuilt"] = concatObjects(profiles["run-test-prebuilt"], macosxRunTestExtra);
+ }
+
//
// Define artifacts for profiles
//
@@ -844,7 +857,7 @@
file: boot_jdk_platform + "/jdk-" + common.boot_jdk_revision
+ "-" + boot_jdk_platform + ".tar.gz",
configure_args: "--with-boot-jdk=" + common.boot_jdk_home,
- environment_path: common.boot_jdk_home
+ environment_path: common.boot_jdk_home + "/bin"
},
devkit: {
--- a/corba/.hgtags Thu Feb 02 05:26:20 2017 -0800
+++ b/corba/.hgtags Thu Feb 09 23:15:52 2017 +0100
@@ -396,3 +396,5 @@
77f827f5bbad3ef795664bc675f72d98d156b9f8 jdk-9+151
ff8cb43c07c069b1debdee44cb88ca22db1ec757 jdk-9+152
68a8e8658511093b322a46ed04b2a321e1da2a43 jdk-9+153
+078ebe23b584466dc8346e620d7821d91751e5a9 jdk-9+154
+a545f54babfa31aa7eb611f36031609acd617cbc jdk-9+155
--- a/corba/src/java.corba/share/classes/com/sun/corba/se/spi/orb/ORB.java Thu Feb 02 05:26:20 2017 -0800
+++ b/corba/src/java.corba/share/classes/com/sun/corba/se/spi/orb/ORB.java Thu Feb 09 23:15:52 2017 +0100
@@ -31,9 +31,6 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger ;
-import java.security.AccessController ;
-import java.security.PrivilegedAction ;
-
import org.omg.CORBA.TCKind ;
import com.sun.corba.se.pept.broker.Broker ;
@@ -89,9 +86,6 @@
import com.sun.corba.se.impl.presentation.rmi.PresentationManagerImpl ;
-import jdk.internal.misc.JavaAWTAccess;
-import jdk.internal.misc.SharedSecrets;
-
public abstract class ORB extends com.sun.corba.se.org.omg.CORBA.ORB
implements Broker, TypeCodeFactory
{
@@ -164,12 +158,9 @@
static class Holder {
static final PresentationManager defaultPresentationManager =
- setupPresentationManager();
+ setupPresentationManager();
}
- private static final Map<Object, PresentationManager> pmContexts =
- new ConcurrentHashMap<>();
-
private static Map<StringPair, LogWrapperBase> staticWrapperMap =
new ConcurrentHashMap<>();
@@ -198,23 +189,10 @@
byteBufferPool = null;
}
- /**
- * Returns the Presentation Manager for the current thread group, using the ThreadGroup-specific
- * AppContext to hold it. Creates and records one if needed.
+ /** Get the single instance of the PresentationManager
*/
public static PresentationManager getPresentationManager()
{
- SecurityManager sm = System.getSecurityManager();
- JavaAWTAccess javaAwtAccess = SharedSecrets.getJavaAWTAccess();
- if (sm != null && javaAwtAccess != null) {
- final Object appletContext = javaAwtAccess.getAppletContext();
- if (appletContext != null) {
- return pmContexts.computeIfAbsent(appletContext,
- x -> setupPresentationManager());
- }
- }
-
- // No security manager or AppletAppContext
return Holder.defaultPresentationManager;
}
--- a/corba/src/java.corba/share/classes/org/omg/CORBA/ORB.java Thu Feb 02 05:26:20 2017 -0800
+++ b/corba/src/java.corba/share/classes/org/omg/CORBA/ORB.java Thu Feb 09 23:15:52 2017 +0100
@@ -36,8 +36,6 @@
import java.security.AccessController;
import java.security.PrivilegedAction;
-import sun.reflect.misc.ReflectUtil;
-
/**
* A class providing APIs for the CORBA Object Request Broker
* features. The {@code ORB} class also provides
@@ -188,6 +186,24 @@
private static final String ORBClassKey = "org.omg.CORBA.ORBClass";
private static final String ORBSingletonClassKey = "org.omg.CORBA.ORBSingletonClass";
+ // check that access to the class is not restricted by the security manager.
+ private static void checkPackageAccess(String name) {
+ SecurityManager s = System.getSecurityManager();
+ if (s != null) {
+ String cname = name.replace('/', '.');
+ if (cname.startsWith("[")) {
+ int b = cname.lastIndexOf('[') + 2;
+ if (b > 1 && b < cname.length()) {
+ cname = cname.substring(b);
+ }
+ }
+ int i = cname.lastIndexOf('.');
+ if (i != -1) {
+ s.checkPackageAccess(cname.substring(0, i));
+ }
+ }
+ }
+
//
// The global instance of the singleton ORB implementation which
// acts as a factory for typecodes for generated Helper classes.
@@ -318,7 +334,7 @@
private static ORB create_impl_with_systemclassloader(String className) {
try {
- ReflectUtil.checkPackageAccess(className);
+ checkPackageAccess(className);
ClassLoader cl = ClassLoader.getSystemClassLoader();
Class<org.omg.CORBA.ORB> orbBaseClass = org.omg.CORBA.ORB.class;
Class<?> singletonOrbClass = Class.forName(className, true, cl).asSubclass(orbBaseClass);
@@ -337,7 +353,7 @@
cl = ClassLoader.getSystemClassLoader();
try {
- ReflectUtil.checkPackageAccess(className);
+ checkPackageAccess(className);
Class<org.omg.CORBA.ORB> orbBaseClass = org.omg.CORBA.ORB.class;
Class<?> orbClass = Class.forName(className, true, cl).asSubclass(orbBaseClass);
return (ORB)orbClass.newInstance();
--- a/corba/src/java.corba/share/classes/org/omg/CORBA_2_3/portable/InputStream.java Thu Feb 02 05:26:20 2017 -0800
+++ b/corba/src/java.corba/share/classes/org/omg/CORBA_2_3/portable/InputStream.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, 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
@@ -75,10 +75,11 @@
/**
* Create a new instance of this class.
*
- * throw SecurityException if SecurityManager is installed and
+ * @implNote
+ * Throws SecurityException if SecurityManager is installed and
* enableSubclassImplementation SerializablePermission
* is not granted or jdk.corba.allowInputStreamSubclass system
- * property is either not set or is set to 'false'
+ * property is either not set or is set to 'false'.
*/
public InputStream() {
this(checkPermission());
--- a/corba/src/java.corba/share/classes/org/omg/CORBA_2_3/portable/OutputStream.java Thu Feb 02 05:26:20 2017 -0800
+++ b/corba/src/java.corba/share/classes/org/omg/CORBA_2_3/portable/OutputStream.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, 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
@@ -72,10 +72,11 @@
/**
* Create a new instance of this class.
*
- * throw SecurityException if SecurityManager is installed and
+ * @implNote
+ * Throws SecurityException if SecurityManager is installed and
* enableSubclassImplementation SerializablePermission
* is not granted or jdk.corba.allowOutputStreamSubclass system
- * property is either not set or is set to 'false'
+ * property is either not set or is set to 'false'.
*/
public OutputStream() {
this(checkPermission());
--- a/corba/src/java.corba/share/classes/sun/corba/Bridge.java Thu Feb 02 05:26:20 2017 -0800
+++ b/corba/src/java.corba/share/classes/sun/corba/Bridge.java Thu Feb 09 23:15:52 2017 +0100
@@ -29,6 +29,10 @@
import java.lang.invoke.MethodHandle;
import java.lang.reflect.Field ;
import java.lang.reflect.Constructor ;
+import java.lang.StackWalker;
+import java.lang.StackWalker.StackFrame;
+import java.util.Optional;
+import java.util.stream.Stream;
import java.security.AccessController;
import java.security.Permission;
@@ -58,6 +62,7 @@
* <li>RuntimePermission "reflectionFactoryAccess"</li>
* <li>BridgePermission "getBridge"</li>
* <li>ReflectPermission "suppressAccessChecks"</li>
+ * <li>StackFramePermission "retainClassReference"</li>
* </ul>
* <p>
* All of these permissions are required to obtain and correctly initialize
@@ -89,9 +94,12 @@
) ;
private final ReflectionFactory reflectionFactory ;
+ private final StackWalker stackWalker;
private Bridge() {
reflectionFactory = ReflectionFactory.getReflectionFactory();
+ stackWalker = StackWalker.getInstance(
+ StackWalker.Option.RETAIN_CLASS_REFERENCE);
}
/** Fetch the Bridge singleton. This requires the following
@@ -100,6 +108,7 @@
* <li>RuntimePermission "reflectionFactoryAccess"</li>
* <li>BridgePermission "getBridge"</li>
* <li>ReflectPermission "suppressAccessChecks"</li>
+ * <li>StackFramePermission "retainClassReference"</li>
* </ul>
* @return The singleton instance of the Bridge class
* @throws SecurityException if the caller does not have the
@@ -118,11 +127,33 @@
return bridge ;
}
+ /** Returns true if the loader that loaded the frame's declaring class
+ * is a user loader (if it is not the platform class loader or one of
+ * its ancestor).
+ */
+ private boolean isUserLoader(StackFrame sf) {
+ ClassLoader cl = sf.getDeclaringClass().getClassLoader();
+ if (cl == null) return false;
+ ClassLoader p = ClassLoader.getPlatformClassLoader();
+ while (cl != p && p != null) p = p.getParent();
+ return cl != p;
+ }
+
+ private Optional<StackFrame> getLatestUserDefinedLoaderFrame(Stream<StackFrame> stream) {
+ return stream.filter(this::isUserLoader).findFirst();
+ }
+
+
/** Obtain the latest user defined ClassLoader from the call stack.
* This is required by the RMI-IIOP specification.
*/
public final ClassLoader getLatestUserDefinedLoader() {
- return jdk.internal.misc.VM.latestUserDefinedLoader();
+ // requires getClassLoader permission => needs doPrivileged.
+ PrivilegedAction<ClassLoader> pa = () ->
+ stackWalker.walk(this::getLatestUserDefinedLoaderFrame)
+ .map(sf -> sf.getDeclaringClass().getClassLoader())
+ .orElseGet(() -> ClassLoader.getPlatformClassLoader());
+ return AccessController.doPrivileged(pa);
}
/**
--- a/hotspot/.hgtags Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/.hgtags Thu Feb 09 23:15:52 2017 +0100
@@ -556,3 +556,5 @@
2a2ac7d9f52c8cb2b80077e515b5840b947e640c jdk-9+151
31f1d26c60df7b2e516a4f84160d76ba017d4e09 jdk-9+152
217ba81b9a4ce8698200370175aa2db86a39f66c jdk-9+153
+a9fdfd55835ef9dccb7f317b07249bd66653b874 jdk-9+154
+f3b3d77a1751897413aae43ac340a130b6fa2ae1 jdk-9+155
--- a/hotspot/make/ide/CreateVSProject.gmk Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/make/ide/CreateVSProject.gmk Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2016, 2017, 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
@@ -121,7 +121,7 @@
-buildBase $(call FixPath, $(IDE_OUTPUTDIR)/vs-output) \
-buildSpace $(call FixPath, $(IDE_OUTPUTDIR)) \
-makeBinary $(call FixPath, $(MAKE)) \
- -makeOutput $(call FixPath, $(HOTSPOT_OUTPUTDIR)/variant-%f/libjvm) \
+ -makeOutput $(call FixPath, $(JDK_OUTPUTDIR)/bin/server) \
-absoluteInclude $(call FixPath, $(HOTSPOT_OUTPUTDIR)/variant-server/gensrc) \
-absoluteSrcInclude $(call FixPath, $(HOTSPOT_OUTPUTDIR)/variant-server/gensrc) \
$(EXTRACTED_DEFINES_client) \
--- a/hotspot/make/lib/CompileJvm.gmk Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/make/lib/CompileJvm.gmk Thu Feb 09 23:15:52 2017 +0100
@@ -63,7 +63,7 @@
# INCLUDE_SUFFIX_* is only meant for including the proper
# platform files. Don't use it to guard code. Use the value of
# HOTSPOT_TARGET_CPU_DEFINE etc. instead.
-# Remaining TARGET_ARCH_* is needed to select the cpu specific
+# Remaining TARGET_ARCH_* is needed to select the cpu specific
# sources for 64-bit ARM ports (arm versus aarch64).
JVM_CFLAGS_TARGET_DEFINES += \
-DTARGET_ARCH_$(HOTSPOT_TARGET_CPU_ARCH) \
@@ -132,7 +132,7 @@
#
# -DDONT_USE_PRECOMPILED_HEADER will exclude all includes in precompiled.hpp.
-ifeq ($(USE_PRECOMPILED_HEADER), 0)
+ifeq ($(USE_PRECOMPILED_HEADER), false)
JVM_CFLAGS += -DDONT_USE_PRECOMPILED_HEADER
endif
@@ -145,7 +145,7 @@
JVM_EXCLUDE_PATTERNS += arm_64
else ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU), linux-aarch64)
- # For 64-bit arm builds, we use the 64 bit hotspot/src/cpu/arm
+ # For 64-bit arm builds, we use the 64 bit hotspot/src/cpu/arm
# hotspot sources if HOTSPOT_TARGET_CPU_ARCH is set to arm.
# Exclude the aarch64 and 32 bit arm files for this build.
ifeq ($(HOTSPOT_TARGET_CPU_ARCH), arm)
--- a/hotspot/make/src/classes/build/tools/projectcreator/WinGammaPlatformVC10.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/make/src/classes/build/tools/projectcreator/WinGammaPlatformVC10.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, 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
@@ -114,8 +114,8 @@
tag(cfg, "CodeAnalysisRuleAssemblies");
}
for (BuildConfig cfg : allConfigs) {
- tagData(cfg, "NMakeBuildCommandLine", cfg.get("MakeBinary") + " -f ../../Makefile import-hotspot LOG=info");
- tagData(cfg, "NMakeReBuildCommandLine", cfg.get("MakeBinary") + " -f ../../Makefile clean-hotspot import-hotspot LOG=info");
+ tagData(cfg, "NMakeBuildCommandLine", cfg.get("MakeBinary") + " -f ../../Makefile hotspot LOG=info");
+ tagData(cfg, "NMakeReBuildCommandLine", cfg.get("MakeBinary") + " -f ../../Makefile clean-hotspot hotspot LOG=info");
tagData(cfg, "NMakeCleanCommandLine", cfg.get("MakeBinary") + " -f ../../Makefile clean-hotspot LOG=info");
tagData(cfg, "NMakeOutput", cfg.get("MakeOutput") + Util.sep + "jvm.dll");
tagData(cfg, "NMakePreprocessorDefinitions", Util.join(";", cfg.getDefines()));
--- a/hotspot/make/symbols/symbols-unix Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/make/symbols/symbols-unix Thu Feb 09 23:15:52 2017 +0100
@@ -192,4 +192,3 @@
JVM_AddReadsModule
JVM_DefineModule
JVM_SetBootLoaderUnnamedModule
-JVM_GetModuleByPackageName
--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad Thu Feb 09 23:15:52 2017 +0100
@@ -1042,8 +1042,10 @@
bool is_card_mark_membar(const MemBarNode *barrier);
bool is_CAS(int opcode);
- MemBarNode *leading_to_trailing(MemBarNode *leading);
- MemBarNode *card_mark_to_leading(const MemBarNode *barrier);
+ MemBarNode *leading_to_normal(MemBarNode *leading);
+ MemBarNode *normal_to_leading(const MemBarNode *barrier);
+ MemBarNode *card_mark_to_trailing(const MemBarNode *barrier);
+ MemBarNode *trailing_to_card_mark(const MemBarNode *trailing);
MemBarNode *trailing_to_leading(const MemBarNode *trailing);
// predicates controlling emit of ldr<x>/ldar<x> and associated dmb
@@ -1420,28 +1422,23 @@
// leading MemBarRelease and a trailing MemBarVolatile as follows
//
// MemBarRelease
- // { || } -- optional
+ // { || } -- optional
// {MemBarCPUOrder}
- // || \\
- // || StoreX[mo_release]
- // | \ Bot / ???
- // | MergeMem
- // | /
+ // || \\
+ // || StoreX[mo_release]
+ // | \ /
+ // | MergeMem
+ // | /
// MemBarVolatile
//
// where
// || and \\ represent Ctl and Mem feeds via Proj nodes
// | \ and / indicate further routing of the Ctl and Mem feeds
//
- // Note that the memory feed from the CPUOrder membar to the
- // MergeMem node is an AliasIdxBot slice while the feed from the
- // StoreX is for a slice determined by the type of value being
- // written.
- //
- // the diagram above shows the graph we see for non-object stores.
- // for a volatile Object store (StoreN/P) we may see other nodes
- // below the leading membar because of the need for a GC pre- or
- // post-write barrier.
+ // this is the graph we see for non-object stores. however, for a
+ // volatile Object store (StoreN/P) we may see other nodes below the
+ // leading membar because of the need for a GC pre- or post-write
+ // barrier.
//
// with most GC configurations we with see this simple variant which
// includes a post-write barrier card mark.
@@ -1449,7 +1446,7 @@
// MemBarRelease______________________________
// || \\ Ctl \ \\
// || StoreN/P[mo_release] CastP2X StoreB/CM
- // | \ Bot / oop . . . /
+ // | \ / . . . /
// | MergeMem
// | /
// || /
@@ -1459,142 +1456,152 @@
// the object address to an int used to compute the card offset) and
// Ctl+Mem to a StoreB node (which does the actual card mark).
//
- // n.b. a StoreCM node is only ever used when CMS (with or without
- // CondCardMark) or G1 is configured. This abstract instruction
- // differs from a normal card mark write (StoreB) because it implies
- // a requirement to order visibility of the card mark (StoreCM)
- // after that of the object put (StoreP/N) using a StoreStore memory
- // barrier. Note that this is /not/ a requirement to order the
- // instructions in the generated code (that is already guaranteed by
- // the order of memory dependencies). Rather it is a requirement to
- // ensure visibility order which only applies on architectures like
- // AArch64 which do not implement TSO. This ordering is required for
- // both non-volatile and volatile puts.
- //
- // That implies that we need to translate a StoreCM using the
- // sequence
+ // n.b. a StoreCM node will only appear in this configuration when
+ // using CMS. StoreCM differs from a normal card mark write (StoreB)
+ // because it implies a requirement to order visibility of the card
+ // mark (StoreCM) relative to the object put (StoreP/N) using a
+ // StoreStore memory barrier (arguably this ought to be represented
+ // explicitly in the ideal graph but that is not how it works). This
+ // ordering is required for both non-volatile and volatile
+ // puts. Normally that means we need to translate a StoreCM using
+ // the sequence
//
// dmb ishst
// stlrb
//
- // This dmb cannot be omitted even when the associated StoreX or
- // CompareAndSwapX is implemented using stlr. However, as described
- // below there are circumstances where a specific GC configuration
- // requires a stronger barrier in which case it can be omitted.
- //
- // With the Serial or Parallel GC using +CondCardMark the card mark
- // is performed conditionally on it currently being unmarked in
- // which case the volatile put graph looks slightly different
+ // However, in the case of a volatile put if we can recognise this
+ // configuration and plant an stlr for the object write then we can
+ // omit the dmb and just plant an strb since visibility of the stlr
+ // is ordered before visibility of subsequent stores. StoreCM nodes
+ // also arise when using G1 or using CMS with conditional card
+ // marking. In these cases (as we shall see) we don't need to insert
+ // the dmb when translating StoreCM because there is already an
+ // intervening StoreLoad barrier between it and the StoreP/N.
+ //
+ // It is also possible to perform the card mark conditionally on it
+ // currently being unmarked in which case the volatile put graph
+ // will look slightly different
//
// MemBarRelease____________________________________________
// || \\ Ctl \ Ctl \ \\ Mem \
// || StoreN/P[mo_release] CastP2X If LoadB |
- // | \ Bot / oop \ |
+ // | \ / \ |
// | MergeMem . . . StoreB
// | / /
// || /
// MemBarVolatile
//
- // It is worth noting at this stage that all the above
+ // It is worth noting at this stage that both the above
// configurations can be uniquely identified by checking that the
// memory flow includes the following subgraph:
//
// MemBarRelease
// {MemBarCPUOrder}
- // | \ . . .
- // | StoreX[mo_release] . . .
- // Bot | / oop
- // MergeMem
- // |
+ // | \ . . .
+ // | StoreX[mo_release] . . .
+ // | /
+ // MergeMem
+ // |
// MemBarVolatile
//
- // This is referred to as a *normal* volatile store subgraph. It can
- // easily be detected starting from any candidate MemBarRelease,
- // StoreX[mo_release] or MemBarVolatile node.
- //
- // A small variation on this normal case occurs for an unsafe CAS
- // operation. The basic memory flow subgraph for a non-object CAS is
- // as follows
+ // This is referred to as a *normal* subgraph. It can easily be
+ // detected starting from any candidate MemBarRelease,
+ // StoreX[mo_release] or MemBarVolatile.
+ //
+ // A simple variation on this normal case occurs for an unsafe CAS
+ // operation. The basic graph for a non-object CAS is
//
// MemBarRelease
// ||
// MemBarCPUOrder
- // | \\ . . .
- // | CompareAndSwapX
- // | |
- // Bot | SCMemProj
- // \ / Bot
- // MergeMem
- // /
+ // || \\ . . .
+ // || CompareAndSwapX
+ // || |
+ // || SCMemProj
+ // | \ /
+ // | MergeMem
+ // | /
// MemBarCPUOrder
// ||
// MemBarAcquire
//
// The same basic variations on this arrangement (mutatis mutandis)
- // occur when a card mark is introduced. i.e. the CPUOrder MemBar
- // feeds the extra CastP2X, LoadB etc nodes but the above memory
- // flow subgraph is still present.
- //
- // This is referred to as a *normal* CAS subgraph. It can easily be
- // detected starting from any candidate MemBarRelease,
- // StoreX[mo_release] or MemBarAcquire node.
- //
- // The code below uses two helper predicates, leading_to_trailing
- // and trailing_to_leading to identify these normal graphs, one
- // validating the layout starting from the top membar and searching
- // down and the other validating the layout starting from the lower
- // membar and searching up.
- //
- // There are two special case GC configurations when the simple
- // normal graphs above may not be generated: when using G1 (which
- // always employs a conditional card mark); and when using CMS with
- // conditional card marking (+CondCardMark) configured. These GCs
- // are both concurrent rather than stop-the world GCs. So they
- // introduce extra Ctl+Mem flow into the graph between the leading
- // and trailing membar nodes, in particular enforcing stronger
- // memory serialisation beween the object put and the corresponding
- // conditional card mark. CMS employs a post-write GC barrier while
- // G1 employs both a pre- and post-write GC barrier.
- //
- // The post-write barrier subgraph for these configurations includes
- // a MemBarVolatile node -- referred to as a card mark membar --
- // which is needed to order the card write (StoreCM) operation in
- // the barrier, the preceding StoreX (or CompareAndSwapX) and Store
- // operations performed by GC threads i.e. a card mark membar
- // constitutes a StoreLoad barrier hence must be translated to a dmb
- // ish (whether or not it sits inside a volatile store sequence).
- //
- // Of course, the use of the dmb ish for the card mark membar also
- // implies theat the StoreCM which follows can omit the dmb ishst
- // instruction. The necessary visibility ordering will already be
- // guaranteed by the dmb ish. In sum, the dmb ishst instruction only
- // needs to be generated for as part of the StoreCM sequence with GC
- // configuration +CMS -CondCardMark.
- //
- // Of course all these extra barrier nodes may well be absent --
- // they are only inserted for object puts. Their potential presence
- // significantly complicates the task of identifying whether a
- // MemBarRelease, StoreX[mo_release], MemBarVolatile or
- // MemBarAcquire forms part of a volatile put or CAS when using
- // these GC configurations (see below) and also complicates the
- // decision as to how to translate a MemBarVolatile and StoreCM.
- //
- // So, thjis means that a card mark MemBarVolatile occurring in the
- // post-barrier graph it needs to be distinguished from a normal
- // trailing MemBarVolatile. Resolving this is straightforward: a
- // card mark MemBarVolatile always projects a Mem feed to a StoreCM
- // node and that is a unique marker
+ // occur when a card mark is introduced. i.e. we se the same basic
+ // shape but the StoreP/N is replaced with CompareAndSawpP/N and the
+ // tail of the graph is a pair comprising a MemBarCPUOrder +
+ // MemBarAcquire.
+ //
+ // So, in the case of a CAS the normal graph has the variant form
+ //
+ // MemBarRelease
+ // MemBarCPUOrder
+ // | \ . . .
+ // | CompareAndSwapX . . .
+ // | |
+ // | SCMemProj
+ // | / . . .
+ // MergeMem
+ // |
+ // MemBarCPUOrder
+ // MemBarAcquire
+ //
+ // This graph can also easily be detected starting from any
+ // candidate MemBarRelease, CompareAndSwapX or MemBarAcquire.
+ //
+ // the code below uses two helper predicates, leading_to_normal and
+ // normal_to_leading to identify these normal graphs, one validating
+ // the layout starting from the top membar and searching down and
+ // the other validating the layout starting from the lower membar
+ // and searching up.
+ //
+ // There are two special case GC configurations when a normal graph
+ // may not be generated: when using G1 (which always employs a
+ // conditional card mark); and when using CMS with conditional card
+ // marking configured. These GCs are both concurrent rather than
+ // stop-the world GCs. So they introduce extra Ctl+Mem flow into the
+ // graph between the leading and trailing membar nodes, in
+ // particular enforcing stronger memory serialisation beween the
+ // object put and the corresponding conditional card mark. CMS
+ // employs a post-write GC barrier while G1 employs both a pre- and
+ // post-write GC barrier. Of course the extra nodes may be absent --
+ // they are only inserted for object puts. This significantly
+ // complicates the task of identifying whether a MemBarRelease,
+ // StoreX[mo_release] or MemBarVolatile forms part of a volatile put
+ // when using these GC configurations (see below). It adds similar
+ // complexity to the task of identifying whether a MemBarRelease,
+ // CompareAndSwapX or MemBarAcquire forms part of a CAS.
+ //
+ // In both cases the post-write subtree includes an auxiliary
+ // MemBarVolatile (StoreLoad barrier) separating the object put and
+ // the read of the corresponding card. This poses two additional
+ // problems.
+ //
+ // Firstly, a card mark MemBarVolatile needs to be distinguished
+ // from a normal trailing MemBarVolatile. Resolving this first
+ // problem is straightforward: a card mark MemBarVolatile always
+ // projects a Mem feed to a StoreCM node and that is a unique marker
//
// MemBarVolatile (card mark)
// C | \ . . .
// | StoreCM . . .
// . . .
//
- // Returning to the task of translating the object put and the
- // leading/trailing membar nodes: what do the node graphs look like
- // for these 2 special cases? and how can we determine the status of
- // a MemBarRelease, StoreX[mo_release] or MemBarVolatile in both
- // normal and non-normal cases?
+ // The second problem is how the code generator is to translate the
+ // card mark barrier? It always needs to be translated to a "dmb
+ // ish" instruction whether or not it occurs as part of a volatile
+ // put. A StoreLoad barrier is needed after the object put to ensure
+ // i) visibility to GC threads of the object put and ii) visibility
+ // to the mutator thread of any card clearing write by a GC
+ // thread. Clearly a normal store (str) will not guarantee this
+ // ordering but neither will a releasing store (stlr). The latter
+ // guarantees that the object put is visible but does not guarantee
+ // that writes by other threads have also been observed.
+ //
+ // So, returning to the task of translating the object put and the
+ // leading/trailing membar nodes: what do the non-normal node graph
+ // look like for these 2 special cases? and how can we determine the
+ // status of a MemBarRelease, StoreX[mo_release] or MemBarVolatile
+ // in both normal and non-normal cases?
//
// A CMS GC post-barrier wraps its card write (StoreCM) inside an If
// which selects conditonal execution based on the value loaded
@@ -1605,117 +1612,91 @@
// which looks like this
//
// MemBarRelease
- // MemBarCPUOrder_(leading)____________________
- // C | | M \ \\ M | C \
- // | | \ StoreN/P[mo_release] | CastP2X
- // | | Bot \ / oop \ |
- // | | MergeMem \ /
- // | | / | /
- // MemBarVolatile (card mark) | /
- // C | || M | | /
- // | LoadB | Bot oop | / Bot
- // | | | / /
- // | Cmp |\ / /
- // | / | \ / /
- // If | \ / /
- // | \ | \ / /
- // IfFalse IfTrue | \ / /
- // \ / \ | | / /
- // \ / StoreCM | / /
- // \ / \ / / /
- // Region Phi / /
- // | \ Raw | / /
- // | . . . | / /
+ // MemBarCPUOrder_(leading)__________________
+ // C | M \ \\ C \
+ // | \ StoreN/P[mo_release] CastP2X
+ // | Bot \ /
+ // | MergeMem
+ // | /
+ // MemBarVolatile (card mark)
+ // C | || M |
+ // | LoadB |
+ // | | |
+ // | Cmp |\
+ // | / | \
+ // If | \
+ // | \ | \
+ // IfFalse IfTrue | \
+ // \ / \ | \
+ // \ / StoreCM |
+ // \ / | |
+ // Region . . . |
+ // | \ /
+ // | . . . \ / Bot
// | MergeMem
- // | |
+ // | |
// MemBarVolatile (trailing)
//
- // Notice that there are two MergeMem nodes below the leading
- // membar. The first MergeMem merges the AliasIdxBot Mem slice from
- // the leading membar and the oopptr Mem slice from the Store into
- // the card mark membar. The trailing MergeMem merges the
- // AliasIdxBot Mem slice from the leading membar, the AliasIdxRaw
- // slice from the StoreCM and an oop slice from the StoreN/P node
- // into the trailing membar (n.b. the raw slice proceeds via a Phi
- // associated with the If region).
- //
- // So, in the case of CMS + CondCardMark the volatile object store
- // graph still includes a normal volatile store subgraph from the
- // leading membar to the trailing membar. However, it also contains
- // the same shape memory flow to the card mark membar. The two flows
- // can be distinguished by testing whether or not the downstream
- // membar is a card mark membar.
- //
- // The graph for a CAS also varies with CMS + CondCardMark, in
- // particular employing a control feed from the CompareAndSwapX node
- // through a CmpI and If to the card mark membar and StoreCM which
- // updates the associated card. This avoids executing the card mark
- // if the CAS fails. However, it can be seen from the diagram below
- // that the presence of the barrier does not alter the normal CAS
- // memory subgraph where the leading membar feeds a CompareAndSwapX,
- // an SCMemProj, a MergeMem then a final trailing MemBarCPUOrder and
- // MemBarAcquire pair.
+ // The first MergeMem merges the AliasIdxBot Mem slice from the
+ // leading membar and the oopptr Mem slice from the Store into the
+ // card mark membar. The trailing MergeMem merges the AliasIdxBot
+ // Mem slice from the card mark membar and the AliasIdxRaw slice
+ // from the StoreCM into the trailing membar (n.b. the latter
+ // proceeds via a Phi associated with the If region).
+ //
+ // The graph for a CAS varies slightly, the obvious difference being
+ // that the StoreN/P node is replaced by a CompareAndSwapP/N node
+ // and the trailing MemBarVolatile by a MemBarCPUOrder +
+ // MemBarAcquire pair. The other important difference is that the
+ // CompareAndSwap node's SCMemProj is not merged into the card mark
+ // membar - it still feeds the trailing MergeMem. This also means
+ // that the card mark membar receives its Mem feed directly from the
+ // leading membar rather than via a MergeMem.
//
// MemBarRelease
- // MemBarCPUOrder__(leading)_______________________
- // C / M | \\ C \
- // . . . | Bot CompareAndSwapN/P CastP2X
- // | C / M |
- // | CmpI |
- // | / |
- // | . . . |
- // | IfTrue |
- // | / |
- // MemBarVolatile (card mark) |
- // C | || M | |
- // | LoadB | Bot ______/|
- // | | | / |
- // | Cmp | / SCMemProj
- // | / | / |
- // If | / /
- // | \ | / / Bot
- // IfFalse IfTrue | / /
- // | / \ / / prec /
- // . . . | / StoreCM /
- // \ | / | raw /
- // Region . . . /
- // | \ /
- // | . . . \ / Bot
- // | MergeMem
- // | /
- // MemBarCPUOrder
- // MemBarAcquire (trailing)
+ // MemBarCPUOrder__(leading)_________________________
+ // || \\ C \
+ // MemBarVolatile (card mark) CompareAndSwapN/P CastP2X
+ // C | || M | |
+ // | LoadB | ______/|
+ // | | | / |
+ // | Cmp | / SCMemProj
+ // | / | / |
+ // If | / /
+ // | \ | / /
+ // IfFalse IfTrue | / /
+ // \ / \ |/ prec /
+ // \ / StoreCM /
+ // \ / | /
+ // Region . . . /
+ // | \ /
+ // | . . . \ / Bot
+ // | MergeMem
+ // | |
+ // MemBarCPUOrder
+ // MemBarAcquire (trailing)
//
// This has a slightly different memory subgraph to the one seen
- // previously but the core of it has a similar memory flow to the
- // CAS normal subgraph:
+ // previously but the core of it is the same as for the CAS normal
+ // sungraph
//
// MemBarRelease
// MemBarCPUOrder____
- // | \ . . .
- // | CompareAndSwapX . . .
- // | C / M |
- // | CmpI |
- // | / |
- // | . . /
- // Bot | IfTrue /
- // | / /
- // MemBarVolatile /
- // | ... /
- // StoreCM ... /
- // | /
- // . . . SCMemProj
- // Raw \ / Bot
- // MergeMem
- // |
+ // || \ . . .
+ // MemBarVolatile CompareAndSwapX . . .
+ // | \ |
+ // . . . SCMemProj
+ // | / . . .
+ // MergeMem
+ // |
// MemBarCPUOrder
// MemBarAcquire
//
- // The G1 graph for a volatile object put is a lot more complicated.
- // Nodes inserted on behalf of G1 may comprise: a pre-write graph
- // which adds the old value to the SATB queue; the releasing store
- // itself; and, finally, a post-write graph which performs a card
- // mark.
+ //
+ // G1 is quite a lot more complicated. The nodes inserted on behalf
+ // of G1 may comprise: a pre-write graph which adds the old value to
+ // the SATB queue; the releasing store itself; and, finally, a
+ // post-write graph which performs a card mark.
//
// The pre-write graph may be omitted, but only when the put is
// writing to a newly allocated (young gen) object and then only if
@@ -1753,60 +1734,25 @@
// | CastP2X | StoreN/P[mo_release] |
// | | | |
// C | M | M | M |
- // \ | Raw | oop / Bot
+ // \ | | /
// . . .
// (post write subtree elided)
// . . .
// C \ M /
// MemBarVolatile (trailing)
//
- // Note that the three memory feeds into the post-write tree are an
- // AliasRawIdx slice associated with the writes in the pre-write
- // tree, an oop type slice from the StoreX specific to the type of
- // the volatile field and the AliasBotIdx slice emanating from the
- // leading membar.
- //
// n.b. the LoadB in this subgraph is not the card read -- it's a
// read of the SATB queue active flag.
//
- // The CAS graph is once again a variant of the above with a
- // CompareAndSwapX node and SCMemProj in place of the StoreX. The
- // value from the CompareAndSwapX node is fed into the post-write
- // graph aling with the AliasIdxRaw feed from the pre-barrier and
- // the AliasIdxBot feeds from the leading membar and the ScMemProj.
- //
- // MemBarRelease (leading)____________
- // C | || M \ M \ M \ M \ . . .
- // | LoadB \ LoadL LoadN \
- // | / \ \
- // If |\ \
- // | \ | \ \
- // IfFalse IfTrue | \ \
- // | | | \ \
- // | If | \ |
- // | | \ |
- // | \ |
- // | . . . \ |
- // | / | / \ |
- // Region Phi[M] \ |
- // | \ | \ |
- // | \_____ | | |
- // C | C \ | | |
- // | CastP2X | CompareAndSwapX |
- // | | res | | |
- // C | M | | SCMemProj M |
- // \ | Raw | | Bot / Bot
- // . . .
- // (post write subtree elided)
- // . . .
- // C \ M /
- // MemBarVolatile (trailing)
+ // Once again the CAS graph is a minor variant on the above with the
+ // expected substitutions of CompareAndSawpX for StoreN/P and
+ // MemBarCPUOrder + MemBarAcquire for trailing MemBarVolatile.
//
// The G1 post-write subtree is also optional, this time when the
// new value being written is either null or can be identified as a
// newly allocated (young gen) object with no intervening control
// flow. The latter cannot happen but the former may, in which case
- // the card mark membar is omitted and the memory feeds from the
+ // the card mark membar is omitted and the memory feeds form the
// leading membar and the SToreN/P are merged direct into the
// trailing membar as per the normal subgraph. So, the only special
// case which arises is when the post-write subgraph is generated.
@@ -1828,106 +1774,94 @@
//
// (pre-write subtree elided)
// . . . . . . . . . . . .
- // C | M | M | M |
- // Region Phi[M] StoreN |
- // | Raw | oop | Bot |
- // / \_______ |\ |\ |\
- // C / C \ . . . | \ | \ | \
- // If CastP2X . . . | \ | \ | \
- // / \ | \ | \ | \
- // / \ | \ | \ | \
- // IfFalse IfTrue | | | \
- // | | \ | / |
- // | If \ | \ / \ |
- // | / \ \ | / \ |
- // | / \ \ | / \ | |
- // | IfFalse IfTrue MergeMem \ | |
- // | . . . / \ | \ | |
- // | / \ | | | |
- // | IfFalse IfTrue | | | |
- // | . . . | | | | |
- // | If / | | |
- // | / \ / | | |
- // | / \ / | | |
- // | IfFalse IfTrue / | | |
- // | . . . | / | | |
- // | \ / | | |
- // | \ / | | |
- // | MemBarVolatile__(card mark ) | | |
- // | || C | \ | | |
- // | LoadB If | / | |
- // | / \ Raw | / / /
- // | . . . | / / /
- // | \ | / / /
- // | StoreCM / / /
- // | | / / /
- // | . . . / /
- // | / /
- // | . . . / /
- // | | | / / /
- // | | Phi[M] / / /
- // | | | / / /
- // | | | / / /
- // | Region . . . Phi[M] / /
- // | | | / /
- // \ | | / /
- // \ | . . . | / /
- // \ | | / /
- // Region Phi[M] / /
- // | \ / /
- // \ MergeMem
- // \ /
- // MemBarVolatile
- //
- // As with CMS + CondCardMark the first MergeMem merges the
- // AliasIdxBot Mem slice from the leading membar and the oopptr Mem
- // slice from the Store into the card mark membar. However, in this
- // case it may also merge an AliasRawIdx mem slice from the pre
- // barrier write.
- //
- // The trailing MergeMem merges an AliasIdxBot Mem slice from the
- // leading membar with an oop slice from the StoreN and an
- // AliasRawIdx slice from the post barrier writes. In this case the
- // AliasIdxRaw Mem slice is merged through a series of Phi nodes
- // which combine feeds from the If regions in the post barrier
- // subgraph.
- //
- // So, for G1 the same characteristic subgraph arises as for CMS +
- // CondCardMark. There is a normal subgraph feeding the card mark
- // membar and a normal subgraph feeding the trailing membar.
- //
- // The CAS graph when using G1GC also includes an optional
- // post-write subgraph. It is very similar to the above graph except
- // for a few details.
- //
- // - The control flow is gated by an additonal If which tests the
- // result from the CompareAndSwapX node
- //
- // - The MergeMem which feeds the card mark membar only merges the
- // AliasIdxBot slice from the leading membar and the AliasIdxRaw
- // slice from the pre-barrier. It does not merge the SCMemProj
- // AliasIdxBot slice. So, this subgraph does not look like the
- // normal CAS subgraph.
- //
- // - The MergeMem which feeds the trailing membar merges the
- // AliasIdxBot slice from the leading membar, the AliasIdxRaw slice
- // from the post-barrier and the SCMemProj AliasIdxBot slice i.e. it
- // has two AliasIdxBot input slices. However, this subgraph does
- // still look like the normal CAS subgraph.
- //
- // So, the upshot is:
- //
- // In all cases a volatile put graph will include a *normal*
- // volatile store subgraph betwen the leading membar and the
- // trailing membar. It may also include a normal volatile store
- // subgraph betwen the leading membar and the card mark membar.
- //
- // In all cases a CAS graph will contain a unique normal CAS graph
- // feeding the trailing membar.
- //
- // In all cases where there is a card mark membar (either as part of
- // a volatile object put or CAS) it will be fed by a MergeMem whose
- // AliasIdxBot slice feed will be a leading membar.
+ // C | M | M | M |
+ // Region Phi[M] StoreN |
+ // | / \ | |
+ // / \_______ / \ | |
+ // C / C \ . . . \ | |
+ // If CastP2X . . . | | |
+ // / \ | | |
+ // / \ | | |
+ // IfFalse IfTrue | | |
+ // | | | | /|
+ // | If | | / |
+ // | / \ | | / |
+ // | / \ \ | / |
+ // | IfFalse IfTrue MergeMem |
+ // | . . . / \ / |
+ // | / \ / |
+ // | IfFalse IfTrue / |
+ // | . . . | / |
+ // | If / |
+ // | / \ / |
+ // | / \ / |
+ // | IfFalse IfTrue / |
+ // | . . . | / |
+ // | \ / |
+ // | \ / |
+ // | MemBarVolatile__(card mark) |
+ // | || C | M \ M \ |
+ // | LoadB If | | |
+ // | / \ | | |
+ // | . . . | | |
+ // | \ | | /
+ // | StoreCM | /
+ // | . . . | /
+ // | _________/ /
+ // | / _____________/
+ // | . . . . . . | / /
+ // | | | / _________/
+ // | | Phi[M] / /
+ // | | | / /
+ // | | | / /
+ // | Region . . . Phi[M] _____/
+ // | / | /
+ // | | /
+ // | . . . . . . | /
+ // | / | /
+ // Region | | Phi[M]
+ // | | | / Bot
+ // \ MergeMem
+ // \ /
+ // MemBarVolatile
+ //
+ // As with CMS the initial MergeMem merges the AliasIdxBot Mem slice
+ // from the leading membar and the oopptr Mem slice from the Store
+ // into the card mark membar i.e. the memory flow to the card mark
+ // membar still looks like a normal graph.
+ //
+ // The trailing MergeMem merges an AliasIdxBot Mem slice with other
+ // Mem slices (from the StoreCM and other card mark queue stores).
+ // However in this case the AliasIdxBot Mem slice does not come
+ // direct from the card mark membar. It is merged through a series
+ // of Phi nodes. These are needed to merge the AliasIdxBot Mem flow
+ // from the leading membar with the Mem feed from the card mark
+ // membar. Each Phi corresponds to one of the Ifs which may skip
+ // around the card mark membar. So when the If implementing the NULL
+ // value check has been elided the total number of Phis is 2
+ // otherwise it is 3.
+ //
+ // The CAS graph when using G1GC also includes a pre-write subgraph
+ // and an optional post-write subgraph. Teh sam evarioations are
+ // introduced as for CMS with conditional card marking i.e. the
+ // StoreP/N is swapped for a CompareAndSwapP/N, the tariling
+ // MemBarVolatile for a MemBarCPUOrder + MemBarAcquire pair and the
+ // Mem feed from the CompareAndSwapP/N includes a precedence
+ // dependency feed to the StoreCM and a feed via an SCMemProj to the
+ // trailing membar. So, as before the configuration includes the
+ // normal CAS graph as a subgraph of the memory flow.
+ //
+ // So, the upshot is that in all cases the volatile put graph will
+ // include a *normal* memory subgraph betwen the leading membar and
+ // its child membar, either a volatile put graph (including a
+ // releasing StoreX) or a CAS graph (including a CompareAndSwapX).
+ // When that child is not a card mark membar then it marks the end
+ // of the volatile put or CAS subgraph. If the child is a card mark
+ // membar then the normal subgraph will form part of a volatile put
+ // subgraph if and only if the child feeds an AliasIdxBot Mem feed
+ // to a trailing barrier via a MergeMem. That feed is either direct
+ // (for CMS) or via 2 or 3 Phi nodes merging the leading barrier
+ // memory flow (for G1).
//
// The predicates controlling generation of instructions for store
// and barrier nodes employ a few simple helper functions (described
@@ -1971,24 +1905,24 @@
}
- // leading_to_trailing
+ // leading_to_normal
//
//graph traversal helper which detects the normal case Mem feed from
// a release membar (or, optionally, its cpuorder child) to a
// dependent volatile membar i.e. it ensures that one or other of
// the following Mem flow subgraph is present.
//
- // MemBarRelease {leading}
- // {MemBarCPUOrder} {optional}
- // Bot | \ . . .
- // | StoreN/P[mo_release] . . .
- // | /
- // MergeMem
- // |
- // MemBarVolatile {not card mark}
- //
- // MemBarRelease {leading}
- // {MemBarCPUOrder} {optional}
+ // MemBarRelease
+ // MemBarCPUOrder {leading}
+ // | \ . . .
+ // | StoreN/P[mo_release] . . .
+ // | /
+ // MergeMem
+ // |
+ // MemBarVolatile {trailing or card mark}
+ //
+ // MemBarRelease
+ // MemBarCPUOrder {leading}
// | \ . . .
// | CompareAndSwapX . . .
// |
@@ -1999,23 +1933,6 @@
// MemBarCPUOrder
// MemBarAcquire {trailing}
//
- // the predicate needs to be capable of distinguishing the following
- // volatile put graph which may arises when a GC post barrier
- // inserts a card mark membar
- //
- // MemBarRelease {leading}
- // {MemBarCPUOrder}__
- // Bot | \ \
- // | StoreN/P \
- // | / \ |
- // MergeMem \ |
- // | \ |
- // MemBarVolatile \ |
- // {card mark} \ |
- // MergeMem
- // |
- // {not card mark} MemBarVolatile
- //
// if the correct configuration is present returns the trailing
// membar otherwise NULL.
//
@@ -2026,7 +1943,7 @@
// the returned value may be a card mark or trailing membar
//
- MemBarNode *leading_to_trailing(MemBarNode *leading)
+ MemBarNode *leading_to_normal(MemBarNode *leading)
{
assert((leading->Opcode() == Op_MemBarRelease ||
leading->Opcode() == Op_MemBarCPUOrder),
@@ -2043,21 +1960,15 @@
StoreNode * st = NULL;
LoadStoreNode *cas = NULL;
MergeMemNode *mm = NULL;
- MergeMemNode *mm2 = NULL;
for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
x = mem->fast_out(i);
if (x->is_MergeMem()) {
if (mm != NULL) {
- if (mm2 != NULL) {
- // should not see more than 2 merge mems
- return NULL;
- } else {
- mm2 = x->as_MergeMem();
- }
- } else {
- mm = x->as_MergeMem();
+ return NULL;
}
+ // two merge mems is one too many
+ mm = x->as_MergeMem();
} else if (x->is_Store() && x->as_Store()->is_release() && x->Opcode() != Op_StoreCM) {
// two releasing stores/CAS nodes is one too many
if (st != NULL || cas != NULL) {
@@ -2077,13 +1988,13 @@
return NULL;
}
- // must have at least one merge if we also have st
+ // must have a merge if we also have st
if (st && !mm) {
return NULL;
}
+ Node *y = NULL;
if (cas) {
- Node *y = NULL;
// look for an SCMemProj
for (DUIterator_Fast imax, i = cas->fast_outs(imax); i < imax; i++) {
x = cas->fast_out(i);
@@ -2103,29 +2014,10 @@
break;
}
}
- if (mm == NULL) {
+ if (mm == NULL)
return NULL;
- }
- MemBarNode *mbar = NULL;
- // ensure the merge feeds a trailing membar cpuorder + acquire pair
- for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) {
- x = mm->fast_out(i);
- if (x->is_MemBar()) {
- int opcode = x->Opcode();
- if (opcode == Op_MemBarCPUOrder) {
- MemBarNode *z = x->as_MemBar();
- z = child_membar(z);
- if (z != NULL && z->Opcode() == Op_MemBarAcquire) {
- mbar = z;
- }
- }
- break;
- }
- }
- return mbar;
} else {
- Node *y = NULL;
- // ensure the store feeds the first mergemem;
+ // ensure the store feeds the existing mergemem;
for (DUIterator_Fast imax, i = st->fast_outs(imax); i < imax; i++) {
if (st->fast_out(i) == mm) {
y = st;
@@ -2135,89 +2027,55 @@
if (y == NULL) {
return NULL;
}
- if (mm2 != NULL) {
- // ensure the store feeds the second mergemem;
- y = NULL;
- for (DUIterator_Fast imax, i = st->fast_outs(imax); i < imax; i++) {
- if (st->fast_out(i) == mm2) {
- y = st;
+ }
+
+ MemBarNode *mbar = NULL;
+ // ensure the merge feeds to the expected type of membar
+ for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) {
+ x = mm->fast_out(i);
+ if (x->is_MemBar()) {
+ int opcode = x->Opcode();
+ if (opcode == Op_MemBarVolatile && st) {
+ mbar = x->as_MemBar();
+ } else if (cas && opcode == Op_MemBarCPUOrder) {
+ MemBarNode *y = x->as_MemBar();
+ y = child_membar(y);
+ if (y != NULL && y->Opcode() == Op_MemBarAcquire) {
+ mbar = y;
}
}
- if (y == NULL) {
- return NULL;
- }
- }
-
- MemBarNode *mbar = NULL;
- // ensure the first mergemem feeds a volatile membar
- for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) {
- x = mm->fast_out(i);
- if (x->is_MemBar()) {
- int opcode = x->Opcode();
- if (opcode == Op_MemBarVolatile) {
- mbar = x->as_MemBar();
- }
- break;
- }
- }
- if (mm2 == NULL) {
- // this is our only option for a trailing membar
- return mbar;
+ break;
}
- // ensure the second mergemem feeds a volatile membar
- MemBarNode *mbar2 = NULL;
- for (DUIterator_Fast imax, i = mm2->fast_outs(imax); i < imax; i++) {
- x = mm2->fast_out(i);
- if (x->is_MemBar()) {
- int opcode = x->Opcode();
- if (opcode == Op_MemBarVolatile) {
- mbar2 = x->as_MemBar();
- }
- break;
- }
- }
- // if we have two merge mems we must have two volatile membars
- if (mbar == NULL || mbar2 == NULL) {
- return NULL;
- }
- // return the trailing membar
- if (is_card_mark_membar(mbar2)) {
- return mbar;
- } else {
- if (is_card_mark_membar(mbar)) {
- return mbar2;
- } else {
- return NULL;
- }
- }
- }
- }
-
- // trailing_to_leading
+ }
+
+ return mbar;
+ }
+
+ // normal_to_leading
//
// graph traversal helper which detects the normal case Mem feed
- // from a trailing membar to a preceding release membar (optionally
- // its cpuorder child) i.e. it ensures that one or other of the
- // following Mem flow subgraphs is present.
- //
- // MemBarRelease {leading}
- // MemBarCPUOrder {optional}
- // | Bot | \ . . .
- // | | StoreN/P[mo_release] . . .
- // | | /
- // | MergeMem
- // | |
- // MemBarVolatile {not card mark}
- //
- // MemBarRelease {leading}
- // MemBarCPUOrder {optional}
+ // from either a card mark or a trailing membar to a preceding
+ // release membar (optionally its cpuorder child) i.e. it ensures
+ // that one or other of the following Mem flow subgraphs is present.
+ //
+ // MemBarRelease
+ // MemBarCPUOrder {leading}
+ // | \ . . .
+ // | StoreN/P[mo_release] . . .
+ // | /
+ // MergeMem
+ // |
+ // MemBarVolatile {card mark or trailing}
+ //
+ // MemBarRelease
+ // MemBarCPUOrder {leading}
// | \ . . .
// | CompareAndSwapX . . .
// |
// . . . SCMemProj
// \ |
// | MergeMem
- // | |
+ // | /
// MemBarCPUOrder
// MemBarAcquire {trailing}
//
@@ -2227,20 +2085,15 @@
// if the configuration is present returns the cpuorder member for
// preference or when absent the release membar otherwise NULL.
//
- // n.b. the input membar is expected to be a MemBarVolatile or
- // MemBarAcquire. if it is a MemBarVolatile it must *not* be a card
- // mark membar.
-
- MemBarNode *trailing_to_leading(const MemBarNode *barrier)
+ // n.b. the input membar is expected to be a MemBarVolatile but
+ // need not be a card mark membar.
+
+ MemBarNode *normal_to_leading(const MemBarNode *barrier)
{
// input must be a volatile membar
assert((barrier->Opcode() == Op_MemBarVolatile ||
barrier->Opcode() == Op_MemBarAcquire),
"expecting a volatile or an acquire membar");
-
- assert((barrier->Opcode() != Op_MemBarVolatile) ||
- !is_card_mark_membar(barrier),
- "not expecting a card mark membar");
Node *x;
bool is_cas = barrier->Opcode() == Op_MemBarAcquire;
@@ -2353,35 +2206,169 @@
return NULL;
}
- // card_mark_to_leading
- //
- // graph traversal helper which traverses from a card mark volatile
- // membar to a leading membar i.e. it ensures that the following Mem
- // flow subgraph is present.
- //
- // MemBarRelease {leading}
- // {MemBarCPUOrder} {optional}
- // | . . .
+ // card_mark_to_trailing
+ //
+ // graph traversal helper which detects extra, non-normal Mem feed
+ // from a card mark volatile membar to a trailing membar i.e. it
+ // ensures that one of the following three GC post-write Mem flow
+ // subgraphs is present.
+ //
+ // 1)
+ // . . .
+ // |
+ // MemBarVolatile (card mark)
+ // | |
+ // | StoreCM
+ // | |
+ // | . . .
+ // Bot | /
+ // MergeMem
+ // |
+ // |
+ // MemBarVolatile {trailing}
+ //
+ // 2)
+ // MemBarRelease/CPUOrder (leading)
+ // |
+ // |
+ // |\ . . .
+ // | \ |
+ // | \ MemBarVolatile (card mark)
+ // | \ | |
+ // \ \ | StoreCM . . .
+ // \ \ |
+ // \ Phi
+ // \ /
+ // Phi . . .
// Bot | /
- // MergeMem
+ // MergeMem
// |
- // MemBarVolatile (card mark)
- // | \
- // . . . StoreCM
- //
- // if the configuration is present returns the cpuorder member for
- // preference or when absent the release membar otherwise NULL.
- //
- // n.b. the input membar is expected to be a MemBarVolatile amd must
- // be a card mark membar.
-
- MemBarNode *card_mark_to_leading(const MemBarNode *barrier)
+ // MemBarVolatile {trailing}
+ //
+ //
+ // 3)
+ // MemBarRelease/CPUOrder (leading)
+ // |
+ // |\
+ // | \
+ // | \ . . .
+ // | \ |
+ // |\ \ MemBarVolatile (card mark)
+ // | \ \ | |
+ // | \ \ | StoreCM . . .
+ // | \ \ |
+ // \ \ Phi
+ // \ \ /
+ // \ Phi
+ // \ /
+ // Phi . . .
+ // Bot | /
+ // MergeMem
+ // |
+ // |
+ // MemBarVolatile {trailing}
+ //
+ // configuration 1 is only valid if UseConcMarkSweepGC &&
+ // UseCondCardMark
+ //
+ // configurations 2 and 3 are only valid if UseG1GC.
+ //
+ // if a valid configuration is present returns the trailing membar
+ // otherwise NULL.
+ //
+ // n.b. the supplied membar is expected to be a card mark
+ // MemBarVolatile i.e. the caller must ensure the input node has the
+ // correct operand and feeds Mem to a StoreCM node
+
+ MemBarNode *card_mark_to_trailing(const MemBarNode *barrier)
{
// input must be a card mark volatile membar
assert(is_card_mark_membar(barrier), "expecting a card mark membar");
+ Node *feed = barrier->proj_out(TypeFunc::Memory);
+ Node *x;
+ MergeMemNode *mm = NULL;
+
+ const int MAX_PHIS = 3; // max phis we will search through
+ int phicount = 0; // current search count
+
+ bool retry_feed = true;
+ while (retry_feed) {
+ // see if we have a direct MergeMem feed
+ for (DUIterator_Fast imax, i = feed->fast_outs(imax); i < imax; i++) {
+ x = feed->fast_out(i);
+ // the correct Phi will be merging a Bot memory slice
+ if (x->is_MergeMem()) {
+ mm = x->as_MergeMem();
+ break;
+ }
+ }
+ if (mm) {
+ retry_feed = false;
+ } else if (UseG1GC & phicount++ < MAX_PHIS) {
+ // the barrier may feed indirectly via one or two Phi nodes
+ PhiNode *phi = NULL;
+ for (DUIterator_Fast imax, i = feed->fast_outs(imax); i < imax; i++) {
+ x = feed->fast_out(i);
+ // the correct Phi will be merging a Bot memory slice
+ if (x->is_Phi() && x->adr_type() == TypePtr::BOTTOM) {
+ phi = x->as_Phi();
+ break;
+ }
+ }
+ if (!phi) {
+ return NULL;
+ }
+ // look for another merge below this phi
+ feed = phi;
+ } else {
+ // couldn't find a merge
+ return NULL;
+ }
+ }
+
+ // sanity check this feed turns up as the expected slice
+ assert(mm->as_MergeMem()->in(Compile::AliasIdxBot) == feed, "expecting membar to feed AliasIdxBot slice to Merge");
+
+ MemBarNode *trailing = NULL;
+ // be sure we have a trailing membar the merge
+ for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) {
+ x = mm->fast_out(i);
+ if (x->is_MemBar() && x->Opcode() == Op_MemBarVolatile) {
+ trailing = x->as_MemBar();
+ break;
+ }
+ }
+
+ return trailing;
+ }
+
+ // trailing_to_card_mark
+ //
+ // graph traversal helper which detects extra, non-normal Mem feed
+ // from a trailing volatile membar to a preceding card mark volatile
+ // membar i.e. it identifies whether one of the three possible extra
+ // GC post-write Mem flow subgraphs is present
+ //
+ // this predicate checks for the same flow as the previous predicate
+ // but starting from the bottom rather than the top.
+ //
+ // if the configuration is present returns the card mark membar
+ // otherwise NULL
+ //
+ // n.b. the supplied membar is expected to be a trailing
+ // MemBarVolatile i.e. the caller must ensure the input node has the
+ // correct opcode
+
+ MemBarNode *trailing_to_card_mark(const MemBarNode *trailing)
+ {
+ assert(trailing->Opcode() == Op_MemBarVolatile,
+ "expecting a volatile membar");
+ assert(!is_card_mark_membar(trailing),
+ "not expecting a card mark membar");
+
// the Mem feed to the membar should be a merge
- Node *x = barrier->in(TypeFunc::Memory);
+ Node *x = trailing->in(TypeFunc::Memory);
if (!x->is_MergeMem()) {
return NULL;
}
@@ -2389,19 +2376,117 @@
MergeMemNode *mm = x->as_MergeMem();
x = mm->in(Compile::AliasIdxBot);
-
+ // with G1 we may possibly see a Phi or two before we see a Memory
+ // Proj from the card mark membar
+
+ const int MAX_PHIS = 3; // max phis we will search through
+ int phicount = 0; // current search count
+
+ bool retry_feed = !x->is_Proj();
+
+ while (retry_feed) {
+ if (UseG1GC && x->is_Phi() && phicount++ < MAX_PHIS) {
+ PhiNode *phi = x->as_Phi();
+ ProjNode *proj = NULL;
+ PhiNode *nextphi = NULL;
+ bool found_leading = false;
+ for (uint i = 1; i < phi->req(); i++) {
+ x = phi->in(i);
+ if (x->is_Phi()) {
+ nextphi = x->as_Phi();
+ } else if (x->is_Proj()) {
+ int opcode = x->in(0)->Opcode();
+ if (opcode == Op_MemBarVolatile) {
+ proj = x->as_Proj();
+ } else if (opcode == Op_MemBarRelease ||
+ opcode == Op_MemBarCPUOrder) {
+ // probably a leading membar
+ found_leading = true;
+ }
+ }
+ }
+ // if we found a correct looking proj then retry from there
+ // otherwise we must see a leading and a phi or this the
+ // wrong config
+ if (proj != NULL) {
+ x = proj;
+ retry_feed = false;
+ } else if (found_leading && nextphi != NULL) {
+ // retry from this phi to check phi2
+ x = nextphi;
+ } else {
+ // not what we were looking for
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+ }
+ // the proj has to come from the card mark membar
+ x = x->in(0);
if (!x->is_MemBar()) {
return NULL;
}
- MemBarNode *leading = x->as_MemBar();
-
- if (leading_membar(leading)) {
+ MemBarNode *card_mark_membar = x->as_MemBar();
+
+ if (!is_card_mark_membar(card_mark_membar)) {
+ return NULL;
+ }
+
+ return card_mark_membar;
+ }
+
+ // trailing_to_leading
+ //
+ // graph traversal helper which checks the Mem flow up the graph
+ // from a (non-card mark) trailing membar attempting to locate and
+ // return an associated leading membar. it first looks for a
+ // subgraph in the normal configuration (relying on helper
+ // normal_to_leading). failing that it then looks for one of the
+ // possible post-write card mark subgraphs linking the trailing node
+ // to a the card mark membar (relying on helper
+ // trailing_to_card_mark), and then checks that the card mark membar
+ // is fed by a leading membar (once again relying on auxiliary
+ // predicate normal_to_leading).
+ //
+ // if the configuration is valid returns the cpuorder member for
+ // preference or when absent the release membar otherwise NULL.
+ //
+ // n.b. the input membar is expected to be either a volatile or
+ // acquire membar but in the former case must *not* be a card mark
+ // membar.
+
+ MemBarNode *trailing_to_leading(const MemBarNode *trailing)
+ {
+ assert((trailing->Opcode() == Op_MemBarAcquire ||
+ trailing->Opcode() == Op_MemBarVolatile),
+ "expecting an acquire or volatile membar");
+ assert((trailing->Opcode() != Op_MemBarVolatile ||
+ !is_card_mark_membar(trailing)),
+ "not expecting a card mark membar");
+
+ MemBarNode *leading = normal_to_leading(trailing);
+
+ if (leading) {
return leading;
}
- return NULL;
- }
+ // nothing more to do if this is an acquire
+ if (trailing->Opcode() == Op_MemBarAcquire) {
+ return NULL;
+ }
+
+ MemBarNode *card_mark_membar = trailing_to_card_mark(trailing);
+
+ if (!card_mark_membar) {
+ return NULL;
+ }
+
+ return normal_to_leading(card_mark_membar);
+ }
+
+ // predicates controlling emit of ldr<x>/ldar<x> and associated dmb
bool unnecessary_acquire(const Node *barrier)
{
@@ -2617,8 +2702,19 @@
}
// must start with a normal feed
- MemBarNode *trailing = leading_to_trailing(barrier);
-
+ MemBarNode *child_barrier = leading_to_normal(barrier);
+
+ if (!child_barrier) {
+ return false;
+ }
+
+ if (!is_card_mark_membar(child_barrier)) {
+ // this is the trailing membar and we are done
+ return true;
+ }
+
+ // must be sure this card mark feeds a trailing membar
+ MemBarNode *trailing = card_mark_to_trailing(child_barrier);
return (trailing != NULL);
}
@@ -2640,7 +2736,7 @@
}
// ok, if it's not a card mark then we still need to check if it is
- // a trailing membar of a volatile put graph.
+ // a trailing membar of a volatile put hgraph.
return (trailing_to_leading(mbvol) != NULL);
}
@@ -2690,9 +2786,20 @@
}
// does this lead a normal subgraph?
- MemBarNode *trailing = leading_to_trailing(barrier);
-
- return (trailing != NULL);
+ MemBarNode *mbvol = leading_to_normal(barrier);
+
+ if (!mbvol) {
+ return false;
+ }
+
+ // all done unless this is a card mark
+ if (!is_card_mark_membar(mbvol)) {
+ return true;
+ }
+
+ // we found a card mark -- just make sure we have a trailing barrier
+
+ return (card_mark_to_trailing(mbvol) != NULL);
}
// predicate controlling translation of CAS
@@ -2734,7 +2841,7 @@
"CAS not fed by cpuorder+release membar pair!");
// does this lead a normal subgraph?
- MemBarNode *mbar = leading_to_trailing(barrier);
+ MemBarNode *mbar = leading_to_normal(barrier);
assert(mbar != NULL, "CAS not embedded in normal graph!");
@@ -2755,27 +2862,48 @@
// we only ever need to generate a dmb ishst between an object put
// and the associated card mark when we are using CMS without
- // conditional card marking. Any other occurence will happen when
- // performing a card mark using CMS with conditional card marking or
- // G1. In those cases the preceding MamBarVolatile will be
- // translated to a dmb ish which guarantes visibility of the
- // preceding StoreN/P before this StoreCM
+ // conditional card marking
if (!UseConcMarkSweepGC || UseCondCardMark) {
return true;
}
- // if we are implementing volatile puts using barriers then we must
- // insert the dmb ishst
+ // if we are implementing volatile puts using barriers then the
+ // object put as an str so we must insert the dmb ishst
if (UseBarriersForVolatile) {
return false;
}
- // we must be using CMS with conditional card marking so we ahve to
- // generate the StoreStore
-
- return false;
+ // we can omit the dmb ishst if this StoreCM is part of a volatile
+ // put because in thta case the put will be implemented by stlr
+ //
+ // we need to check for a normal subgraph feeding this StoreCM.
+ // that means the StoreCM must be fed Memory from a leading membar,
+ // either a MemBarRelease or its dependent MemBarCPUOrder, and the
+ // leading membar must be part of a normal subgraph
+
+ Node *x = storecm->in(StoreNode::Memory);
+
+ if (!x->is_Proj()) {
+ return false;
+ }
+
+ x = x->in(0);
+
+ if (!x->is_MemBar()) {
+ return false;
+ }
+
+ MemBarNode *leading = x->as_MemBar();
+
+ // reject invalid candidates
+ if (!leading_membar(leading)) {
+ return false;
+ }
+
+ // we can omit the StoreStore if it is the head of a normal subgraph
+ return (leading_to_normal(leading) != NULL);
}
@@ -3008,6 +3136,10 @@
__ notify(Assembler::method_reentry);
}
+ if (StackReservedPages > 0 && C->has_reserved_stack_access()) {
+ __ reserved_stack_check();
+ }
+
if (do_polling() && C->is_method_compilation()) {
__ read_polling_page(rscratch1, os::get_polling_page(), relocInfo::poll_return_type);
}
@@ -9862,7 +9994,7 @@
// END This section of the file is automatically generated. Do not edit --------------
// ---------------------------------------------------------------------
-instruct get_and_setI(indirect mem, iRegINoSp newv, iRegI prev) %{
+instruct get_and_setI(indirect mem, iRegI newv, iRegINoSp prev) %{
match(Set prev (GetAndSetI mem newv));
format %{ "atomic_xchgw $prev, $newv, [$mem]" %}
ins_encode %{
@@ -9871,7 +10003,7 @@
ins_pipe(pipe_serial);
%}
-instruct get_and_setL(indirect mem, iRegLNoSp newv, iRegL prev) %{
+instruct get_and_setL(indirect mem, iRegL newv, iRegLNoSp prev) %{
match(Set prev (GetAndSetL mem newv));
format %{ "atomic_xchg $prev, $newv, [$mem]" %}
ins_encode %{
@@ -9880,7 +10012,7 @@
ins_pipe(pipe_serial);
%}
-instruct get_and_setN(indirect mem, iRegNNoSp newv, iRegI prev) %{
+instruct get_and_setN(indirect mem, iRegN newv, iRegINoSp prev) %{
match(Set prev (GetAndSetN mem newv));
format %{ "atomic_xchgw $prev, $newv, [$mem]" %}
ins_encode %{
@@ -9889,7 +10021,7 @@
ins_pipe(pipe_serial);
%}
-instruct get_and_setP(indirect mem, iRegPNoSp newv, iRegP prev) %{
+instruct get_and_setP(indirect mem, iRegP newv, iRegPNoSp prev) %{
match(Set prev (GetAndSetP mem newv));
format %{ "atomic_xchg $prev, $newv, [$mem]" %}
ins_encode %{
--- a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -532,8 +532,14 @@
void LIR_Assembler::return_op(LIR_Opr result) {
assert(result->is_illegal() || !result->is_single_cpu() || result->as_register() == r0, "word returns are in r0,");
+
// Pop the stack before the safepoint code
__ remove_frame(initial_frame_size_in_bytes());
+
+ if (StackReservedPages > 0 && compilation()->has_reserved_stack_access()) {
+ __ reserved_stack_check();
+ }
+
address polling_page(os::get_polling_page());
__ read_polling_page(rscratch1, polling_page, relocInfo::poll_return_type);
__ ret(lr);
--- a/hotspot/src/cpu/aarch64/vm/c1_Runtime1_aarch64.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/aarch64/vm/c1_Runtime1_aarch64.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -1179,6 +1179,15 @@
Label done;
Label runtime;
+ // Is marking still active?
+ if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+ __ ldrw(tmp, in_progress);
+ } else {
+ assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+ __ ldrb(tmp, in_progress);
+ }
+ __ cbzw(tmp, done);
+
// Can we store original value in the thread's buffer?
__ ldr(tmp, queue_index);
__ cbz(tmp, runtime);
--- a/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -375,7 +375,8 @@
fr._unextended_sp = unextended_sp;
address original_pc = nm->get_original_pc(&fr);
- assert(nm->insts_contains(original_pc), "original PC must be in nmethod");
+ assert(nm->insts_contains_inclusive(original_pc),
+ "original PC must be in the main code section of the the compiled method (or must be immediately following it)");
}
#endif
@@ -629,6 +630,7 @@
DESCRIBE_FP_OFFSET(interpreter_frame_last_sp);
DESCRIBE_FP_OFFSET(interpreter_frame_method);
DESCRIBE_FP_OFFSET(interpreter_frame_mdp);
+ DESCRIBE_FP_OFFSET(interpreter_frame_mirror);
DESCRIBE_FP_OFFSET(interpreter_frame_cache);
DESCRIBE_FP_OFFSET(interpreter_frame_locals);
DESCRIBE_FP_OFFSET(interpreter_frame_bcp);
--- a/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/aarch64/vm/frame_aarch64.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -46,6 +46,9 @@
// [pointer to locals ] = locals() locals_offset
// [constant pool cache ] = cache() cache_offset
+// [klass of method ] = mirror() mirror_offset
+// [padding ]
+
// [methodData ] = mdp() mdx_offset
// [methodOop ] = method() method_offset
--- a/hotspot/src/cpu/aarch64/vm/frame_aarch64.inline.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/aarch64/vm/frame_aarch64.inline.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -82,7 +82,8 @@
address original_pc = CompiledMethod::get_deopt_original_pc(this);
if (original_pc != NULL) {
_pc = original_pc;
- assert(((CompiledMethod*)_cb)->insts_contains(_pc), "original PC must be in CompiledMethod");
+ assert(_cb->as_compiled_method()->insts_contains_inclusive(_pc),
+ "original PC must be in the main code section of the the compiled method (or must be immediately following it)");
_deopt_state = is_deoptimized;
} else {
_deopt_state = not_deoptimized;
--- a/hotspot/src/cpu/aarch64/vm/globalDefinitions_aarch64.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/aarch64/vm/globalDefinitions_aarch64.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -53,4 +53,6 @@
// evidence that it's worth doing.
#define DEOPTIMIZE_WHEN_PATCHING
+#define SUPPORT_RESERVED_STACK_AREA
+
#endif // CPU_AARCH64_VM_GLOBALDEFINITIONS_AARCH64_HPP
--- a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -46,8 +46,11 @@
#define DEFAULT_STACK_YELLOW_PAGES (2)
#define DEFAULT_STACK_RED_PAGES (1)
-#define DEFAULT_STACK_SHADOW_PAGES (4 DEBUG_ONLY(+5))
-#define DEFAULT_STACK_RESERVED_PAGES (0)
+// Java_java_net_SocketOutputStream_socketWrite0() uses a 64k buffer on the
+// stack if compiled for unix and LP64. To pass stack overflow tests we need
+// 20 shadow pages.
+#define DEFAULT_STACK_SHADOW_PAGES (20 DEBUG_ONLY(+5))
+#define DEFAULT_STACK_RESERVED_PAGES (1)
#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
--- a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -619,6 +619,22 @@
// get sender esp
ldr(esp,
Address(rfp, frame::interpreter_frame_sender_sp_offset * wordSize));
+ if (StackReservedPages > 0) {
+ // testing if reserved zone needs to be re-enabled
+ Label no_reserved_zone_enabling;
+
+ ldr(rscratch1, Address(rthread, JavaThread::reserved_stack_activation_offset()));
+ cmp(esp, rscratch1);
+ br(Assembler::LS, no_reserved_zone_enabling);
+
+ call_VM_leaf(
+ CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), rthread);
+ call_VM(noreg, CAST_FROM_FN_PTR(address,
+ InterpreterRuntime::throw_delayed_StackOverflowError));
+ should_not_reach_here();
+
+ bind(no_reserved_zone_enabling);
+ }
// remove frame anchor
leave();
// If we're returning to interpreted code we will shortly be
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -402,6 +402,30 @@
}
}
+void MacroAssembler::reserved_stack_check() {
+ // testing if reserved zone needs to be enabled
+ Label no_reserved_zone_enabling;
+
+ ldr(rscratch1, Address(rthread, JavaThread::reserved_stack_activation_offset()));
+ cmp(sp, rscratch1);
+ br(Assembler::LO, no_reserved_zone_enabling);
+
+ enter(); // LR and FP are live.
+ lea(rscratch1, CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone));
+ mov(c_rarg0, rthread);
+ blr(rscratch1);
+ leave();
+
+ // We have already removed our own frame.
+ // throw_delayed_StackOverflowError will think that it's been
+ // called by our caller.
+ lea(rscratch1, RuntimeAddress(StubRoutines::throw_delayed_StackOverflowError_entry()));
+ br(rscratch1);
+ should_not_reach_here();
+
+ bind(no_reserved_zone_enabling);
+}
+
int MacroAssembler::biased_locking_enter(Register lock_reg,
Register obj_reg,
Register swap_reg,
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -957,6 +957,9 @@
// stack overflow + shadow pages. Also, clobbers tmp
void bang_stack_size(Register size, Register tmp);
+ // Check for reserved stack access in method being exited (for JIT)
+ void reserved_stack_check();
+
virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr,
Register tmp,
int offset);
--- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -4676,8 +4676,11 @@
StubRoutines::_throw_StackOverflowError_entry =
generate_throw_exception("StackOverflowError throw_exception",
CAST_FROM_FN_PTR(address,
- SharedRuntime::
- throw_StackOverflowError));
+ SharedRuntime::throw_StackOverflowError));
+ StubRoutines::_throw_delayed_StackOverflowError_entry =
+ generate_throw_exception("delayed StackOverflowError throw_exception",
+ CAST_FROM_FN_PTR(address,
+ SharedRuntime::throw_delayed_StackOverflowError));
if (UseCRC32Intrinsics) {
// set table address before stub generation which use it
StubRoutines::_crc_table_adr = (address)StubRoutines::aarch64::_crc_table;
--- a/hotspot/src/cpu/arm/vm/c1_Runtime1_arm.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/arm/vm/c1_Runtime1_arm.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2017, 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
@@ -551,6 +551,8 @@
const Register r_index_1 = R1;
const Register r_buffer_2 = R2;
+ Address queue_active(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
+ SATBMarkQueue::byte_offset_of_active()));
Address queue_index(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_index()));
Address buffer(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
@@ -559,6 +561,11 @@
Label done;
Label runtime;
+ // Is marking still active?
+ assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+ __ ldrb(R1, queue_active);
+ __ cbz(R1, done);
+
__ ldr(r_index_1, queue_index);
__ ldr(r_pre_val_0, Address(SP, nb_saved_regs*wordSize));
__ ldr(r_buffer_2, buffer);
--- a/hotspot/src/cpu/arm/vm/frame_arm.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/arm/vm/frame_arm.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -364,7 +364,8 @@
fr._unextended_sp = unextended_sp;
address original_pc = nm->get_original_pc(&fr);
- assert(nm->insts_contains(original_pc), "original PC must be in nmethod");
+ assert(nm->insts_contains_inclusive(original_pc),
+ "original PC must be in the main code section of the the compiled method (or must be immediately following it)");
assert(nm->is_method_handle_return(original_pc) == is_method_handle_return, "must be");
}
#endif
--- a/hotspot/src/cpu/arm/vm/frame_arm.inline.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/arm/vm/frame_arm.inline.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -75,7 +75,8 @@
address original_pc = CompiledMethod::get_deopt_original_pc(this);
if (original_pc != NULL) {
_pc = original_pc;
- assert(_cb->as_compiled_method()->insts_contains(_pc), "original PC must be in CompiledMethod");
+ assert(_cb->as_compiled_method()->insts_contains_inclusive(_pc),
+ "original PC must be in the main code section of the the compiled method (or must be immediately following it)");
_deopt_state = is_deoptimized;
} else {
_deopt_state = not_deoptimized;
--- a/hotspot/src/cpu/ppc/vm/c1_Runtime1_ppc.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/ppc/vm/c1_Runtime1_ppc.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -741,7 +741,10 @@
Register tmp = R14;
Register tmp2 = R15;
- Label refill, restart;
+ Label refill, restart, marking_not_active;
+ int satb_q_active_byte_offset =
+ in_bytes(JavaThread::satb_mark_queue_offset() +
+ SATBMarkQueue::byte_offset_of_active());
int satb_q_index_byte_offset =
in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_index());
@@ -753,6 +756,16 @@
__ std(tmp, -16, R1_SP);
__ std(tmp2, -24, R1_SP);
+ // Is marking still active?
+ if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+ __ lwz(tmp, satb_q_active_byte_offset, R16_thread);
+ } else {
+ assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+ __ lbz(tmp, satb_q_active_byte_offset, R16_thread);
+ }
+ __ cmpdi(CCR0, tmp, 0);
+ __ beq(CCR0, marking_not_active);
+
__ bind(restart);
// Load the index into the SATB buffer. SATBMarkQueue::_index is a
// size_t so ld_ptr is appropriate.
@@ -769,6 +782,7 @@
__ std(tmp, satb_q_index_byte_offset, R16_thread);
__ stdx(pre_val, tmp2, tmp); // [_buf + index] := <address_of_card>
+ __ bind(marking_not_active);
// Restore temp registers and return-from-leaf.
__ ld(tmp2, -24, R1_SP);
__ ld(tmp, -16, R1_SP);
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -2569,7 +2569,7 @@
}
// Spin and retry if lock is busy.
-// inputs: box_Reg (monitor address)
+// inputs: owner_addr_Reg (monitor address)
// : retry_count_Reg
// output: retry_count_Reg decremented by 1
// CTR is killed
@@ -2577,15 +2577,22 @@
Label SpinLoop, doneRetry;
addic_(retry_count_Reg, retry_count_Reg, -1);
blt(CCR0, doneRetry);
- li(R0, RTMSpinLoopCount);
- mtctr(R0);
+
+ if (RTMSpinLoopCount > 1) {
+ li(R0, RTMSpinLoopCount);
+ mtctr(R0);
+ }
bind(SpinLoop);
smt_yield(); // Can't use waitrsv(). No permission (SIGILL).
- bdz(retryLabel);
- ld(R0, 0, owner_addr_Reg);
- cmpdi(CCR0, R0, 0);
- bne(CCR0, SpinLoop);
+
+ if (RTMSpinLoopCount > 1) {
+ bdz(retryLabel);
+ ld(R0, 0, owner_addr_Reg);
+ cmpdi(CCR0, R0, 0);
+ bne(CCR0, SpinLoop);
+ }
+
b(retryLabel);
bind(doneRetry);
--- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -327,7 +327,10 @@
warning("RTMAbortRatio must be in the range 0 to 100, resetting it to 50");
FLAG_SET_DEFAULT(RTMAbortRatio, 50);
}
- guarantee(RTMSpinLoopCount > 0, "unsupported");
+ if (RTMSpinLoopCount < 0) {
+ warning("RTMSpinLoopCount must not be a negative value, resetting it to 0");
+ FLAG_SET_DEFAULT(RTMSpinLoopCount, 0);
+ }
#else
// Only C2 does RTM locking optimization.
// Can't continue because UseRTMLocking affects UseBiasedLocking flag
--- a/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -1105,16 +1105,16 @@
}
case T_FLOAT :
if (short_disp) {
- __ z_ste(from->as_float_reg(), disp_value, disp_reg, dest);
+ __ z_ste(from->as_float_reg(), disp_value, disp_reg, dest);
} else {
- __ z_stey(from->as_float_reg(), disp_value, disp_reg, dest);
+ __ z_stey(from->as_float_reg(), disp_value, disp_reg, dest);
}
break;
case T_DOUBLE:
if (short_disp) {
- __ z_std(from->as_double_reg(), disp_value, disp_reg, dest);
+ __ z_std(from->as_double_reg(), disp_value, disp_reg, dest);
} else {
- __ z_stdy(from->as_double_reg(), disp_value, disp_reg, dest);
+ __ z_stdy(from->as_double_reg(), disp_value, disp_reg, dest);
}
break;
default: ShouldNotReachHere();
@@ -1148,6 +1148,10 @@
__ restore_return_pc();
}
+ if (StackReservedPages > 0 && compilation()->has_reserved_stack_access()) {
+ __ reserved_stack_check(Z_R14);
+ }
+
// We need to mark the code position where the load from the safepoint
// polling page was emitted as relocInfo::poll_return_type here.
__ relocate(relocInfo::poll_return_type);
--- a/hotspot/src/cpu/s390/vm/c1_Runtime1_s390.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/s390/vm/c1_Runtime1_s390.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -784,7 +784,10 @@
Register tmp = Z_R6; // Must be non-volatile because it is used to save pre_val.
Register tmp2 = Z_R7;
- Label refill, restart;
+ Label refill, restart, marking_not_active;
+ int satb_q_active_byte_offset =
+ in_bytes(JavaThread::satb_mark_queue_offset() +
+ SATBMarkQueue::byte_offset_of_active());
int satb_q_index_byte_offset =
in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_index());
@@ -796,6 +799,15 @@
__ z_stg(tmp, 0*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
__ z_stg(tmp2, 1*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
+ // Is marking still active?
+ if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+ __ load_and_test_int(tmp, Address(Z_thread, satb_q_active_byte_offset));
+ } else {
+ assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+ __ load_and_test_byte(tmp, Address(Z_thread, satb_q_active_byte_offset));
+ }
+ __ z_bre(marking_not_active); // Activity indicator is zero, so there is no marking going on currently.
+
__ bind(restart);
// Load the index into the SATB buffer. SATBMarkQueue::_index is a
// size_t so ld_ptr is appropriate.
@@ -810,6 +822,7 @@
__ z_stg(pre_val, 0, tmp, tmp2); // [_buf + index] := <address_of_card>
__ z_stg(tmp, satb_q_index_byte_offset, Z_thread);
+ __ bind(marking_not_active);
// Restore tmp registers (see assertion in G1PreBarrierStub::emit_code()).
__ z_lg(tmp, 0*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
__ z_lg(tmp2, 1*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
--- a/hotspot/src/cpu/s390/vm/globalDefinitions_s390.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/s390/vm/globalDefinitions_s390.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -52,4 +52,6 @@
// The expected size in bytes of a cache line, used to pad data structures.
#define DEFAULT_CACHE_LINE_SIZE 256
+#define SUPPORT_RESERVED_STACK_AREA
+
#endif // CPU_S390_VM_GLOBALDEFINITIONS_S390_HPP
--- a/hotspot/src/cpu/s390/vm/globals_s390.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/s390/vm/globals_s390.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -56,7 +56,7 @@
// Java_java_net_SocketOutputStream_socketWrite0() uses a 64k buffer on the
// stack. To pass stack overflow tests we need 20 shadow pages.
#define DEFAULT_STACK_SHADOW_PAGES (20 DEBUG_ONLY(+2))
-#define DEFAULT_STACK_RESERVED_PAGES (0)
+#define DEFAULT_STACK_RESERVED_PAGES (1)
#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
--- a/hotspot/src/cpu/s390/vm/interp_masm_s390.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/s390/vm/interp_masm_s390.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -860,16 +860,39 @@
bool throw_monitor_exception,
bool install_monitor_exception,
bool notify_jvmti) {
-
+ BLOCK_COMMENT("remove_activation {");
unlock_if_synchronized_method(state, throw_monitor_exception, install_monitor_exception);
// Save result (push state before jvmti call and pop it afterwards) and notify jvmti.
notify_method_exit(false, state, notify_jvmti ? NotifyJVMTI : SkipNotifyJVMTI);
+ if (StackReservedPages > 0) {
+ BLOCK_COMMENT("reserved_stack_check:");
+ // Test if reserved zone needs to be enabled.
+ Label no_reserved_zone_enabling;
+
+ // Compare frame pointers. There is no good stack pointer, as with stack
+ // frame compression we can get different SPs when we do calls. A subsequent
+ // call could have a smaller SP, so that this compare succeeds for an
+ // inner call of the method annotated with ReservedStack.
+ z_lg(Z_R0, Address(Z_SP, (intptr_t)_z_abi(callers_sp)));
+ z_clg(Z_R0, Address(Z_thread, JavaThread::reserved_stack_activation_offset())); // Compare with frame pointer in memory.
+ z_brl(no_reserved_zone_enabling);
+
+ // Enable reserved zone again, throw stack overflow exception.
+ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), Z_thread);
+ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_delayed_StackOverflowError));
+
+ should_not_reach_here();
+
+ bind(no_reserved_zone_enabling);
+ }
+
verify_oop(Z_tos, state);
verify_thread();
pop_interpreter_frame(return_pc, Z_ARG2, Z_ARG3);
+ BLOCK_COMMENT("} remove_activation");
}
// lock object
--- a/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -2666,6 +2666,32 @@
}
}
+void MacroAssembler::reserved_stack_check(Register return_pc) {
+ // Test if reserved zone needs to be enabled.
+ Label no_reserved_zone_enabling;
+ assert(return_pc == Z_R14, "Return pc must be in R14 before z_br() to StackOverflow stub.");
+ BLOCK_COMMENT("reserved_stack_check {");
+
+ z_clg(Z_SP, Address(Z_thread, JavaThread::reserved_stack_activation_offset()));
+ z_brl(no_reserved_zone_enabling);
+
+ // Enable reserved zone again, throw stack overflow exception.
+ save_return_pc();
+ push_frame_abi160(0);
+ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), Z_thread);
+ pop_frame();
+ restore_return_pc();
+
+ load_const_optimized(Z_R1, StubRoutines::throw_delayed_StackOverflowError_entry());
+ // Don't use call() or z_basr(), they will invalidate Z_R14 which contains the return pc.
+ z_br(Z_R1);
+
+ should_not_reach_here();
+
+ bind(no_reserved_zone_enabling);
+ BLOCK_COMMENT("} reserved_stack_check");
+}
+
// Defines obj, preserves var_size_in_bytes, okay for t2 == var_size_in_bytes.
void MacroAssembler::tlab_allocate(Register obj,
Register var_size_in_bytes,
--- a/hotspot/src/cpu/s390/vm/macroAssembler_s390.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/s390/vm/macroAssembler_s390.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -627,6 +627,11 @@
// Stack overflow checking
void bang_stack_with_offset(int offset);
+ // Check for reserved stack access in method being exited. If the reserved
+ // stack area was accessed, protect it again and throw StackOverflowError.
+ // Uses Z_R1.
+ void reserved_stack_check(Register return_pc);
+
// Atomics
// -- none?
--- a/hotspot/src/cpu/s390/vm/s390.ad Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/s390/vm/s390.ad Thu Feb 09 23:15:52 2017 +0100
@@ -909,15 +909,8 @@
// If this does safepoint polling, then do it here.
bool need_polling = do_polling() && C->is_method_compilation();
- // Touch the polling page.
- // Part 1: get the page's address.
- if (need_polling) {
- AddressLiteral pp(os::get_polling_page());
- __ load_const_optimized(Z_R1_scratch, pp);
- }
-
// Pop frame, restore return_pc, and all stuff needed by interpreter.
- // Pop frame by add insted of load (a penny saved is a penny got :-).
+ // Pop frame by add instead of load (a penny saved is a penny got :-).
int frame_size_in_bytes = Assembler::align((C->frame_slots() << LogBytesPerInt), frame::alignment_in_bytes);
int retPC_offset = frame_size_in_bytes + _z_abi16(return_pc);
if (Displacement::is_validDisp(retPC_offset)) {
@@ -928,9 +921,14 @@
__ restore_return_pc();
}
- // Touch the polling page,
- // part 2: touch the page now.
+ if (StackReservedPages > 0 && C->has_reserved_stack_access()) {
+ __ reserved_stack_check(Z_R14);
+ }
+
+ // Touch the polling page.
if (need_polling) {
+ AddressLiteral pp(os::get_polling_page());
+ __ load_const_optimized(Z_R1_scratch, pp);
// We need to mark the code position where the load from the safepoint
// polling page was emitted as relocInfo::poll_return_type here.
__ relocate(relocInfo::poll_return_type);
@@ -939,7 +937,7 @@
}
uint MachEpilogNode::size(PhaseRegAlloc *ra_) const {
- // variable size. determine dynamically.
+ // Variable size. determine dynamically.
return MachNode::size(ra_);
}
--- a/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -2433,13 +2433,12 @@
StubRoutines::_throw_StackOverflowError_entry =
generate_throw_exception("StackOverflowError throw_exception",
CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError), false);
+ StubRoutines::_throw_delayed_StackOverflowError_entry =
+ generate_throw_exception("delayed StackOverflowError throw_exception",
+ CAST_FROM_FN_PTR(address, SharedRuntime::throw_delayed_StackOverflowError), false);
//----------------------------------------------------------------------
// Entry points that are platform specific.
- // Build this early so it's available for the interpreter.
- StubRoutines::_throw_StackOverflowError_entry =
- generate_throw_exception("StackOverflowError throw_exception",
- CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError), false);
if (UseCRC32Intrinsics) {
// We have no CRC32 table on z/Architecture.
--- a/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -1112,16 +1112,21 @@
// top_frame_size = TOP_IJAVA_FRAME_ABI + max_stack + size of interpreter state
__ add2reg(top_frame_size,
frame::z_top_ijava_frame_abi_size +
- frame::z_ijava_state_size +
- frame::interpreter_frame_monitor_size() * wordSize,
+ frame::z_ijava_state_size +
+ frame::interpreter_frame_monitor_size() * wordSize,
max_stack);
- // Check if there's room for the new frame...
- Register frame_size = max_stack; // Reuse the regiser for max_stack.
- __ z_lgr(frame_size, Z_SP);
- __ z_sgr(frame_size, sp_after_resize);
- __ z_agr(frame_size, top_frame_size);
- generate_stack_overflow_check(frame_size, fp/*tmp1*/);
+ if (!native_call) {
+ // Stack overflow check.
+ // Native calls don't need the stack size check since they have no
+ // expression stack and the arguments are already on the stack and
+ // we only add a handful of words to the stack.
+ Register frame_size = max_stack; // Reuse the regiser for max_stack.
+ __ z_lgr(frame_size, Z_SP);
+ __ z_sgr(frame_size, sp_after_resize);
+ __ z_agr(frame_size, top_frame_size);
+ generate_stack_overflow_check(frame_size, fp/*tmp1*/);
+ }
DEBUG_ONLY(__ z_cg(Z_R14, _z_abi16(return_pc), Z_SP));
__ asm_assert_eq("killed Z_R14", 0);
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, 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
@@ -694,6 +694,7 @@
int LIR_Assembler::store(LIR_Opr from_reg, Register base, int offset, BasicType type, bool wide, bool unaligned) {
int store_offset;
if (!Assembler::is_simm13(offset + (type == T_LONG) ? wordSize : 0)) {
+ assert(base != O7, "destroying register");
assert(!unaligned, "can't handle this");
// for offsets larger than a simm13 we setup the offset in O7
__ set(offset, O7);
@@ -712,9 +713,12 @@
case T_LONG :
#ifdef _LP64
if (unaligned || PatchALot) {
- __ srax(from_reg->as_register_lo(), 32, O7);
+ // Don't use O7 here because it may be equal to 'base' (see LIR_Assembler::reg2mem)
+ assert(G3_scratch != base, "can't handle this");
+ assert(G3_scratch != from_reg->as_register_lo(), "can't handle this");
+ __ srax(from_reg->as_register_lo(), 32, G3_scratch);
__ stw(from_reg->as_register_lo(), base, offset + lo_word_offset_in_bytes);
- __ stw(O7, base, offset + hi_word_offset_in_bytes);
+ __ stw(G3_scratch, base, offset + hi_word_offset_in_bytes);
} else {
__ stx(from_reg->as_register_lo(), base, offset);
}
@@ -821,7 +825,7 @@
case T_SHORT : __ ldsh(base, offset, to_reg->as_register()); break;
case T_INT : __ ld(base, offset, to_reg->as_register()); break;
case T_LONG :
- if (!unaligned) {
+ if (!unaligned && !PatchALot) {
#ifdef _LP64
__ ldx(base, offset, to_reg->as_register_lo());
#else
@@ -1297,7 +1301,7 @@
disp_reg = O7;
}
} else if (unaligned || PatchALot) {
- __ add(src, addr->index()->as_register(), O7);
+ __ add(src, addr->index()->as_pointer_register(), O7);
src = O7;
} else {
disp_reg = addr->index()->as_pointer_register();
@@ -1424,7 +1428,7 @@
disp_reg = O7;
}
} else if (unaligned || PatchALot) {
- __ add(src, addr->index()->as_register(), O7);
+ __ add(src, addr->index()->as_pointer_register(), O7);
src = O7;
} else {
disp_reg = addr->index()->as_pointer_register();
--- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, 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
@@ -856,7 +856,9 @@
Register tmp2 = G3_scratch;
Label refill, restart;
- bool with_frame = false; // I don't know if we can do with-frame.
+ int satb_q_active_byte_offset =
+ in_bytes(JavaThread::satb_mark_queue_offset() +
+ SATBMarkQueue::byte_offset_of_active());
int satb_q_index_byte_offset =
in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_index());
@@ -864,6 +866,17 @@
in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_buf());
+ // Is marking still active?
+ if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+ __ ld(G2_thread, satb_q_active_byte_offset, tmp);
+ } else {
+ assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+ __ ldsb(G2_thread, satb_q_active_byte_offset, tmp);
+ }
+ __ cmp_and_br_short(tmp, G0, Assembler::notEqual, Assembler::pt, restart);
+ __ retl();
+ __ delayed()->nop();
+
__ bind(restart);
// Load the index into the SATB buffer. SATBMarkQueue::_index is a
// size_t so ld_ptr is appropriate
--- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, 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
@@ -1623,6 +1623,8 @@
NOT_LP64(__ get_thread(thread);)
+ Address queue_active(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
+ SATBMarkQueue::byte_offset_of_active()));
Address queue_index(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
SATBMarkQueue::byte_offset_of_index()));
Address buffer(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
@@ -1631,6 +1633,15 @@
Label done;
Label runtime;
+ // Is marking still active?
+ if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+ __ cmpl(queue_active, 0);
+ } else {
+ assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+ __ cmpb(queue_active, 0);
+ }
+ __ jcc(Assembler::equal, done);
+
// Can we store original value in the thread's buffer?
__ movptr(tmp, queue_index);
--- a/hotspot/src/cpu/x86/vm/frame_x86.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/x86/vm/frame_x86.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -376,7 +376,8 @@
fr._unextended_sp = unextended_sp;
address original_pc = nm->get_original_pc(&fr);
- assert(nm->insts_contains(original_pc), "original PC must be in CompiledMethod");
+ assert(nm->insts_contains_inclusive(original_pc),
+ "original PC must be in the main code section of the the compiled method (or must be immediately following it)");
}
#endif
--- a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -75,7 +75,8 @@
address original_pc = CompiledMethod::get_deopt_original_pc(this);
if (original_pc != NULL) {
_pc = original_pc;
- assert(((CompiledMethod*)_cb)->insts_contains(_pc), "original PC must be in CompiledMethod");
+ assert(_cb->as_compiled_method()->insts_contains_inclusive(_pc),
+ "original PC must be in the main code section of the the compiled method (or must be immediately following it)");
_deopt_state = is_deoptimized;
} else {
if (_cb->is_deoptimization_stub()) {
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -3499,12 +3499,12 @@
}
}
-void MacroAssembler::movdqu(XMMRegister dst, AddressLiteral src) {
+void MacroAssembler::movdqu(XMMRegister dst, AddressLiteral src, Register scratchReg) {
if (reachable(src)) {
movdqu(dst, as_Address(src));
} else {
- lea(rscratch1, src);
- movdqu(dst, Address(rscratch1, 0));
+ lea(scratchReg, src);
+ movdqu(dst, Address(scratchReg, 0));
}
}
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -1085,7 +1085,7 @@
void movdqu(Address dst, XMMRegister src);
void movdqu(XMMRegister dst, Address src);
void movdqu(XMMRegister dst, XMMRegister src);
- void movdqu(XMMRegister dst, AddressLiteral src);
+ void movdqu(XMMRegister dst, AddressLiteral src, Register scratchReg = rscratch1);
// AVX Unaligned forms
void vmovdqu(Address dst, XMMRegister src);
void vmovdqu(XMMRegister dst, Address src);
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86_sha.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86_sha.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -817,7 +817,7 @@
movl(d, Address(CTX, 4*3));
movl(e, Address(CTX, 4*4));
movl(f, Address(CTX, 4*5));
- movl(g, Address(CTX, 4*6));
+ // load g - r10 after it is used as scratch
movl(h, Address(CTX, 4*7));
pshuffle_byte_flip_mask_addr = pshuffle_byte_flip_mask;
@@ -825,6 +825,8 @@
vmovdqu(SHUF_00BA, ExternalAddress(pshuffle_byte_flip_mask_addr + 32)); //[_SHUF_00BA wrt rip]
vmovdqu(SHUF_DC00, ExternalAddress(pshuffle_byte_flip_mask_addr + 64)); //[_SHUF_DC00 wrt rip]
+ movl(g, Address(CTX, 4*6));
+
movq(Address(rsp, _CTX), CTX); // store
bind(loop0);
@@ -977,7 +979,7 @@
movl(d, Address(CTX, 4*3)); // 0xa54ff53a
movl(e, Address(CTX, 4*4)); // 0x510e527f
movl(f, Address(CTX, 4*5)); // 0x9b05688c
- movl(g, Address(CTX, 4*6)); // 0x1f83d9ab
+ // load g - r10 after use as scratch
movl(h, Address(CTX, 4*7)); // 0x5be0cd19
@@ -986,6 +988,8 @@
vmovdqu(SHUF_00BA, ExternalAddress(pshuffle_byte_flip_mask_addr + 32)); //[_SHUF_00BA wrt rip]
vmovdqu(SHUF_DC00, ExternalAddress(pshuffle_byte_flip_mask_addr + 64)); //[_SHUF_DC00 wrt rip]
+ movl(g, Address(CTX, 4*6)); // 0x1f83d9ab
+
movq(Address(rsp, _CTX), CTX);
jmpb(do_last_block);
@@ -1154,9 +1158,8 @@
// Move to appropriate lanes for calculating w[16] and w[17]
vperm2f128(xmm4, xmm0, xmm0, 0); //xmm4 = W[-16] + W[-7] + s0{ BABA }
- address MASK_YMM_LO = StubRoutines::x86::pshuffle_byte_flip_mask_addr_sha512();
//Move to appropriate lanes for calculating w[18] and w[19]
- vpand(xmm0, xmm0, ExternalAddress(MASK_YMM_LO + 32), AVX_256bit); //xmm0 = W[-16] + W[-7] + s0{ DC00 }
+ vpand(xmm0, xmm0, xmm10, AVX_256bit); //xmm0 = W[-16] + W[-7] + s0{ DC00 }
//Calculate w[16] and w[17] in both 128 bit lanes
//Calculate sigma1 for w[16] and w[17] on both 128 bit lanes
vperm2f128(xmm2, xmm7, xmm7, 17); //xmm2 = W[-2] {BABA}
@@ -1250,6 +1253,7 @@
const XMMRegister& XFER = xmm0; // YTMP0
const XMMRegister& BYTE_FLIP_MASK = xmm9; // ymm9
+ const XMMRegister& YMM_MASK_LO = xmm10; // ymm10
#ifdef _WIN64
const Register& INP = rcx; //1st arg
const Register& CTX = rdx; //2nd arg
@@ -1368,11 +1372,14 @@
movq(d, Address(CTX, 8 * 3));
movq(e, Address(CTX, 8 * 4));
movq(f, Address(CTX, 8 * 5));
- movq(g, Address(CTX, 8 * 6));
+ // load g - r10 after it is used as scratch
movq(h, Address(CTX, 8 * 7));
pshuffle_byte_flip_mask_addr = pshuffle_byte_flip_mask_sha512;
vmovdqu(BYTE_FLIP_MASK, ExternalAddress(pshuffle_byte_flip_mask_addr + 0)); //PSHUFFLE_BYTE_FLIP_MASK wrt rip
+ vmovdqu(YMM_MASK_LO, ExternalAddress(pshuffle_byte_flip_mask_addr + 32));
+
+ movq(g, Address(CTX, 8 * 6));
bind(loop0);
lea(TBL, ExternalAddress(K512_W));
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -3207,7 +3207,7 @@
const Register len_reg = c_rarg4; // src len (must be multiple of blocksize 16)
#else
const Address len_mem(rbp, 6 * wordSize); // length is on stack on Win64
- const Register len_reg = r10; // pick the first volatile windows register
+ const Register len_reg = r11; // pick the volatile windows register
#endif
const Register pos = rax;
@@ -3404,7 +3404,7 @@
const Register len_reg = c_rarg4; // src len (must be multiple of blocksize 16)
#else
const Address len_mem(rbp, 6 * wordSize); // length is on stack on Win64
- const Register len_reg = r10; // pick the first volatile windows register
+ const Register len_reg = r11; // pick the volatile windows register
#endif
const Register pos = rax;
@@ -3930,7 +3930,7 @@
__ push(rbx); // Save RBX
__ movdqu(xmm_curr_counter, Address(counter, 0x00)); // initialize counter with initial counter
- __ movdqu(xmm_counter_shuf_mask, ExternalAddress(StubRoutines::x86::counter_shuffle_mask_addr()));
+ __ movdqu(xmm_counter_shuf_mask, ExternalAddress(StubRoutines::x86::counter_shuffle_mask_addr()), pos); // pos as scratch
__ pshufb(xmm_curr_counter, xmm_counter_shuf_mask); //counter is shuffled
__ movptr(pos, 0);
@@ -3953,7 +3953,7 @@
__ movl(Address(used_addr, 0), used);
// key length could be only {11, 13, 15} * 4 = {44, 52, 60}
- __ movdqu(xmm_key_shuf_mask, ExternalAddress(StubRoutines::x86::key_shuffle_mask_addr()));
+ __ movdqu(xmm_key_shuf_mask, ExternalAddress(StubRoutines::x86::key_shuffle_mask_addr()), rbx); // rbx as scratch
__ movl(rbx, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
__ cmpl(rbx, 52);
__ jcc(Assembler::equal, L_multiBlock_loopTop[1]);
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java Thu Feb 09 23:15:52 2017 +0100
@@ -37,6 +37,7 @@
import jdk.tools.jaotc.binformat.Symbol.Kind;
import jdk.tools.jaotc.binformat.elf.JELFRelocObject;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
/**
* A format-agnostic container class that holds various components of a binary.
@@ -257,9 +258,9 @@
* prefix {@code prefix}. It also initializes internal code container, symbol table and
* relocation tables.
*/
- public BinaryContainer(GraalHotSpotVMConfig config, String jvmVersion) {
- this.codeSegmentSize = config.codeSegmentSize;
- this.codeEntryAlignment = config.codeEntryAlignment;
+ public BinaryContainer(GraalHotSpotVMConfig graalHotSpotVMConfig, GraphBuilderConfiguration graphBuilderConfig, String jvmVersion) {
+ this.codeSegmentSize = graalHotSpotVMConfig.codeSegmentSize;
+ this.codeEntryAlignment = graalHotSpotVMConfig.codeEntryAlignment;
// read only, code
codeContainer = new CodeContainer(".text", this);
@@ -289,30 +290,31 @@
addGlobalSymbols();
- recordConfiguration(config);
+ recordConfiguration(graalHotSpotVMConfig, graphBuilderConfig);
}
- private void recordConfiguration(GraalHotSpotVMConfig config) {
+ private void recordConfiguration(GraalHotSpotVMConfig graalHotSpotVMConfig, GraphBuilderConfiguration graphBuilderConfig) {
// @formatter:off
- boolean[] booleanFlags = { config.cAssertions, // Debug VM
- config.useCompressedOops,
- config.useCompressedClassPointers,
- config.compactFields,
- config.useG1GC,
- config.useCMSGC,
- config.useTLAB,
- config.useBiasedLocking,
+ boolean[] booleanFlags = { graalHotSpotVMConfig.cAssertions, // Debug VM
+ graalHotSpotVMConfig.useCompressedOops,
+ graalHotSpotVMConfig.useCompressedClassPointers,
+ graalHotSpotVMConfig.compactFields,
+ graalHotSpotVMConfig.useG1GC,
+ graalHotSpotVMConfig.useCMSGC,
+ graalHotSpotVMConfig.useTLAB,
+ graalHotSpotVMConfig.useBiasedLocking,
TieredAOT.getValue(),
- config.enableContended,
- config.restrictContended,
+ graalHotSpotVMConfig.enableContended,
+ graalHotSpotVMConfig.restrictContended,
+ graphBuilderConfig.omitAssertions()
};
- int[] intFlags = { config.narrowOopShift,
- config.narrowKlassShift,
- config.contendedPaddingWidth,
- config.fieldsAllocationStyle,
- config.objectAlignment,
- config.codeSegmentSize,
+ int[] intFlags = { graalHotSpotVMConfig.getOopEncoding().shift,
+ graalHotSpotVMConfig.getKlassEncoding().shift,
+ graalHotSpotVMConfig.contendedPaddingWidth,
+ graalHotSpotVMConfig.fieldsAllocationStyle,
+ 1 << graalHotSpotVMConfig.getOopEncoding().alignment,
+ graalHotSpotVMConfig.codeSegmentSize,
};
// @formatter:on
@@ -395,6 +397,10 @@
return "_aot_narrow_klass_base_address";
}
+ public String getNarrowOopBaseAddressSymbolName() {
+ return "_aot_narrow_oop_base_address";
+ }
+
public String getLogOfHeapRegionGrainBytesSymbolName() {
return "_aot_log_of_heap_region_grain_bytes";
}
@@ -445,6 +451,7 @@
createGotSymbol(getHeapTopAddressSymbolName());
createGotSymbol(getHeapEndAddressSymbolName());
createGotSymbol(getNarrowKlassBaseAddressSymbolName());
+ createGotSymbol(getNarrowOopBaseAddressSymbolName());
createGotSymbol(getPollingPageSymbolName());
createGotSymbol(getLogOfHeapRegionGrainBytesSymbolName());
createGotSymbol(getInlineContiguousAllocationSupportedSymbolName());
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java Thu Feb 09 23:15:52 2017 +0100
@@ -77,10 +77,14 @@
this.filters = filters;
providers = backend.getProviders();
codeCache = providers.getCodeCache();
- graphBuilderSuite = initGraphBuilderSuite(backend);
+ graphBuilderSuite = initGraphBuilderSuite(backend, main.options.compileWithAssertions);
highTierContext = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.ALL);
}
+ public PhaseSuite<HighTierContext> getGraphBuilderSuite() {
+ return graphBuilderSuite;
+ }
+
private Suites getSuites() {
// create suites every time, as we modify options for the compiler
return backend.getSuites().getDefaultSuites();
@@ -146,14 +150,14 @@
return backend.getRuntime().getVMConfig().cAssertions;
}
- private static PhaseSuite<HighTierContext> initGraphBuilderSuite(HotSpotBackend backend) {
+ private static PhaseSuite<HighTierContext> initGraphBuilderSuite(HotSpotBackend backend, boolean compileWithAssertions) {
PhaseSuite<HighTierContext> graphBuilderSuite = backend.getSuites().getDefaultGraphBuilderSuite().copy();
ListIterator<BasePhase<? super HighTierContext>> iterator = graphBuilderSuite.findPhase(GraphBuilderPhase.class);
GraphBuilderConfiguration baseConfig = ((GraphBuilderPhase) iterator.previous()).getGraphBuilderConfig();
// Use all default plugins.
Plugins plugins = baseConfig.getPlugins();
- GraphBuilderConfiguration aotConfig = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true);
+ GraphBuilderConfiguration aotConfig = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true).withOmitAssertions(!compileWithAssertions);
iterator.next();
iterator.remove();
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java Thu Feb 09 23:15:52 2017 +0100
@@ -293,12 +293,18 @@
// Record methods holder
methodInfo.addDependentKlassData(binaryContainer, resolvedJavaType);
// Record inlinee classes
- for (ResolvedJavaMethod m : methodInfo.getCompilationResult().getMethods()) {
- methodInfo.addDependentKlassData(binaryContainer, (HotSpotResolvedObjectType) m.getDeclaringClass());
+ ResolvedJavaMethod[] inlinees = methodInfo.getCompilationResult().getMethods();
+ if (inlinees != null) {
+ for (ResolvedJavaMethod m : inlinees) {
+ methodInfo.addDependentKlassData(binaryContainer, (HotSpotResolvedObjectType) m.getDeclaringClass());
+ }
}
// Record classes of fields that were accessed
- for (ResolvedJavaField f : methodInfo.getCompilationResult().getFields()) {
- methodInfo.addDependentKlassData(binaryContainer, (HotSpotResolvedObjectType) f.getDeclaringClass());
+ ResolvedJavaField[] fields = methodInfo.getCompilationResult().getFields();
+ if (fields != null) {
+ for (ResolvedJavaField f : fields) {
+ methodInfo.addDependentKlassData(binaryContainer, (HotSpotResolvedObjectType) f.getDeclaringClass());
+ }
}
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/LoadedClass.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,64 @@
+package jdk.tools.jaotc;/*
+ * Copyright (c) 2015, 2017, 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.
+ */
+
+public class LoadedClass {
+ private final String name;
+ private final Class<?> clz;
+
+ public LoadedClass(String name, Class<?> clz) {
+ this.name = name;
+ this.clz = clz;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Class<?> getLoadedClass() {
+ return clz;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof LoadedClass)) return false;
+
+ LoadedClass that = (LoadedClass) o;
+
+ if (name != null ? !name.equals(that.name) : that.name != null) return false;
+ return clz != null ? clz.equals(that.clz) : that.clz == null;
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result = name != null ? name.hashCode() : 0;
+ result = 31 * result + (clz != null ? clz.hashCode() : 0);
+ return result;
+ }
+}
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -43,19 +43,31 @@
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
+import java.util.ListIterator;
import java.util.Set;
import java.util.stream.Stream;
import jdk.tools.jaotc.binformat.BinaryContainer;
import jdk.tools.jaotc.binformat.ByteContainer;
-import jdk.tools.jaotc.collect.ClassCollector;
+import jdk.tools.jaotc.collect.*;
+import jdk.tools.jaotc.collect.classname.ClassNameSourceProvider;
+import jdk.tools.jaotc.collect.directory.DirectorySourceProvider;
+import jdk.tools.jaotc.collect.jar.JarSourceProvider;
+import jdk.tools.jaotc.collect.module.ModuleSourceProvider;
import jdk.tools.jaotc.utils.Timer;
import org.graalvm.compiler.api.runtime.GraalJVMCICompiler;
+import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
import org.graalvm.compiler.hotspot.HotSpotHostBackend;
+import org.graalvm.compiler.java.GraphBuilderPhase;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
+import org.graalvm.compiler.phases.BasePhase;
+import org.graalvm.compiler.phases.PhaseSuite;
+import org.graalvm.compiler.phases.tiers.HighTierContext;
import org.graalvm.compiler.runtime.RuntimeProvider;
import jdk.vm.ci.meta.MetaAccessProvider;
@@ -120,17 +132,7 @@
abstract void process(Main task, String opt, String arg) throws BadArgs;
}
- static Option[] recognizedOptions = {new Option(" --module <name> Module to compile", true, "--module") {
- @Override
- void process(Main task, String opt, String arg) {
- task.options.module = arg;
- }
- }, new Option(" --module-path <path> Specify where to find module to compile", true, "--module-path") {
- @Override
- void process(Main task, String opt, String arg) {
- task.options.modulepath = arg;
- }
- }, new Option(" --output <file> Output file name", true, "--output") {
+ static Option[] recognizedOptions = { new Option(" --output <file> Output file name", true, "--output") {
@Override
void process(Main task, String opt, String arg) {
String name = arg;
@@ -139,22 +141,48 @@
}
task.options.outputName = name;
}
+ }, new Option(" --class-name <class names> List of classes to compile", true, "--class-name", "--classname") {
+ @Override
+ void process(Main task, String opt, String arg) {
+ task.options.files.addAll(ClassSearch.makeList(ClassNameSourceProvider.TYPE, arg));
+ }
+ }, new Option(" --jar <jarfiles> List of jar files to compile", true, "--jar") {
+ @Override
+ void process(Main task, String opt, String arg) {
+ task.options.files.addAll(ClassSearch.makeList(JarSourceProvider.TYPE, arg));
+ }
+ }, new Option(" --module <modules> List of modules to compile", true, "--module") {
+ @Override
+ void process(Main task, String opt, String arg) {
+ task.options.files.addAll(ClassSearch.makeList(ModuleSourceProvider.TYPE, arg));
+ }
+ }, new Option(" --directory <dirs> List of directories where to search for files to compile", true, "--directory") {
+ @Override
+ void process(Main task, String opt, String arg) {
+ task.options.files.addAll(ClassSearch.makeList(DirectorySourceProvider.TYPE, arg));
+ }
+ }, new Option(" --search-path <dirs> List of directories where to search for specified files", true, "--search-path") {
+ @Override
+ void process(Main task, String opt, String arg) {
+ String[] elements = arg.split(":");
+ task.options.searchPath.add(elements);
+ }
}, new Option(" --compile-commands <file> Name of file with compile commands", true, "--compile-commands") {
@Override
void process(Main task, String opt, String arg) {
task.options.methodList = arg;
}
- }, new Option(" --compile-for-tiered Generated profiling code for tiered compilation", false, "--compile-for-tiered") {
+ }, new Option(" --compile-for-tiered Generate profiling code for tiered compilation", false, "--compile-for-tiered") {
@Override
void process(Main task, String opt, String arg) {
TieredAOT.setValue(true);
}
- }, new Option(" --classpath <path> Specify where to find user class files", true, "--classpath", "--class-path") {
+ }, new Option(" --compile-with-assertions Compile with java assertions", false, "--compile-with-assertions") {
@Override
void process(Main task, String opt, String arg) {
- task.options.classpath = arg;
+ task.options.compileWithAssertions = true;
}
- }, new Option(" --threads <number> Number of compilation threads to be used", true, "--threads") {
+ }, new Option(" --compile-threads <number> Number of compilation threads to be used", true, "--compile-threads", "--threads") {
@Override
void process(Main task, String opt, String arg) {
int threads = Integer.parseInt(arg);
@@ -213,27 +241,27 @@
}};
public static class Options {
- public List<String> files = new LinkedList<>();
- public String module = null;
- public String modulepath = "modules";
+ public List<SearchFor> files = new LinkedList<>();
public String outputName = "unnamed";
public String methodList;
- public String classpath = ".";
+ public List<ClassSource> sources = new ArrayList<>();
+ public SearchPath searchPath = new SearchPath();
/**
* We don't see scaling beyond 16 threads.
*/
private static final int COMPILER_THREADS = 16;
- int threads = Integer.min(COMPILER_THREADS, Runtime.getRuntime().availableProcessors());
+ public int threads = Integer.min(COMPILER_THREADS, Runtime.getRuntime().availableProcessors());
public boolean ignoreClassLoadingErrors;
public boolean exitOnError;
- boolean info;
- boolean verbose;
- boolean debug;
- boolean help;
- boolean version;
+ public boolean info;
+ public boolean verbose;
+ public boolean debug;
+ public boolean help;
+ public boolean version;
+ public boolean compileWithAssertions;
}
/* package */final Options options = new Options();
@@ -275,7 +303,9 @@
printlnInfo("Compiling " + options.outputName + "...");
final long start = System.currentTimeMillis();
- run();
+ if (!run()) {
+ return EXIT_ABNORMAL;
+ }
final long end = System.currentTimeMillis();
printlnInfo("Total time: " + (end - start) + " ms");
@@ -318,17 +348,34 @@
}
@SuppressWarnings("try")
- private void run() throws Exception {
+ private boolean run() throws Exception {
openLog();
try {
CompilationSpec compilationRestrictions = collectSpecifiedMethods();
- Set<Class<?>> classesToCompile;
+ Set<Class<?>> classesToCompile = new HashSet<>();
try (Timer t = new Timer(this, "")) {
- ClassCollector collector = new ClassCollector(this.options, this);
- classesToCompile = collector.collectClassesToCompile();
+ FileSupport fileSupport = new FileSupport();
+ ClassSearch lookup = new ClassSearch();
+ lookup.addProvider(new ModuleSourceProvider());
+ lookup.addProvider(new ClassNameSourceProvider(fileSupport));
+ lookup.addProvider(new JarSourceProvider());
+ lookup.addProvider(new DirectorySourceProvider(fileSupport));
+
+ List<LoadedClass> found = null;
+ try {
+ found = lookup.search(options.files, options.searchPath);
+ } catch (InternalError e) {
+ reportError(e);
+ return false;
+ }
+
+ for (LoadedClass loadedClass : found) {
+ classesToCompile.add(loadedClass.getLoadedClass());
+ }
+
printInfo(classesToCompile.size() + " classes found");
}
@@ -356,6 +403,11 @@
AOTCompiler compiler = new AOTCompiler(this, aotBackend, options.threads);
classes = compiler.compileClasses(classes);
+ GraalHotSpotVMConfig graalHotSpotVMConfig = runtime.getVMConfig();
+ PhaseSuite<HighTierContext> graphBuilderSuite = aotBackend.getGraphBuilderSuite();
+ ListIterator<BasePhase<? super HighTierContext>> iterator = graphBuilderSuite.findPhase(GraphBuilderPhase.class);
+ GraphBuilderConfiguration graphBuilderConfig = ((GraphBuilderPhase) iterator.previous()).getGraphBuilderConfig();
+
// Free memory!
try (Timer t = options.verbose ? new Timer(this, "Freeing memory") : null) {
printMemoryUsage();
@@ -364,7 +416,7 @@
System.gc();
}
- BinaryContainer binaryContainer = new BinaryContainer(runtime.getVMConfig(), JVM_VERSION);
+ BinaryContainer binaryContainer = new BinaryContainer(graalHotSpotVMConfig, graphBuilderConfig, JVM_VERSION);
DataBuilder dataBuilder = new DataBuilder(this, backend, classes, binaryContainer);
dataBuilder.prepareData();
@@ -446,6 +498,7 @@
} finally {
closeLog();
}
+ return true;
}
private void addMethods(AOTCompiledClass aotClass, ResolvedJavaMethod[] methods, CompilationSpec compilationRestrictions, GraalFilters filters) {
@@ -509,7 +562,7 @@
break;
}
} else {
- options.files.add(arg);
+ options.files.add(new SearchFor(arg));
}
}
}
@@ -570,6 +623,12 @@
log.flush();
}
+ private void reportError(Throwable e) {
+ log.println("Error: " + e.getMessage());
+ e.printStackTrace(log);
+ log.flush();
+ }
+
private void reportError(String key, Object... args) {
printError(MessageFormat.format(key, args));
}
@@ -580,17 +639,17 @@
}
private void showUsage() {
- log.println("Usage: " + PROGNAME + " <options> list...");
+ log.println("Usage: " + PROGNAME + " <options> list");
log.println("use --help for a list of possible options");
}
private void showHelp() {
- log.println("Usage: " + PROGNAME + " <options> <--module name> | <list...>");
+ log.println("Usage: " + PROGNAME + " <options> list");
log.println();
- log.println(" list A list of class files, jar files or directories which");
- log.println(" contains class files.");
+ log.println(" list A : separated list of class names, modules, jar files");
+ log.println(" or directories which contain class files.");
log.println();
- log.println("where possible options include:");
+ log.println("where options include:");
for (Option o : recognizedOptions) {
String name = o.aliases[0].substring(1); // there must always be at least one name
name = name.charAt(0) == '-' ? name.substring(1) : name;
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkId.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkId.java Thu Feb 09 23:15:52 2017 +0100
@@ -48,6 +48,7 @@
HEAP_TOP_ADDRESS("CodeInstaller::HEAP_TOP_ADDRESS"),
HEAP_END_ADDRESS("CodeInstaller::HEAP_END_ADDRESS"),
NARROW_KLASS_BASE_ADDRESS("CodeInstaller::NARROW_KLASS_BASE_ADDRESS"),
+ NARROW_OOP_BASE_ADDRESS("CodeInstaller::NARROW_OOP_BASE_ADDRESS"),
CRC_TABLE_ADDRESS("CodeInstaller::CRC_TABLE_ADDRESS"),
LOG_OF_HEAP_REGION_GRAIN_BYTES("CodeInstaller::LOG_OF_HEAP_REGION_GRAIN_BYTES"),
INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED("CodeInstaller::INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED");
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkProcessor.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MarkProcessor.java Thu Feb 09 23:15:52 2017 +0100
@@ -57,6 +57,7 @@
case HEAP_TOP_ADDRESS:
case HEAP_END_ADDRESS:
case NARROW_KLASS_BASE_ADDRESS:
+ case NARROW_OOP_BASE_ADDRESS:
case CRC_TABLE_ADDRESS:
case LOG_OF_HEAP_REGION_GRAIN_BYTES:
case INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED:
@@ -78,6 +79,9 @@
case NARROW_KLASS_BASE_ADDRESS:
vmSymbolName = binaryContainer.getNarrowKlassBaseAddressSymbolName();
break;
+ case NARROW_OOP_BASE_ADDRESS:
+ vmSymbolName = binaryContainer.getNarrowOopBaseAddressSymbolName();
+ break;
case CRC_TABLE_ADDRESS:
vmSymbolName = binaryContainer.getCrcTableAddressSymbolName();
break;
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassCollector.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,332 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.tools.jaotc.collect;
-
-import jdk.tools.jaotc.LogPrinter;
-import jdk.tools.jaotc.Main;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.*;
-import java.nio.file.*;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.*;
-
-import static java.nio.file.FileVisitResult.CONTINUE;
-
-public class ClassCollector {
- private final Main.Options options;
- private final LogPrinter log;
-
- public ClassCollector(Main.Options options, LogPrinter log) {
- this.options = options;
- this.log = log;
- }
-
- /**
- * Collect all class names passed by the user.
- *
- * @return array list of classes
- */
- public Set<Class<?>> collectClassesToCompile() {
- Set<Class<?>> classes = new HashSet<>();
- List<String> filesToScan = new LinkedList<>(options.files);
-
- if (options.module != null) {
- classes.addAll(scanModule(filesToScan));
- }
-
- classes.addAll(scanFiles(filesToScan));
- return classes;
- }
-
- private Set<Class<?>> scanModule(List<String> filesToScan) {
- String module = options.module;
- // Search module in standard JDK installation.
- Path dir = getModuleDirectory(options.modulepath, module);
-
- if (Files.isDirectory(dir)) {
- return loadFromModuleDirectory(dir);
- } else {
- findFilesToScan(filesToScan, module);
- return new HashSet<>();
- }
- }
-
- private Set<Class<?>> loadFromModuleDirectory(Path dir) {
- log.printInfo("Scanning module: " + dir + " ...");
- log.printlnVerbose(" "); // Break line
-
- FileSystemFinder finder = new FileSystemFinder(dir, pathname -> entryIsClassFile(pathname.toString()));
- Set<Class<?>> cls = loadWithClassLoader(() -> ClassLoader.getSystemClassLoader(), dir, finder);
- log.printlnInfo(" " + cls.size() + " classes loaded.");
- return cls;
- }
-
- private void findFilesToScan(List<String> filesToScan, String module) {
- // Try to search regular directory, .jar or .class files
- Path path = Paths.get(options.modulepath, module);
-
- if (Files.isDirectory(path)) {
- filesToScan.add(".");
- options.classpath = path.toString();
- } else if (path.endsWith(".jar") || path.endsWith(".class")) {
- filesToScan.add(path.toString());
- } else {
- path = Paths.get(options.modulepath, module + ".jar");
- if (Files.exists(path)) {
- filesToScan.add(path.toString());
- } else {
- path = Paths.get(options.modulepath, module + ".class");
- if (Files.exists(path)) {
- filesToScan.add(path.toString());
- } else {
- throw new InternalError("Expecting a .class, .jar or directory: " + path);
- }
- }
- }
- }
-
- private boolean entryIsClassFile(String entry) {
- return entry.endsWith(".class") && !entry.endsWith("module-info.class");
- }
-
- private Set<Class<?>> scanFiles(List<String> filesToScan) {
- Set<Class<?>> classes = new HashSet<>();
- for (String fileName : filesToScan) {
- Set<Class<?>> loaded = scanFile(fileName);
- log.printlnInfo(" " + loaded.size() + " classes loaded.");
- classes.addAll(loaded);
- }
- return classes;
- }
-
- interface ClassLoaderFactory {
- ClassLoader create() throws IOException;
- }
-
- private Set<Class<?>> loadWithClassLoader(ClassLoaderFactory factory, Path root, FileSystemFinder finder) {
- ClassLoader loader = null;
- try {
- loader = factory.create();
- return loadClassFiles(root, finder, loader);
- } catch (IOException e) {
- throw new InternalError(e);
- } finally {
- if (loader instanceof AutoCloseable) {
- try {
- ((AutoCloseable) loader).close();
- } catch (Exception e) {
- throw new InternalError(e);
- }
- }
- }
- }
-
- private Set<Class<?>> scanFile(String fileName) {
- log.printInfo("Scanning: " + fileName + " ...");
- log.printlnVerbose(" "); // Break line
-
- if (fileName.endsWith(".jar")) {
- return loadFromJarFile(fileName);
- } else if (fileName.endsWith(".class")) {
- Set<Class<?>> classes = new HashSet<>();
- loadFromClassFile(fileName, classes);
- return classes;
- } else {
- return scanClassPath(fileName);
- }
- }
-
- private Set<Class<?>> loadFromJarFile(String fileName) {
- FileSystem fs = makeFileSystem(fileName);
- FileSystemFinder finder = new FileSystemFinder(fs.getPath("/"), pathname -> entryIsClassFile(pathname.toString()));
- return loadWithClassLoader(() -> URLClassLoader.newInstance(buildUrls(fileName)), fs.getPath("/"), finder);
- }
-
- private void loadFromClassFile(String fileName, Set<Class<?>> classes) {
- Class<?> result;
- File file = new File(options.classpath);
- try (URLClassLoader loader = URLClassLoader.newInstance(buildUrls(file))) {
- result = loadClassFile(loader, fileName);
- } catch (IOException e) {
- throw new InternalError(e);
- }
- Class<?> c = result;
- addClass(classes, fileName, c);
- }
-
- private Set<Class<?>> scanClassPath(String fileName) {
- Path classPath = Paths.get(options.classpath);
- if (!Files.exists(classPath)) {
- throw new InternalError("Path does not exist: " + classPath);
- }
- if (!Files.isDirectory(classPath)) {
- throw new InternalError("Path must be a directory: " + classPath);
- }
-
- // Combine class path and file name and see what it is.
- Path combinedPath = Paths.get(options.classpath + File.separator + fileName);
- if (combinedPath.endsWith(".class")) {
- throw new InternalError("unimplemented");
- } else if (Files.isDirectory(combinedPath)) {
- return scanDirectory(classPath, combinedPath);
- } else {
- throw new InternalError("Expecting a .class, .jar or directory: " + fileName);
- }
- }
-
- private FileSystem makeFileSystem(String fileName) {
- try {
- return FileSystems.newFileSystem(makeJarFileURI(fileName), new HashMap<>());
- } catch (IOException e) {
- throw new InternalError(e);
- }
- }
-
- private URI makeJarFileURI(String fileName) {
- try {
- return new URI("jar:file:" + Paths.get(fileName).toAbsolutePath() + "!/");
- } catch (URISyntaxException e) {
- throw new InternalError(e);
- }
- }
-
- private PathMatcher combine(PathMatcher m1, PathMatcher m2) {
- return path -> m1.matches(path) && m2.matches(path);
- }
-
- private Set<Class<?>> scanDirectory(Path classPath, Path combinedPath) {
- String dir = options.classpath;
-
- FileSystem fileSystem = FileSystems.getDefault();
- PathMatcher matcher = fileSystem.getPathMatcher("glob:" + "*.class");
- FileSystemFinder finder = new FileSystemFinder(combinedPath,
- combine(matcher, pathname -> entryIsClassFile(pathname.toString())));
-
- File file = new File(dir);
- try (URLClassLoader loader = URLClassLoader.newInstance(buildUrls(file))) {
- return loadClassFiles(classPath, finder, loader);
- } catch (IOException e) {
- throw new InternalError(e);
- }
- }
-
- private Set<Class<?>> loadClassFiles(Path root, FileSystemFinder finder, ClassLoader loader) {
- Set<Class<?>> classes = new HashSet<>();
- for (Path name : finder.done()) {
- // Now relativize to the class path so we get the actual class names.
- String entry = root.relativize(name).normalize().toString();
- Class<?> c = loadClassFile(loader, entry);
- addClass(classes, entry, c);
- }
- return classes;
- }
-
- private void addClass(Set<Class<?>> classes, String name, Class<?> c) {
- if (c != null) {
- classes.add(c);
- log.printlnVerbose(" loaded " + name);
- }
- }
-
- private URL[] buildUrls(String fileName) throws MalformedURLException {
- return new URL[]{ new URL("jar:file:" + Paths.get(fileName).toAbsolutePath() + "!/") };
- }
-
- private URL[] buildUrls(File file) throws MalformedURLException {
- return new URL[] {file.toURI().toURL() };
- }
-
- private Path getModuleDirectory(String modulepath, String module) {
- FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
- return fs.getPath(modulepath, module);
- }
-
- /**
- * Loads a class with the given file name from the specified {@link URLClassLoader}.
- */
- private Class<?> loadClassFile(final ClassLoader loader, final String fileName) {
- int start = 0;
- if (fileName.startsWith("/")) {
- start = 1;
- }
- String className = fileName.substring(start, fileName.length() - ".class".length());
- className = className.replace('/', '.');
- try {
- return loader.loadClass(className);
- } catch (Throwable e) {
- // If we are running in JCK mode we ignore all exceptions.
- if (options.ignoreClassLoadingErrors) {
- log.printError(className + ": " + e);
- return null;
- }
- throw new InternalError(e);
- }
- }
-
- /**
- * {@link FileVisitor} implementation to find class files recursively.
- */
- private static class FileSystemFinder extends SimpleFileVisitor<Path> {
- private final ArrayList<Path> fileNames = new ArrayList<>();
- private final PathMatcher filter;
-
- FileSystemFinder(Path combinedPath, PathMatcher filter) {
- this.filter = filter;
- try {
- Files.walkFileTree(combinedPath, this);
- } catch (IOException e) {
- throw new InternalError(e);
- }
- }
-
- /**
- * Compares the glob pattern against the file name.
- */
- void find(Path file) {
- Path name = file.getFileName();
- if (name != null && filter.matches(name)) {
- fileNames.add(file);
- }
- }
-
- List<Path> done() {
- return fileNames;
- }
-
- @Override
- public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
- find(file);
- return CONTINUE;
- }
-
- @Override
- public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
- find(dir);
- return CONTINUE;
- }
-
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSearch.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect;
+
+import jdk.tools.jaotc.LoadedClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ClassSearch {
+ private List<SourceProvider> providers = new ArrayList<>();
+
+ public void addProvider(SourceProvider provider) {
+ providers.add(provider);
+ }
+
+ public List<LoadedClass> search(List<SearchFor> search, SearchPath searchPath) {
+ List<LoadedClass> loaded = new ArrayList<>();
+
+ List<ClassSource> sources = new ArrayList<>();
+
+ for (SearchFor entry : search) {
+ sources.add(findSource(entry, searchPath));
+ }
+
+ for (ClassSource source : sources) {
+ source.eachClass((name, loader) -> loaded.add(loadClass(name, loader)));
+ }
+
+ return loaded;
+ }
+
+ private LoadedClass loadClass(String name, ClassLoader loader) {
+ try {
+ Class<?> clzz = loader.loadClass(name);
+ return new LoadedClass(name, clzz);
+ } catch (ClassNotFoundException e) {
+ throw new InternalError("Failed to load with: " + loader, e);
+ }
+ }
+
+ private ClassSource findSource(SearchFor searchFor, SearchPath searchPath) {
+ ClassSource found = null;
+
+ for (SourceProvider provider : providers) {
+ if (!searchFor.isUnknown() && !provider.supports(searchFor.getType())) {
+ continue;
+ }
+
+ ClassSource source = provider.findSource(searchFor.getName(), searchPath);
+ if (source != null) {
+ if (found != null) {
+ throw new InternalError("Multiple possible sources: " + source + " and: " + found);
+ }
+ found = source;
+ }
+ }
+
+ if (found == null) {
+ throw new InternalError("Failed to find: " + searchFor.toString());
+ }
+ return found;
+ }
+
+ public static List<SearchFor> makeList(String type, String argument) {
+ List<SearchFor> list = new ArrayList<>();
+ String[] elements = argument.split(":");
+ for (String element : elements) {
+ list.add(new SearchFor(element, type));
+ }
+ return list;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSource.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect;
+
+import java.nio.file.Path;
+import java.util.function.BiConsumer;
+
+public interface ClassSource {
+ static boolean pathIsClassFile(Path entry) {
+ String fileName = entry.getFileName().toString();
+ return fileName.endsWith(".class") && !fileName.endsWith("module-info.class");
+ }
+
+ static String makeClassName(Path path) {
+ String fileName = path.toString();
+
+ if (!fileName.endsWith(".class")) {
+ throw new IllegalArgumentException("File doesn't end with .class: '" + fileName + "'");
+ }
+
+ int start = 0;
+ if (fileName.startsWith("/")) {
+ start = 1;
+ }
+
+ String className = fileName.substring(start, fileName.length() - ".class".length());
+ className = className.replace('/', '.');
+ return className;
+ }
+
+ void eachClass(BiConsumer<String, ClassLoader> consumer);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSupport.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect;
+
+import java.io.IOException;
+import java.net.*;
+import java.nio.file.*;
+import java.util.HashMap;
+
+public class FileSupport {
+ public boolean exists(Path path) {
+ return Files.exists(path);
+ }
+
+ public boolean isDirectory(Path path) {
+ return Files.isDirectory(path);
+ }
+
+ private FileSystem makeJarFileSystem(Path path) {
+ try {
+ return FileSystems.newFileSystem(makeJarFileURI(path), new HashMap<>());
+ } catch (IOException e) {
+ throw new InternalError(e);
+ }
+ }
+
+ private URI makeJarFileURI(Path path) {
+ try {
+ return new URI("jar:file:" + path.toAbsolutePath() + "!/");
+ } catch (URISyntaxException e) {
+ throw new InternalError(e);
+ }
+ }
+
+ public ClassLoader createClassLoader(Path path, ClassLoader parent) {
+ try {
+ return URLClassLoader.newInstance(buildUrls(path), parent);
+ } catch (MalformedURLException e) {
+ throw new InternalError(e);
+ }
+ }
+
+ public ClassLoader createClassLoader(Path path) throws MalformedURLException {
+ return URLClassLoader.newInstance(buildUrls(path));
+ }
+
+ private URL[] buildUrls(Path path) throws MalformedURLException {
+ return new URL[] { path.toUri().toURL() };
+ }
+
+ public Path getJarFileSystemRoot(Path jarFile) {
+ FileSystem fileSystem = makeJarFileSystem(jarFile);
+ return fileSystem.getPath("/");
+ }
+
+ public boolean isAbsolute(Path entry) {
+ return entry.isAbsolute();
+ }
+
+ public Path getSubDirectory(FileSystem fileSystem, Path root, Path path) throws IOException {
+ DirectoryStream<Path> paths = fileSystem.provider().newDirectoryStream(root,null);
+ for (Path entry : paths) {
+ Path relative = root.relativize(entry);
+ if (relative.equals(path)) {
+ return entry;
+ }
+ }
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSystemFinder.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect;
+
+import java.io.IOException;
+import java.nio.file.*;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import static java.nio.file.FileVisitResult.CONTINUE;
+
+/**
+ * {@link FileVisitor} implementation to find class files recursively.
+ */
+public class FileSystemFinder extends SimpleFileVisitor<Path> implements Iterable<Path> {
+ private final ArrayList<Path> fileNames = new ArrayList<>();
+ private final PathMatcher filter;
+
+ public FileSystemFinder(Path combinedPath, PathMatcher filter) {
+ this.filter = filter;
+ try {
+ Files.walkFileTree(combinedPath, this);
+ } catch (IOException e) {
+ throw new InternalError(e);
+ }
+ }
+
+ /**
+ * Compares the glob pattern against the file name.
+ */
+ private void find(Path file) {
+ Path name = file.getFileName();
+ if (name != null && filter.matches(name)) {
+ fileNames.add(file);
+ }
+ }
+
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
+ find(file);
+ return CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
+ find(dir);
+ return CONTINUE;
+ }
+
+
+ @Override
+ public Iterator<Path> iterator() {
+ return fileNames.iterator();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchFor.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect;
+
+public class SearchFor {
+ private final String name;
+ private final String type;
+
+ public SearchFor(String name) {
+ this(name, "unknown");
+ }
+
+ public SearchFor(String name, String type) {
+ this.name = name;
+ this.type = type;
+ }
+
+ public boolean isUnknown() {
+ return "unknown".equals(type);
+ }
+
+ public String getType() {
+ return this.type;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ @Override
+ public String toString() {
+ return type + ":" + name;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchPath.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect;
+
+import java.nio.file.FileSystem;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
+public class SearchPath {
+ private final List<Path> searchPaths = new ArrayList<>();
+ private final FileSupport fileSupport;
+
+ public SearchPath() {
+ this(new FileSupport());
+ }
+
+ public SearchPath(FileSupport fileSupport) {
+ this.fileSupport = fileSupport;
+ }
+
+ public Path find(FileSystem fileSystem, Path entry, String... defaults) {
+ if (isAbsolute(entry)) {
+ if (exists(entry)) {
+ return entry;
+ }
+ return null;
+ }
+
+ if (exists(entry)) {
+ return entry;
+ }
+
+ for (String searchPath : defaults) {
+ Path newPath = fileSystem.getPath(searchPath, entry.toString());
+ if (exists(newPath)) {
+ return newPath;
+ }
+ }
+
+ for (Path searchPath : searchPaths) {
+ Path newPath = fileSystem.getPath(searchPath.toString(), entry.toString());
+ if (exists(newPath)) {
+ return newPath;
+ }
+ }
+
+ return null;
+ }
+
+ private boolean isAbsolute(Path entry) {
+ return fileSupport.isAbsolute(entry);
+ }
+
+ private boolean exists(Path entry) {
+ return fileSupport.exists(entry);
+ }
+
+ public void add(String... paths) {
+ for (String name : paths) {
+ Path path = Paths.get(name);
+ searchPaths.add(path);
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SourceProvider.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect;
+
+public interface SourceProvider {
+ ClassSource findSource(String name, SearchPath searchPath);
+
+ boolean supports(String type);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSource.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect.classname;
+
+import jdk.tools.jaotc.collect.ClassSource;
+
+import java.util.function.BiConsumer;
+
+public class ClassNameSource implements ClassSource {
+ private final String name;
+ private final ClassLoader classLoader;
+
+ public ClassNameSource(String name, ClassLoader classLoader) {
+ this.name = name;
+ this.classLoader = classLoader;
+ }
+
+ @Override
+ public void eachClass(BiConsumer<String, ClassLoader> consumer) {
+ consumer.accept(name, classLoader);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSourceProvider.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect.classname;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSupport;
+import jdk.tools.jaotc.collect.SearchPath;
+import jdk.tools.jaotc.collect.SourceProvider;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class ClassNameSourceProvider implements SourceProvider {
+ public final static String TYPE = "classname";
+ private final ClassLoader classLoader;
+
+ public ClassNameSourceProvider(FileSupport fileSupport) {
+ String classPath = System.getProperty("java.class.path");
+ ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
+ if (classPath != null && !classPath.isEmpty()) {
+ classLoader = systemClassLoader;
+ } else {
+ Path path = Paths.get(".").toAbsolutePath();
+ classLoader = fileSupport.createClassLoader(path, systemClassLoader);
+ }
+ }
+
+ @Override
+ public ClassSource findSource(String name, SearchPath searchPath) {
+ try {
+ classLoader.loadClass(name);
+ return new ClassNameSource(name, classLoader);
+ } catch (ClassNotFoundException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public boolean supports(String type) {
+ return TYPE.equals(type);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySource.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect.directory;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSystemFinder;
+
+import java.nio.file.Path;
+import java.util.function.BiConsumer;
+
+public class DirectorySource implements ClassSource {
+ private final Path directoryPath;
+ private final ClassLoader classLoader;
+
+ public DirectorySource(Path directoryPath, ClassLoader classLoader) {
+ this.directoryPath = directoryPath;
+ this.classLoader = classLoader;
+ }
+
+ @Override
+ public void eachClass(BiConsumer<String, ClassLoader> consumer) {
+ FileSystemFinder finder = new FileSystemFinder(directoryPath, ClassSource::pathIsClassFile);
+
+ for (Path path : finder) {
+ consumer.accept(ClassSource.makeClassName(directoryPath.relativize(path).normalize()), classLoader);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "directory:" + directoryPath.toString();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySourceProvider.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect.directory;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSupport;
+import jdk.tools.jaotc.collect.SearchPath;
+import jdk.tools.jaotc.collect.SourceProvider;
+
+import java.net.MalformedURLException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+
+public class DirectorySourceProvider implements SourceProvider {
+ private final FileSupport fileSupport;
+ private final FileSystem fileSystem;
+ public final static String TYPE = "directory";
+
+ public DirectorySourceProvider(FileSupport fileSupport) {
+ this.fileSupport = fileSupport;
+ fileSystem = FileSystems.getDefault();
+ }
+
+ @Override
+ public ClassSource findSource(String name, SearchPath searchPath) {
+ Path directoryPath = fileSystem.getPath(name);
+
+ if (!fileSupport.exists(directoryPath)) {
+ return null;
+ }
+ if (!fileSupport.isDirectory(directoryPath)) {
+ return null;
+ }
+
+ try {
+ ClassLoader classLoader = fileSupport.createClassLoader(directoryPath);
+ return new DirectorySource(directoryPath, classLoader);
+ } catch (MalformedURLException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public boolean supports(String type) {
+ return TYPE.equals(type);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarFileSource.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect.jar;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSystemFinder;
+
+import java.nio.file.Path;
+import java.util.function.BiConsumer;
+
+public class JarFileSource implements ClassSource {
+ private final Path jarFile;
+ private final Path jarRootPath;
+ private final ClassLoader classLoader;
+
+
+ public JarFileSource(Path jarFile, Path jarRootPath, ClassLoader classLoader) {
+ this.jarFile = jarFile;
+ this.jarRootPath = jarRootPath;
+ this.classLoader = classLoader;
+ }
+
+ public void eachClass(BiConsumer<String, ClassLoader> consumer) {
+ FileSystemFinder finder = new FileSystemFinder(jarRootPath, ClassSource::pathIsClassFile);
+
+ for (Path path : finder) {
+ consumer.accept(ClassSource.makeClassName(jarRootPath.relativize(path).normalize()), classLoader);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "jar:" + jarFile.toString();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarSourceProvider.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect.jar;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSupport;
+import jdk.tools.jaotc.collect.SearchPath;
+import jdk.tools.jaotc.collect.SourceProvider;
+
+import java.net.MalformedURLException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.ProviderNotFoundException;
+
+public class JarSourceProvider implements SourceProvider {
+ private final FileSystem fileSystem;
+ private final FileSupport fileSupport;
+ public final static String TYPE = "jar";
+
+ public JarSourceProvider() {
+ this(new FileSupport());
+ }
+
+ public JarSourceProvider(FileSupport fileSupport) {
+ this.fileSupport = fileSupport;
+ fileSystem = FileSystems.getDefault();
+ }
+
+ @Override
+ public ClassSource findSource(String name, SearchPath searchPath) {
+ Path fileName = fileSystem.getPath(name);
+ Path jarFile = searchPath.find(fileSystem, fileName);
+
+ if (!validPath(jarFile)) {
+ return null;
+ }
+
+ return createSource(jarFile);
+ }
+
+ private ClassSource createSource(Path jarFile) {
+ try {
+ Path jarRootPath = fileSupport.getJarFileSystemRoot(jarFile);
+ if (jarRootPath == null) {
+ return null;
+ }
+ ClassLoader classLoader = fileSupport.createClassLoader(jarFile);
+ return new JarFileSource(jarFile, jarRootPath, classLoader);
+ } catch (ProviderNotFoundException | MalformedURLException e) {
+ }
+ return null;
+ }
+
+ @Override
+ public boolean supports(String type) {
+ return TYPE.equals(type);
+ }
+
+ private boolean validPath(Path jarFile) {
+ return jarFile != null && !fileSupport.isDirectory(jarFile);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSource.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect.module;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSystemFinder;
+
+import java.nio.file.Path;
+import java.util.function.BiConsumer;
+
+public class ModuleSource implements ClassSource {
+ private final Path modulePath;
+ private final ClassLoader classLoader;
+
+ public ModuleSource(Path modulePath, ClassLoader classLoader) {
+ this.modulePath = modulePath;
+ this.classLoader = classLoader;
+ }
+
+ @Override
+ public void eachClass(BiConsumer<String, ClassLoader> consumer) {
+ FileSystemFinder finder = new FileSystemFinder(modulePath, ClassSource::pathIsClassFile);
+
+ for (Path path : finder) {
+ consumer.accept(ClassSource.makeClassName(modulePath.relativize(path).normalize()), classLoader);
+ }
+ }
+
+ public Path getModulePath() {
+ return modulePath;
+ }
+
+ @Override
+ public String toString() {
+ return "module:" + modulePath.toString();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSourceProvider.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.collect.module;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSupport;
+import jdk.tools.jaotc.collect.SearchPath;
+import jdk.tools.jaotc.collect.SourceProvider;
+
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+
+public class ModuleSourceProvider implements SourceProvider {
+ private final FileSystem fileSystem;
+ private final ClassLoader classLoader;
+ private final FileSupport fileSupport;
+ public final static String TYPE = "module";
+
+ public ModuleSourceProvider() {
+ this(FileSystems.getFileSystem(URI.create("jrt:/")), ClassLoader.getSystemClassLoader(), new FileSupport());
+ }
+
+ public ModuleSourceProvider(FileSystem fileSystem, ClassLoader classLoader, FileSupport fileSupport) {
+ this.fileSystem = fileSystem;
+ this.classLoader = classLoader;
+ this.fileSupport = fileSupport;
+ }
+
+ @Override
+ public ClassSource findSource(String name, SearchPath searchPath) {
+ Path path = fileSystem.getPath(name);
+ Path dir = fileSystem.getPath("modules");
+
+ if (dir == null || !fileSupport.isDirectory(dir)) {
+ return null;
+ }
+
+ Path found = findModuleDirectory(dir, path);
+
+ if (found == null) {
+ return null;
+ }
+
+ return new ModuleSource(found, classLoader);
+ }
+
+ private Path findModuleDirectory(Path root, Path path) {
+ try {
+ return fileSupport.getSubDirectory(fileSystem, root, path);
+ } catch (IOException e) {
+ throw new InternalError(e);
+ }
+ }
+
+ @Override
+ public boolean supports(String type) {
+ return TYPE.equals(type);
+ }
+}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java Thu Feb 09 23:15:52 2017 +0100
@@ -100,15 +100,19 @@
native long getExceptionTableStart(HotSpotResolvedJavaMethodImpl method);
/**
- * Determines if {@code method} can be inlined. A method may not be inlinable for a number of
- * reasons such as:
- * <ul>
- * <li>a CompileOracle directive may prevent inlining or compilation of methods</li>
- * <li>the method may have a bytecode breakpoint set</li>
- * <li>the method may have other bytecode features that require special handling by the VM</li>
- * </ul>
+ * Determines whether {@code method} is currently compilable by the JVMCI compiler being used by
+ * the VM. This can return false if JVMCI compilation failed earlier for {@code method}, a
+ * breakpoint is currently set in {@code method} or {@code method} contains other bytecode
+ * features that require special handling by the VM.
*/
- native boolean canInlineMethod(HotSpotResolvedJavaMethodImpl method);
+ native boolean isCompilable(HotSpotResolvedJavaMethodImpl method);
+
+ /**
+ * Determines if {@code method} is targeted by a VM directive (e.g.,
+ * {@code -XX:CompileCommand=dontinline,<pattern>}) or annotation (e.g.,
+ * {@code jdk.internal.vm.annotation.DontInline}) that specifies it should not be inlined.
+ */
+ native boolean hasNeverInlineDirective(HotSpotResolvedJavaMethodImpl method);
/**
* Determines if {@code method} should be inlined at any cost. This could be because:
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java Thu Feb 09 23:15:52 2017 +0100
@@ -50,13 +50,6 @@
boolean isForceInline();
/**
- * Returns true if this method has a {@code DontInline} annotation.
- *
- * @return true if DontInline annotation present, false otherwise
- */
- boolean isDontInline();
-
- /**
* Returns true if this method has a {@code ReservedStackAccess} annotation.
*
* @return true if ReservedStackAccess annotation present, false otherwise
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java Thu Feb 09 23:15:52 2017 +0100
@@ -299,15 +299,6 @@
}
/**
- * Returns true if this method has a {@code DontInline} annotation.
- *
- * @return true if DontInline annotation present, false otherwise
- */
- public boolean isDontInline() {
- return (getFlags() & config().methodFlagsDontInline) != 0;
- }
-
- /**
* Returns true if this method has a {@code ReservedStackAccess} annotation.
*
* @return true if ReservedStackAccess annotation present, false otherwise
@@ -582,10 +573,15 @@
@Override
public boolean canBeInlined() {
- if (isDontInline()) {
+ if (hasNeverInlineDirective()) {
return false;
}
- return compilerToVM().canInlineMethod(this);
+ return compilerToVM().isCompilable(this);
+ }
+
+ @Override
+ public boolean hasNeverInlineDirective() {
+ return compilerToVM().hasNeverInlineDirective(this);
}
@Override
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java Thu Feb 09 23:15:52 2017 +0100
@@ -347,6 +347,13 @@
boolean canBeInlined();
/**
+ * Determines if this method is targeted by a VM directive (e.g.,
+ * {@code -XX:CompileCommand=dontinline,<pattern>}) or VM recognized annotation (e.g.,
+ * {@code jdk.internal.vm.annotation.DontInline}) that specifies it should not be inlined.
+ */
+ boolean hasNeverInlineDirective();
+
+ /**
* Returns {@code true} if the inlining of this method should be forced.
*/
boolean shouldBeInlined();
--- a/hotspot/src/jdk.vm.compiler/.mx.graal/suite.py Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/jdk.vm.compiler/.mx.graal/suite.py Thu Feb 09 23:15:52 2017 +0100
@@ -638,6 +638,7 @@
"annotationProcessors" : [
"GRAAL_NODEINFO_PROCESSOR",
"GRAAL_REPLACEMENTS_VERIFIER",
+ "GRAAL_OPTIONS_PROCESSOR",
],
"workingSets" : "Graal,Graph",
},
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java Thu Feb 09 23:15:52 2017 +0100
@@ -116,6 +116,7 @@
public static final int INFO_LOG_LEVEL = 2;
public static final int VERBOSE_LOG_LEVEL = 3;
public static final int DETAILED_LOG_LEVEL = 4;
+ public static final int VERY_DETAILED_LOG_LEVEL = 5;
public static boolean isDumpEnabled(int dumpLevel) {
return ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel);
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java Thu Feb 09 23:15:52 2017 +0100
@@ -267,10 +267,15 @@
if (config.useCompressedClassPointers) {
Register register = r10;
- AMD64HotSpotMove.decodeKlassPointer(asm, register, providers.getRegisters().getHeapBaseRegister(), src, config.getKlassEncoding());
- if (config.narrowKlassBase != 0) {
- // The heap base register was destroyed above, so restore it
- asm.movq(providers.getRegisters().getHeapBaseRegister(), config.narrowOopBase);
+ AMD64HotSpotMove.decodeKlassPointer(crb, asm, register, providers.getRegisters().getHeapBaseRegister(), src, config);
+ if (GeneratePIC.getValue()) {
+ asm.movq(providers.getRegisters().getHeapBaseRegister(), asm.getPlaceholder(-1));
+ crb.recordMark(config.MARKID_NARROW_OOP_BASE_ADDRESS);
+ } else {
+ if (config.narrowKlassBase != 0) {
+ // The heap base register was destroyed above, so restore it
+ asm.movq(providers.getRegisters().getHeapBaseRegister(), config.narrowOopBase);
+ }
}
asm.cmpq(inlineCacheKlass, register);
} else {
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java Thu Feb 09 23:15:52 2017 +0100
@@ -265,14 +265,21 @@
}
}
- public static void decodeKlassPointer(AMD64MacroAssembler masm, Register register, Register scratch, AMD64Address address, CompressEncoding encoding) {
+ public static void decodeKlassPointer(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register register, Register scratch, AMD64Address address, GraalHotSpotVMConfig config) {
+ CompressEncoding encoding = config.getKlassEncoding();
masm.movl(register, address);
if (encoding.shift != 0) {
assert encoding.alignment == encoding.shift : "Decode algorithm is wrong";
masm.shlq(register, encoding.alignment);
}
- if (encoding.base != 0) {
- masm.movq(scratch, encoding.base);
+ if (GeneratePIC.getValue() || encoding.base != 0) {
+ if (GeneratePIC.getValue()) {
+ masm.movq(scratch, masm.getPlaceholder(-1));
+ crb.recordMark(config.MARKID_NARROW_KLASS_BASE_ADDRESS);
+ } else {
+ assert encoding.base != 0;
+ masm.movq(scratch, encoding.base);
+ }
masm.addq(register, scratch);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017, 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 org.graalvm.compiler.hotspot;
+
+import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
+
+public class AOTGraalHotSpotVMConfig extends GraalHotSpotVMConfig {
+ private final CompressEncoding aotOopEncoding;
+ private final CompressEncoding aotKlassEncoding;
+
+ public AOTGraalHotSpotVMConfig(HotSpotVMConfigStore store) {
+ super(store);
+ // In AOT, force the shift to be always equal to alignment therefore avoiding zero-shift.
+ CompressEncoding vmOopEncoding = super.getOopEncoding();
+ aotOopEncoding = new CompressEncoding(vmOopEncoding.base, vmOopEncoding.alignment, vmOopEncoding.alignment);
+ CompressEncoding vmKlassEncoding = super.getKlassEncoding();
+ aotKlassEncoding = new CompressEncoding(vmKlassEncoding.base, vmKlassEncoding.alignment, vmKlassEncoding.alignment);
+ assert check();
+ }
+
+ @Override
+ public CompressEncoding getOopEncoding() {
+ return aotOopEncoding;
+ }
+
+ @Override
+ public CompressEncoding getKlassEncoding() {
+ return aotKlassEncoding;
+ }
+}
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java Thu Feb 09 23:15:52 2017 +0100
@@ -479,7 +479,6 @@
public final int methodCompiledEntryOffset = getFieldOffset("Method::_from_compiled_entry", Integer.class, "address");
public final int methodCodeOffset = getFieldOffset("Method::_code", Integer.class, isJDK8 ? "nmethod*" : "CompiledMethod*");
- public final int methodFlagsJfrTowrite = getConstant("Method::_jfr_towrite", Integer.class);
public final int methodFlagsCallerSensitive = getConstant("Method::_caller_sensitive", Integer.class);
public final int methodFlagsForceInline = getConstant("Method::_force_inline", Integer.class);
public final int methodFlagsDontInline = getConstant("Method::_dont_inline", Integer.class);
@@ -773,13 +772,14 @@
public final int MARKID_HEAP_TOP_ADDRESS = getConstant("CodeInstaller::HEAP_TOP_ADDRESS", Integer.class, 17);
public final int MARKID_HEAP_END_ADDRESS = getConstant("CodeInstaller::HEAP_END_ADDRESS", Integer.class, 18);
public final int MARKID_NARROW_KLASS_BASE_ADDRESS = getConstant("CodeInstaller::NARROW_KLASS_BASE_ADDRESS", Integer.class, 19);
- public final int MARKID_CRC_TABLE_ADDRESS = getConstant("CodeInstaller::CRC_TABLE_ADDRESS", Integer.class, 20);
- public final int MARKID_LOG_OF_HEAP_REGION_GRAIN_BYTES = getConstant("CodeInstaller::LOG_OF_HEAP_REGION_GRAIN_BYTES", Integer.class, 21);
- public final int MARKID_INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED = getConstant("CodeInstaller::INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED", Integer.class, 22);
+ public final int MARKID_NARROW_OOP_BASE_ADDRESS = getConstant("CodeInstaller::NARROW_OOP_BASE_ADDRESS", Integer.class, 20);
+ public final int MARKID_CRC_TABLE_ADDRESS = getConstant("CodeInstaller::CRC_TABLE_ADDRESS", Integer.class, 21);
+ public final int MARKID_LOG_OF_HEAP_REGION_GRAIN_BYTES = getConstant("CodeInstaller::LOG_OF_HEAP_REGION_GRAIN_BYTES", Integer.class, 22);
+ public final int MARKID_INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED = getConstant("CodeInstaller::INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED", Integer.class, 23);
// Checkstyle: resume
- private boolean check() {
+ protected boolean check() {
for (Field f : getClass().getDeclaredFields()) {
int modifiers = f.getModifiers();
if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) {
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java Thu Feb 09 23:15:52 2017 +0100
@@ -22,6 +22,7 @@
*/
package org.graalvm.compiler.hotspot;
+import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.debug.GraalDebugConfig.areScopedGlobalMetricsEnabled;
import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DebugValueSummary;
import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Dump;
@@ -99,7 +100,7 @@
HotSpotGraalRuntime(HotSpotJVMCIRuntime jvmciRuntime, CompilerConfigurationFactory compilerConfigurationFactory) {
HotSpotVMConfigStore store = jvmciRuntime.getConfigStore();
- config = new GraalHotSpotVMConfig(store);
+ config = GeneratePIC.getValue() ? new AOTGraalHotSpotVMConfig(store) : new GraalHotSpotVMConfig(store);
CompileTheWorldOptions.overrideWithNativeOptions(config);
// Only set HotSpotPrintInlining if it still has its default value (false).
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java Thu Feb 09 23:15:52 2017 +0100
@@ -22,7 +22,6 @@
*/
package org.graalvm.compiler.hotspot.meta;
-import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode;
import static org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider.FieldReadEnabledInImmutableCode;
@@ -112,11 +111,6 @@
return true;
}
}
- if (GeneratePIC.getValue()) {
- if (field.isSynthetic() && field.getName().startsWith("$assertionsDisabled")) {
- return tryReadField(b, field, null);
- }
- }
if (b.parsingIntrinsic() && wordOperationPlugin.handleLoadStaticField(b, field)) {
return true;
}
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Thu Feb 09 23:15:52 2017 +0100
@@ -1738,9 +1738,8 @@
} else {
// Intrinsic was not applied: remove intrinsic guard
// and restore the original receiver node in the arguments array
- for (Node node : graph.getNewNodes(intrinsicGuard.mark)) {
- GraphUtil.killCFG(node);
- }
+ intrinsicGuard.lastInstr.setNext(null);
+ GraphUtil.removeNewNodes(graph, intrinsicGuard.mark);
lastInstr = intrinsicGuard.lastInstr;
args[0] = intrinsicGuard.receiver;
}
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/SimplifyingGraphDecoder.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/SimplifyingGraphDecoder.java Thu Feb 09 23:15:52 2017 +0100
@@ -153,9 +153,7 @@
}
for (Node node : methodScope.graph.getNewNodes(methodScope.methodStartMark)) {
- if (!(node instanceof FixedNode) && node.hasNoUsages()) {
- GraphUtil.killCFG(node);
- }
+ GraphUtil.tryKillUnused(node);
}
}
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java Thu Feb 09 23:15:52 2017 +0100
@@ -506,7 +506,7 @@
for (Node successor : snapshot) {
if (successor != null && successor.isAlive()) {
if (successor != survivingSuccessor) {
- GraphUtil.killCFG(successor, tool);
+ GraphUtil.killCFG((FixedNode) successor, tool);
}
}
}
@@ -566,6 +566,9 @@
reduceTrivialMerge(begin);
} else { // convert to merge
AbstractMergeNode merge = this.add(new MergeNode());
+ for (EndNode end : begin.forwardEnds()) {
+ merge.addForwardEnd(end);
+ }
this.replaceFixedWithFixed(begin, merge);
}
}
@@ -576,7 +579,14 @@
for (PhiNode phi : merge.phis().snapshot()) {
assert phi.valueCount() == 1;
ValueNode singleValue = phi.valueAt(0);
- phi.replaceAtUsagesAndDelete(singleValue);
+ if (phi.hasUsages()) {
+ phi.replaceAtUsagesAndDelete(singleValue);
+ } else {
+ phi.safeDelete();
+ if (singleValue != null) {
+ GraphUtil.tryKillUnused(singleValue);
+ }
+ }
}
// remove loop exits
if (merge instanceof LoopBeginNode) {
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,18 +22,30 @@
*/
package org.graalvm.compiler.nodes.util;
+import static org.graalvm.compiler.graph.Graph.Options.VerifyGraalGraphEdges;
+import static org.graalvm.compiler.nodes.util.GraphUtil.Options.VerifyKillCFGUnusedNodes;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
+import java.util.Set;
import org.graalvm.compiler.bytecode.Bytecode;
import org.graalvm.compiler.code.SourceStackTraceBailoutException;
+import org.graalvm.compiler.core.common.CollectionsFactory;
import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
+import org.graalvm.compiler.core.common.type.StampFactory;
+import org.graalvm.compiler.debug.Debug;
+import org.graalvm.compiler.graph.Graph;
import org.graalvm.compiler.graph.Node;
+import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.NodeWorkList;
+import org.graalvm.compiler.graph.Position;
import org.graalvm.compiler.graph.iterators.NodeIterable;
import org.graalvm.compiler.graph.spi.SimplifierTool;
+import org.graalvm.compiler.nodeinfo.InputType;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.AbstractBeginNode;
import org.graalvm.compiler.nodes.AbstractEndNode;
import org.graalvm.compiler.nodes.AbstractMergeNode;
@@ -48,11 +60,15 @@
import org.graalvm.compiler.nodes.StateSplit;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.calc.FloatingNode;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
import org.graalvm.compiler.nodes.spi.ArrayLengthProvider;
import org.graalvm.compiler.nodes.spi.LimitedValueProxy;
import org.graalvm.compiler.nodes.spi.LoweringProvider;
import org.graalvm.compiler.nodes.spi.ValueProxy;
+import org.graalvm.compiler.options.Option;
+import org.graalvm.compiler.options.OptionType;
+import org.graalvm.compiler.options.OptionValue;
import jdk.vm.ci.code.BailoutException;
import jdk.vm.ci.code.BytecodePosition;
@@ -64,22 +80,78 @@
public class GraphUtil {
- public static void killCFG(Node node, SimplifierTool tool) {
- NodeWorkList worklist = killCFG(node, tool, null);
- if (worklist != null) {
- for (Node successor : worklist) {
- killCFG(successor, tool, worklist);
+ public static class Options {
+ @Option(help = "Verify that there are no new unused nodes when performing killCFG", type = OptionType.Debug)//
+ public static final OptionValue<Boolean> VerifyKillCFGUnusedNodes = new OptionValue<>(false);
+ }
+
+ @SuppressWarnings("try")
+ public static void killCFG(FixedNode node, SimplifierTool tool) {
+ try (Debug.Scope scope = Debug.scope("KillCFG", node)) {
+ Set<Node> unusedNodes = null;
+ Set<Node> unsafeNodes = null;
+ Graph.NodeEventScope nodeEventScope = null;
+ if (VerifyGraalGraphEdges.getValue()) {
+ unsafeNodes = collectUnsafeNodes(node.graph());
+ }
+ if (VerifyKillCFGUnusedNodes.getValue()) {
+ Set<Node> collectedUnusedNodes = unusedNodes = CollectionsFactory.newSet();
+ nodeEventScope = node.graph().trackNodeEvents(new Graph.NodeEventListener() {
+ @Override
+ public void event(Graph.NodeEvent e, Node n) {
+ if (e == Graph.NodeEvent.ZERO_USAGES && isFloatingNode(n)) {
+ collectedUnusedNodes.add(n);
+ }
+ }
+ });
+ }
+ Debug.dump(Debug.VERY_DETAILED_LOG_LEVEL, node.graph(), "Before killCFG %s", node);
+ NodeWorkList worklist = killCFG(node, tool, null);
+ if (worklist != null) {
+ for (Node n : worklist) {
+ killCFG(n, tool, worklist);
+ }
+ }
+ if (VerifyGraalGraphEdges.getValue()) {
+ Set<Node> newUnsafeNodes = collectUnsafeNodes(node.graph());
+ newUnsafeNodes.removeAll(unsafeNodes);
+ assert newUnsafeNodes.isEmpty() : "New unsafe nodes: " + newUnsafeNodes;
+ }
+ if (VerifyKillCFGUnusedNodes.getValue()) {
+ nodeEventScope.close();
+ unusedNodes.removeIf(n -> n.isDeleted());
+ assert unusedNodes.isEmpty() : "New unused nodes: " + unusedNodes;
+ }
+ } catch (Throwable t) {
+ throw Debug.handle(t);
+ }
+ }
+
+ /**
+ * Collects all node in the graph which have non-optional inputs that are null.
+ */
+ private static Set<Node> collectUnsafeNodes(Graph graph) {
+ Set<Node> unsafeNodes = CollectionsFactory.newSet();
+ for (Node n : graph.getNodes()) {
+ for (Position pos : n.inputPositions()) {
+ Node input = pos.get(n);
+ if (input == null) {
+ if (!pos.isInputOptional()) {
+ unsafeNodes.add(n);
+ }
+ }
}
}
+ return unsafeNodes;
}
private static NodeWorkList killCFG(Node node, SimplifierTool tool, NodeWorkList worklist) {
NodeWorkList newWorklist = worklist;
- // DebugScope.forceDump(node.graph(), "kill CFG %s", node);
if (node instanceof FixedNode) {
newWorklist = killCFGLinear((FixedNode) node, newWorklist, tool);
} else {
- propagateKill(node);
+ newWorklist = propagateKill(node, newWorklist);
+ Debug.dump(Debug.VERY_DETAILED_LOG_LEVEL, node.graph(), "killCFG (Floating) %s", node);
}
return newWorklist;
}
@@ -93,19 +165,20 @@
if (current instanceof AbstractEndNode) {
// We reached a control flow end.
AbstractEndNode end = (AbstractEndNode) current;
- killEnd(end, tool);
+ newWorklist = killEnd(end, newWorklist, tool);
} else if (current instanceof FixedWithNextNode) {
- next = ((FixedWithNextNode) current).next();
+ // Node guaranteed to have a single successor
+ FixedWithNextNode fixedWithNext = (FixedWithNextNode) current;
+ assert fixedWithNext.successors().count() == 1 || fixedWithNext.successors().count() == 0;
+ assert fixedWithNext.successors().first() == fixedWithNext.next();
+ next = fixedWithNext.next();
} else {
- // Normal control flow node.
/*
* We do not take a successor snapshot because this iterator supports concurrent
* modifications as long as they do not change the size of the successor list. Not
* taking a snapshot allows us to see modifications to other branches that may
* happen while processing one branch.
*/
- // assert node.successors().count() > 1 || node.successors().count() == 0 :
- // node.getClass();
Iterator<Node> successors = current.successors().iterator();
if (successors.hasNext()) {
Node first = successors.next();
@@ -126,100 +199,158 @@
}
}
current.replaceAtPredecessor(null);
- propagateKill(current);
+ newWorklist = propagateKill(current, newWorklist);
+ Debug.dump(Debug.VERY_DETAILED_LOG_LEVEL, current.graph(), "killCFGLinear %s", current);
current = next;
}
+ Debug.dump(Debug.DETAILED_LOG_LEVEL, in.graph(), "killCFGLinear %s", in);
return newWorklist;
}
- public static void killCFG(Node node) {
+ public static void killCFG(FixedNode node) {
killCFG(node, null);
}
- private static void killEnd(AbstractEndNode end, SimplifierTool tool) {
+ /**
+ * Node type used temporarily while deleting loops.
+ *
+ * It is used as replacement for the loop {@link PhiNode PhiNodes} in order to break data-flow
+ * cycles before deleting the loop. The control-flow of the whole loop is killed before killing
+ * the poison node if they are still alive.
+ */
+ @NodeInfo(allowedUsageTypes = InputType.Unchecked)
+ private static final class PoisonNode extends FloatingNode {
+ public static final NodeClass<PoisonNode> TYPE = NodeClass.create(PoisonNode.class);
+
+ protected PoisonNode() {
+ super(TYPE, StampFactory.forVoid());
+ }
+ }
+
+ private static NodeWorkList killEnd(AbstractEndNode end, NodeWorkList worklist, SimplifierTool tool) {
+ NodeWorkList newWorklist = worklist;
AbstractMergeNode merge = end.merge();
if (merge != null) {
merge.removeEnd(end);
StructuredGraph graph = end.graph();
if (merge instanceof LoopBeginNode && merge.forwardEndCount() == 0) {
// dead loop
- for (PhiNode phi : merge.phis().snapshot()) {
- propagateKill(phi);
- }
LoopBeginNode begin = (LoopBeginNode) merge;
// disconnect and delete loop ends & loop exits
for (LoopEndNode loopend : begin.loopEnds().snapshot()) {
loopend.predecessor().replaceFirstSuccessor(loopend, null);
loopend.safeDelete();
}
+ // clean unused proxies to avoid creating new unused nodes
+ for (LoopExitNode exit : begin.loopExits()) {
+ for (ProxyNode vpn : exit.proxies().snapshot()) {
+ tryKillUnused(vpn);
+ }
+ }
begin.removeExits();
+ PoisonNode poison = null;
+ if (merge.phis().isNotEmpty()) {
+ poison = graph.unique(new PoisonNode());
+ for (PhiNode phi : merge.phis()) {
+ phi.replaceAtUsages(poison);
+ }
+ for (PhiNode phi : merge.phis().snapshot()) {
+ killWithUnusedFloatingInputs(phi);
+ }
+ }
FixedNode loopBody = begin.next();
- if (loopBody != null) { // for small infinite loops, the body may be killed while
- // killing the loop ends
- killCFG(loopBody);
+ Debug.dump(Debug.VERY_DETAILED_LOG_LEVEL, end.graph(), "killEnd (Loop) %s after initial loop cleanup", end);
+ if (loopBody != null) {
+ // for small infinite loops, the body may already be killed while killing the
+ // LoopEnds
+ newWorklist = killCFG(loopBody, tool, worklist);
+ }
+ FrameState frameState = begin.stateAfter();
+ begin.safeDelete();
+ if (frameState != null) {
+ tryKillUnused(frameState);
}
- begin.safeDelete();
+ if (poison != null && poison.isAlive()) {
+ if (newWorklist == null) {
+ newWorklist = graph.createNodeWorkList();
+ }
+ // drain the worklist to finish the loop before adding the poison
+ for (Node n : newWorklist) {
+ killCFG(n, tool, newWorklist);
+ }
+ if (poison.isAlive()) {
+ newWorklist.add(poison);
+ }
+ }
} else if (merge instanceof LoopBeginNode && ((LoopBeginNode) merge).loopEnds().isEmpty()) {
// not a loop anymore
if (tool != null) {
- merge.phis().forEach(phi -> tool.addToWorkList(phi.usages()));
+ for (PhiNode phi : merge.phis()) {
+ tool.addToWorkList(phi.usages());
+ }
}
graph.reduceDegenerateLoopBegin((LoopBeginNode) merge);
} else if (merge.phiPredecessorCount() == 1) {
// not a merge anymore
if (tool != null) {
- merge.phis().forEach(phi -> tool.addToWorkList(phi.usages()));
+ for (PhiNode phi : merge.phis()) {
+ tool.addToWorkList(phi.usages());
+ }
}
graph.reduceTrivialMerge(merge);
}
}
+ return newWorklist;
}
public static boolean isFloatingNode(Node n) {
return !(n instanceof FixedNode);
}
- private static void propagateKill(Node node) {
+ private static NodeWorkList propagateKill(Node node, NodeWorkList workList) {
+ NodeWorkList newWorkList = workList;
if (node != null && node.isAlive()) {
- node.markDeleted();
-
- for (Node in : node.inputs()) {
- if (in.isAlive()) {
- in.removeUsage(node);
- if (in.hasNoUsages() && !(in instanceof FixedNode)) {
- killWithUnusedFloatingInputs(in);
+ for (Node usage : node.usages().snapshot()) {
+ assert usage.isAlive();
+ if (isFloatingNode(usage)) {
+ boolean addUsage = false;
+ if (usage instanceof PhiNode) {
+ PhiNode phi = (PhiNode) usage;
+ assert phi.merge() != null;
+ if (phi.merge() == node) {
+ // we reach the phi directly through he merge, queue it.
+ addUsage = true;
+ } else {
+ // we reach it though a value
+ assert phi.values().contains(node);
+ // let that be handled when we reach the corresponding End node
+ }
+ } else {
+ addUsage = true;
+ }
+ if (addUsage) {
+ if (newWorkList == null) {
+ newWorkList = node.graph().createNodeWorkList();
+ }
+ newWorkList.add(usage);
}
}
- }
-
- ArrayList<Node> usageToKill = null;
- for (Node usage : node.usages()) {
- if (usage.isAlive() && !(usage instanceof FixedNode)) {
- if (usageToKill == null) {
- usageToKill = new ArrayList<>();
- }
- usageToKill.add(usage);
- }
+ usage.replaceFirstInput(node, null);
}
- if (usageToKill != null) {
- for (Node usage : usageToKill) {
- if (usage.isAlive()) {
- if (usage instanceof PhiNode) {
- PhiNode phiNode = (PhiNode) usage;
- usage.replaceFirstInput(node, null);
- if (phiNode.merge() == null || !phiNode.hasValidInput()) {
- propagateKill(usage);
- }
- } else {
- propagateKill(usage);
- }
- }
- }
- }
+ killWithUnusedFloatingInputs(node);
}
+ return newWorkList;
+ }
+
+ private static boolean checkKill(Node node) {
+ node.assertTrue(node.isAlive(), "must be alive");
+ node.assertTrue(node.hasNoUsages(), "cannot kill node %s because of usages: %s", node, node.usages());
+ node.assertTrue(node.predecessor() == null, "cannot kill node %s because of predecessor: %s", node, node.predecessor());
+ return true;
}
public static void killWithUnusedFloatingInputs(Node node) {
+ assert checkKill(node);
node.markDeleted();
outer: for (Node in : node.inputs()) {
if (in.isAlive()) {
@@ -227,7 +358,7 @@
if (in.hasNoUsages()) {
node.maybeNotifyZeroUsages(in);
}
- if (!(in instanceof FixedNode)) {
+ if (isFloatingNode(in)) {
if (in.hasNoUsages()) {
killWithUnusedFloatingInputs(in);
} else if (in instanceof PhiNode) {
@@ -244,6 +375,35 @@
}
}
+ /**
+ * Removes all nodes created after the {@code mark}, assuming no "old" nodes point to "new"
+ * nodes.
+ */
+ public static void removeNewNodes(Graph graph, Graph.Mark mark) {
+ assert checkNoOldToNewEdges(graph, mark);
+ for (Node n : graph.getNewNodes(mark)) {
+ n.markDeleted();
+ for (Node in : n.inputs()) {
+ in.removeUsage(n);
+ }
+ }
+ }
+
+ private static boolean checkNoOldToNewEdges(Graph graph, Graph.Mark mark) {
+ for (Node old : graph.getNodes()) {
+ if (graph.isNew(mark, old)) {
+ break;
+ }
+ for (Node n : old.successors()) {
+ assert !graph.isNew(mark, n) : old + " -> " + n;
+ }
+ for (Node n : old.inputs()) {
+ assert !graph.isNew(mark, n) : old + " -> " + n;
+ }
+ }
+ return true;
+ }
+
public static void removeFixedWithUnusedInputs(FixedWithNextNode fixed) {
if (fixed instanceof StateSplit) {
FrameState stateAfter = ((StateSplit) fixed).stateAfter();
@@ -688,8 +848,9 @@
@Override
public void deleteBranch(Node branch) {
- branch.predecessor().replaceFirstSuccessor(branch, null);
- GraphUtil.killCFG(branch, this);
+ FixedNode fixedBranch = (FixedNode) branch;
+ fixedBranch.predecessor().replaceFirstSuccessor(fixedBranch, null);
+ GraphUtil.killCFG(fixedBranch, this);
}
@Override
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java Thu Feb 09 23:15:52 2017 +0100
@@ -444,8 +444,9 @@
@Override
public void deleteBranch(Node branch) {
- branch.predecessor().replaceFirstSuccessor(branch, null);
- GraphUtil.killCFG(branch, this);
+ FixedNode fixedBranch = (FixedNode) branch;
+ fixedBranch.predecessor().replaceFirstSuccessor(fixedBranch, null);
+ GraphUtil.killCFG(fixedBranch, this);
}
@Override
--- a/hotspot/src/os/aix/vm/os_aix.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/os/aix/vm/os_aix.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2016 SAP SE. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017 SAP SE. 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
@@ -632,7 +632,6 @@
sigaddset(&unblocked_sigs, SIGBUS);
sigaddset(&unblocked_sigs, SIGFPE);
sigaddset(&unblocked_sigs, SIGTRAP);
- sigaddset(&unblocked_sigs, SIGDANGER);
sigaddset(&unblocked_sigs, SR_signum);
if (!ReduceSignalUsage) {
@@ -1553,6 +1552,8 @@
print_signal_handler(st, SHUTDOWN3_SIGNAL , buf, buflen);
print_signal_handler(st, BREAK_SIGNAL, buf, buflen);
print_signal_handler(st, SIGTRAP, buf, buflen);
+ // We also want to know if someone else adds a SIGDANGER handler because
+ // that will interfere with OOM killling.
print_signal_handler(st, SIGDANGER, buf, buflen);
}
@@ -3156,7 +3157,6 @@
set_signal_handler(SIGFPE, true);
set_signal_handler(SIGTRAP, true);
set_signal_handler(SIGXFSZ, true);
- set_signal_handler(SIGDANGER, true);
if (libjsig_is_loaded) {
// Tell libjsig jvm finishes setting signal handlers.
@@ -3273,7 +3273,6 @@
if (UseSIGTRAP) {
DO_SIGNAL_CHECK(SIGTRAP);
}
- DO_SIGNAL_CHECK(SIGDANGER);
// ReduceSignalUsage allows the user to override these handlers
// see comments at the very top and jvm_solaris.h
--- a/hotspot/src/os/windows/vm/os_windows.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -778,6 +778,11 @@
// is already attached to a debugger; debugger must observe
// the exception below to show the correct name.
+ // If there is no debugger attached skip raising the exception
+ if (!IsDebuggerPresent()) {
+ return;
+ }
+
const DWORD MS_VC_EXCEPTION = 0x406D1388;
struct {
DWORD dwType; // must be 0x1000
--- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2016 SAP SE. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017 SAP SE. 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
@@ -258,13 +258,6 @@
}
}
- // Handle SIGDANGER right away. AIX would raise SIGDANGER whenever available swap
- // space falls below 30%. This is only a chance for the process to gracefully abort.
- // We can't hope to proceed after SIGDANGER since SIGKILL tailgates.
- if (sig == SIGDANGER) {
- goto report_and_die;
- }
-
if (info == NULL || uc == NULL || thread == NULL && vmthread == NULL) {
goto run_chained_handler;
}
--- a/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -87,6 +87,7 @@
#define SPELL_REG_FP "rbp"
#else
#define REG_FP 29
+#define REG_LR 30
#define SPELL_REG_SP "sp"
#define SPELL_REG_FP "x29"
@@ -182,6 +183,46 @@
return frame(sp, fp, epc.pc());
}
+bool os::Linux::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) {
+ address pc = (address) os::Linux::ucontext_get_pc(uc);
+ if (Interpreter::contains(pc)) {
+ // interpreter performs stack banging after the fixed frame header has
+ // been generated while the compilers perform it before. To maintain
+ // semantic consistency between interpreted and compiled frames, the
+ // method returns the Java sender of the current frame.
+ *fr = os::fetch_frame_from_context(uc);
+ if (!fr->is_first_java_frame()) {
+ assert(fr->safe_for_sender(thread), "Safety check");
+ *fr = fr->java_sender();
+ }
+ } else {
+ // more complex code with compiled code
+ assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above");
+ CodeBlob* cb = CodeCache::find_blob(pc);
+ if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) {
+ // Not sure where the pc points to, fallback to default
+ // stack overflow handling
+ return false;
+ } else {
+ // In compiled code, the stack banging is performed before LR
+ // has been saved in the frame. LR is live, and SP and FP
+ // belong to the caller.
+ intptr_t* fp = os::Linux::ucontext_get_fp(uc);
+ intptr_t* sp = os::Linux::ucontext_get_sp(uc);
+ address pc = (address)(uc->uc_mcontext.regs[REG_LR]
+ - NativeInstruction::instruction_size);
+ *fr = frame(sp, fp, pc);
+ if (!fr->is_java_frame()) {
+ assert(fr->safe_for_sender(thread), "Safety check");
+ assert(!fr->is_first_frame(), "Safety check");
+ *fr = fr->java_sender();
+ }
+ }
+ }
+ assert(fr->is_java_frame(), "Safety check");
+ return true;
+}
+
// By default, gcc always saves frame pointer rfp on this stack. This
// may get turned off by -fomit-frame-pointer.
frame os::get_sender_for_C_frame(frame* fr) {
@@ -313,6 +354,24 @@
if (thread->in_stack_yellow_reserved_zone(addr)) {
thread->disable_stack_yellow_reserved_zone();
if (thread->thread_state() == _thread_in_Java) {
+ if (thread->in_stack_reserved_zone(addr)) {
+ frame fr;
+ if (os::Linux::get_frame_at_stack_banging_point(thread, uc, &fr)) {
+ assert(fr.is_java_frame(), "Must be a Java frame");
+ frame activation =
+ SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
+ if (activation.sp() != NULL) {
+ thread->disable_stack_reserved_zone();
+ if (activation.is_interpreted_frame()) {
+ thread->set_reserved_stack_activation((address)(
+ activation.fp() + frame::interpreter_frame_initial_sp_offset));
+ } else {
+ thread->set_reserved_stack_activation((address)activation.unextended_sp());
+ }
+ return 1;
+ }
+ }
+ }
// Throw a stack overflow exception. Guard pages will be reenabled
// while unwinding the stack.
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
@@ -475,9 +534,9 @@
// Minimum usable stack sizes required to get to user code. Space for
// HotSpot guard pages is added later.
-size_t os::Posix::_compiler_thread_min_stack_allowed = 32 * K;
-size_t os::Posix::_java_thread_min_stack_allowed = 32 * K;
-size_t os::Posix::_vm_internal_thread_min_stack_allowed = 64 * K;
+size_t os::Posix::_compiler_thread_min_stack_allowed = 72 * K;
+size_t os::Posix::_java_thread_min_stack_allowed = 72 * K;
+size_t os::Posix::_vm_internal_thread_min_stack_allowed = 72 * K;
// return default stack size for thr_type
size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
--- a/hotspot/src/os_cpu/linux_s390/vm/os_linux_s390.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/os_cpu/linux_s390/vm/os_linux_s390.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -144,6 +144,42 @@
return frame(sp, epc.pc());
}
+bool os::Linux::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) {
+ address pc = (address) os::Linux::ucontext_get_pc(uc);
+ if (Interpreter::contains(pc)) {
+ // Interpreter performs stack banging after the fixed frame header has
+ // been generated while the compilers perform it before. To maintain
+ // semantic consistency between interpreted and compiled frames, the
+ // method returns the Java sender of the current frame.
+ *fr = os::fetch_frame_from_context(uc);
+ if (!fr->is_first_java_frame()) {
+ assert(fr->safe_for_sender(thread), "Safety check");
+ *fr = fr->java_sender();
+ }
+ } else {
+ // More complex code with compiled code.
+ assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above");
+ CodeBlob* cb = CodeCache::find_blob(pc);
+ if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) {
+ // Not sure where the pc points to, fallback to default
+ // stack overflow handling. In compiled code, we bang before
+ // the frame is complete.
+ return false;
+ } else {
+ intptr_t* fp = os::Linux::ucontext_get_fp(uc);
+ intptr_t* sp = os::Linux::ucontext_get_sp(uc);
+ *fr = frame(sp, (address)*sp);
+ if (!fr->is_java_frame()) {
+ assert(fr->safe_for_sender(thread), "Safety check");
+ assert(!fr->is_first_frame(), "Safety check");
+ *fr = fr->java_sender();
+ }
+ }
+ }
+ assert(fr->is_java_frame(), "Safety check");
+ return true;
+}
+
frame os::get_sender_for_C_frame(frame* fr) {
if (*fr->sp() == 0) {
// fr is the last C frame.
@@ -279,13 +315,31 @@
if (thread->on_local_stack(addr)) {
// stack overflow
if (thread->in_stack_yellow_reserved_zone(addr)) {
- thread->disable_stack_yellow_reserved_zone();
if (thread->thread_state() == _thread_in_Java) {
+ if (thread->in_stack_reserved_zone(addr)) {
+ frame fr;
+ if (os::Linux::get_frame_at_stack_banging_point(thread, uc, &fr)) {
+ assert(fr.is_java_frame(), "Must be a Javac frame");
+ frame activation =
+ SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);
+ if (activation.sp() != NULL) {
+ thread->disable_stack_reserved_zone();
+ if (activation.is_interpreted_frame()) {
+ thread->set_reserved_stack_activation((address)activation.fp());
+ } else {
+ thread->set_reserved_stack_activation((address)activation.unextended_sp());
+ }
+ return 1;
+ }
+ }
+ }
// Throw a stack overflow exception.
// Guard pages will be reenabled while unwinding the stack.
+ thread->disable_stack_yellow_reserved_zone();
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
} else {
// Thread was in the vm or native code. Return and try to finish.
+ thread->disable_stack_yellow_reserved_zone();
return 1;
}
} else if (thread->in_stack_red_zone(addr)) {
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -89,7 +89,10 @@
// Minimum usable stack sizes required to get to user code. Space for
// HotSpot guard pages is added later.
#ifdef _LP64
-size_t os::Posix::_compiler_thread_min_stack_allowed = 202 * K;
+// The adlc generated method 'State::MachNodeGenerator(int)' used by the C2 compiler
+// threads requires a large stack with the Solaris Studio C++ compiler version 5.13
+// and product VM builds (debug builds require significantly less stack space).
+size_t os::Posix::_compiler_thread_min_stack_allowed = 325 * K;
size_t os::Posix::_java_thread_min_stack_allowed = 48 * K;
size_t os::Posix::_vm_internal_thread_min_stack_allowed = 224 * K;
#else
--- a/hotspot/src/share/vm/adlc/formssel.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/adlc/formssel.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -650,6 +650,7 @@
if( strcmp(_matrule->_opType,"MemBarReleaseLock") == 0 ) return true;
if( strcmp(_matrule->_opType,"MemBarAcquireLock") == 0 ) return true;
if( strcmp(_matrule->_opType,"MemBarStoreStore") == 0 ) return true;
+ if( strcmp(_matrule->_opType,"MemBarVolatile") == 0 ) return true;
if( strcmp(_matrule->_opType,"StoreFence") == 0 ) return true;
if( strcmp(_matrule->_opType,"LoadFence") == 0 ) return true;
--- a/hotspot/src/share/vm/aot/aotCodeHeap.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/aot/aotCodeHeap.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -25,6 +25,7 @@
#include "aot/aotCodeHeap.hpp"
#include "aot/aotLoader.hpp"
+#include "classfile/javaAssertions.hpp"
#include "gc/g1/heapRegion.hpp"
#include "gc/shared/gcLocker.hpp"
#include "interpreter/abstractInterpreter.hpp"
@@ -294,6 +295,8 @@
// When the AOT compiler compiles something big we fail to generate metadata
// in CodeInstaller::gather_metadata. In that case the scopes_pcs_begin == scopes_pcs_end.
// In all successful cases we always have 2 entries of scope pcs.
+ log_info(aot, class, resolve)("Failed to load %s (no metadata available)", mh->name_and_sig_as_C_string());
+ _code_to_aot[code_id]._state = invalid;
return;
}
@@ -536,6 +539,7 @@
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_heap_end_address", address, (heap->supports_inline_contig_alloc() ? heap->end_addr() : NULL));
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_polling_page", address, os::get_polling_page());
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_narrow_klass_base_address", address, Universe::narrow_klass_base());
+ SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_narrow_oop_base_address", address, Universe::narrow_oop_base());
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_log_of_heap_region_grain_bytes", int, HeapRegion::LogOfHRGrainBytes);
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_inline_contiguous_allocation_supported", bool, heap->supports_inline_contig_alloc());
link_shared_runtime_symbols();
@@ -706,6 +710,12 @@
return false;
}
+ if (_lib->config()->_omitAssertions && JavaAssertions::enabled(kh->name()->as_C_string(), kh->class_loader() == NULL)) {
+ log_trace(aot, class, load)("class %s in %s does not have java assertions in compiled code, but assertions are enabled for this execution.", kh->internal_name(), _lib->name());
+ sweep_dependent_methods(klass_data);
+ return false;
+ }
+
NOT_PRODUCT( aot_klasses_found++; )
log_trace(aot, class, load)("found %s in %s for classloader %p tid=" INTPTR_FORMAT, kh->internal_name(), _lib->name(), kh->class_loader_data(), p2i(thread));
@@ -714,7 +724,7 @@
// Set klass's Resolve (second) got cell.
_metaspace_got[klass_data->_got_index] = kh();
- // Initialize global symbols of the DSO to the correspondingVM symbol values.
+ // Initialize global symbols of the DSO to the corresponding VM symbol values.
link_global_lib_symbols();
int methods_offset = klass_data->_compiled_methods_offset;
--- a/hotspot/src/share/vm/aot/aotCodeHeap.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/aot/aotCodeHeap.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -88,7 +88,7 @@
} AOTHeader;
typedef struct {
- enum { CONFIG_SIZE = 11 + 7 * 4 };
+ enum { CONFIG_SIZE = 12 + 7 * 4 };
int _config_size;
int _narrowOopShift;
int _narrowKlassShift;
@@ -108,6 +108,7 @@
bool _tieredAOT;
bool _enableContended;
bool _restrictContended;
+ bool _omitAssertions;
} AOTConfiguration;
class AOTLib : public CHeapObj<mtCode> {
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -3298,7 +3298,9 @@
// for osr compile, bailout if some requirements are not fulfilled
if (osr_bci != -1) {
BlockBegin* osr_block = blm.bci2block()->at(osr_bci);
- assert(osr_block->is_set(BlockBegin::was_visited_flag),"osr entry must have been visited for osr compile");
+ if (!osr_block->is_set(BlockBegin::was_visited_flag)) {
+ BAILOUT("osr entry must have been visited for osr compile");
+ }
// check if osr entry point has empty stack - we cannot handle non-empty stacks at osr entry points
if (!osr_block->state()->stack_is_empty()) {
--- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -895,8 +895,32 @@
ciMethod* target = s.get_method(ignored_will_link, &declared_signature);
ciKlass* holder = s.get_declared_method_holder();
assert(declared_signature != NULL, "cannot be null");
- // Push appendix argument, if one.
- if (s.has_appendix()) {
+ // If the current bytecode has an attached appendix argument,
+ // push an unknown object to represent that argument. (Analysis
+ // of dynamic call sites, especially invokehandle calls, needs
+ // the appendix argument on the stack, in addition to "regular" arguments
+ // pushed onto the stack by bytecode instructions preceding the call.)
+ //
+ // The escape analyzer does _not_ use the ciBytecodeStream::has_appendix(s)
+ // method to determine whether the current bytecode has an appendix argument.
+ // The has_appendix() method obtains the appendix from the
+ // ConstantPoolCacheEntry::_f1 field, which can happen concurrently with
+ // resolution of dynamic call sites. Callees in the
+ // ciBytecodeStream::get_method() call above also access the _f1 field;
+ // interleaving the get_method() and has_appendix() calls in the current
+ // method with call site resolution can lead to an inconsistent view of
+ // the current method's argument count. In particular, some interleaving(s)
+ // can cause the method's argument count to not include the appendix, which
+ // then leads to stack over-/underflow in the escape analyzer.
+ //
+ // Instead of pushing the argument if has_appendix() is true, the escape analyzer
+ // pushes an appendix for all call sites targeted by invokedynamic and invokehandle
+ // instructions, except if the call site is the _invokeBasic intrinsic
+ // (that intrinsic is always targeted by an invokehandle instruction but does
+ // not have an appendix argument).
+ if (target->is_loaded() &&
+ Bytecodes::has_optional_appendix(s.cur_bc_raw()) &&
+ target->intrinsic_id() != vmIntrinsics::_invokeBasic) {
state.apush(unknown_obj);
}
// Pass in raw bytecode because we need to see invokehandle instructions.
--- a/hotspot/src/share/vm/ci/ciMethod.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/ci/ciMethod.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -136,15 +136,19 @@
check_is_loaded();
return _signature->size() + (_flags.is_static() ? 0 : 1);
}
- // Report the number of elements on stack when invoking this method.
- // This is different than the regular arg_size because invokedynamic
- // has an implicit receiver.
+ // Report the number of elements on stack when invoking the current method.
+ // If the method is loaded, arg_size() gives precise information about the
+ // number of stack elements (using the method's signature and its flags).
+ // However, if the method is not loaded, the number of stack elements must
+ // be determined differently, as the method's flags are not yet available.
+ // The invoke_arg_size() method assumes in that case that all bytecodes except
+ // invokestatic and invokedynamic have a receiver that is also pushed onto the
+ // stack by the caller of the current method.
int invoke_arg_size(Bytecodes::Code code) const {
if (is_loaded()) {
return arg_size();
} else {
int arg_size = _signature->size();
- // Add a receiver argument, maybe:
if (code != Bytecodes::_invokestatic &&
code != Bytecodes::_invokedynamic) {
arg_size++;
--- a/hotspot/src/share/vm/classfile/classLoader.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -364,7 +364,12 @@
if (verstr != NULL) {
version = atoi(verstr);
if (version < base_version || version > cur_ver) {
- is_multi_ver = false;
+ // If the specified version is lower than the base version, the base
+ // entry will be used; if the version is higher than the current
+ // jdk version, the highest versioned entry will be used.
+ if (version < base_version) {
+ is_multi_ver = false;
+ }
// print out warning, do not use assertion here since it will continue to look
// for proper version.
warning("JDK%d is not supported in multiple version jars", version);
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -94,7 +94,7 @@
_metaspace(NULL), _unloading(false), _klasses(NULL),
_modules(NULL), _packages(NULL),
_claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL),
- _next(NULL), _dependencies(dependencies), _shared_class_loader_id(-1),
+ _next(NULL), _dependencies(dependencies),
_metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true,
Monitor::_safepoint_check_never)) {
TRACE_INIT_ID(this);
--- a/hotspot/src/share/vm/classfile/classLoaderData.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -204,9 +204,6 @@
// Support for walking class loader data objects
ClassLoaderData* _next; /// Next loader_datas created
- // CDS
- int _shared_class_loader_id;
-
// ReadOnly and ReadWrite metaspaces (static because only on the null
// class loader for now).
static Metaspace* _ro_metaspace;
@@ -338,15 +335,6 @@
Metaspace* rw_metaspace();
void initialize_shared_metaspaces();
- int shared_class_loader_id() const {
- return _shared_class_loader_id;
- }
- void set_shared_class_loader_id(int id) {
- assert(id >= 0, "sanity");
- assert(_shared_class_loader_id <0, "cannot be assigned more than once");
- _shared_class_loader_id = id;
- }
-
TRACE_DEFINE_TRACE_ID_METHODS;
};
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -163,8 +163,8 @@
Klass* k = SystemDictionary::String_klass();
compute_offset(value_offset, k, vmSymbols::value_name(), vmSymbols::byte_array_signature());
- compute_optional_offset(hash_offset, k, vmSymbols::hash_name(), vmSymbols::int_signature());
- compute_optional_offset(coder_offset, k, vmSymbols::coder_name(), vmSymbols::byte_signature());
+ compute_offset(hash_offset, k, vmSymbols::hash_name(), vmSymbols::int_signature());
+ compute_offset(coder_offset, k, vmSymbols::coder_name(), vmSymbols::byte_signature());
initialized = true;
}
@@ -3977,12 +3977,8 @@
// java.lang.String
CHECK_OFFSET("java/lang/String", java_lang_String, value, "[B");
- if (java_lang_String::has_hash_field()) {
- CHECK_OFFSET("java/lang/String", java_lang_String, hash, "I");
- }
- if (java_lang_String::has_coder_field()) {
- CHECK_OFFSET("java/lang/String", java_lang_String, coder, "B");
- }
+ CHECK_OFFSET("java/lang/String", java_lang_String, hash, "I");
+ CHECK_OFFSET("java/lang/String", java_lang_String, coder, "B");
// java.lang.Class
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -81,15 +81,6 @@
static Handle create_from_platform_dependent_str(const char* str, TRAPS);
static Handle char_converter(Handle java_string, jchar from_char, jchar to_char, TRAPS);
- static bool has_hash_field() {
- assert(initialized, "Must be initialized");
- return (hash_offset > 0);
- }
- static bool has_coder_field() {
- assert(initialized, "Must be initialized");
- return (coder_offset > 0);
- }
-
static void set_compact_strings(bool value);
static int value_offset_in_bytes() {
--- a/hotspot/src/share/vm/classfile/javaClasses.inline.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/classfile/javaClasses.inline.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -30,10 +30,8 @@
#include "oops/oopsHierarchy.hpp"
void java_lang_String::set_coder(oop string, jbyte coder) {
- assert(initialized, "Must be initialized");
- if (coder_offset > 0) {
- string->byte_field_put(coder_offset, coder);
- }
+ assert(initialized && (coder_offset > 0), "Must be initialized");
+ string->byte_field_put(coder_offset, coder);
}
void java_lang_String::set_value_raw(oop string, typeArrayOop buffer) {
@@ -61,15 +59,11 @@
return java_string->int_field(hash_offset);
}
bool java_lang_String::is_latin1(oop java_string) {
- assert(initialized, "Must be initialized");
+ assert(initialized && (coder_offset > 0), "Must be initialized");
assert(is_instance(java_string), "must be java_string");
- if (coder_offset > 0) {
- jbyte coder = java_string->byte_field(coder_offset);
- assert(CompactStrings || coder == CODER_UTF16, "Must be UTF16 without CompactStrings");
- return coder == CODER_LATIN1;
- } else {
- return false;
- }
+ jbyte coder = java_string->byte_field(coder_offset);
+ assert(CompactStrings || coder == CODER_UTF16, "Must be UTF16 without CompactStrings");
+ return coder == CODER_LATIN1;
}
int java_lang_String::length(oop java_string) {
assert(initialized, "Must be initialized");
--- a/hotspot/src/share/vm/classfile/modules.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/classfile/modules.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+* Copyright (c) 2016, 2017, 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
@@ -39,8 +39,6 @@
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "oops/instanceKlass.hpp"
-#include "oops/objArrayKlass.hpp"
-#include "oops/objArrayOop.inline.hpp"
#include "runtime/arguments.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/javaCalls.hpp"
@@ -48,17 +46,17 @@
#include "utilities/stringUtils.hpp"
#include "utilities/utf8.hpp"
-static bool verify_module_name(char *module_name) {
+static bool verify_module_name(const char *module_name) {
if (module_name == NULL) return false;
int len = (int)strlen(module_name);
return (len > 0 && len <= Symbol::max_length());
}
-bool Modules::verify_package_name(char *package_name) {
+bool Modules::verify_package_name(const char* package_name) {
if (package_name == NULL) return false;
int len = (int)strlen(package_name);
return (len > 0 && len <= Symbol::max_length() &&
- UTF8::is_legal_utf8((unsigned char *)package_name, len, false) &&
+ UTF8::is_legal_utf8((const unsigned char *)package_name, len, false) &&
ClassFileParser::verify_unqualified_name(package_name, len,
ClassFileParser::LegalClass));
}
@@ -107,10 +105,8 @@
return java_lang_reflect_Module::module_entry(module_h(), CHECK_NULL);
}
-static PackageEntry* get_package_entry(ModuleEntry* module_entry, jstring package, TRAPS) {
+static PackageEntry* get_package_entry(ModuleEntry* module_entry, const char* package_name, TRAPS) {
ResourceMark rm(THREAD);
- if (package == NULL) return NULL;
- const char *package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
if (package_name == NULL) return NULL;
TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package_name, CHECK_NULL);
PackageEntryTable* package_entry_table = module_entry->loader_data()->packages();
@@ -139,7 +135,8 @@
}
static void define_javabase_module(jobject module, jstring version,
- jstring location, jobjectArray packages, TRAPS) {
+ jstring location, const char* const* packages,
+ jsize num_packages, TRAPS) {
ResourceMark rm(THREAD);
Handle module_handle(THREAD, JNIHandles::resolve(module));
@@ -164,21 +161,12 @@
}
}
- objArrayOop packages_oop = objArrayOop(JNIHandles::resolve(packages));
- objArrayHandle packages_h(THREAD, packages_oop);
- int num_packages = (packages_h == NULL ? 0 : packages_h->length());
// Check that the list of packages has no duplicates and that the
// packages are syntactically ok.
GrowableArray<Symbol*>* pkg_list = new GrowableArray<Symbol*>(num_packages);
for (int x = 0; x < num_packages; x++) {
- oop string_obj = packages_h->obj_at(x);
-
- if (string_obj == NULL || !string_obj->is_a(SystemDictionary::String_klass())) {
- THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
- "Bad package name for module: " JAVA_BASE_NAME);
- }
- char *package_name = java_lang_String::as_utf8_string(string_obj);
+ const char *package_name = packages[x];
if (!Modules::verify_package_name(package_name)) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Invalid package name: %s for module: " JAVA_BASE_NAME, package_name));
@@ -239,7 +227,7 @@
}
}
if (duplicate_javabase) {
- THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+ THROW_MSG(vmSymbols::java_lang_InternalError(),
"Module " JAVA_BASE_NAME " is already defined");
}
@@ -262,13 +250,39 @@
}
}
+// Caller needs ResourceMark.
+void throw_dup_pkg_exception(const char* module_name, PackageEntry* package, TRAPS) {
+ const char* package_name = package->name()->as_C_string();
+ if (package->module()->is_named()) {
+ THROW_MSG(vmSymbols::java_lang_IllegalStateException(),
+ err_msg("Package %s for module %s is already in another module, %s, defined to the class loader",
+ package_name, module_name, package->module()->name()->as_C_string()));
+ } else {
+ THROW_MSG(vmSymbols::java_lang_IllegalStateException(),
+ err_msg("Package %s for module %s is already in the unnamed module defined to the class loader",
+ package_name, module_name));
+ }
+}
+
void Modules::define_module(jobject module, jstring version,
- jstring location, jobjectArray packages, TRAPS) {
+ jstring location, const char* const* packages,
+ jsize num_packages, TRAPS) {
ResourceMark rm(THREAD);
if (module == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Null module object");
}
+
+ if (num_packages < 0) {
+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+ "num_packages must be >= 0");
+ }
+
+ if (packages == NULL && num_packages > 0) {
+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+ "num_packages should be zero if packages is null");
+ }
+
Handle module_handle(THREAD, JNIHandles::resolve(module));
if (!java_lang_reflect_Module::is_instance(module_handle())) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
@@ -283,7 +297,7 @@
// Special handling of java.base definition
if (strcmp(module_name, JAVA_BASE_NAME) == 0) {
- define_javabase_module(module, version, location, packages, CHECK);
+ define_javabase_module(module, version, location, packages, num_packages, CHECK);
return;
}
@@ -297,21 +311,11 @@
}
Handle h_loader = Handle(THREAD, loader);
- objArrayOop packages_oop = objArrayOop(JNIHandles::resolve(packages));
- objArrayHandle packages_h(THREAD, packages_oop);
- int num_packages = (packages_h == NULL ? 0 : packages_h->length());
-
// Check that the list of packages has no duplicates and that the
// packages are syntactically ok.
GrowableArray<Symbol*>* pkg_list = new GrowableArray<Symbol*>(num_packages);
for (int x = 0; x < num_packages; x++) {
- oop string_obj = packages_h->obj_at(x);
-
- if (string_obj == NULL || !string_obj->is_a(SystemDictionary::String_klass())) {
- THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
- err_msg("Bad package name for module: %s", module_name));
- }
- char *package_name = java_lang_String::as_utf8_string(string_obj);
+ const char* package_name = packages[x];
if (!verify_package_name(package_name)) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Invalid package name: %s for module: %s",
@@ -323,12 +327,15 @@
!SystemDictionary::is_platform_class_loader(h_loader) &&
strncmp(package_name, JAVAPKG, JAVAPKG_LEN) == 0) {
const char* class_loader_name = SystemDictionary::loader_name(h_loader());
- StringUtils::replace_no_expand(package_name, "/", ".");
+ size_t pkg_len = strlen(package_name);
+ char* pkg_name = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, pkg_len);
+ strncpy(pkg_name, package_name, pkg_len);
+ StringUtils::replace_no_expand(pkg_name, "/", ".");
const char* msg_text1 = "Class loader (instance of): ";
const char* msg_text2 = " tried to define prohibited package name: ";
- size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + strlen(package_name) + 1;
+ size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + pkg_len + 1;
char* message = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, len);
- jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, package_name);
+ jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, pkg_name);
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), message);
}
@@ -347,7 +354,6 @@
// Create symbol* entry for module name.
TempNewSymbol module_symbol = SymbolTable::new_symbol(module_name, CHECK);
- int dupl_pkg_index = -1;
bool dupl_modules = false;
// Create symbol* entry for module version.
@@ -373,6 +379,7 @@
assert(loader_data != NULL, "class loader data shouldn't be null");
PackageEntryTable* package_table = NULL;
+ PackageEntry* existing_pkg = NULL;
{
MutexLocker ml(Module_lock, THREAD);
@@ -382,13 +389,12 @@
// Check that none of the packages exist in the class loader's package table.
for (int x = 0; x < pkg_list->length(); x++) {
- if (package_table->lookup_only(pkg_list->at(x)) != NULL) {
+ existing_pkg = package_table->lookup_only(pkg_list->at(x));
+ if (existing_pkg != NULL) {
// This could be because the module was already defined. If so,
// report that error instead of the package error.
if (module_table->lookup_only(module_symbol) != NULL) {
dupl_modules = true;
- } else {
- dupl_pkg_index = x;
}
break;
}
@@ -396,9 +402,8 @@
} // if (num_packages > 0)...
// Add the module and its packages.
- if (!dupl_modules && dupl_pkg_index == -1) {
+ if (!dupl_modules && existing_pkg == NULL) {
// Create the entry for this module in the class loader's module entry table.
-
ModuleEntry* module_entry = module_table->locked_create_entry_or_null(module_handle, module_symbol,
version_symbol, location_symbol, loader_data);
@@ -426,13 +431,10 @@
// any errors ?
if (dupl_modules) {
- THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+ THROW_MSG(vmSymbols::java_lang_IllegalStateException(),
err_msg("Module %s is already defined", module_name));
- }
- if (dupl_pkg_index != -1) {
- THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
- err_msg("Package %s for module %s already exists for class loader",
- pkg_list->at(dupl_pkg_index)->as_C_string(), module_name));
+ } else if (existing_pkg != NULL) {
+ throw_dup_pkg_exception(module_name, existing_pkg, CHECK);
}
if (log_is_enabled(Debug, modules)) {
@@ -497,8 +499,8 @@
java_lang_reflect_Module::set_module_entry(module_handle(), unnamed_module);
}
-void Modules::add_module_exports(jobject from_module, jstring package, jobject to_module, TRAPS) {
- if (package == NULL) {
+void Modules::add_module_exports(jobject from_module, const char* package_name, jobject to_module, TRAPS) {
+ if (package_name == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"package is null");
}
@@ -526,10 +528,9 @@
}
}
- PackageEntry *package_entry = get_package_entry(from_module_entry, package, CHECK);
+ PackageEntry *package_entry = get_package_entry(from_module_entry, package_name, CHECK);
ResourceMark rm(THREAD);
if (package_entry == NULL) {
- const char *package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Package %s not found in from_module %s",
package_name != NULL ? package_name : "",
@@ -557,7 +558,7 @@
}
-void Modules::add_module_exports_qualified(jobject from_module, jstring package,
+void Modules::add_module_exports_qualified(jobject from_module, const char* package,
jobject to_module, TRAPS) {
if (to_module == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
@@ -649,21 +650,15 @@
}
-jobject Modules::get_module_by_package_name(jobject loader, jstring package, TRAPS) {
+jobject Modules::get_module_by_package_name(jobject loader, const char* package_name, TRAPS) {
ResourceMark rm(THREAD);
assert(ModuleEntryTable::javabase_defined(),
"Attempt to call get_module_from_pkg before " JAVA_BASE_NAME " is defined");
- if (NULL == package) {
+ if (package_name == NULL) {
THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
"package is null", JNI_FALSE);
}
- const char* package_str =
- java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
- if (NULL == package_str) {
- THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
- "Invalid package", JNI_FALSE);
- }
Handle h_loader (THREAD, JNIHandles::resolve(loader));
// Check that loader is a subclass of java.lang.ClassLoader.
@@ -672,7 +667,7 @@
"Class loader is not a subclass of java.lang.ClassLoader", JNI_FALSE);
}
- if (strlen(package_str) == 0) {
+ if (strlen(package_name) == 0) {
// Return the unnamed module
ModuleEntryTable* module_table = get_module_entry_table(h_loader, CHECK_NULL);
if (NULL == module_table) return NULL;
@@ -680,24 +675,24 @@
return JNIHandles::make_local(THREAD, JNIHandles::resolve(unnamed_module->module()));
} else {
- TempNewSymbol package_sym = SymbolTable::new_symbol(package_str, CHECK_NULL);
+ TempNewSymbol package_sym = SymbolTable::new_symbol(package_name, CHECK_NULL);
return get_module(package_sym, h_loader, CHECK_NULL);
}
return NULL;
}
-jobject Modules::get_named_module(Handle h_loader, const char* package_str, TRAPS) {
+jobject Modules::get_named_module(Handle h_loader, const char* package_name, TRAPS) {
assert(ModuleEntryTable::javabase_defined(),
"Attempt to call get_named_module before " JAVA_BASE_NAME " is defined");
assert(h_loader.is_null() || java_lang_ClassLoader::is_subclass(h_loader->klass()),
"Class loader is not a subclass of java.lang.ClassLoader");
- assert(package_str != NULL, "the package_str should not be NULL");
+ assert(package_name != NULL, "the package_name should not be NULL");
- if (strlen(package_str) == 0) {
+ if (strlen(package_name) == 0) {
return NULL;
}
- TempNewSymbol package_sym = SymbolTable::new_symbol(package_str, CHECK_NULL);
+ TempNewSymbol package_sym = SymbolTable::new_symbol(package_name, CHECK_NULL);
const PackageEntry* const pkg_entry =
get_package_entry_by_name(package_sym, h_loader, THREAD);
const ModuleEntry* const module_entry = (pkg_entry != NULL ? pkg_entry->module() : NULL);
@@ -723,14 +718,14 @@
return NULL;
}
-void Modules::add_module_package(jobject module, jstring package, TRAPS) {
+void Modules::add_module_package(jobject module, const char* package_name, TRAPS) {
ResourceMark rm(THREAD);
if (module == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"module is null");
}
- if (package == NULL) {
+ if (package_name == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"package is null");
}
@@ -743,11 +738,6 @@
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"module cannot be an unnamed module");
}
- char *package_name = java_lang_String::as_utf8_string(
- JNIHandles::resolve_non_null(package));
- if (package_name == NULL) {
- THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Bad package");
- }
if (!verify_package_name(package_name)) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Invalid package name: %s", package_name));
@@ -760,12 +750,15 @@
!loader_data->is_platform_class_loader_data() &&
strncmp(package_name, JAVAPKG, JAVAPKG_LEN) == 0) {
const char* class_loader_name = SystemDictionary::loader_name(loader_data);
- StringUtils::replace_no_expand(package_name, "/", ".");
+ size_t pkg_len = strlen(package_name);
+ char* pkg_name = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, pkg_len);
+ strncpy(pkg_name, package_name, pkg_len);
+ StringUtils::replace_no_expand(pkg_name, "/", ".");
const char* msg_text1 = "Class loader (instance of): ";
const char* msg_text2 = " tried to define prohibited package name: ";
- size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + strlen(package_name) + 1;
+ size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + pkg_len + 1;
char* message = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, len);
- jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, package_name);
+ jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, pkg_name);
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), message);
}
@@ -776,31 +769,29 @@
PackageEntryTable* package_table = loader_data->packages();
assert(package_table != NULL, "Missing package_table");
- bool pkg_exists = false;
+ PackageEntry* existing_pkg = NULL;
{
MutexLocker ml(Module_lock, THREAD);
// Check that the package does not exist in the class loader's package table.
- if (!package_table->lookup_only(pkg_symbol)) {
+ existing_pkg = package_table->lookup_only(pkg_symbol);
+ if (existing_pkg == NULL) {
PackageEntry* pkg = package_table->locked_create_entry_or_null(pkg_symbol, module_entry);
assert(pkg != NULL, "Unable to create a module's package entry");
- } else {
- pkg_exists = true;
}
}
- if (pkg_exists) {
- THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
- err_msg("Package %s already exists for class loader", package_name));
+ if (existing_pkg != NULL) {
+ throw_dup_pkg_exception(module_entry->name()->as_C_string(), existing_pkg, CHECK);
}
}
// Export package in module to all unnamed modules.
-void Modules::add_module_exports_to_all_unnamed(jobject module, jstring package, TRAPS) {
+void Modules::add_module_exports_to_all_unnamed(jobject module, const char* package_name, TRAPS) {
if (module == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"module is null");
}
- if (package == NULL) {
+ if (package_name == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"package is null");
}
@@ -811,10 +802,9 @@
}
if (module_entry->is_named()) { // No-op for unnamed module.
- PackageEntry *package_entry = get_package_entry(module_entry, package, CHECK);
+ PackageEntry *package_entry = get_package_entry(module_entry, package_name, CHECK);
ResourceMark rm(THREAD);
if (package_entry == NULL) {
- const char *package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Package %s not found in module %s",
package_name != NULL ? package_name : "",
@@ -833,10 +823,7 @@
package_entry->name()->as_C_string(),
module_entry->name()->as_C_string());
- // Mark package as exported to all unnamed modules, unless already
- // unqualifiedly exported.
- if (!package_entry->is_unqual_exported()) {
- package_entry->set_is_exported_allUnnamed();
- }
+ // Mark package as exported to all unnamed modules.
+ package_entry->set_is_exported_allUnnamed();
}
}
--- a/hotspot/src/share/vm/classfile/modules.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/classfile/modules.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -48,9 +48,12 @@
// * Packages contains a duplicate package name
// * A package already exists in another module for this class loader
// * Module is an unnamed module
+ // * num_packages is negative
+ // * num_packages is non-zero when packages is null
// NullPointerExceptions are thrown if module is null.
static void define_module(jobject module, jstring version,
- jstring location, jobjectArray packages, TRAPS);
+ jstring location, const char* const* packages,
+ jsize num_packages, TRAPS);
// Provides the java.lang.reflect.Module for the unnamed module defined
// to the boot loader.
@@ -72,7 +75,7 @@
// * Package is not syntactically correct
// * Package is not defined for from_module's class loader
// * Package is not in module from_module.
- static void add_module_exports(jobject from_module, jstring package, jobject to_module, TRAPS);
+ static void add_module_exports(jobject from_module, const char* package, jobject to_module, TRAPS);
// This does a qualified export of package in module from_module to module
// to_module. The format for the package name must use "/' not ".".
@@ -83,7 +86,7 @@
// * Package is not syntactically correct
// * Package is not defined for from_module's class loader
// * Package is not in module from_module.
- static void add_module_exports_qualified(jobject from_module, jstring package, jobject to_module, TRAPS);
+ static void add_module_exports_qualified(jobject from_module, const char* package, jobject to_module, TRAPS);
// add_reads_module adds module to_module to the list of modules that from_module
// can read. If from_module is the same as to_module then this is a no-op.
@@ -102,7 +105,7 @@
// NullPointerException is thrown if package is null.
// IllegalArgumentException is thrown if loader is neither null nor a subtype of
// java/lang/ClassLoader.
- static jobject get_module_by_package_name(jobject loader, jstring package, TRAPS);
+ static jobject get_module_by_package_name(jobject loader, const char* package, TRAPS);
static jobject get_named_module(Handle h_loader, const char* package, TRAPS);
// If package is defined by loader, return the
@@ -116,16 +119,16 @@
// * Module is unnamed
// * Package is not syntactically correct
// * Package is already defined for module's class loader.
- static void add_module_package(jobject module, jstring package, TRAPS);
+ static void add_module_package(jobject module, const char* package, TRAPS);
// Marks the specified package as exported to all unnamed modules.
// If either module or package is null then NullPointerException is thrown.
// If module or package is bad, or module is unnamed, or package is not in
// module then IllegalArgumentException is thrown.
- static void add_module_exports_to_all_unnamed(jobject module, jstring package, TRAPS);
+ static void add_module_exports_to_all_unnamed(jobject module, const char* package, TRAPS);
// Return TRUE if package_name is syntactically valid, false otherwise.
- static bool verify_package_name(char *package_name);
+ static bool verify_package_name(const char *package_name);
// Return TRUE iff package is defined by loader
static bool is_package_defined(Symbol* package_name, Handle h_loader, TRAPS);
--- a/hotspot/src/share/vm/classfile/packageEntry.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/classfile/packageEntry.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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,8 +37,8 @@
// Returns true if this package specifies m as a qualified export, including through an unnamed export
bool PackageEntry::is_qexported_to(ModuleEntry* m) const {
+ assert(Module_lock->owned_by_self(), "should have the Module_lock");
assert(m != NULL, "No module to lookup in this package's qualified exports list");
- MutexLocker m1(Module_lock);
if (is_exported_allUnnamed() && !m->is_named()) {
return true;
} else if (!has_qual_exports_list()) {
@@ -98,15 +98,8 @@
}
if (m == NULL) {
- // NULL indicates the package is being unqualifiedly exported
- if (has_qual_exports_list()) {
- // Legit to transition a package from being qualifiedly exported
- // to unqualified. Clean up the qualified lists at the next
- // safepoint.
- _exported_pending_delete = _qualified_exports;
- }
-
- // Mark package as unqualifiedly exported
+ // NULL indicates the package is being unqualifiedly exported. Clean up
+ // the qualified list at the next safepoint.
set_unqual_exported();
} else {
@@ -115,14 +108,19 @@
}
}
+// Set the package as exported to all unnamed modules unless the package is
+// already unqualifiedly exported.
void PackageEntry::set_is_exported_allUnnamed() {
MutexLocker m1(Module_lock);
if (!is_unqual_exported()) {
- _is_exported_allUnnamed = true;
+ _export_flags = PKG_EXP_ALLUNNAMED;
}
}
-// Remove dead module entries within the package's exported list.
+// Remove dead module entries within the package's exported list. Note that
+// if all of the modules on the _qualified_exports get purged the list does not
+// get deleted. This prevents the package from illegally transitioning from
+// exported to non-exported.
void PackageEntry::purge_qualified_exports() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
if (_must_walk_exports &&
@@ -160,18 +158,9 @@
void PackageEntry::delete_qualified_exports() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
- if (_exported_pending_delete != NULL) {
- // If a transition occurred from qualified to unqualified, the _qualified_exports
- // field should have been NULL'ed out.
- assert(_qualified_exports == NULL, "Package's exported pending delete, exported list should not be active");
- delete _exported_pending_delete;
- }
-
if (_qualified_exports != NULL) {
delete _qualified_exports;
}
-
- _exported_pending_delete = NULL;
_qualified_exports = NULL;
}
@@ -314,6 +303,11 @@
}
}
+bool PackageEntry::exported_pending_delete() const {
+ assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+ return (is_unqual_exported() && _qualified_exports != NULL);
+}
+
// Remove dead entries from all packages' exported list
void PackageEntryTable::purge_all_package_exports() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
@@ -344,13 +338,17 @@
}
}
+// This function may be called from debuggers so access private fields directly
+// to prevent triggering locking-related asserts that could result from calling
+// getter methods.
void PackageEntry::print(outputStream* st) {
ResourceMark rm;
st->print_cr("package entry " PTR_FORMAT " name %s module %s classpath_index "
INT32_FORMAT " is_exported_unqualified %d is_exported_allUnnamed %d " "next " PTR_FORMAT,
p2i(this), name()->as_C_string(),
(module()->is_named() ? module()->name()->as_C_string() : UNNAMED_MODULE),
- _classpath_index, _is_exported_unqualified, _is_exported_allUnnamed, p2i(next()));
+ _classpath_index, _export_flags == PKG_EXP_UNQUALIFIED,
+ _export_flags == PKG_EXP_ALLUNNAMED, p2i(next()));
}
void PackageEntryTable::verify() {
--- a/hotspot/src/share/vm/classfile/packageEntry.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/classfile/packageEntry.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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,8 @@
// A PackageEntry basically represents a Java package. It contains:
// - Symbol* containing the package's name.
// - ModuleEntry* for this package's containing module.
-// - a flag indicating if package is exported unqualifiedly
-// - a flag indicating if this package is exported to all unnamed modules.
+// - a field indicating if the package is exported unqualifiedly or to all
+// unnamed modules.
// - a growable array containing other module entries that this
// package is exported to.
//
@@ -44,9 +44,9 @@
// - qualified exports: the package has been explicitly qualified to at least
// one particular module or has been qualifiedly exported
// to all unnamed modules.
-// Note: _is_exported_allUnnamed is a form of a qualified
-// export. It is equivalent to the package being
-// explicitly exported to all current and future unnamed modules.
+// Note: being exported to all unnamed is a form of a qualified
+// export. It is equivalent to the package being explicitly
+// exported to all current and future unnamed modules.
// - unqualified exports: the package is exported to all modules.
//
// A package can transition from:
@@ -56,21 +56,53 @@
// A package cannot transition from:
// - being unqualifiedly exported, to exported qualifiedly to a specific module.
// This transition attempt is silently ignored in set_exported.
+// - being qualifiedly exported to not exported.
+// Because transitions are only allowed from less exposure to greater exposure,
+// the transition from qualifiedly exported to not exported would be considered
+// a backward direction. Therefore the implementation considers a package as
+// qualifiedly exported even if its export-list exists but is empty.
//
// The Mutex Module_lock is shared between ModuleEntry and PackageEntry, to lock either
// data structure.
+
+// PKG_EXP_UNQUALIFIED and PKG_EXP_ALLUNNAMED indicate whether the package is
+// exported unqualifiedly or exported to all unnamed modules. They are used to
+// set the value of _export_flags. Field _export_flags and the _qualified_exports
+// list are used to determine a package's export state.
+// Valid states are:
+//
+// 1. Package is not exported
+// _export_flags is zero and _qualified_exports is null
+// 2. Package is unqualifiedly exported
+// _export_flags is set to PKG_EXP_UNQUALIFIED
+// _qualified_exports may or may not be null depending on whether the package
+// transitioned from qualifiedly exported to unqualifiedly exported.
+// 3. Package is qualifiedly exported
+// _export_flags may be set to PKG_EXP_ALLUNNAMED if the package is also
+// exported to all unnamed modules
+// _qualified_exports will be non-null
+// 4. Package is exported to all unnamed modules
+// _export_flags is set to PKG_EXP_ALLUNNAMED
+// _qualified_exports may or may not be null depending on whether the package
+// is also qualifiedly exported to one or more named modules.
+#define PKG_EXP_UNQUALIFIED 0x0001
+#define PKG_EXP_ALLUNNAMED 0x0002
+#define PKG_EXP_UNQUALIFIED_OR_ALL_UNAMED (PKG_EXP_UNQUALIFIED | PKG_EXP_ALLUNNAMED)
+
class PackageEntry : public HashtableEntry<Symbol*, mtModule> {
private:
ModuleEntry* _module;
+ // Indicates if package is exported unqualifiedly or to all unnamed. Access to
+ // this field is protected by the Module_lock.
+ int _export_flags;
// Used to indicate for packages with classes loaded by the boot loader that
// a class in that package has been loaded. And, for packages with classes
// loaded by the boot loader from -Xbootclasspath/a in an unnamed module, it
// indicates from which class path entry.
s2 _classpath_index;
- bool _is_exported_unqualified;
- bool _is_exported_allUnnamed;
bool _must_walk_exports;
- GrowableArray<ModuleEntry*>* _exported_pending_delete; // transitioned from qualified to unqualified, delete at safepoint
+ // Contains list of modules this package is qualifiedly exported to. Access
+ // to this list is protected by the Module_lock.
GrowableArray<ModuleEntry*>* _qualified_exports;
TRACE_DEFINE_TRACE_ID_FIELD;
@@ -80,17 +112,14 @@
public:
void init() {
_module = NULL;
+ _export_flags = 0;
_classpath_index = -1;
- _is_exported_unqualified = false;
- _is_exported_allUnnamed = false;
_must_walk_exports = false;
- _exported_pending_delete = NULL;
_qualified_exports = NULL;
}
// package name
Symbol* name() const { return literal(); }
- void set_name(Symbol* n) { set_literal(n); }
// the module containing the package definition
ModuleEntry* module() const { return _module; }
@@ -98,37 +127,39 @@
// package's export state
bool is_exported() const { // qualifiedly or unqualifiedly exported
- return (is_unqual_exported() || has_qual_exports_list() || is_exported_allUnnamed());
+ assert_locked_or_safepoint(Module_lock);
+ return ((_export_flags & PKG_EXP_UNQUALIFIED_OR_ALL_UNAMED) != 0) || has_qual_exports_list();
}
// Returns true if the package has any explicit qualified exports or is exported to all unnamed
bool is_qual_exported() const {
+ assert_locked_or_safepoint(Module_lock);
return (has_qual_exports_list() || is_exported_allUnnamed());
}
- // Returns true if there are any explicit qualified exports
+ // Returns true if there are any explicit qualified exports. Note that even
+ // if the _qualified_exports list is now empty (because the modules that were
+ // on the list got gc-ed and deleted from the list) this method may still
+ // return true.
bool has_qual_exports_list() const {
- assert(!(_qualified_exports != NULL && _is_exported_unqualified),
- "_qualified_exports set at same time as _is_exported_unqualified");
- return (_qualified_exports != NULL);
+ assert_locked_or_safepoint(Module_lock);
+ return (!is_unqual_exported() && _qualified_exports != NULL);
}
bool is_exported_allUnnamed() const {
- assert(!(_is_exported_allUnnamed && _is_exported_unqualified),
- "_is_exported_allUnnamed set at same time as _is_exported_unqualified");
- return _is_exported_allUnnamed;
+ assert_locked_or_safepoint(Module_lock);
+ return (_export_flags == PKG_EXP_ALLUNNAMED);
}
bool is_unqual_exported() const {
- assert(!(_qualified_exports != NULL && _is_exported_unqualified),
- "_qualified_exports set at same time as _is_exported_unqualified");
- assert(!(_is_exported_allUnnamed && _is_exported_unqualified),
- "_is_exported_allUnnamed set at same time as _is_exported_unqualified");
- return _is_exported_unqualified;
+ assert_locked_or_safepoint(Module_lock);
+ return (_export_flags == PKG_EXP_UNQUALIFIED);
}
+
+ // Explicitly set _export_flags to PKG_EXP_UNQUALIFIED and clear
+ // PKG_EXP_ALLUNNAMED, if it was set.
void set_unqual_exported() {
assert(Module_lock->owned_by_self(), "should have the Module_lock");
- _is_exported_unqualified = true;
- _is_exported_allUnnamed = false;
- _qualified_exports = NULL;
+ _export_flags = PKG_EXP_UNQUALIFIED;
}
- bool exported_pending_delete() const { return (_exported_pending_delete != NULL); }
+
+ bool exported_pending_delete() const;
void set_exported(ModuleEntry* m);
--- a/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -29,7 +29,6 @@
#include "classfile/dictionary.hpp"
class ClassFileStream;
-class SerializeClosure;
class SystemDictionaryShared: public SystemDictionary {
public:
@@ -79,8 +78,6 @@
return NULL;
}
- static void serialize(SerializeClosure* soc) {}
-
// The (non-application) CDS implementation supports only classes in the boot
// class loader, which ensures that the verification constraints are the same
// during archive creation time and runtime. Thus we can do the constraint checks
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -590,11 +590,11 @@
template(java_lang_management_ThreadState, "java/lang/management/ThreadState") \
template(java_lang_management_MemoryUsage, "java/lang/management/MemoryUsage") \
template(java_lang_management_ThreadInfo, "java/lang/management/ThreadInfo") \
+ template(jdk_internal_agent_Agent, "jdk/internal/agent/Agent") \
template(sun_management_Sensor, "sun/management/Sensor") \
- template(sun_management_Agent, "sun/management/Agent") \
+ template(sun_management_ManagementFactoryHelper, "sun/management/ManagementFactoryHelper") \
template(com_sun_management_internal_DiagnosticCommandImpl, "com/sun/management/internal/DiagnosticCommandImpl") \
template(com_sun_management_internal_GarbageCollectorExtImpl,"com/sun/management/internal/GarbageCollectorExtImpl") \
- template(sun_management_ManagementFactoryHelper, "sun/management/ManagementFactoryHelper") \
template(getDiagnosticCommandMBean_name, "getDiagnosticCommandMBean") \
template(getDiagnosticCommandMBean_signature, "()Lcom/sun/management/DiagnosticCommandMBean;") \
template(getGcInfoBuilder_name, "getGcInfoBuilder") \
--- a/hotspot/src/share/vm/code/codeCache.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/code/codeCache.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -149,16 +149,17 @@
size_t total_size = non_nmethod_size + profiled_size + non_profiled_size;
// Prepare error message
const char* error = "Invalid code heap sizes";
- err_msg message("NonNMethodCodeHeapSize (%zuK) + ProfiledCodeHeapSize (%zuK) + NonProfiledCodeHeapSize (%zuK) = %zuK",
+ err_msg message("NonNMethodCodeHeapSize (" SIZE_FORMAT "K) + ProfiledCodeHeapSize (" SIZE_FORMAT "K)"
+ " + NonProfiledCodeHeapSize (" SIZE_FORMAT "K) = " SIZE_FORMAT "K",
non_nmethod_size/K, profiled_size/K, non_profiled_size/K, total_size/K);
if (total_size > cache_size) {
// Some code heap sizes were explicitly set: total_size must be <= cache_size
- message.append(" is greater than ReservedCodeCacheSize (%zuK).", cache_size/K);
+ message.append(" is greater than ReservedCodeCacheSize (" SIZE_FORMAT "K).", cache_size/K);
vm_exit_during_initialization(error, message);
} else if (all_set && total_size != cache_size) {
// All code heap sizes were explicitly set: total_size must equal cache_size
- message.append(" is not equal to ReservedCodeCacheSize (%zuK).", cache_size/K);
+ message.append(" is not equal to ReservedCodeCacheSize (" SIZE_FORMAT "K).", cache_size/K);
vm_exit_during_initialization(error, message);
}
}
@@ -267,7 +268,7 @@
uint min_code_cache_size = CodeCacheMinimumUseSpace DEBUG_ONLY(* 3);
if (non_nmethod_size < (min_code_cache_size + code_buffers_size)) {
vm_exit_during_initialization(err_msg(
- "Not enough space in non-nmethod code heap to run VM: %zuK < %zuK",
+ "Not enough space in non-nmethod code heap to run VM: " SIZE_FORMAT "K < " SIZE_FORMAT "K",
non_nmethod_size/K, (min_code_cache_size + code_buffers_size)/K));
}
--- a/hotspot/src/share/vm/code/compiledMethod.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/code/compiledMethod.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -250,7 +250,11 @@
address insts_begin() const { return code_begin(); }
address insts_end() const { return stub_begin(); }
+ // Returns true if a given address is in the 'insts' section. The method
+ // insts_contains_inclusive() is end-inclusive.
bool insts_contains(address addr) const { return insts_begin() <= addr && addr < insts_end(); }
+ bool insts_contains_inclusive(address addr) const { return insts_begin() <= addr && addr <= insts_end(); }
+
int insts_size() const { return insts_end() - insts_begin(); }
virtual address consts_begin() const = 0;
--- a/hotspot/src/share/vm/compiler/compilerDefinitions.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/compiler/compilerDefinitions.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -23,6 +23,8 @@
*/
#include "precompiled.hpp"
+#include "runtime/globals.hpp"
+#include "runtime/globals_extension.hpp"
#include "compiler/compilerDefinitions.hpp"
const char* compilertype2name_tab[compiler_number_of_types] = {
@@ -32,3 +34,82 @@
"jvmci",
"shark"
};
+
+#if defined(COMPILER2) || defined(SHARK)
+CompLevel CompLevel_highest_tier = CompLevel_full_optimization; // pure C2 and tiered or JVMCI and tiered
+#elif defined(COMPILER1)
+CompLevel CompLevel_highest_tier = CompLevel_simple; // pure C1 or JVMCI
+#else
+CompLevel CompLevel_highest_tier = CompLevel_none;
+#endif
+
+#if defined(TIERED)
+CompLevel CompLevel_initial_compile = CompLevel_full_profile; // tiered
+#elif defined(COMPILER1) || INCLUDE_JVMCI
+CompLevel CompLevel_initial_compile = CompLevel_simple; // pure C1 or JVMCI
+#elif defined(COMPILER2) || defined(SHARK)
+CompLevel CompLevel_initial_compile = CompLevel_full_optimization; // pure C2
+#else
+CompLevel CompLevel_initial_compile = CompLevel_none;
+#endif
+
+#if defined(COMPILER2)
+CompMode Compilation_mode = CompMode_server;
+#elif defined(COMPILER1)
+CompMode Compilation_mode = CompMode_client;
+#else
+CompMode Compilation_mode = CompMode_none;
+#endif
+
+#ifdef TIERED
+void set_client_compilation_mode() {
+ Compilation_mode = CompMode_client;
+ CompLevel_highest_tier = CompLevel_simple;
+ CompLevel_initial_compile = CompLevel_simple;
+ FLAG_SET_ERGO(bool, TieredCompilation, false);
+ FLAG_SET_ERGO(bool, ProfileInterpreter, false);
+#if INCLUDE_JVMCI
+ FLAG_SET_ERGO(bool, EnableJVMCI, false);
+ FLAG_SET_ERGO(bool, UseJVMCICompiler, false);
+#endif
+#if INCLUDE_AOT
+ FLAG_SET_ERGO(bool, UseAOT, false);
+#endif
+ if (FLAG_IS_DEFAULT(NeverActAsServerClassMachine)) {
+ FLAG_SET_ERGO(bool, NeverActAsServerClassMachine, true);
+ }
+ if (FLAG_IS_DEFAULT(InitialCodeCacheSize)) {
+ FLAG_SET_ERGO(uintx, InitialCodeCacheSize, 160*K);
+ }
+ if (FLAG_IS_DEFAULT(ReservedCodeCacheSize)) {
+ FLAG_SET_ERGO(uintx, ReservedCodeCacheSize, 32*M);
+ }
+ if (FLAG_IS_DEFAULT(NonProfiledCodeHeapSize)) {
+ FLAG_SET_ERGO(uintx, NonProfiledCodeHeapSize, 27*M);
+ }
+ if (FLAG_IS_DEFAULT(ProfiledCodeHeapSize)) {
+ FLAG_SET_ERGO(uintx, ProfiledCodeHeapSize, 0);
+ }
+ if (FLAG_IS_DEFAULT(NonNMethodCodeHeapSize)) {
+ FLAG_SET_ERGO(uintx, NonNMethodCodeHeapSize, 5*M);
+ }
+ if (FLAG_IS_DEFAULT(CodeCacheExpansionSize)) {
+ FLAG_SET_ERGO(uintx, CodeCacheExpansionSize, 32*K);
+ }
+ if (FLAG_IS_DEFAULT(MetaspaceSize)) {
+ FLAG_SET_ERGO(size_t, MetaspaceSize, 12*M);
+ }
+ if (FLAG_IS_DEFAULT(MaxRAM)) {
+ FLAG_SET_ERGO(uint64_t, MaxRAM, 1ULL*G);
+ }
+ if (FLAG_IS_DEFAULT(CompileThreshold)) {
+ FLAG_SET_ERGO(intx, CompileThreshold, 1500);
+ }
+ if (FLAG_IS_DEFAULT(OnStackReplacePercentage)) {
+ FLAG_SET_ERGO(intx, OnStackReplacePercentage, 933);
+ }
+ if (FLAG_IS_DEFAULT(CICompilerCount)) {
+ FLAG_SET_ERGO(intx, CICompilerCount, 1);
+ }
+}
+#endif // TIERED
--- a/hotspot/src/share/vm/compiler/compilerDefinitions.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/compiler/compilerDefinitions.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -54,26 +54,29 @@
CompLevel_simple = 1, // C1
CompLevel_limited_profile = 2, // C1, invocation & backedge counters
CompLevel_full_profile = 3, // C1, invocation & backedge counters + mdo
- CompLevel_full_optimization = 4, // C2, Shark or JVMCI
+ CompLevel_full_optimization = 4 // C2, Shark or JVMCI
+};
+
+extern CompLevel CompLevel_highest_tier;
+extern CompLevel CompLevel_initial_compile;
-#if defined(COMPILER2) || defined(SHARK)
- CompLevel_highest_tier = CompLevel_full_optimization, // pure C2 and tiered or JVMCI and tiered
-#elif defined(COMPILER1)
- CompLevel_highest_tier = CompLevel_simple, // pure C1 or JVMCI
-#else
- CompLevel_highest_tier = CompLevel_none,
-#endif
+enum CompMode {
+ CompMode_none = 0,
+ CompMode_client = 1,
+ CompMode_server = 2
+};
-#if defined(TIERED)
- CompLevel_initial_compile = CompLevel_full_profile // tiered
-#elif defined(COMPILER1) || INCLUDE_JVMCI
- CompLevel_initial_compile = CompLevel_simple // pure C1 or JVMCI
-#elif defined(COMPILER2) || defined(SHARK)
- CompLevel_initial_compile = CompLevel_full_optimization // pure C2
-#else
- CompLevel_initial_compile = CompLevel_none
-#endif
-};
+extern CompMode Compilation_mode;
+
+inline bool is_server_compilation_mode_vm() {
+ return Compilation_mode == CompMode_server;
+}
+
+inline bool is_client_compilation_mode_vm() {
+ return Compilation_mode == CompMode_client;
+}
+
+extern void set_client_compilation_mode();
inline bool is_c1_compile(int comp_level) {
return comp_level > CompLevel_none && comp_level < CompLevel_full_optimization;
--- a/hotspot/src/share/vm/compiler/compilerDirectives.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/compiler/compilerDirectives.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -445,7 +445,9 @@
_default_directives->_c1_store->EnableOption = true;
#endif
#ifdef COMPILER2
- _default_directives->_c2_store->EnableOption = true;
+ if (is_server_compilation_mode_vm()) {
+ _default_directives->_c2_store->EnableOption = true;
+ }
#endif
assert(error_msg == NULL, "Must succeed.");
push(_default_directives);
--- a/hotspot/src/share/vm/compiler/compilerDirectives.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/compiler/compilerDirectives.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -60,13 +60,12 @@
cflags(BlockLayoutByFrequency, bool, BlockLayoutByFrequency, BlockLayoutByFrequency) \
cflags(PrintOptoAssembly, bool, PrintOptoAssembly, PrintOptoAssembly) \
cflags(PrintIntrinsics, bool, PrintIntrinsics, PrintIntrinsics) \
- cflags(TraceOptoPipelining, bool, false, TraceOptoPipelining) \
- cflags(TraceOptoOutput, bool, false, TraceOptoOutput) \
+NOT_PRODUCT(cflags(TraceOptoPipelining, bool, TraceOptoPipelining, TraceOptoPipelining)) \
+NOT_PRODUCT(cflags(TraceOptoOutput, bool, TraceOptoOutput, TraceOptoOutput)) \
cflags(TraceSpilling, bool, TraceSpilling, TraceSpilling) \
cflags(Vectorize, bool, false, Vectorize) \
cflags(VectorizeDebug, uintx, 0, VectorizeDebug) \
cflags(CloneMapDebug, bool, false, CloneMapDebug) \
- cflags(DoReserveCopyInSuperWordDebug, bool, false, DoReserveCopyInSuperWordDebug) \
cflags(IGVPrintLevel, intx, PrintIdealGraphLevel, IGVPrintLevel) \
cflags(MaxNodeLimit, intx, MaxNodeLimit, MaxNodeLimit)
#else
--- a/hotspot/src/share/vm/gc/g1/g1BiasedArray.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/gc/g1/g1BiasedArray.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -69,12 +69,12 @@
void initialize(HeapWord* bottom, HeapWord* end, size_t target_elem_size_in_bytes, size_t mapping_granularity_in_bytes) {
assert(mapping_granularity_in_bytes > 0, "just checking");
assert(is_power_of_2(mapping_granularity_in_bytes),
- "mapping granularity must be power of 2, is %zd", mapping_granularity_in_bytes);
+ "mapping granularity must be power of 2, is " SIZE_FORMAT, mapping_granularity_in_bytes);
assert((uintptr_t)bottom % mapping_granularity_in_bytes == 0,
- "bottom mapping area address must be a multiple of mapping granularity %zd, is " PTR_FORMAT,
+ "bottom mapping area address must be a multiple of mapping granularity " SIZE_FORMAT ", is " PTR_FORMAT,
mapping_granularity_in_bytes, p2i(bottom));
assert((uintptr_t)end % mapping_granularity_in_bytes == 0,
- "end mapping area address must be a multiple of mapping granularity %zd, is " PTR_FORMAT,
+ "end mapping area address must be a multiple of mapping granularity " SIZE_FORMAT ", is " PTR_FORMAT,
mapping_granularity_in_bytes, p2i(end));
size_t num_target_elems = pointer_delta(end, bottom, mapping_granularity_in_bytes);
idx_t bias = (uintptr_t)bottom / mapping_granularity_in_bytes;
--- a/hotspot/src/share/vm/gc/shared/collectedHeap.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/gc/shared/collectedHeap.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -233,7 +233,7 @@
// Used for ReduceInitialCardMarks (when COMPILER2 is used);
// otherwise remains unused.
#if defined(COMPILER2) || INCLUDE_JVMCI
- _defer_initial_card_mark = ReduceInitialCardMarks && can_elide_tlab_store_barriers()
+ _defer_initial_card_mark = is_server_compilation_mode_vm() && ReduceInitialCardMarks && can_elide_tlab_store_barriers()
&& (DeferInitialCardMark || card_mark_must_follow_store());
#else
assert(_defer_initial_card_mark == false, "Who would set it?");
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -1209,7 +1209,7 @@
#if defined(COMPILER2) || INCLUDE_JVMCI
assert(DerivedPointerTable::is_empty(), "derived pointer present");
size_t actual_gap = pointer_delta((HeapWord*) (max_uintx-3), *(end_addr()));
- guarantee(actual_gap > (size_t)FastAllocateSizeLimit, "inline allocation wraps");
+ guarantee(is_client_compilation_mode_vm() || actual_gap > (size_t)FastAllocateSizeLimit, "inline allocation wraps");
#endif /* COMPILER2 || INCLUDE_JVMCI */
resize_all_tlabs();
--- a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -57,11 +57,11 @@
java_lang_ref_SoftReference::set_clock(_soft_ref_timestamp_clock);
_always_clear_soft_ref_policy = new AlwaysClearPolicy();
-#if defined(COMPILER2) || INCLUDE_JVMCI
- _default_soft_ref_policy = new LRUMaxHeapPolicy();
-#else
- _default_soft_ref_policy = new LRUCurrentHeapPolicy();
-#endif
+ if (is_server_compilation_mode_vm()) {
+ _default_soft_ref_policy = new LRUMaxHeapPolicy();
+ } else {
+ _default_soft_ref_policy = new LRUCurrentHeapPolicy();
+ }
if (_always_clear_soft_ref_policy == NULL || _default_soft_ref_policy == NULL) {
vm_exit_during_initialization("Could not allocate reference policy object");
}
--- a/hotspot/src/share/vm/gc/shared/threadLocalAllocBuffer.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/gc/shared/threadLocalAllocBuffer.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -233,9 +233,11 @@
// If the C2 compiler is not present, no space is reserved.
// +1 for rounding up to next cache line, +1 to be safe
- int lines = MAX2(AllocatePrefetchLines, AllocateInstancePrefetchLines) + 2;
- _reserve_for_allocation_prefetch = (AllocatePrefetchDistance + AllocatePrefetchStepSize * lines) /
- (int)HeapWordSize;
+ if (is_server_compilation_mode_vm()) {
+ int lines = MAX2(AllocatePrefetchLines, AllocateInstancePrefetchLines) + 2;
+ _reserve_for_allocation_prefetch = (AllocatePrefetchDistance + AllocatePrefetchStepSize * lines) /
+ (int)HeapWordSize;
+ }
#endif
// During jvm startup, the main (primordial) thread is initialized
--- a/hotspot/src/share/vm/interpreter/bytecode.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/interpreter/bytecode.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -112,7 +112,7 @@
// Implementation of Bytecode_tableupswitch
int Bytecode_tableswitch::dest_offset_at(int i) const {
- return get_Java_u4_at(aligned_offset(1 + (3 + i)*jintSize));
+ return get_aligned_Java_u4_at(1 + (3 + i)*jintSize);
}
--- a/hotspot/src/share/vm/interpreter/bytecode.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/interpreter/bytecode.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -45,11 +45,11 @@
address addr_at (int offset) const { return (address)_bcp + offset; }
u_char byte_at(int offset) const { return *addr_at(offset); }
address aligned_addr_at (int offset) const { return (address)round_to((intptr_t)addr_at(offset), jintSize); }
- int aligned_offset (int offset) const { return aligned_addr_at(offset) - addr_at(0); }
// Word access:
int get_Java_u2_at (int offset) const { return Bytes::get_Java_u2(addr_at(offset)); }
int get_Java_u4_at (int offset) const { return Bytes::get_Java_u4(addr_at(offset)); }
+ int get_aligned_Java_u4_at(int offset) const { return Bytes::get_Java_u4(aligned_addr_at(offset)); }
int get_native_u2_at (int offset) const { return Bytes::get_native_u2(addr_at(offset)); }
int get_native_u4_at (int offset) const { return Bytes::get_native_u4(addr_at(offset)); }
@@ -150,8 +150,8 @@
void verify() const PRODUCT_RETURN;
// Attributes
- int default_offset() const { return get_Java_u4_at(aligned_offset(1 + 0*jintSize)); }
- int number_of_pairs() const { return get_Java_u4_at(aligned_offset(1 + 1*jintSize)); }
+ int default_offset() const { return get_aligned_Java_u4_at(1 + 0*jintSize); }
+ int number_of_pairs() const { return get_aligned_Java_u4_at(1 + 1*jintSize); }
LookupswitchPair pair_at(int i) const {
assert(0 <= i && i < number_of_pairs(), "pair index out of bounds");
return LookupswitchPair(aligned_addr_at(1 + (1 + i)*2*jintSize));
@@ -166,9 +166,9 @@
void verify() const PRODUCT_RETURN;
// Attributes
- int default_offset() const { return get_Java_u4_at(aligned_offset(1 + 0*jintSize)); }
- int low_key() const { return get_Java_u4_at(aligned_offset(1 + 1*jintSize)); }
- int high_key() const { return get_Java_u4_at(aligned_offset(1 + 2*jintSize)); }
+ int default_offset() const { return get_aligned_Java_u4_at(1 + 0*jintSize); }
+ int low_key() const { return get_aligned_Java_u4_at(1 + 1*jintSize); }
+ int high_key() const { return get_aligned_Java_u4_at(1 + 2*jintSize); }
int dest_offset_at(int i) const;
int length() { return high_key()-low_key()+1; }
};
--- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -554,7 +554,7 @@
_constants = buffer.consts();
initialize_fields(target(), JNIHandles::resolve(compiled_code_obj), CHECK_OK);
- JVMCIEnv::CodeInstallResult result = initialize_buffer(buffer, CHECK_OK);
+ JVMCIEnv::CodeInstallResult result = initialize_buffer(buffer, false, CHECK_OK);
if (result != JVMCIEnv::ok) {
return result;
}
@@ -587,7 +587,7 @@
_constants = buffer.consts();
initialize_fields(target(), JNIHandles::resolve(compiled_code_obj), CHECK_OK);
- JVMCIEnv::CodeInstallResult result = initialize_buffer(buffer, CHECK_OK);
+ JVMCIEnv::CodeInstallResult result = initialize_buffer(buffer, true, CHECK_OK);
if (result != JVMCIEnv::ok) {
return result;
}
@@ -726,7 +726,7 @@
}
// perform data and call relocation on the CodeBuffer
-JVMCIEnv::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer, TRAPS) {
+JVMCIEnv::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer, bool check_size, TRAPS) {
HandleMark hm;
objArrayHandle sites = this->sites();
int locs_buffer_size = sites->length() * (relocInfo::length_limit + sizeof(relocInfo));
@@ -738,7 +738,7 @@
int stubs_size = estimate_stubs_size(CHECK_OK);
int total_size = round_to(_code_size, buffer.insts()->alignment()) + round_to(_constants_size, buffer.consts()->alignment()) + round_to(stubs_size, buffer.stubs()->alignment());
- if (total_size > JVMCINMethodSizeLimit) {
+ if (check_size && total_size > JVMCINMethodSizeLimit) {
return JVMCIEnv::code_too_large;
}
@@ -1258,6 +1258,7 @@
case HEAP_TOP_ADDRESS:
case HEAP_END_ADDRESS:
case NARROW_KLASS_BASE_ADDRESS:
+ case NARROW_OOP_BASE_ADDRESS:
case CRC_TABLE_ADDRESS:
case LOG_OF_HEAP_REGION_GRAIN_BYTES:
case INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED:
--- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -133,9 +133,10 @@
HEAP_TOP_ADDRESS = 17,
HEAP_END_ADDRESS = 18,
NARROW_KLASS_BASE_ADDRESS = 19,
- CRC_TABLE_ADDRESS = 20,
- LOG_OF_HEAP_REGION_GRAIN_BYTES = 21,
- INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED = 22,
+ NARROW_OOP_BASE_ADDRESS = 20,
+ CRC_TABLE_ADDRESS = 21,
+ LOG_OF_HEAP_REGION_GRAIN_BYTES = 22,
+ INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED = 23,
INVOKE_INVALID = -1
};
@@ -227,7 +228,7 @@
int estimate_stubs_size(TRAPS);
// perform data and call relocation on the CodeBuffer
- JVMCIEnv::CodeInstallResult initialize_buffer(CodeBuffer& buffer, TRAPS);
+ JVMCIEnv::CodeInstallResult initialize_buffer(CodeBuffer& buffer, bool check_size, TRAPS);
void assumption_NoFinalizableSubclass(Handle assumption);
void assumption_ConcreteSubtype(Handle assumption);
--- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -591,12 +591,16 @@
return method->is_ignored_by_security_stack_walk();
C2V_END
-C2V_VMENTRY(jboolean, canInlineMethod,(JNIEnv *, jobject, jobject jvmci_method))
+C2V_VMENTRY(jboolean, isCompilable,(JNIEnv *, jobject, jobject jvmci_method))
methodHandle method = CompilerToVM::asMethod(jvmci_method);
- // In hosted mode ignore the not_compilable flags since they are never set by
+ // Ignore the not_compilable flags in hosted mode since they are never set by
// the JVMCI compiler.
- bool is_compilable = UseJVMCICompiler ? !method->is_not_compilable(CompLevel_full_optimization) : true;
- return is_compilable && !CompilerOracle::should_not_inline(method) && !method->dont_inline();
+ return UseJVMCICompiler || !method->is_not_compilable(CompLevel_full_optimization);
+C2V_END
+
+C2V_VMENTRY(jboolean, hasNeverInlineDirective,(JNIEnv *, jobject, jobject jvmci_method))
+ methodHandle method = CompilerToVM::asMethod(jvmci_method);
+ return CompilerOracle::should_not_inline(method) || method->dont_inline();
C2V_END
C2V_VMENTRY(jboolean, shouldInlineMethod,(JNIEnv *, jobject, jobject jvmci_method))
@@ -1591,7 +1595,8 @@
{CC "getStackTraceElement", CC "(" HS_RESOLVED_METHOD "I)" STACK_TRACE_ELEMENT, FN_PTR(getStackTraceElement)},
{CC "methodIsIgnoredBySecurityStackWalk", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(methodIsIgnoredBySecurityStackWalk)},
{CC "doNotInlineOrCompile", CC "(" HS_RESOLVED_METHOD ")V", FN_PTR(doNotInlineOrCompile)},
- {CC "canInlineMethod", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(canInlineMethod)},
+ {CC "isCompilable", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(isCompilable)},
+ {CC "hasNeverInlineDirective", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(hasNeverInlineDirective)},
{CC "shouldInlineMethod", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(shouldInlineMethod)},
{CC "lookupType", CC "(" STRING CLASS "Z)" HS_RESOLVED_KLASS, FN_PTR(lookupType)},
{CC "lookupNameInPool", CC "(" HS_CONSTANT_POOL "I)" STRING, FN_PTR(lookupNameInPool)},
--- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -429,6 +429,7 @@
declare_constant(CodeInstaller::HEAP_TOP_ADDRESS) \
declare_constant(CodeInstaller::HEAP_END_ADDRESS) \
declare_constant(CodeInstaller::NARROW_KLASS_BASE_ADDRESS) \
+ declare_constant(CodeInstaller::NARROW_OOP_BASE_ADDRESS) \
declare_constant(CodeInstaller::CRC_TABLE_ADDRESS) \
declare_constant(CodeInstaller::LOG_OF_HEAP_REGION_GRAIN_BYTES) \
declare_constant(CodeInstaller::INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED) \
@@ -534,7 +535,6 @@
\
declare_constant(markOopDesc::no_hash) \
\
- declare_constant(Method::_jfr_towrite) \
declare_constant(Method::_caller_sensitive) \
declare_constant(Method::_force_inline) \
declare_constant(Method::_dont_inline) \
--- a/hotspot/src/share/vm/logging/logConfiguration.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/logging/logConfiguration.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -478,7 +478,7 @@
void LogConfiguration::print_command_line_help(FILE* out) {
jio_fprintf(out, "-Xlog Usage: -Xlog[:[what][:[output][:[decorators][:output-options]]]]\n"
- "\t where 'what' is a combination of tags and levels on the form tag1[+tag2...][*][=level][,...]\n"
+ "\t where 'what' is a combination of tags and levels of the form tag1[+tag2...][*][=level][,...]\n"
"\t Unless wildcard (*) is specified, only log messages tagged with exactly the tags specified will be matched.\n\n");
jio_fprintf(out, "Available log levels:\n");
@@ -514,6 +514,14 @@
" -Xlog:gc\n"
"\t Log messages tagged with 'gc' tag using 'info' level to stdout, with default decorations.\n\n"
+ " -Xlog:gc,safepoint\n"
+ "\t Log messages tagged either with 'gc' or 'safepoint' tags, both using 'info' level, to stdout, with default decorations.\n"
+ "\t (Messages tagged with both 'gc' and 'safepoint' will not be logged.)\n\n"
+
+ " -Xlog:gc+ref=debug\n"
+ "\t Log messages tagged with both 'gc' and 'ref' tags, using 'debug' level, to stdout, with default decorations.\n"
+ "\t (Messages tagged only with one of the two tags will not be logged.)\n\n"
+
" -Xlog:gc=debug:file=gc.txt:none\n"
"\t Log messages tagged with 'gc' tag using 'debug' level to file 'gc.txt' with no decorations.\n\n"
--- a/hotspot/src/share/vm/memory/metaspaceShared.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -145,10 +145,6 @@
StringTable::serialize(soc, string_space, space_size);
soc->do_tag(--tag);
- // Dump/restore the misc information for system dictionary
- SystemDictionaryShared::serialize(soc);
- soc->do_tag(--tag);
-
soc->do_tag(666);
}
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -2139,8 +2139,6 @@
}
void InstanceKlass::release_C_heap_structures() {
- assert(!this->is_shared(), "should not be called for a shared class");
-
// Can't release the constant pool here because the constant pool can be
// deallocated separately from the InstanceKlass for default methods and
// redefine classes.
@@ -2191,7 +2189,7 @@
}
// deallocate the cached class file
- if (_cached_class_file != NULL) {
+ if (_cached_class_file != NULL && !MetaspaceShared::is_in_shared_space(_cached_class_file)) {
os::free(_cached_class_file);
_cached_class_file = NULL;
}
--- a/hotspot/src/share/vm/oops/method.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/oops/method.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -85,7 +85,6 @@
set_constMethod(xconst);
set_access_flags(access_flags);
set_intrinsic_id(vmIntrinsics::_none);
- set_jfr_towrite(false);
set_force_inline(false);
set_hidden(false);
set_dont_inline(false);
--- a/hotspot/src/share/vm/oops/method.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/oops/method.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -75,18 +75,19 @@
// Flags
enum Flags {
- _jfr_towrite = 1 << 0,
- _caller_sensitive = 1 << 1,
- _force_inline = 1 << 2,
- _dont_inline = 1 << 3,
- _hidden = 1 << 4,
- _has_injected_profile = 1 << 5,
- _running_emcp = 1 << 6,
- _intrinsic_candidate = 1 << 7,
- _reserved_stack_access = 1 << 8
+ _caller_sensitive = 1 << 0,
+ _force_inline = 1 << 1,
+ _dont_inline = 1 << 2,
+ _hidden = 1 << 3,
+ _has_injected_profile = 1 << 4,
+ _running_emcp = 1 << 5,
+ _intrinsic_candidate = 1 << 6,
+ _reserved_stack_access = 1 << 7
};
mutable u2 _flags;
+ TRACE_DEFINE_FLAG;
+
#ifndef PRODUCT
int _compiled_invocation_count; // Number of nmethod invocations so far (for perf. debugging)
#endif
@@ -833,13 +834,6 @@
void init_intrinsic_id(); // updates from _none if a match
static vmSymbols::SID klass_id_for_intrinsics(const Klass* holder);
- bool jfr_towrite() const {
- return (_flags & _jfr_towrite) != 0;
- }
- void set_jfr_towrite(bool x) const {
- _flags = x ? (_flags | _jfr_towrite) : (_flags & ~_jfr_towrite);
- }
-
bool caller_sensitive() {
return (_flags & _caller_sensitive) != 0;
}
@@ -890,6 +884,8 @@
_flags = x ? (_flags | _reserved_stack_access) : (_flags & ~_reserved_stack_access);
}
+ TRACE_DEFINE_FLAG_ACCESSOR;
+
ConstMethod::MethodType method_type() const {
return _constMethod->method_type();
}
--- a/hotspot/src/share/vm/oops/methodData.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/oops/methodData.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -717,9 +717,9 @@
}
int MethodData::bytecode_cell_count(Bytecodes::Code code) {
-#if defined(COMPILER1) && !(defined(COMPILER2) || INCLUDE_JVMCI)
- return no_profile_data;
-#else
+ if (is_client_compilation_mode_vm()) {
+ return no_profile_data;
+ }
switch (code) {
case Bytecodes::_checkcast:
case Bytecodes::_instanceof:
@@ -778,7 +778,6 @@
return variable_cell_count;
}
return no_profile_data;
-#endif
}
// Compute the size of the profiling information corresponding to
@@ -840,7 +839,9 @@
case Bytecodes::_ifnonnull:
case Bytecodes::_invokestatic:
#ifdef COMPILER2
- return UseTypeSpeculation;
+ if (is_server_compilation_mode_vm()) {
+ return UseTypeSpeculation;
+ }
#endif
default:
return false;
@@ -942,9 +943,9 @@
// the segment in bytes.
int MethodData::initialize_data(BytecodeStream* stream,
int data_index) {
-#if defined(COMPILER1) && !(defined(COMPILER2) || INCLUDE_JVMCI)
- return 0;
-#else
+ if (is_client_compilation_mode_vm()) {
+ return 0;
+ }
int cell_count = -1;
int tag = DataLayout::no_tag;
DataLayout* data_layout = data_layout_at(data_index);
@@ -1061,7 +1062,6 @@
assert(!bytecode_has_profile(c), "agree w/ !BHP");
return 0;
}
-#endif
}
// Get the data at an arbitrary (sort of) data index.
--- a/hotspot/src/share/vm/oops/methodData.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/oops/methodData.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -2183,7 +2183,7 @@
uint _nof_overflow_traps; // trap count, excluding _trap_hist
union {
intptr_t _align;
- u1 _array[_trap_hist_limit];
+ u1 _array[JVMCI_ONLY(2 *) _trap_hist_limit];
} _trap_hist;
// Support for interprocedural escape analysis, from Thomas Kotzmann.
--- a/hotspot/src/share/vm/opto/cfgnode.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/opto/cfgnode.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -2097,6 +2097,7 @@
uint ideal_reg = _type->ideal_reg();
assert( ideal_reg != Node::NotAMachineReg, "invalid type at Phi" );
if( ideal_reg == 0 ) return RegMask::Empty;
+ assert(ideal_reg != Op_RegFlags, "flags register is not spillable");
return *(Compile::current()->matcher()->idealreg2spillmask[ideal_reg]);
}
--- a/hotspot/src/share/vm/opto/coalesce.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/opto/coalesce.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -292,7 +292,14 @@
// Copy any flags as well
_phc.clone_projs(pred, pred->end_idx(), m, copy, _phc._lrg_map);
} else {
- const RegMask *rm = C->matcher()->idealreg2spillmask[m->ideal_reg()];
+ int ireg = m->ideal_reg();
+ if (ireg == 0 || ireg == Op_RegFlags) {
+ assert(false, "attempted to spill a non-spillable item: %d: %s, ireg = %d, spill_type: %s",
+ m->_idx, m->Name(), ireg, MachSpillCopyNode::spill_type(MachSpillCopyNode::PhiInput));
+ C->record_method_not_compilable("attempted to spill a non-spillable item");
+ return;
+ }
+ const RegMask *rm = C->matcher()->idealreg2spillmask[ireg];
copy = new MachSpillCopyNode(MachSpillCopyNode::PhiInput, m, *rm, *rm);
// Find a good place to insert. Kinda tricky, use a subroutine
insert_copy_with_overlap(pred,copy,phi_name,src_name);
@@ -326,7 +333,14 @@
b->insert_node(copy, l++);
l += _phc.clone_projs(b, l, m, copy, _phc._lrg_map);
} else {
- const RegMask *rm = C->matcher()->idealreg2spillmask[m->ideal_reg()];
+ int ireg = m->ideal_reg();
+ if (ireg == 0 || ireg == Op_RegFlags) {
+ assert(false, "attempted to spill a non-spillable item: %d: %s, ireg = %d, spill_type: %s",
+ m->_idx, m->Name(), ireg, MachSpillCopyNode::spill_type(MachSpillCopyNode::TwoAddress));
+ C->record_method_not_compilable("attempted to spill a non-spillable item");
+ return;
+ }
+ const RegMask *rm = C->matcher()->idealreg2spillmask[ireg];
copy = new MachSpillCopyNode(MachSpillCopyNode::TwoAddress, m, *rm, *rm);
// Insert the copy in the basic block, just before us
b->insert_node(copy, l++);
@@ -373,7 +387,14 @@
if( k < b->_num_succs )
continue; // Live out; do not pre-split
// Split the lrg at this use
- const RegMask *rm = C->matcher()->idealreg2spillmask[inp->ideal_reg()];
+ int ireg = inp->ideal_reg();
+ if (ireg == 0 || ireg == Op_RegFlags) {
+ assert(false, "attempted to spill a non-spillable item: %d: %s, ireg = %d, spill_type: %s",
+ inp->_idx, inp->Name(), ireg, MachSpillCopyNode::spill_type(MachSpillCopyNode::DebugUse));
+ C->record_method_not_compilable("attempted to spill a non-spillable item");
+ return;
+ }
+ const RegMask *rm = C->matcher()->idealreg2spillmask[ireg];
Node* copy = new MachSpillCopyNode(MachSpillCopyNode::DebugUse, inp, *rm, *rm);
// Insert the copy in the use-def chain
n->set_req(inpidx, copy );
--- a/hotspot/src/share/vm/opto/compile.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/opto/compile.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -971,7 +971,7 @@
_java_calls(0),
_inner_loops(0),
#ifndef PRODUCT
- _trace_opto_output(TraceOptoOutput),
+ _trace_opto_output(directive->TraceOptoOutputOption),
_in_dump_cnt(0),
_printer(NULL),
#endif
--- a/hotspot/src/share/vm/opto/graphKit.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/opto/graphKit.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -3152,19 +3152,6 @@
return membar;
}
-void GraphKit::insert_store_load_for_barrier() {
- Node* mem = reset_memory();
- MemBarNode* mb = MemBarNode::make(C, Op_MemBarVolatile, Compile::AliasIdxBot);
- mb->init_req(TypeFunc::Control, control());
- mb->init_req(TypeFunc::Memory, mem);
- Node* membar = _gvn.transform(mb);
- set_control(_gvn.transform(new ProjNode(membar, TypeFunc::Control)));
- Node* newmem = _gvn.transform(new ProjNode(membar, TypeFunc::Memory));
- set_all_memory(mem);
- set_memory(newmem, Compile::AliasIdxRaw);
-}
-
-
//------------------------------shared_lock------------------------------------
// Emit locking code.
FastLockNode* GraphKit::shared_lock(Node* obj) {
@@ -3854,7 +3841,7 @@
BasicType bt = T_BYTE;
if (UseConcMarkSweepGC && UseCondCardMark) {
- insert_store_load_for_barrier();
+ insert_mem_bar(Op_MemBarVolatile); // StoreLoad barrier
__ sync_kit(this);
}
@@ -4294,7 +4281,8 @@
__ if_then(card_val, BoolTest::ne, young_card); {
sync_kit(ideal);
- insert_store_load_for_barrier();
+ // Use Op_MemBarVolatile to achieve the effect of a StoreLoad barrier.
+ insert_mem_bar(Op_MemBarVolatile, oop_store);
__ sync_kit(this);
Node* card_val_reload = __ load(__ ctrl(), card_adr, TypeInt::INT, T_BYTE, Compile::AliasIdxRaw);
@@ -4348,20 +4336,16 @@
}
Node* GraphKit::load_String_coder(Node* ctrl, Node* str) {
- if (java_lang_String::has_coder_field()) {
- if (!CompactStrings) {
- return intcon(java_lang_String::CODER_UTF16);
- }
- int coder_offset = java_lang_String::coder_offset_in_bytes();
- const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
- false, NULL, 0);
- const TypePtr* coder_field_type = string_type->add_offset(coder_offset);
- int coder_field_idx = C->get_alias_index(coder_field_type);
- return make_load(ctrl, basic_plus_adr(str, str, coder_offset),
- TypeInt::BYTE, T_BYTE, coder_field_idx, MemNode::unordered);
- } else {
- return intcon(0); // false
+ if (!CompactStrings) {
+ return intcon(java_lang_String::CODER_UTF16);
}
+ int coder_offset = java_lang_String::coder_offset_in_bytes();
+ const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
+ false, NULL, 0);
+ const TypePtr* coder_field_type = string_type->add_offset(coder_offset);
+ int coder_field_idx = C->get_alias_index(coder_field_type);
+ return make_load(ctrl, basic_plus_adr(str, str, coder_offset),
+ TypeInt::BYTE, T_BYTE, coder_field_idx, MemNode::unordered);
}
void GraphKit::store_String_value(Node* ctrl, Node* str, Node* value) {
--- a/hotspot/src/share/vm/opto/graphKit.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/opto/graphKit.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -837,7 +837,6 @@
int next_monitor();
Node* insert_mem_bar(int opcode, Node* precedent = NULL);
Node* insert_mem_bar_volatile(int opcode, int alias_idx, Node* precedent = NULL);
- void insert_store_load_for_barrier();
// Optional 'precedent' is appended as an extra edge, to force ordering.
FastLockNode* shared_lock(Node* obj);
void shared_unlock(Node* box, Node* obj);
--- a/hotspot/src/share/vm/opto/library_call.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/opto/library_call.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -6335,7 +6335,7 @@
//------------------------------get_key_start_from_aescrypt_object-----------------------
Node * LibraryCallKit::get_key_start_from_aescrypt_object(Node *aescrypt_object) {
-#ifdef PPC64
+#if defined(PPC64) || defined(S390)
// MixColumns for decryption can be reduced by preprocessing MixColumns with round keys.
// Intel's extention is based on this optimization and AESCrypt generates round keys by preprocessing MixColumns.
// However, ppc64 vncipher processes MixColumns and requires the same round keys with encryption.
--- a/hotspot/src/share/vm/opto/machnode.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/opto/machnode.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -643,6 +643,7 @@
}
// Values outside the domain represent debug info
+ assert(in(idx)->ideal_reg() != Op_RegFlags, "flags register is not spillable");
return *Compile::current()->matcher()->idealreg2spillmask[in(idx)->ideal_reg()];
}
--- a/hotspot/src/share/vm/opto/macro.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/opto/macro.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -426,7 +426,7 @@
// Generate loads from source of the arraycopy for fields of
// destination needed at a deoptimization point
-Node* PhaseMacroExpand::make_arraycopy_load(ArrayCopyNode* ac, intptr_t offset, Node* ctl, BasicType ft, const Type *ftype, AllocateNode *alloc) {
+Node* PhaseMacroExpand::make_arraycopy_load(ArrayCopyNode* ac, intptr_t offset, Node* ctl, Node* mem, BasicType ft, const Type *ftype, AllocateNode *alloc) {
BasicType bt = ft;
const Type *type = ftype;
if (ft == T_NARROWOOP) {
@@ -438,8 +438,7 @@
Node* base = ac->in(ArrayCopyNode::Src)->in(AddPNode::Base);
Node* adr = _igvn.transform(new AddPNode(base, base, MakeConX(offset)));
const TypePtr* adr_type = _igvn.type(base)->is_ptr()->add_offset(offset);
- Node* m = ac->in(TypeFunc::Memory);
- res = LoadNode::make(_igvn, ctl, m, adr, adr_type, type, bt, MemNode::unordered, LoadNode::Pinned);
+ res = LoadNode::make(_igvn, ctl, mem, adr, adr_type, type, bt, MemNode::unordered, LoadNode::Pinned);
} else {
if (ac->modifies(offset, offset, &_igvn, true)) {
assert(ac->in(ArrayCopyNode::Dest) == alloc->result_cast(), "arraycopy destination should be allocation's result");
@@ -454,8 +453,7 @@
Node* base = ac->in(ArrayCopyNode::Src);
Node* adr = _igvn.transform(new AddPNode(base, base, off));
const TypePtr* adr_type = _igvn.type(base)->is_ptr()->add_offset(offset);
- Node* m = ac->in(TypeFunc::Memory);
- res = LoadNode::make(_igvn, ctl, m, adr, adr_type, type, bt, MemNode::unordered, LoadNode::Pinned);
+ res = LoadNode::make(_igvn, ctl, mem, adr, adr_type, type, bt, MemNode::unordered, LoadNode::Pinned);
}
}
if (res != NULL) {
@@ -544,7 +542,7 @@
assert(false, "Object is not scalar replaceable if a LoadStore node accesses its field");
return NULL;
} else if (val->is_ArrayCopy()) {
- Node* res = make_arraycopy_load(val->as_ArrayCopy(), offset, val->in(0), ft, phi_type, alloc);
+ Node* res = make_arraycopy_load(val->as_ArrayCopy(), offset, val->in(0), val->in(TypeFunc::Memory), ft, phi_type, alloc);
if (res == NULL) {
return NULL;
}
@@ -657,11 +655,13 @@
}
} else if (mem->is_ArrayCopy()) {
Node* ctl = mem->in(0);
+ Node* m = mem->in(TypeFunc::Memory);
if (sfpt_ctl->is_Proj() && sfpt_ctl->as_Proj()->is_uncommon_trap_proj(Deoptimization::Reason_none)) {
// pin the loads in the uncommon trap path
ctl = sfpt_ctl;
+ m = sfpt_mem;
}
- return make_arraycopy_load(mem->as_ArrayCopy(), offset, ctl, ft, ftype, alloc);
+ return make_arraycopy_load(mem->as_ArrayCopy(), offset, ctl, m, ft, ftype, alloc);
}
}
// Something go wrong.
--- a/hotspot/src/share/vm/opto/macro.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/opto/macro.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -200,7 +200,7 @@
Node* old_eden_top, Node* new_eden_top,
Node* length);
- Node* make_arraycopy_load(ArrayCopyNode* ac, intptr_t offset, Node* ctl, BasicType ft, const Type *ftype, AllocateNode *alloc);
+ Node* make_arraycopy_load(ArrayCopyNode* ac, intptr_t offset, Node* ctl, Node* mem, BasicType ft, const Type *ftype, AllocateNode *alloc);
public:
PhaseMacroExpand(PhaseIterGVN &igvn) : Phase(Macro_Expand), _igvn(igvn), _has_locks(false) {
--- a/hotspot/src/share/vm/opto/matcher.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/opto/matcher.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -85,6 +85,7 @@
idealreg2spillmask [Op_VecX] = NULL;
idealreg2spillmask [Op_VecY] = NULL;
idealreg2spillmask [Op_VecZ] = NULL;
+ idealreg2spillmask [Op_RegFlags] = NULL;
idealreg2debugmask [Op_RegI] = NULL;
idealreg2debugmask [Op_RegN] = NULL;
@@ -97,6 +98,7 @@
idealreg2debugmask [Op_VecX] = NULL;
idealreg2debugmask [Op_VecY] = NULL;
idealreg2debugmask [Op_VecZ] = NULL;
+ idealreg2debugmask [Op_RegFlags] = NULL;
idealreg2mhdebugmask[Op_RegI] = NULL;
idealreg2mhdebugmask[Op_RegN] = NULL;
@@ -109,6 +111,7 @@
idealreg2mhdebugmask[Op_VecX] = NULL;
idealreg2mhdebugmask[Op_VecY] = NULL;
idealreg2mhdebugmask[Op_VecZ] = NULL;
+ idealreg2mhdebugmask[Op_RegFlags] = NULL;
debug_only(_mem_node = NULL;) // Ideal memory node consumed by mach node
}
--- a/hotspot/src/share/vm/precompiled/precompiled.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/precompiled/precompiled.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -23,7 +23,7 @@
*/
// Precompiled headers are turned off for Sun Studion,
-// or if the user passes USE_PRECOMPILED_HEADER=0 to the makefiles.
+// or if the user passes --disable-precompiled-headers to configure.
#ifndef DONT_USE_PRECOMPILED_HEADER
# include "asm/assembler.hpp"
--- a/hotspot/src/share/vm/prims/jniCheck.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/prims/jniCheck.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -238,8 +238,8 @@
size_t live_handles = handles->get_number_of_live_handles();
if (live_handles > planned_capacity) {
IN_VM(
- tty->print_cr("WARNING: JNI local refs: %zu, exceeds capacity: %zu",
- live_handles, planned_capacity);
+ tty->print_cr("WARNING: JNI local refs: " SIZE_FORMAT ", exceeds capacity: " SIZE_FORMAT,
+ live_handles, planned_capacity);
thr->print_stack();
)
// Complain just the once, reset to current + warn threshold
--- a/hotspot/src/share/vm/prims/jvm.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/prims/jvm.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -1009,9 +1009,9 @@
// Module support //////////////////////////////////////////////////////////////////////////////
JVM_ENTRY(void, JVM_DefineModule(JNIEnv *env, jobject module, jboolean is_open, jstring version,
- jstring location, jobjectArray packages))
+ jstring location, const char* const* packages, jsize num_packages))
JVMWrapper("JVM_DefineModule");
- Modules::define_module(module, version, location, packages, CHECK);
+ Modules::define_module(module, version, location, packages, num_packages, CHECK);
JVM_END
JVM_ENTRY(void, JVM_SetBootLoaderUnnamedModule(JNIEnv *env, jobject module))
@@ -1019,17 +1019,17 @@
Modules::set_bootloader_unnamed_module(module, CHECK);
JVM_END
-JVM_ENTRY(void, JVM_AddModuleExports(JNIEnv *env, jobject from_module, jstring package, jobject to_module))
+JVM_ENTRY(void, JVM_AddModuleExports(JNIEnv *env, jobject from_module, const char* package, jobject to_module))
JVMWrapper("JVM_AddModuleExports");
Modules::add_module_exports_qualified(from_module, package, to_module, CHECK);
JVM_END
-JVM_ENTRY(void, JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, jstring package))
+JVM_ENTRY(void, JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, const char* package))
JVMWrapper("JVM_AddModuleExportsToAllUnnamed");
Modules::add_module_exports_to_all_unnamed(from_module, package, CHECK);
JVM_END
-JVM_ENTRY(void, JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, jstring package))
+JVM_ENTRY(void, JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, const char* package))
JVMWrapper("JVM_AddModuleExportsToAll");
Modules::add_module_exports(from_module, package, NULL, CHECK);
JVM_END
@@ -1039,16 +1039,11 @@
Modules::add_reads_module(from_module, source_module, CHECK);
JVM_END
-JVM_ENTRY (void, JVM_AddModulePackage(JNIEnv *env, jobject module, jstring package))
+JVM_ENTRY (void, JVM_AddModulePackage(JNIEnv *env, jobject module, const char* package))
JVMWrapper("JVM_AddModulePackage");
Modules::add_module_package(module, package, CHECK);
JVM_END
-JVM_ENTRY (jobject, JVM_GetModuleByPackageName(JNIEnv *env, jobject loader, jstring package))
- JVMWrapper("JVM_GetModuleByPackageName");
- return Modules::get_module_by_package_name(loader, package, THREAD);
-JVM_END
-
// Reflection support //////////////////////////////////////////////////////////////////////////////
JVM_ENTRY(jstring, JVM_GetClassName(JNIEnv *env, jclass cls))
--- a/hotspot/src/share/vm/prims/jvm.h Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/prims/jvm.h Thu Feb 09 23:15:52 2017 +0100
@@ -412,30 +412,67 @@
* Module support funcions
*/
+/*
+ * Define a module with the specified packages and bind the module to the
+ * given class loader.
+ * module: module to define
+ * is_open: specifies if module is open (currently ignored)
+ * version: the module version
+ * location: the module location
+ * packages: list of packages in the module
+ * num_packages: number of packages in the module
+ */
JNIEXPORT void JNICALL
JVM_DefineModule(JNIEnv *env, jobject module, jboolean is_open, jstring version,
- jstring location, jobjectArray packages);
+ jstring location, const char* const* packages, jsize num_packages);
+/*
+ * Set the boot loader's unnamed module.
+ * module: boot loader's unnamed module
+ */
JNIEXPORT void JNICALL
JVM_SetBootLoaderUnnamedModule(JNIEnv *env, jobject module);
+/*
+ * Do a qualified export of a package.
+ * from_module: module containing the package to export
+ * package: name of the package to export
+ * to_module: module to export the package to
+ */
JNIEXPORT void JNICALL
-JVM_AddModuleExports(JNIEnv *env, jobject from_module, jstring package, jobject to_module);
+JVM_AddModuleExports(JNIEnv *env, jobject from_module, const char* package, jobject to_module);
+/*
+ * Do an export of a package to all unnamed modules.
+ * from_module: module containing the package to export
+ * package: name of the package to export to all unnamed modules
+ */
JNIEXPORT void JNICALL
-JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, jstring package);
+JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, const char* package);
+/*
+ * Do an unqualified export of a package.
+ * from_module: module containing the package to export
+ * package: name of the package to export
+ */
JNIEXPORT void JNICALL
-JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, jstring package);
+JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, const char* package);
+/*
+ * Add a module to the list of modules that a given module can read.
+ * from_module: module requesting read access
+ * source_module: module that from_module wants to read
+ */
JNIEXPORT void JNICALL
JVM_AddReadsModule(JNIEnv *env, jobject from_module, jobject source_module);
+/*
+ * Add a package to a module.
+ * module: module that will contain the package
+ * package: package to add to the module
+ */
JNIEXPORT void JNICALL
-JVM_AddModulePackage(JNIEnv* env, jobject module, jstring package);
-
-JNIEXPORT jobject JNICALL
-JVM_GetModuleByPackageName(JNIEnv* env, jobject loader, jstring package);
+JVM_AddModulePackage(JNIEnv* env, jobject module, const char* package);
/*
* Reflection support functions
--- a/hotspot/src/share/vm/prims/jvmti.xml Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/prims/jvmti.xml Thu Feb 09 23:15:52 2017 +0100
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="jvmti.xsl"?>
<!--
- Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2002, 2017, 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
@@ -12864,11 +12864,13 @@
If the capability has been added then the VM posts the event as early
as possible. The VM is capable of executing bytecode but it may not have
initialized to the point where it can load classes in modules other than
- <code>java.base</code>. Agents that do load-time instrumentation in this
+ <code>java.base</code>, or even arbitrary classes in <code>java.base</code>.
+ Agents that do load-time instrumentation in this
phase must take great care when instrumenting code that potentially
- executes in this phase. Care should also be taken with JNI
- <code>FindClass</code> as it may not be possible to load classes that are
- not in the <code>java.base</code> module.
+ executes in this phase. Extreme care should also be taken with JNI
+ <code>FindClass</code> as it may not be possible to load classes and attempts
+ to do so may result in unpredictable behavior, maybe even stability issues
+ on some VM implementations.
If the capability has not been added then the VM delays posting this
event until it is capable of loading classes in modules other than
<code>java.base</code> or the VM has completed its initialization.
--- a/hotspot/src/share/vm/prims/jvmtiEnter.xsl Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiEnter.xsl Thu Feb 09 23:15:52 2017 +0100
@@ -1246,7 +1246,7 @@
<xsl:param name="name"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$name"/>
- <xsl:text>=0x%zx</xsl:text>
+ <xsl:text>=" SIZE_FORMAT_HEX "</xsl:text>
</xsl:template>
<xsl:template match="jfloat|jdouble" mode="traceInFormat">
--- a/hotspot/src/share/vm/prims/whitebox.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/prims/whitebox.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -40,6 +40,8 @@
#include "memory/universe.hpp"
#include "memory/oopFactory.hpp"
#include "oops/constantPool.hpp"
+#include "oops/objArrayKlass.hpp"
+#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
#include "prims/wbtestmethods/parserTests.hpp"
#include "prims/whitebox.hpp"
@@ -659,6 +661,9 @@
WB_END
WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr))
+ if (method == NULL || comp_level > MIN2((CompLevel) TieredStopAtLevel, CompLevel_highest_tier)) {
+ return false;
+ }
jmethodID jmid = reflected_method_to_jmid(thread, env, method);
CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
MutexLockerEx mu(Compile_lock);
@@ -760,7 +765,7 @@
bool WhiteBox::compile_method(Method* method, int comp_level, int bci, Thread* THREAD) {
// Screen for unavailable/bad comp level or null method
- if (method == NULL || comp_level > TieredStopAtLevel ||
+ if (method == NULL || comp_level > MIN2((CompLevel) TieredStopAtLevel, CompLevel_highest_tier) ||
CompileBroker::compiler(comp_level) == NULL) {
return false;
}
@@ -1400,19 +1405,52 @@
WB_ENTRY(void, WB_DefineModule(JNIEnv* env, jobject o, jobject module, jstring version, jstring location,
jobjectArray packages))
- Modules::define_module(module, version, location, packages, CHECK);
+ ResourceMark rm(THREAD);
+
+ objArrayOop packages_oop = objArrayOop(JNIHandles::resolve(packages));
+ objArrayHandle packages_h(THREAD, packages_oop);
+ int num_packages = (packages_h == NULL ? 0 : packages_h->length());
+
+ char** pkgs = NULL;
+ if (num_packages > 0) {
+ pkgs = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char*, num_packages);
+ for (int x = 0; x < num_packages; x++) {
+ oop pkg_str = packages_h->obj_at(x);
+ if (pkg_str == NULL || !pkg_str->is_a(SystemDictionary::String_klass())) {
+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+ err_msg("Bad package name"));
+ }
+ pkgs[x] = java_lang_String::as_utf8_string(pkg_str);
+ }
+ }
+ Modules::define_module(module, version, location, (const char* const*)pkgs, num_packages, CHECK);
WB_END
WB_ENTRY(void, WB_AddModuleExports(JNIEnv* env, jobject o, jobject from_module, jstring package, jobject to_module))
- Modules::add_module_exports_qualified(from_module, package, to_module, CHECK);
+ ResourceMark rm(THREAD);
+ char* package_name = NULL;
+ if (package != NULL) {
+ package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
+ }
+ Modules::add_module_exports_qualified(from_module, package_name, to_module, CHECK);
WB_END
WB_ENTRY(void, WB_AddModuleExportsToAllUnnamed(JNIEnv* env, jobject o, jclass module, jstring package))
- Modules::add_module_exports_to_all_unnamed(module, package, CHECK);
+ ResourceMark rm(THREAD);
+ char* package_name = NULL;
+ if (package != NULL) {
+ package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
+ }
+ Modules::add_module_exports_to_all_unnamed(module, package_name, CHECK);
WB_END
WB_ENTRY(void, WB_AddModuleExportsToAll(JNIEnv* env, jobject o, jclass module, jstring package))
- Modules::add_module_exports(module, package, NULL, CHECK);
+ ResourceMark rm(THREAD);
+ char* package_name = NULL;
+ if (package != NULL) {
+ package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
+ }
+ Modules::add_module_exports(module, package_name, NULL, CHECK);
WB_END
WB_ENTRY(void, WB_AddReadsModule(JNIEnv* env, jobject o, jobject from_module, jobject source_module))
@@ -1420,11 +1458,21 @@
WB_END
WB_ENTRY(void, WB_AddModulePackage(JNIEnv* env, jobject o, jclass module, jstring package))
- Modules::add_module_package(module, package, CHECK);
+ ResourceMark rm(THREAD);
+ char* package_name = NULL;
+ if (package != NULL) {
+ package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
+ }
+ Modules::add_module_package(module, package_name, CHECK);
WB_END
WB_ENTRY(jobject, WB_GetModuleByPackageName(JNIEnv* env, jobject o, jobject loader, jstring package))
- return Modules::get_module_by_package_name(loader, package, THREAD);
+ ResourceMark rm(THREAD);
+ char* package_name = NULL;
+ if (package != NULL) {
+ package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
+ }
+ return Modules::get_module_by_package_name(loader, package_name, THREAD);
WB_END
WB_ENTRY(jlong, WB_IncMetaspaceCapacityUntilGC(JNIEnv* env, jobject wb, jlong inc))
--- a/hotspot/src/share/vm/runtime/arguments.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -1819,6 +1819,25 @@
#endif // INCLUDE_ALL_GCS
}
+#ifdef TIERED
+bool Arguments::compilation_mode_selected() {
+ return !FLAG_IS_DEFAULT(TieredCompilation) || !FLAG_IS_DEFAULT(TieredStopAtLevel) ||
+ !FLAG_IS_DEFAULT(UseAOT) JVMCI_ONLY(|| !FLAG_IS_DEFAULT(EnableJVMCI) || !FLAG_IS_DEFAULT(UseJVMCICompiler));
+
+}
+
+void Arguments::select_compilation_mode_ergonomically() {
+#if defined(_WINDOWS) && !defined(_LP64)
+ if (FLAG_IS_DEFAULT(NeverActAsServerClassMachine)) {
+ FLAG_SET_ERGO(bool, NeverActAsServerClassMachine, true);
+ }
+#endif
+ if (NeverActAsServerClassMachine) {
+ set_client_compilation_mode();
+ }
+}
+#endif //TIERED
+
void Arguments::select_gc_ergonomically() {
#if INCLUDE_ALL_GCS
if (os::is_server_class_machine()) {
@@ -1854,7 +1873,40 @@
}
}
+#if INCLUDE_JVMCI
+void Arguments::set_jvmci_specific_flags() {
+ if (UseJVMCICompiler) {
+ if (FLAG_IS_DEFAULT(TypeProfileWidth)) {
+ FLAG_SET_DEFAULT(TypeProfileWidth, 8);
+ }
+ if (FLAG_IS_DEFAULT(OnStackReplacePercentage)) {
+ FLAG_SET_DEFAULT(OnStackReplacePercentage, 933);
+ }
+ if (FLAG_IS_DEFAULT(ReservedCodeCacheSize)) {
+ FLAG_SET_DEFAULT(ReservedCodeCacheSize, 64*M);
+ }
+ if (FLAG_IS_DEFAULT(InitialCodeCacheSize)) {
+ FLAG_SET_DEFAULT(InitialCodeCacheSize, 16*M);
+ }
+ if (FLAG_IS_DEFAULT(MetaspaceSize)) {
+ FLAG_SET_DEFAULT(MetaspaceSize, 12*M);
+ }
+ if (FLAG_IS_DEFAULT(NewSizeThreadIncrease)) {
+ FLAG_SET_DEFAULT(NewSizeThreadIncrease, 4*K);
+ }
+ if (FLAG_IS_DEFAULT(TypeProfileLevel)) {
+ FLAG_SET_DEFAULT(TypeProfileLevel, 0);
+ }
+ }
+}
+#endif
+
void Arguments::set_ergonomics_flags() {
+#ifdef TIERED
+ if (!compilation_mode_selected()) {
+ select_compilation_mode_ergonomically();
+ }
+#endif
select_gc();
#if defined(COMPILER2) || INCLUDE_JVMCI
@@ -1863,7 +1915,7 @@
// server performance. When -server is specified, keep the default off
// unless it is asked for. Future work: either add bytecode rewriting
// at link time, or rewrite bytecodes in non-shared methods.
- if (!DumpSharedSpaces && !RequireSharedSpaces &&
+ if (is_server_compilation_mode_vm() && !DumpSharedSpaces && !RequireSharedSpaces &&
(FLAG_IS_DEFAULT(UseSharedSpaces) || !UseSharedSpaces)) {
no_shared_spaces("COMPILER2 default: -Xshare:auto | off, have to manually setup to on.");
}
@@ -2463,14 +2515,6 @@
warning("forcing ScavengeRootsInCode non-zero because JVMCI is enabled");
ScavengeRootsInCode = 1;
}
- if (FLAG_IS_DEFAULT(TypeProfileLevel)) {
- TypeProfileLevel = 0;
- }
- if (UseJVMCICompiler) {
- if (FLAG_IS_DEFAULT(TypeProfileWidth)) {
- TypeProfileWidth = 8;
- }
- }
}
#endif
@@ -3195,8 +3239,8 @@
if (FLAG_SET_CMDLINE(bool, ManagementServer, true) != Flag::SUCCESS) {
return JNI_EINVAL;
}
- // management agent in module java.management
- if (!create_numbered_property("jdk.module.addmods", "java.management", addmods_count++)) {
+ // management agent in module jdk.management.agent
+ if (!create_numbered_property("jdk.module.addmods", "jdk.management.agent", addmods_count++)) {
return JNI_ENOMEM;
}
#else
@@ -3691,6 +3735,12 @@
return JNI_ERR;
}
+#if INCLUDE_JVMCI
+ if (UseJVMCICompiler) {
+ Compilation_mode = CompMode_server;
+ }
+#endif
+
return JNI_OK;
}
@@ -3820,6 +3870,9 @@
return JNI_ENOMEM;
}
+ jio_fprintf(defaultStream::error_stream(),
+ "Picked up %s: %s\n", name, buffer);
+
int retcode = parse_options_buffer(name, buffer, strlen(buffer), vm_args);
os::free(buffer);
@@ -4420,6 +4473,10 @@
// Set flags based on ergonomics.
set_ergonomics_flags();
+#if INCLUDE_JVMCI
+ set_jvmci_specific_flags();
+#endif
+
set_shared_spaces_flags();
// Check the GC selections again.
@@ -4432,7 +4489,9 @@
} else {
int max_compilation_policy_choice = 1;
#ifdef COMPILER2
- max_compilation_policy_choice = 2;
+ if (is_server_compilation_mode_vm()) {
+ max_compilation_policy_choice = 2;
+ }
#endif
// Check if the policy is valid.
if (CompilationPolicyChoice >= max_compilation_policy_choice) {
--- a/hotspot/src/share/vm/runtime/arguments.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/runtime/arguments.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -455,6 +455,10 @@
static intx _Tier3InvokeNotifyFreqLog;
static intx _Tier4InvocationThreshold;
+ // Compilation mode.
+ static bool compilation_mode_selected();
+ static void select_compilation_mode_ergonomically();
+
// Tiered
static void set_tiered_flags();
// CMS/ParNew garbage collectors
@@ -638,6 +642,7 @@
#if INCLUDE_JVMCI
// Check consistency of jvmci vm argument settings.
static bool check_jvmci_args_consistency();
+ static void set_jvmci_specific_flags();
#endif
// Check for consistency in the selection of the garbage collector.
static bool check_gc_consistency(); // Check user-selected gc
--- a/hotspot/src/share/vm/runtime/compilationPolicy.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/runtime/compilationPolicy.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -238,31 +238,17 @@
// Note: this policy is used ONLY if TieredCompilation is off.
// compiler_count() behaves the following way:
// - with TIERED build (with both COMPILER1 and COMPILER2 defined) it should return
-// zero for the c1 compilation levels, hence the particular ordering of the
-// statements.
-// - the same should happen when COMPILER2 is defined and COMPILER1 is not
-// (server build without TIERED defined).
-// - if only COMPILER1 is defined (client build), zero should be returned for
-// the c2 level.
+// zero for the c1 compilation levels in server compilation mode runs
+// and c2 compilation levels in client compilation mode runs.
+// - with COMPILER2 not defined it should return zero for c2 compilation levels.
+// - with COMPILER1 not defined it should return zero for c1 compilation levels.
// - if neither is defined - always return zero.
int NonTieredCompPolicy::compiler_count(CompLevel comp_level) {
assert(!TieredCompilation, "This policy should not be used with TieredCompilation");
-#ifdef COMPILER2
- if (is_c2_compile(comp_level)) {
+ if (COMPILER2_PRESENT(is_server_compilation_mode_vm() && is_c2_compile(comp_level) ||)
+ is_client_compilation_mode_vm() && is_c1_compile(comp_level)) {
return _compiler_count;
- } else {
- return 0;
}
-#endif
-
-#ifdef COMPILER1
- if (is_c1_compile(comp_level)) {
- return _compiler_count;
- } else {
- return 0;
- }
-#endif
-
return 0;
}
--- a/hotspot/src/share/vm/runtime/globals.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/runtime/globals.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -469,14 +469,18 @@
}
if (!printRanges) {
+ // Use some named constants to make code more readable.
+ const unsigned int nSpaces = 10;
+ const unsigned int maxFlagLen = 40 + nSpaces;
+
// The print below assumes that the flag name is 40 characters or less.
// This works for most flags, but there are exceptions. Our longest flag
// name right now is UseAdaptiveGenerationSizePolicyAtMajorCollection and
// its minor collection buddy. These are 48 characters. We use a buffer of
- // 10 spaces below to adjust the space between the flag value and the
+ // nSpaces spaces below to adjust the space between the flag value and the
// column of flag type and origin that is printed in the end of the line.
- char spaces[10 + 1] = " ";
- st->print("%9s %-40s = ", _type, _name);
+ char spaces[nSpaces + 1] = " ";
+ st->print("%9s %-*s = ", _type, maxFlagLen-nSpaces, _name);
if (is_bool()) {
st->print("%-20s", get_bool() ? "true" : "false");
@@ -509,9 +513,12 @@
}
else st->print("%-20s", "");
}
- assert(strlen(_name) < 50, "Flag name is longer than expected");
- spaces[50 - MAX2((size_t)40, strlen(_name))] = '\0';
- st->print("%s", spaces);
+ // Make sure we do not punch a '\0' at a negative char array index.
+ unsigned int nameLen = (unsigned int)strlen(_name);
+ if (nameLen <= maxFlagLen) {
+ spaces[maxFlagLen - MAX2(maxFlagLen-nSpaces, nameLen)] = '\0';
+ st->print("%s", spaces);
+ }
print_kind_and_origin(st);
#ifndef PRODUCT
--- a/hotspot/src/share/vm/runtime/os.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/runtime/os.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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,6 +25,7 @@
#include "precompiled.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/javaClasses.hpp"
+#include "classfile/moduleEntry.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
@@ -1229,7 +1230,7 @@
FREE_C_HEAP_ARRAY(char, jimage);
// check if developer build with exploded modules
- char* base_classes = format_boot_path("%/modules/java.base", home, home_len, fileSep, pathSep);
+ char* base_classes = format_boot_path("%/modules/" JAVA_BASE_NAME, home, home_len, fileSep, pathSep);
if (base_classes == NULL) return false;
if (os::stat(base_classes, &st) == 0) {
Arguments::set_sysclasspath(base_classes, false);
--- a/hotspot/src/share/vm/runtime/reflection.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/runtime/reflection.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -534,22 +534,26 @@
PackageEntry* package_to = new_class->package();
assert(package_to != NULL, "can not obtain new_class' package");
- // Once readability is established, if module_to exports T unqualifiedly,
- // (to all modules), than whether module_from is in the unnamed module
- // or not does not matter, access is allowed.
- if (package_to->is_unqual_exported()) {
- return ACCESS_OK;
- }
+ {
+ MutexLocker m1(Module_lock);
+
+ // Once readability is established, if module_to exports T unqualifiedly,
+ // (to all modules), than whether module_from is in the unnamed module
+ // or not does not matter, access is allowed.
+ if (package_to->is_unqual_exported()) {
+ return ACCESS_OK;
+ }
- // Access is allowed if both 1 & 2 hold:
- // 1. Readability, module_from can read module_to (established above).
- // 2. Either module_to exports T to module_from qualifiedly.
- // or
- // module_to exports T to all unnamed modules and module_from is unnamed.
- // or
- // module_to exports T unqualifiedly to all modules (checked above).
- if (!package_to->is_qexported_to(module_from)) {
- return TYPE_NOT_EXPORTED;
+ // Access is allowed if both 1 & 2 hold:
+ // 1. Readability, module_from can read module_to (established above).
+ // 2. Either module_to exports T to module_from qualifiedly.
+ // or
+ // module_to exports T to all unnamed modules and module_from is unnamed.
+ // or
+ // module_to exports T unqualifiedly to all modules (checked above).
+ if (!package_to->is_qexported_to(module_from)) {
+ return TYPE_NOT_EXPORTED;
+ }
}
return ACCESS_OK;
}
--- a/hotspot/src/share/vm/runtime/vframe_hp.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/runtime/vframe_hp.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -158,7 +158,7 @@
deferred = new(ResourceObj::C_HEAP, mtCompiler) GrowableArray<jvmtiDeferredLocalVariableSet*> (1, true);
thread()->set_deferred_locals(deferred);
}
- deferred->push(new jvmtiDeferredLocalVariableSet(method(), bci(), fr().id()));
+ deferred->push(new jvmtiDeferredLocalVariableSet(method(), bci(), fr().id(), vframe_id()));
assert(deferred->top()->id() == fr().id(), "Huh? Must match");
deferred->top()->set_local_at(index, type, value);
}
@@ -243,6 +243,7 @@
compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, CompiledMethod* nm)
: javaVFrame(fr, reg_map, thread) {
_scope = NULL;
+ _vframe_id = 0;
// Compiled method (native stub or Java code)
// native wrappers have no scope data, it is implied
if (!nm->is_compiled() || !nm->as_compiled_method()->is_native_method()) {
@@ -250,9 +251,10 @@
}
}
-compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, ScopeDesc* scope)
+compiledVFrame::compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, ScopeDesc* scope, int vframe_id)
: javaVFrame(fr, reg_map, thread) {
_scope = scope;
+ _vframe_id = vframe_id;
guarantee(_scope != NULL, "scope must be present");
}
@@ -316,14 +318,15 @@
} else {
return scope()->is_top()
? vframe::sender()
- : new compiledVFrame(&f, register_map(), thread(), scope()->sender());
+ : new compiledVFrame(&f, register_map(), thread(), scope()->sender(), vframe_id() + 1);
}
}
-jvmtiDeferredLocalVariableSet::jvmtiDeferredLocalVariableSet(Method* method, int bci, intptr_t* id) {
+jvmtiDeferredLocalVariableSet::jvmtiDeferredLocalVariableSet(Method* method, int bci, intptr_t* id, int vframe_id) {
_method = method;
_bci = bci;
_id = id;
+ _vframe_id = vframe_id;
// Alway will need at least one, must be on C heap
_locals = new(ResourceObj::C_HEAP, mtCompiler) GrowableArray<jvmtiDeferredLocalVariable*> (1, true);
}
@@ -339,7 +342,11 @@
bool jvmtiDeferredLocalVariableSet::matches(vframe* vf) {
if (!vf->is_compiled_frame()) return false;
compiledVFrame* cvf = (compiledVFrame*)vf;
- return cvf->fr().id() == id() && cvf->method() == method() && cvf->bci() == bci();
+ if (cvf->fr().id() == id() && cvf->vframe_id() == vframe_id()) {
+ assert(cvf->method() == method() && cvf->bci() == bci(), "must agree");
+ return true;
+ }
+ return false;
}
void jvmtiDeferredLocalVariableSet::set_local_at(int idx, BasicType type, jvalue val) {
--- a/hotspot/src/share/vm/runtime/vframe_hp.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/runtime/vframe_hp.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -36,6 +36,7 @@
StackValueCollection* locals() const;
StackValueCollection* expressions() const;
GrowableArray<MonitorInfo*>* monitors() const;
+ int vframe_id() const { return _vframe_id; }
void set_locals(StackValueCollection* values) const;
@@ -68,14 +69,14 @@
protected:
ScopeDesc* _scope;
-
+ int _vframe_id;
//StackValue resolve(ScopeValue* sv) const;
BasicLock* resolve_monitor_lock(Location location) const;
StackValue *create_stack_value(ScopeValue *sv) const;
private:
- compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, ScopeDesc* scope);
+ compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, ScopeDesc* scope, int vframe_id);
#ifndef PRODUCT
public:
@@ -95,6 +96,7 @@
Method* _method;
int _bci;
intptr_t* _id;
+ int _vframe_id;
GrowableArray<jvmtiDeferredLocalVariable*>* _locals;
public:
@@ -102,6 +104,7 @@
Method* method() const { return _method; }
int bci() const { return _bci; }
intptr_t* id() const { return _id; }
+ int vframe_id() const { return _vframe_id; }
GrowableArray<jvmtiDeferredLocalVariable*>* locals() const { return _locals; }
void set_local_at(int idx, BasicType typ, jvalue val);
@@ -111,7 +114,7 @@
void oops_do(OopClosure* f);
// constructor
- jvmtiDeferredLocalVariableSet(Method* method, int bci, intptr_t* id);
+ jvmtiDeferredLocalVariableSet(Method* method, int bci, intptr_t* id, int vframe_id);
// destructor
~jvmtiDeferredLocalVariableSet();
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -2453,7 +2453,6 @@
/* ConstMethod anon-enum */ \
/********************************/ \
\
- declare_constant(Method::_jfr_towrite) \
declare_constant(Method::_caller_sensitive) \
declare_constant(Method::_force_inline) \
declare_constant(Method::_dont_inline) \
--- a/hotspot/src/share/vm/runtime/vm_version.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/runtime/vm_version.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -131,19 +131,32 @@
return UseSharedSpaces ? "interpreted mode, sharing" : "interpreted mode";
case Arguments::_mixed:
if (UseSharedSpaces) {
- if (UseAOT) {
- return "mixed mode, aot, sharing";
- } else {
- return "mixed mode, sharing";
- }
+ if (UseAOT) {
+ return "mixed mode, aot, sharing";
+#ifdef TIERED
+ } else if(is_client_compilation_mode_vm()) {
+ return "mixed mode, emulated-client, sharing";
+#endif
+ } else {
+ return "mixed mode, sharing";
+ }
} else {
if (UseAOT) {
return "mixed mode, aot";
+#ifdef TIERED
+ } else if(is_client_compilation_mode_vm()) {
+ return "mixed mode, emulated-client";
+#endif
} else {
return "mixed mode";
}
}
case Arguments::_comp:
+#ifdef TIERED
+ if (is_client_compilation_mode_vm()) {
+ return UseSharedSpaces ? "compiled mode, emulated-client, sharing" : "compiled mode, emulated-client";
+ }
+#endif
return UseSharedSpaces ? "compiled mode, sharing" : "compiled mode";
};
ShouldNotReachHere();
--- a/hotspot/src/share/vm/services/diagnosticCommand.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -292,7 +292,7 @@
char *opt = (char *)os::malloc(opt_len, mtInternal);
if (opt == NULL) {
output()->print_cr("JVMTI agent attach failed: "
- "Could not allocate %zu bytes for argument.",
+ "Could not allocate " SIZE_FORMAT " bytes for argument.",
opt_len);
return;
}
@@ -748,13 +748,13 @@
ResourceMark rm(THREAD);
HandleMark hm(THREAD);
- // Load and initialize the sun.management.Agent class
+ // Load and initialize the jdk.internal.agent.Agent class
// invoke startRemoteManagementAgent(string) method to start
// the remote management server.
// throw java.lang.NoSuchMethodError if the method doesn't exist
Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
- Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::sun_management_Agent(), loader, Handle(), true, CHECK);
+ Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK);
instanceKlassHandle ik (THREAD, k);
JavaValue result(T_VOID);
@@ -821,13 +821,13 @@
ResourceMark rm(THREAD);
HandleMark hm(THREAD);
- // Load and initialize the sun.management.Agent class
+ // Load and initialize the jdk.internal.agent.Agent class
// invoke startLocalManagementAgent(void) method to start
// the local management server
// throw java.lang.NoSuchMethodError if method doesn't exist
Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
- Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::sun_management_Agent(), loader, Handle(), true, CHECK);
+ Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK);
instanceKlassHandle ik (THREAD, k);
JavaValue result(T_VOID);
@@ -838,13 +838,13 @@
ResourceMark rm(THREAD);
HandleMark hm(THREAD);
- // Load and initialize the sun.management.Agent class
+ // Load and initialize the jdk.internal.agent.Agent class
// invoke stopRemoteManagementAgent method to stop the
// management server
// throw java.lang.NoSuchMethodError if method doesn't exist
Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
- Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::sun_management_Agent(), loader, Handle(), true, CHECK);
+ Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK);
instanceKlassHandle ik (THREAD, k);
JavaValue result(T_VOID);
@@ -860,12 +860,12 @@
ResourceMark rm(THREAD);
HandleMark hm(THREAD);
- // Load and initialize the sun.management.Agent class
+ // Load and initialize the jdk.internal.agent.Agent class
// invoke getManagementAgentStatus() method to generate the status info
// throw java.lang.NoSuchMethodError if method doesn't exist
Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
- Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::sun_management_Agent(), loader, Handle(), true, CHECK);
+ Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK);
instanceKlassHandle ik (THREAD, k);
JavaValue result(T_OBJECT);
--- a/hotspot/src/share/vm/services/management.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/services/management.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -145,16 +145,16 @@
ResourceMark rm(THREAD);
HandleMark hm(THREAD);
- // Load and initialize the sun.management.Agent class
+ // Load and initialize the jdk.internal.agent.Agent class
// invoke startAgent method to start the management server
Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
- Klass* k = SystemDictionary::resolve_or_null(vmSymbols::sun_management_Agent(),
+ Klass* k = SystemDictionary::resolve_or_null(vmSymbols::jdk_internal_agent_Agent(),
loader,
Handle(),
THREAD);
if (k == NULL) {
vm_exit_during_initialization("Management agent initialization failure: "
- "class sun.management.Agent not found.");
+ "class jdk.internal.agent.Agent not found.");
}
instanceKlassHandle ik (THREAD, k);
--- a/hotspot/src/share/vm/trace/traceMacros.hpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/trace/traceMacros.hpp Thu Feb 09 23:15:52 2017 +0100
@@ -55,6 +55,8 @@
#define TRACE_DEFINE_THREAD_ID_SIZE typedef int ___IGNORED_hs_trace_type6
#define TRACE_DEFINE_THREAD_DATA_WRITER_OFFSET typedef int ___IGNORED_hs_trace_type7
#define TRACE_THREAD_DATA_WRITER_OFFSET in_ByteSize(0); ShouldNotReachHere()
+#define TRACE_DEFINE_FLAG typedef int ___IGNORED_hs_trace_type8
+#define TRACE_DEFINE_FLAG_ACCESSOR typedef int ___IGNORED_hs_trace_type9
#define TRACE_TEMPLATES(template)
#define TRACE_INTRINSICS(do_intrinsic, do_class, do_name, do_signature, do_alias)
--- a/hotspot/src/share/vm/utilities/copy.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/src/share/vm/utilities/copy.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -214,7 +214,7 @@
case 2: do_conjoint_swap<uint16_t,D>(src, dst, byte_count); break;
case 4: do_conjoint_swap<uint32_t,D>(src, dst, byte_count); break;
case 8: do_conjoint_swap<uint64_t,D>(src, dst, byte_count); break;
- default: guarantee(false, "do_conjoint_swap: Invalid elem_size %zd\n", elem_size);
+ default: guarantee(false, "do_conjoint_swap: Invalid elem_size " SIZE_FORMAT "\n", elem_size);
}
}
};
--- a/hotspot/test/ProblemList.txt Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/ProblemList.txt Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2016, 2017, 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
@@ -55,7 +55,7 @@
gc/g1/humongousObjects/objectGraphTest/TestObjectGraphAfterGC.java 8156755 generic-all
gc/survivorAlignment/TestPromotionToSurvivor.java 8129886 generic-all
-gc/stress/TestStressG1Humongous.java 8171045 generic-all
+gc/g1/logging/TestG1LoggingFailure.java 8169634 generic-all
#############################################################################
@@ -78,5 +78,7 @@
# :hotspot_misc
+testlibrary_tests/ctw/JarDirTest.java 8172457 windows-all
+
#############################################################################
--- a/hotspot/test/TEST.ROOT Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/TEST.ROOT Thu Feb 09 23:15:52 2017 +0100
@@ -46,6 +46,8 @@
vm.gc.Parallel \
vm.gc.ConcMarkSweep \
vm.jvmci \
+ vm.emulatedClient \
+ vm.cpu.features \
vm.debug
# Tests using jtreg 4.2 b04 features
--- a/hotspot/test/compiler/aot/AotCompiler.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/aot/AotCompiler.java Thu Feb 09 23:15:52 2017 +0100
@@ -69,7 +69,7 @@
extraopts.add("-classpath");
extraopts.add(Utils.TEST_CLASS_PATH + File.pathSeparator + Utils.TEST_SRC);
if (className != null && libName != null) {
- OutputAnalyzer oa = launchCompiler(libName, className + ".class", extraopts, compileList);
+ OutputAnalyzer oa = launchCompiler(libName, className, extraopts, compileList);
oa.shouldHaveExitValue(0);
} else {
printUsage();
@@ -93,12 +93,14 @@
}
}
List<String> args = new ArrayList<>();
+ args.add("--compile-with-assertions");
args.add("--output");
args.add(libName);
if (file != null) {
args.add("--compile-commands");
args.add(file.toString());
}
+ args.add("--class-name");
args.add(item);
return launchJaotc(args, extraopts);
}
--- a/hotspot/test/compiler/aot/RecompilationTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/aot/RecompilationTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -33,6 +33,7 @@
* @run main compiler.aot.AotCompiler -libname libRecompilationTest1.so
* -class compiler.whitebox.SimpleTestCaseHelper
* -extraopt -Dgraal.TieredAOT=true -extraopt -Dgraal.ProfileSimpleMethods=true
+ * -extraopt -Dgraal.ProbabilisticProfiling=false
* -extraopt -XX:+UnlockDiagnosticVMOptions -extraopt -XX:+WhiteBoxAPI -extraopt -Xbootclasspath/a:.
* -extraopt -XX:-UseCompressedOops
* -extraopt -XX:CompileCommand=dontinline,compiler.whitebox.SimpleTestCaseHelper::*
--- a/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionTest.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @library / /test/lib /testlibrary
- * @modules java.base/jdk.internal.misc
- * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
- * @build compiler.aot.cli.jaotc.ClasspathOptionTest
- * @run driver ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne
- * @run driver compiler.aot.cli.jaotc.ClasspathOptionTest
- * @summary check jaotc can compile class from classpath
- */
-
-package compiler.aot.cli.jaotc;
-
-import compiler.aot.cli.jaotc.data.HelloWorldOne;
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import jdk.test.lib.Asserts;
-import jdk.test.lib.process.OutputAnalyzer;
-
-public class ClasspathOptionTest {
- public static void main(String[] args) {
- Path cp = Paths.get("testClasspath");
- try {
- Files.createDirectory(cp);
- Files.move(Paths.get("compiler"), cp.resolve("compiler"));
- } catch (IOException e) {
- throw new Error("TESTBUG: can't create test data " + e, e);
- }
- OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--classpath", cp.toString(),
- JaotcTestHelper.getClassAotCompilationName(HelloWorldOne.class));
- oa.shouldHaveExitValue(0);
- File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
- Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file missing");
- Asserts.assertGT(compiledLibrary.length(), 0L, "Unexpected compiled library size");
- JaotcTestHelper.checkLibraryUsage(HelloWorldOne.class.getName());
- }
-}
--- a/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionUnknownClassTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionUnknownClassTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -39,7 +39,7 @@
public class ClasspathOptionUnknownClassTest {
public static void main(String[] args) {
- OutputAnalyzer oa = JaotcTestHelper.compileLibrary("HelloWorldOne.class");
+ OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--class-name", "HelloWorldOne");
Asserts.assertNE(oa.getExitValue(), 0, "Unexpected compilation exit code");
File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
Asserts.assertFalse(compiledLibrary.exists(), "Compiler library unexpectedly exists");
--- a/hotspot/test/compiler/aot/cli/jaotc/CompileClassTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/aot/cli/jaotc/CompileClassTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -41,7 +41,7 @@
public class CompileClassTest {
public static void main(String[] args) {
- OutputAnalyzer oa = JaotcTestHelper.compileLibrary(JaotcTestHelper
+ OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--class-name", JaotcTestHelper
.getClassAotCompilationName(HelloWorldOne.class));
oa.shouldHaveExitValue(0);
File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
--- a/hotspot/test/compiler/aot/cli/jaotc/CompileDirectoryTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/aot/cli/jaotc/CompileDirectoryTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -42,7 +42,7 @@
public class CompileDirectoryTest {
public static void main(String[] args) {
- OutputAnalyzer oa =JaotcTestHelper.compileLibrary(".");
+ OutputAnalyzer oa =JaotcTestHelper.compileLibrary("--directory", ".");
oa.shouldHaveExitValue(0);
File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file missing");
--- a/hotspot/test/compiler/aot/cli/jaotc/CompileJarTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/aot/cli/jaotc/CompileJarTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -48,7 +48,7 @@
public static void main(String[] args) {
createJar();
- OutputAnalyzer oa = JaotcTestHelper.compileLibrary(JAR_NAME);
+ OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--jar", JAR_NAME);
oa.shouldHaveExitValue(0);
File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file missing");
--- a/hotspot/test/compiler/aot/cli/jaotc/JaotcTestHelper.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/aot/cli/jaotc/JaotcTestHelper.java Thu Feb 09 23:15:52 2017 +0100
@@ -44,6 +44,7 @@
for (String vmOpt : Utils.getTestJavaOpts()) {
launcher.addVMArg(vmOpt);
}
+ launcher.addToolArg("--compile-with-assertions");
for (String arg : args) {
launcher.addToolArg(arg);
}
@@ -70,7 +71,11 @@
}
}
- public static String getClassAotCompilationName(Class<?> classToCompile) {
+ public static String getClassAotCompilationFilename(Class<?> classToCompile) {
return classToCompile.getName().replaceAll("\\.", File.separator) + ".class";
}
+
+ public static String getClassAotCompilationName(Class<?> classToCompile) {
+ return classToCompile.getName();
+ }
}
--- a/hotspot/test/compiler/aot/cli/jaotc/ListOptionNotExistingTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/aot/cli/jaotc/ListOptionNotExistingTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -45,7 +45,7 @@
public static void main(String[] args) {
OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--compile-commands", "./notExisting.list",
- COMPILE_ITEM);
+ "--class-name", COMPILE_ITEM);
int exitCode = oa.getExitValue();
Asserts.assertNE(exitCode, 0, "Unexpected compilation exit code");
File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
--- a/hotspot/test/compiler/aot/cli/jaotc/ListOptionTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/aot/cli/jaotc/ListOptionTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -66,7 +66,7 @@
throw new Error("TESTBUG: can't write list file " + e, e);
}
OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--compile-commands", COMPILE_COMMAND_FILE.toString(),
- JaotcTestHelper.getClassAotCompilationName(HelloWorldOne.class));
+ "--class-name", JaotcTestHelper.getClassAotCompilationName(HelloWorldOne.class));
oa.shouldHaveExitValue(0);
File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file missing");
--- a/hotspot/test/compiler/aot/cli/jaotc/ListOptionWrongFileTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/aot/cli/jaotc/ListOptionWrongFileTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -49,12 +49,15 @@
private static final String COMPILE_ITEM
= JaotcTestHelper.getClassAotCompilationName(HelloWorldOne.class);
+ private static final String COMPILE_FILE
+ = JaotcTestHelper.getClassAotCompilationFilename(HelloWorldOne.class);
+
public static void main(String[] args) {
// expecting wrong file to be read but no compilation directive recognized, so, all compiled
- OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--compile-commands", COMPILE_ITEM, COMPILE_ITEM);
+ OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--compile-commands", COMPILE_FILE, "--class-name", COMPILE_ITEM);
oa.shouldHaveExitValue(0);
File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
- Asserts.assertTrue(compiledLibrary.exists(), "Expecte compiler library to exist");
+ Asserts.assertTrue(compiledLibrary.exists(), "Expected compiler library to exist");
JaotcTestHelper.checkLibraryUsage(HelloWorldOne.class.getName(), EXPECTED, null);
}
}
--- a/hotspot/test/compiler/aot/fingerprint/CDSDumper.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package compiler.aot.fingerprint;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.PrintStream;
-
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.process.ProcessTools;
-
-// Usage:
-// java CDSDumper <classpath> <classlist> <archive> <class1> <class2> ...
-public class CDSDumper {
- public static void main(String[] args) throws Exception {
- String classpath = args[0];
- String classlist = args[1];
- String archive = args[2];
-
- // Prepare the classlist
- FileOutputStream fos = new FileOutputStream(classlist);
- PrintStream ps = new PrintStream(fos);
-
- for (int i=3; i<args.length; i++) {
- ps.println(args[i].replace('.', '/'));
- }
- ps.close();
- fos.close();
-
- // Dump the archive
- ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
- "-XX:+UnlockCommercialFeatures",
- "-XX:+UseAppCDS",
- "-XX:+UnlockDiagnosticVMOptions",
- "-cp", classpath,
- "-XX:ExtraSharedClassListFile=" + classlist,
- "-XX:SharedArchiveFile=" + archive,
- "-Xshare:dump",
- "-XX:+PrintSharedSpaces");
-
- OutputAnalyzer output = new OutputAnalyzer(pb.start());
- output.shouldContain("Loading classes to share");
- output.shouldHaveExitValue(0);
- }
-}
--- a/hotspot/test/compiler/aot/fingerprint/CDSRunner.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package compiler.aot.fingerprint;
-
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.process.ProcessTools;
-
-// Usage:
-// java CDSRunner <vmargs> <class> <args> ...
-public class CDSRunner {
- public static void main(String[] args) throws Exception {
- ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args);
- OutputAnalyzer output = new OutputAnalyzer(pb.start());
-
- System.out.println("[stdout = " + output.getStdout() + "]");
- System.out.println("[stderr = " + output.getStderr() + "]");
-
- output.shouldContain("PASSED");
- output.shouldHaveExitValue(0);
- }
-}
--- a/hotspot/test/compiler/aot/fingerprint/SelfChanged.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @summary AOT methods should be swept if a super class has changed.
- * @library /test/lib /
- * @modules java.base/jdk.internal.misc
- * java.management
- * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
- * @build compiler.aot.fingerprint.SelfChanged
- * compiler.aot.AotCompiler
- *
- * @run main
- * compiler.aot.fingerprint.SelfChanged WRITE-UNMODIFIED-CLASS
- * @run main/othervm compiler.aot.AotCompiler -libname libSelfChanged.so
- * -class compiler.aot.fingerprint.Blah
- *
- * @run main/othervm
- * compiler.aot.fingerprint.SelfChanged TEST-UNMODIFIED
- * @run main/othervm -XX:+UseAOT -XX:+PrintAOT -XX:AOTLibrary=./libSelfChanged.so
- * -Xlog:aot+class+fingerprint=trace -Xlog:aot+class+load=trace
- * compiler.aot.fingerprint.SelfChanged TEST-UNMODIFIED
- *
- * @run main
- * compiler.aot.fingerprint.SelfChanged WRITE-MODIFIED-CLASS
- * @run main
- * compiler.aot.fingerprint.SelfChanged TEST-MODIFIED
- * @run main/othervm -XX:+UseAOT -XX:+PrintAOT -XX:AOTLibrary=./libSelfChanged.so
- * -Xlog:aot+class+fingerprint=trace -Xlog:aot+class+load=trace
- * compiler.aot.fingerprint.SelfChanged TEST-MODIFIED
- */
-
-package compiler.aot.fingerprint;
-
-import jdk.test.lib.Asserts;
-import jdk.test.lib.InMemoryJavaCompiler;
-
-import java.io.*;
-
-class Blah {
- volatile int z;
- int getX() {
- for (z = 0; z < 10000; z++) {
- if (z % 7 == 1) {
- z += 2;
- }
- }
- return 0;
- }
-}
-
-public class SelfChanged {
- public static void main(String args[]) throws Throwable {
- Blah f = new Blah();
- System.out.println("f.getX = " + f.getX());
- switch (args[0]) {
- case "WRITE-UNMODIFIED-CLASS":
- compileClass(false);
- break;
- case "WRITE-MODIFIED-CLASS":
- compileClass(true);
- break;
- case "TEST-UNMODIFIED":
- Asserts.assertTrue(f.getX() == 0, "getX from unmodified Blah class should return 0");
- break;
- case "TEST-MODIFIED":
- Asserts.assertTrue(f.getX() == 1, "getX from modified Blah class should return 1");
- break;
- default:
- throw new RuntimeException("unexpected option: " + args[0]);
- }
- }
-
- static void compileClass(boolean isModified) throws Throwable {
- String src =
- "package compiler.aot.fingerprint;"
- + "public class Blah {"
- + " volatile int z;"
- + " int getX() {"
- + " for (z = 0; z < 10000; z++) {"
- + " if (z % 7 == 1) {"
- + " z += 2;"
- + " }"
- + " }"
- + " return " + ((isModified) ? "1" : "0") + ";"
- + " }"
- + " int getY() {return 255;}"
-
- // The following is for the SelfChangedCDS.java test case. We always load an unmodified
- // version of Blah from the CDS archive. However, we would load an AOT library that
- // was compiled using a modified version of Blah. The getX method in this AOT library should
- // not be used.
-
- + " public static void main(String args[]) {"
- + " Blah b = new Blah();"
- + " int n = b.getX();"
- + " if (n != 0) {"
- + " throw new RuntimeException(args[0] + \" : \" + n);"
- + " }"
- + " System.out.println(\"PASSED\");"
- + " }"
- + "}";
-
- String filename = System.getProperty("test.classes") + "/compiler/aot/fingerprint/Blah.class";
- FileOutputStream fos = new FileOutputStream(filename);
- fos.write(InMemoryJavaCompiler.compile("compiler.aot.fingerprint.Blah", src));
- fos.close();
- }
-}
--- a/hotspot/test/compiler/aot/fingerprint/SelfChangedCDS.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @summary AOT methods should be swept if a super class has changed (with CDS).
- * @library /test/lib /
- * @modules java.base/jdk.internal.misc
- * java.management
- * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
- * @build compiler.aot.fingerprint.SelfChanged
- * compiler.aot.AotCompiler
- *
- * @run main compiler.aot.fingerprint.SelfChanged WRITE-UNMODIFIED-CLASS
- * @run main/othervm compiler.aot.AotCompiler -libname libSelfChanged.so
- * -class compiler.aot.fingerprint.Blah
- *
- * @run main ClassFileInstaller -jar SelfChangedCDS.jar compiler.aot.fingerprint.Blah
- * @run main compiler.aot.fingerprint.CDSDumper SelfChangedCDS.jar SelfChangedCDS.classlist SelfChangedCDS.jsa
- * compiler.aot.fingerprint.Blah
- *
- * @run main compiler.aot.fingerprint.CDSRunner -cp SelfChangedCDS.jar
- * compiler.aot.fingerprint.Blah TEST-UNMODIFIED
- * @run main compiler.aot.fingerprint.CDSRunner -cp SelfChangedCDS.jar
- * -XX:+UseAOT -XX:+PrintAOT -XX:AOTLibrary=./libSelfChanged.so
- * -XX:+UnlockDiagnosticVMOptions -XX:SharedArchiveFile=SelfChangedCDS.jsa
- * -Xshare:auto -XX:+UnlockCommercialFeatures -XX:+UseAppCDS -showversion
- * -Xlog:aot+class+fingerprint=trace -Xlog:aot+class+load=trace
- * compiler.aot.fingerprint.Blah TEST-UNMODIFIED
- *
- * @run main
- * compiler.aot.fingerprint.SelfChanged WRITE-MODIFIED-CLASS
- * @run main/othervm compiler.aot.AotCompiler -libname libSelfChanged.so
- * -class compiler.aot.fingerprint.Blah
- *
- * @run main compiler.aot.fingerprint.CDSRunner -cp SelfChangedCDS.jar
- * compiler.aot.fingerprint.Blah TEST-MODIFIED
- * @run main compiler.aot.fingerprint.CDSRunner -cp SelfChangedCDS.jar
- * -XX:+UseAOT -XX:+PrintAOT -XX:AOTLibrary=./libSelfChanged.so
- * -XX:+UnlockDiagnosticVMOptions -XX:SharedArchiveFile=SelfChangedCDS.jsa
- * -Xshare:auto -XX:+UnlockCommercialFeatures -XX:+UseAppCDS -showversion
- * -Xlog:aot+class+fingerprint=trace -Xlog:aot+class+load=trace
- * compiler.aot.fingerprint.Blah TEST-MODIFIED
- */
--- a/hotspot/test/compiler/aot/fingerprint/SuperChanged.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @summary AOT methods should be swept if a super class has changed.
- * @library /test/lib /
- * @modules java.base/jdk.internal.misc
- * java.management
- * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
- * @build compiler.aot.fingerprint.SuperChanged
- * compiler.aot.AotCompiler
- *
- * @run main
- * compiler.aot.fingerprint.SuperChanged WRITE-UNMODIFIED-CLASS
- * @run main/othervm compiler.aot.AotCompiler -libname libSuperChanged.so
- * -class compiler.aot.fingerprint.Foo
- *
- * @run main
- * compiler.aot.fingerprint.SuperChanged TEST-UNMODIFIED
- * @run main/othervm -XX:+UseAOT -XX:+PrintAOT -XX:AOTLibrary=./libSuperChanged.so
- * -Xlog:aot+class+fingerprint=trace -Xlog:aot+class+load=trace
- * compiler.aot.fingerprint.SuperChanged TEST-UNMODIFIED
- *
- * @run main
- * compiler.aot.fingerprint.SuperChanged WRITE-MODIFIED-CLASS
- * @run main
- * compiler.aot.fingerprint.SuperChanged TEST-MODIFIED
- * @run main/othervm -XX:+UseAOT -XX:+PrintAOT -XX:AOTLibrary=./libSuperChanged.so
- * -Xlog:aot+class+fingerprint=trace -Xlog:aot+class+load=trace
- * compiler.aot.fingerprint.SuperChanged TEST-MODIFIED
- */
-
-package compiler.aot.fingerprint;
-
-import jdk.test.lib.Asserts;
-import jdk.test.lib.InMemoryJavaCompiler;
-
-import java.io.*;
-
-class Bar {
- volatile int x = 0;
- volatile int y = 1;
-}
-
-class Foo extends Bar {
-
- volatile int z;
- int getX() {
- for (z = 0; z < 10000; z++) {
- if (z % 7 == 1) {
- z += 2;
- }
- }
- return x;
- }
-}
-
-public class SuperChanged {
- public static void main(String args[]) throws Throwable {
- Foo f = new Foo();
- System.out.println("f.getX = " + f.getX());
- switch (args[0]) {
- case "WRITE-UNMODIFIED-CLASS":
- compileClass(false);
- break;
- case "WRITE-MODIFIED-CLASS":
- compileClass(true);
- break;
- case "TEST-UNMODIFIED":
- Asserts.assertTrue(f.getX() == 0, "getX from unmodified Foo class should return 0");
- break;
- case "TEST-MODIFIED":
- Asserts.assertTrue(f.getX() == 1, "getX from modified Foo class should return 1");
- break;
- default:
- throw new RuntimeException("unexpected option: " + args[0]);
- }
- }
-
- static void compileClass(boolean isModified) throws Throwable {
- String class_src_0 = "package compiler.aot.fingerprint; class Bar {volatile int x = 0; volatile int y = 1;}";
- String class_src_1 = "package compiler.aot.fingerprint; class Bar {volatile int y = 0; volatile int x = 1;}";
- String src = (isModified) ? class_src_1 : class_src_0;
-
- String filename = System.getProperty("test.classes") + "/compiler/aot/fingerprint/Bar.class";
- FileOutputStream fos = new FileOutputStream(filename);
- fos.write(InMemoryJavaCompiler.compile("compiler.aot.fingerprint.Bar", src));
- fos.close();
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSearchTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.test.collect;
+
+
+import jdk.tools.jaotc.LoadedClass;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.function.BiConsumer;
+
+public class ClassSearchTest {
+ @Test(expected = InternalError.class)
+ public void itShouldThrowExceptionIfNoProvidersAvailable() {
+ ClassSearch target = new ClassSearch();
+ SearchPath searchPath = new SearchPath();
+ target.search(list("foo"), searchPath);
+ }
+
+ @Test
+ public void itShouldFindAProviderForEachEntry() {
+ Set<String> searched = new HashSet<>();
+ ClassSearch target = new ClassSearch();
+ target.addProvider(new SourceProvider() {
+ @Override
+ public ClassSource findSource(String name, SearchPath searchPath) {
+ searched.add(name);
+ return new NoopSource();
+ }
+ });
+ target.search(list("foo", "bar", "foobar"), null);
+ Assert.assertEquals(hashset("foo", "bar", "foobar"), searched);
+ }
+
+ @Test
+ public void itShouldSearchAllProviders() {
+ Set<String> visited = new HashSet<>();
+ ClassSearch target = new ClassSearch();
+ target.addProvider((name, searchPath) -> {
+ visited.add("1");
+ return null;
+ });
+ target.addProvider((name, searchPath) -> {
+ visited.add("2");
+ return null;
+ });
+
+ try {
+ target.search(list("foo"), null);
+ } catch (InternalError e) {
+ // throws because no provider gives a source
+ }
+
+ Assert.assertEquals(hashset("1", "2"), visited);
+ }
+
+ @Test
+ public void itShouldTryToLoadSaidClassFromClassLoader() {
+ Set<String> loaded = new HashSet<>();
+
+ ClassSearch target = new ClassSearch();
+ target.addProvider(new SourceProvider() {
+ @Override
+ public ClassSource findSource(String name, SearchPath searchPath) {
+ return new ClassSource() {
+ @Override
+ public void eachClass(BiConsumer<String, ClassLoader> consumer) {
+ consumer.accept("foo.Bar", new ClassLoader() {
+ @Override
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ loaded.add(name);
+ return null;
+ }
+ });
+ }
+ };
+ }
+ });
+
+ java.util.List<LoadedClass> search = target.search(list("/tmp/something"), null);
+ Assert.assertEquals(list(new LoadedClass("foo.Bar", null)), search);
+ }
+
+ @Test(expected = InternalError.class)
+ public void itShouldThrowInternalErrorWhenClassLoaderFails() {
+ ClassLoader classLoader = new ClassLoader() {
+ @Override
+ public Class<?> loadClass(String name1) throws ClassNotFoundException {
+ throw new ClassNotFoundException("failed to find " + name1);
+ }
+ };
+
+ ClassSearch target = new ClassSearch();
+ target.addProvider((name, searchPath) -> consumer -> consumer.accept("foo.Bar", classLoader));
+ target.search(list("foobar"), null);
+ }
+
+ private <T> List<T> list(T... entries) {
+ List<T> list = new ArrayList<T>();
+ for (T entry : entries) {
+ list.add(entry);
+ }
+ return list;
+ }
+
+ private <T> Set<T> hashset(T... entries) {
+ Set<T> set = new HashSet<T>();
+ for (T entry : entries) {
+ set.add(entry);
+ }
+ return set;
+ }
+
+ private static class NoopSource implements ClassSource {
+ @Override
+ public void eachClass(BiConsumer<String, ClassLoader> consumer) {
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSourceTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.test.collect;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.nio.file.Paths;
+
+import static jdk.tools.jaotc.collect.ClassSource.makeClassName;
+
+public class ClassSourceTest {
+ @Test(expected=IllegalArgumentException.class)
+ public void itShouldThrowExceptionIfPathDoesntEndWithClass() {
+ makeClassName(Paths.get("Bar.clazz"));
+ }
+
+ @Test
+ public void itShouldReplaceSlashesWithDots() {
+ Assert.assertEquals("foo.Bar", makeClassName(Paths.get("foo/Bar.class")));
+ }
+
+ @Test
+ public void itShouldStripLeadingSlash() {
+ Assert.assertEquals("Hello", makeClassName(Paths.get("/Hello.class")));
+ }
+
+ @Test
+ public void itShouldReplaceMultipleDots() {
+ Assert.assertEquals("some.foo.bar.FooBar", makeClassName(Paths.get("/some/foo/bar/FooBar.class")));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeFileSupport.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.test.collect;
+
+import java.net.MalformedURLException;
+import java.nio.file.Path;
+import java.util.HashSet;
+import java.util.Set;
+
+public class FakeFileSupport extends FileSupport {
+ private final Set<String> exists = new HashSet<>();
+ private final Set<String> directories = new HashSet<>();
+
+ private final Set<String> checkedExists = new HashSet<>();
+ private final Set<String> checkedDirectory = new HashSet<>();
+ private final Set<String> checkedJarFileSystemRoots = new HashSet<>();
+ private final Set<String> classloaderPaths = new HashSet<>();
+
+ private Path jarFileSystemRoot = null;
+ private final ClassLoader classLoader;
+
+ public FakeFileSupport(Set<String> existing, Set<String> directories) {
+ this.exists.addAll(existing);
+ this.directories.addAll(directories);
+
+ classLoader = new ClassLoader() {
+ @Override
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ return null;
+ }
+ };
+ }
+
+ public void setJarFileSystemRoot(Path path) {
+ jarFileSystemRoot = path;
+ }
+
+ @Override
+ public boolean exists(Path path) {
+ checkedExists.add(path.toString());
+ return exists.contains(path.toString());
+ }
+
+ @Override
+ public boolean isDirectory(Path path) {
+ checkedDirectory.add(path.toString());
+ return directories.contains(path.toString());
+ }
+
+ @Override
+ public ClassLoader createClassLoader(Path path) throws MalformedURLException {
+ classloaderPaths.add(path.toString());
+ return classLoader;
+ }
+
+ @Override
+ public Path getJarFileSystemRoot(Path jarFile) {
+ checkedJarFileSystemRoots.add(jarFile.toString());
+ return jarFileSystemRoot;
+ }
+
+ @Override
+ public boolean isAbsolute(Path entry) {
+ return entry.toString().startsWith("/");
+ }
+
+ public void addExist(String name) {
+ exists.add(name);
+ }
+
+ public void addDirectory(String name) {
+ directories.add(name);
+ }
+
+ public Set<String> getCheckedExists() {
+ return checkedExists;
+ }
+
+ public Set<String> getCheckedDirectory() {
+ return checkedDirectory;
+ }
+
+ public Set<String> getCheckedJarFileSystemRoots() {
+ return checkedJarFileSystemRoots;
+ }
+
+ public Set<String> getClassloaderPaths() {
+ return classloaderPaths;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeSearchPath.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.test.collect;
+
+import java.nio.file.FileSystem;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Set;
+
+import static jdk.tools.jaotc.test.collect.Utils.set;
+
+public class FakeSearchPath extends SearchPath {
+ private Path path = null;
+ public Set<String> entries = set();
+
+ public FakeSearchPath(String name) {
+ if (name != null) {
+ path = Paths.get(name);
+ }
+ }
+
+ @Override
+ public Path find(FileSystem fileSystem, Path entry, String... defaults) {
+ entries.add(entry.toString());
+ return path;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/SearchPathTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.test.collect;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import static jdk.tools.jaotc.test.collect.Utils.set;
+import static org.junit.Assert.*;
+
+public class SearchPathTest {
+ private FakeFileSupport fileSupport;
+ private FileSystem fs;
+
+ @Before
+ public void setUp() throws Exception {
+ fs = FileSystems.getDefault();
+ }
+
+ @Test
+ public void itShouldUsePathIfPathIsAbsoluteAndExisting() {
+ fileSupport = new FakeFileSupport(set("/foo"), set());
+ SearchPath target = new SearchPath(fileSupport);
+ Path foo = Paths.get("/foo");
+ Path result = target.find(fs, foo);
+ assertSame(result, foo);
+ }
+
+ @Test
+ public void itShouldReturnNullIfPathIsAbsoluteAndNonExisting() {
+ fileSupport = new FakeFileSupport(set(), set());
+ SearchPath target = new SearchPath(fileSupport);
+ Path result = target.find(fs, Paths.get("/bar"));
+ assertNull(result);
+ }
+
+ @Test
+ public void itShouldUseRelativeExisting() {
+ fileSupport = new FakeFileSupport(set("hello", "tmp/hello", "search/hello"), set());
+ SearchPath target = new SearchPath(fileSupport);
+ target.add("search");
+ Path hello = Paths.get("hello");
+ Path result = target.find(fs, hello, "tmp");
+ assertSame(result, hello);
+ }
+
+ @Test
+ public void itShouldSearchDefaultsBeforeSearchPaths() {
+ fileSupport = new FakeFileSupport(set("bar/foobar"), set());
+ SearchPath target = new SearchPath(fileSupport);
+ Path result = target.find(fs, Paths.get("foobar"), "default1", "bar");
+ assertEquals("bar/foobar", result.toString());
+ assertEquals(set("foobar", "default1/foobar", "bar/foobar"), fileSupport.getCheckedExists());
+ }
+
+ @Test
+ public void itShouldUseSearchPathsIfNotInDefaults() {
+ fileSupport = new FakeFileSupport(set("bar/tmp/foobar"), set());
+ SearchPath target = new SearchPath(fileSupport);
+ target.add("foo/tmp", "bar/tmp");
+
+ Path result = target.find(fs, Paths.get("foobar"), "foo", "bar");
+ assertEquals("bar/tmp/foobar", result.toString());
+ assertEquals(set("foobar", "foo/foobar", "bar/foobar", "bar/tmp/foobar", "foo/tmp/foobar"), fileSupport.getCheckedExists());
+ }
+
+ @Test
+ public void itShouldReturnNullIfNoExistingPathIsFound() {
+ fileSupport = new FakeFileSupport(set(), set());
+ SearchPath target = new SearchPath(fileSupport);
+ target.add("dir1", "dir2");
+
+ Path result = target.find(fs, Paths.get("entry"), "dir3", "dir4");
+ assertNull(result);
+ assertEquals(set("entry", "dir1/entry", "dir2/entry", "dir3/entry", "dir4/entry"), fileSupport.getCheckedExists());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/Utils.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.test.collect;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class Utils {
+ public static <T> Set<T> set(T... entries) {
+ Set<T> set = new HashSet<T>();
+ for (T entry : entries) {
+ set.add(entry);
+ }
+ return set;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/directory/DirectorySourceProviderTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.test.collect.directory;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.test.collect.FakeFileSupport;
+import jdk.tools.jaotc.test.collect.FileSupport;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.net.MalformedURLException;
+import java.nio.file.Path;
+import java.util.Set;
+
+import static jdk.tools.jaotc.test.collect.Utils.set;
+
+public class DirectorySourceProviderTest {
+ @Test
+ public void itShouldReturnNullForNonExistantPath() {
+ DirectorySourceProvider target = new DirectorySourceProvider(new FakeFileSupport(set(), set()));
+ ClassSource result = target.findSource("hello", null);
+ Assert.assertNull(result);
+ }
+
+ @Test
+ public void itShouldReturnNullForNonDirectory() {
+ DirectorySourceProvider target = new DirectorySourceProvider(new FakeFileSupport(set("foobar"), set()));
+ ClassSource result = target.findSource("foobar", null);
+ Assert.assertNull(result);
+ }
+
+ @Test
+ public void itShouldReturnNullForMalformedURI() {
+ Set<String> visited = set();
+ DirectorySourceProvider target = new DirectorySourceProvider(new FakeFileSupport(set("foobar"), set("foobar")) {
+ @Override
+ public ClassLoader createClassLoader(Path path) throws MalformedURLException {
+ visited.add("1");
+ throw new MalformedURLException("...");
+ }
+ });
+ ClassSource result = target.findSource("foobar", null);
+ Assert.assertNull(result);
+ Assert.assertEquals(set("1"), visited);
+ }
+
+ @Test
+ public void itShouldCreateSourceIfNameExistsAndIsADirectory() {
+ FileSupport fileSupport = new FakeFileSupport(set("foo"), set("foo"));
+ DirectorySourceProvider target = new DirectorySourceProvider(fileSupport);
+ ClassSource foo = target.findSource("foo", null);
+ Assert.assertNotNull(foo);
+ Assert.assertEquals("directory:foo", foo.toString());
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/jar/JarSourceProviderTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.test.collect.jar;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.test.collect.FakeFileSupport;
+import jdk.tools.jaotc.test.collect.FakeSearchPath;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.ProviderNotFoundException;
+import java.util.Set;
+
+import static jdk.tools.jaotc.test.collect.Utils.set;
+
+public class JarSourceProviderTest {
+
+ private FakeFileSupport fileSupport;
+ private JarSourceProvider target;
+
+ @Before
+ public void setUp() throws Exception {
+ fileSupport = new FakeFileSupport(set(), set());
+ target = new JarSourceProvider(fileSupport);
+ }
+
+ @Test
+ public void itShouldUseSearchPathToFindPath() {
+ Set<String> visited = set();
+ JarSourceProvider target = new JarSourceProvider(fileSupport);
+ FakeSearchPath searchPath = new FakeSearchPath(null);
+ ClassSource source = target.findSource("hello", searchPath);
+
+ Assert.assertEquals(set("hello"), searchPath.entries);
+ }
+
+ @Test
+ public void itShouldReturnNullIfPathIsNull() {
+ JarSourceProvider target = new JarSourceProvider(fileSupport);
+ ClassSource source = target.findSource("foobar", new FakeSearchPath(null));
+ Assert.assertNull(source);
+ }
+
+ @Test
+ public void itShouldReturnNullIfPathIsDirectory() {
+ fileSupport.addDirectory("hello/foobar");
+ ClassSource source = target.findSource("foobar", new FakeSearchPath("hello/foobar"));
+
+ Assert.assertNull(source);
+ Assert.assertEquals(set("hello/foobar"), fileSupport.getCheckedDirectory());
+ }
+
+ @Test
+ public void itShouldReturnNullIfUnableToMakeJarFileSystem() {
+ fileSupport.setJarFileSystemRoot(null);
+ ClassSource result = target.findSource("foobar", new FakeSearchPath("foo/bar"));
+
+ Assert.assertEquals(set("foo/bar"), fileSupport.getCheckedJarFileSystemRoots());
+ Assert.assertNull(result);
+ }
+
+ @Test
+ public void itShouldReturnNullIfNotValidJarProvider() {
+ fileSupport = new FakeFileSupport(set(), set()) {
+
+ @Override
+ public Path getJarFileSystemRoot(Path jarFile) {
+ super.getJarFileSystemRoot(jarFile);
+ throw new ProviderNotFoundException();
+ }
+ };
+ fileSupport.setJarFileSystemRoot(null);
+ target = new JarSourceProvider(fileSupport);
+
+ ClassSource result = target.findSource("foobar", new FakeSearchPath("foo/bar"));
+
+ Assert.assertEquals(set("foo/bar"), fileSupport.getCheckedJarFileSystemRoots());
+ Assert.assertNull(result);
+ }
+
+ @Test
+ public void itShouldReturnSourceWhenAllIsValid() {
+ fileSupport.setJarFileSystemRoot(Paths.get("some/bar"));
+ ClassSource result = target.findSource("foobar", new FakeSearchPath("this/bar"));
+
+ Assert.assertEquals(set("this/bar"), fileSupport.getClassloaderPaths());
+ Assert.assertEquals("jar:this/bar", result.toString());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/module/ModuleSourceProviderTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2017, 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 jdk.tools.jaotc.test.collect.module;
+
+import jdk.tools.jaotc.*;
+import jdk.tools.jaotc.test.collect.FakeSearchPath;
+import jdk.tools.jaotc.test.collect.Utils;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.nio.file.FileSystems;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+public class ModuleSourceProviderTest {
+ private ClassLoader classLoader;
+ private ModuleSourceProvider target;
+
+ @Before
+ public void setUp() {
+ classLoader = new FakeClassLoader();
+ target = new ModuleSourceProvider(FileSystems.getDefault(), classLoader);
+ }
+
+ @Test
+ public void itShouldUseSearchPath() {
+ FakeSearchPath searchPath = new FakeSearchPath("blah/java.base");
+ ModuleSource source = (ModuleSource) target.findSource("java.base", searchPath);
+ assertEquals(Utils.set("java.base"), searchPath.entries);
+ assertEquals("blah/java.base", source.getModulePath().toString());
+ assertEquals("module:blah/java.base", source.toString());
+ }
+
+ @Test
+ public void itShouldReturnNullIfSearchPathReturnsNull() {
+ FakeSearchPath searchPath = new FakeSearchPath(null);
+ ModuleSource source = (ModuleSource) target.findSource("jdk.base", searchPath);
+ assertEquals(Utils.set("jdk.base"), searchPath.entries);
+ assertNull(source);
+ }
+
+ private static class FakeClassLoader extends ClassLoader {
+ @Override
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ return null;
+ }
+ }
+}
--- a/hotspot/test/compiler/aot/verification/ClassAndLibraryNotMatchTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/aot/verification/ClassAndLibraryNotMatchTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -85,9 +85,8 @@
}
private void compileAotLibrary() {
- AotCompiler.launchCompiler(LIB_NAME, HELLO_WORLD_CLASS_NAME + ".class",
- Arrays.asList("-classpath", Utils.TEST_CLASS_PATH + File.pathSeparator
- + Utils.TEST_SRC), null);
+ AotCompiler.launchCompiler(LIB_NAME, HELLO_WORLD_CLASS_NAME,
+ Arrays.asList("-classpath", Utils.TEST_CLASS_PATH + ":."), null);
}
private void runAndCheckHelloWorld(String checkString) {
--- a/hotspot/test/compiler/aot/verification/vmflags/BasicFlagsChange.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/aot/verification/vmflags/BasicFlagsChange.java Thu Feb 09 23:15:52 2017 +0100
@@ -76,7 +76,7 @@
extraOpts.add(option);
extraOpts.add("-classpath");
extraOpts.add(Utils.TEST_CLASS_PATH + File.pathSeparator + Utils.TEST_SRC);
- AotCompiler.launchCompiler(libName, className + ".class", extraOpts, null);
+ AotCompiler.launchCompiler(libName, className, extraOpts, null);
}
private static void runAndCheck(String option, String libName,
--- a/hotspot/test/compiler/arraycopy/TestArrayCopyNoInitDeopt.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/arraycopy/TestArrayCopyNoInitDeopt.java Thu Feb 09 23:15:52 2017 +0100
@@ -25,7 +25,7 @@
* @test
* @bug 8072016
* @summary Infinite deoptimization/recompilation cycles in case of arraycopy with tightly coupled allocation
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
@@ -86,8 +86,8 @@
}
static public void main(String[] args) throws Exception {
- if (!Platform.isServer()) {
- throw new Error("TESTBUG: Not server VM");
+ if (!Platform.isServer() || Platform.isEmulatedClient()) {
+ throw new Error("TESTBUG: Not server mode");
}
// Only execute if C2 is available
if (TIERED_STOP_AT_LEVEL == CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arraycopy/TestArrayCopyUNCBadMem.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017, Red Hat, 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
+ * @bug 8173147
+ * @summary Loads generated at uncommon trap from eliminated arraycopy have incorrect memory state
+ * @run main/othervm -XX:CompileOnly=TestArrayCopyUNCBadMem::test -Xcomp TestArrayCopyUNCBadMem
+ *
+ */
+
+
+public class TestArrayCopyUNCBadMem {
+
+ volatile static int field;
+
+ static class unloaded {
+ static int dummy;
+ }
+
+ static int test(int[] input) {
+ int[] alloc = new int[10];
+ System.arraycopy(input, 0, alloc, 0, 10);
+
+ // membars to have anti-dependence edges and make scheduling
+ // fail
+ field = 0x42;
+
+ // uncommon trap
+ unloaded.dummy = 0x42;
+
+ return alloc[0] + alloc[1];
+ }
+
+ public static void main(String[] args) {
+ int[] array = new int[10];
+ System.arraycopy(array, 0, array, 0, 0); // load System class
+ test(array);
+ }
+}
--- a/hotspot/test/compiler/c1/CanonicalizeArrayLength.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/c1/CanonicalizeArrayLength.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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,7 +23,7 @@
/*
* @test
- * @bug 8150102 8150514 8150534
+ * @bug 8150102 8150514 8150534 8171435
* @summary C1 crashes in Canonicalizer::do_ArrayLength() after fix for JDK-8150102
*
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
@@ -31,7 +31,7 @@
* -XX:-BackgroundCompilation
* compiler.c1.CanonicalizeArrayLength
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
- * -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1
+ * -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=3
* -XX:-BackgroundCompilation
* -XX:+PatchALot
* compiler.c1.CanonicalizeArrayLength
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/c1/Test8172751.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017, 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 8172751
+ * @summary OSR compilation at unreachable bci causes C1 crash
+ *
+ * @run main/othervm -XX:-BackgroundCompilation compiler.c1.Test8172751
+ */
+
+package compiler.c1;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MutableCallSite;
+
+public class Test8172751 {
+ private static final MethodHandle CONSTANT_TRUE = MethodHandles.constant(boolean.class, true);
+ private static final MethodHandle CONSTANT_FALSE = MethodHandles.constant(boolean.class, false);
+ private static final MutableCallSite CALL_SITE = new MutableCallSite(CONSTANT_FALSE);
+ private static final int LIMIT = 1_000_000;
+ private static volatile int counter;
+
+ private static boolean doSomething() {
+ return counter++ < LIMIT;
+ }
+
+ private static void executeLoop() {
+ /*
+ * Start off with executing the first loop, then change the call site
+ * target so as to switch over to the second loop but continue running
+ * in the first loop. Eventually, an OSR compilation of the first loop
+ * is triggered. Yet C1 will not find the OSR entry, since it will
+ * have optimized out the first loop already during parsing.
+ */
+ if (CALL_SITE.getTarget() == CONSTANT_FALSE) {
+ int count = 0;
+ while (doSomething()) {
+ if (count++ == 1) {
+ flipSwitch();
+ }
+ }
+ } else {
+ while (doSomething()) {
+ }
+ }
+ }
+
+ private static void flipSwitch() {
+ CALL_SITE.setTarget(CONSTANT_TRUE);
+ }
+
+ public static void main(String[] args) {
+ executeLoop();
+ }
+}
--- a/hotspot/test/compiler/c2/cr6589834/Test_ia32.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/c2/cr6589834/Test_ia32.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
*
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
--- a/hotspot/test/compiler/c2/cr7200264/Test7200264.sh Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2012, 2015, 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.
-#
-#
-
-## some tests require path to find test source dir
-if [ "${TESTSRC}" = "" ]
-then
- TESTSRC=${PWD}
- echo "TESTSRC not set. Using "${TESTSRC}" as default"
-fi
-echo "TESTSRC=${TESTSRC}"
-## Adding common setup Variables for running shell tests.
-. ${TESTSRC}/../../../test_env.sh
-
-${TESTJAVA}${FS}bin${FS}java ${TESTOPTS} -Xinternalversion | sed 's/amd64/x86/' | grep "x86" | grep "Server VM" | grep "debug"
-
-# Only test fastdebug Server VM on x86
-if [ $? != 0 ]
-then
- echo "Test Passed"
- exit 0
-fi
-
-# grep for support integer multiply vectors (cpu with SSE4.1)
-${TESTJAVA}${FS}bin${FS}java ${TESTOPTS} -XX:+PrintMiscellaneous -XX:+Verbose -version | grep "cores per cpu" | grep "sse4.1"
-
-if [ $? != 0 ]
-then
- SSE=2
-else
- SSE=4
-fi
-
-cp ${TESTSRC}${FS}TestIntVect.java .
-${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} -d . TestIntVect.java
-
-# CICompilerCount must be at least 2 with -TieredCompilation
-${TESTJAVA}${FS}bin${FS}java ${TESTOPTS} -Xbatch -XX:-TieredCompilation \
- -XX:CICompilerCount=2 -XX:+PrintCompilation -XX:+TraceNewVectors \
- compiler.c2.cr7200264.TestIntVect > test.out 2>&1
-
-COUNT=`grep AddVI test.out | wc -l | awk '{print $1}'`
-if [ $COUNT -lt 4 ]
-then
- echo "Test Failed: AddVI $COUNT < 4"
- exit 1
-fi
-
-# AddVI is generated for test_subc
-COUNT=`grep SubVI test.out | wc -l | awk '{print $1}'`
-if [ $COUNT -lt 4 ]
-then
- echo "Test Failed: SubVI $COUNT < 4"
- exit 1
-fi
-
-# MulVI is only supported with SSE4.1.
-if [ $SSE -gt 3 ]
-then
-# LShiftVI+SubVI is generated for test_mulc
-COUNT=`grep MulVI test.out | wc -l | awk '{print $1}'`
-if [ $COUNT -lt 2 ]
-then
- echo "Test Failed: MulVI $COUNT < 2"
- exit 1
-fi
-fi
-
-COUNT=`grep AndV test.out | wc -l | awk '{print $1}'`
-if [ $COUNT -lt 3 ]
-then
- echo "Test Failed: AndV $COUNT < 3"
- exit 1
-fi
-
-COUNT=`grep OrV test.out | wc -l | awk '{print $1}'`
-if [ $COUNT -lt 3 ]
-then
- echo "Test Failed: OrV $COUNT < 3"
- exit 1
-fi
-
-COUNT=`grep XorV test.out | wc -l | awk '{print $1}'`
-if [ $COUNT -lt 3 ]
-then
- echo "Test Failed: XorV $COUNT < 3"
- exit 1
-fi
-
-# LShiftVI+SubVI is generated for test_mulc
-COUNT=`grep LShiftVI test.out | wc -l | awk '{print $1}'`
-if [ $COUNT -lt 5 ]
-then
- echo "Test Failed: LShiftVI $COUNT < 5"
- exit 1
-fi
-
-COUNT=`grep RShiftVI test.out | sed '/URShiftVI/d' | wc -l | awk '{print $1}'`
-if [ $COUNT -lt 3 ]
-then
- echo "Test Failed: RShiftVI $COUNT < 3"
- exit 1
-fi
-
-COUNT=`grep URShiftVI test.out | wc -l | awk '{print $1}'`
-if [ $COUNT -lt 3 ]
-then
- echo "Test Failed: URShiftVI $COUNT < 3"
- exit 1
-fi
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/c2/cr7200264/TestDriver.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.c2.cr7200264;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import jdk.test.lib.Asserts;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class TestDriver {
+ private final Map<String, Long> expectedVectorizationNumbers
+ = new HashMap<>();
+
+ public void addExpectedVectorization(String v, long num) {
+ expectedVectorizationNumbers.put(v, num);
+ }
+
+ public void run() throws Throwable {
+ verifyVectorizationNumber(executeApplication());
+ }
+
+ private List<String> executeApplication() throws Throwable {
+ OutputAnalyzer outputAnalyzer = ProcessTools.executeTestJvmAllArgs(
+ "-Xbatch",
+ "-XX:-TieredCompilation",
+ "-XX:+PrintCompilation",
+ "-XX:+TraceNewVectors",
+ TestIntVect.class.getName());
+ outputAnalyzer.shouldHaveExitValue(0);
+ return outputAnalyzer.asLines();
+ }
+
+ private void verifyVectorizationNumber(List<String> vectorizationLog) {
+ for (Map.Entry<String, Long> entry : expectedVectorizationNumbers.entrySet()) {
+ String v = "\t" + entry.getKey();
+ long actualNum = vectorizationLog.stream()
+ .filter(s -> s.contains(v)).count();
+ long expectedNum = entry.getValue();
+ Asserts.assertGTE(actualNum, expectedNum,
+ "Unexpected " + entry.getKey() + " number");
+ }
+ }
+}
--- a/hotspot/test/compiler/c2/cr7200264/TestIntVect.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/c2/cr7200264/TestIntVect.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -21,14 +21,6 @@
* questions.
*/
-/**
- * @test
- * @bug 7200264
- * @summary 7192963 changes disabled shift vectors
- *
- * @run shell Test7200264.sh
- */
-
package compiler.c2.cr7200264;
/*
* Copy of test/compiler/6340864/TestIntVect.java without performance tests.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/c2/cr7200264/TestSSE2IntVect.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 7200264
+ * @summary 7192963 changes disabled shift vectors
+ * @requires vm.cpu.features ~= ".*sse2.*" & vm.debug & vm.flavor == "server"
+ * @requires !vm.emulatedClient
+ * @library /test/lib /
+ * @run driver compiler.c2.cr7200264.TestSSE2IntVect
+ */
+
+package compiler.c2.cr7200264;
+
+public class TestSSE2IntVect {
+ public static void main(String[] args) throws Throwable {
+ TestDriver test = new TestDriver();
+ test.addExpectedVectorization("AddVI", 4);
+ test.addExpectedVectorization("SubVI", 4);
+ test.addExpectedVectorization("AndV", 3);
+ test.addExpectedVectorization("OrV", 3);
+ test.addExpectedVectorization("XorV", 3);
+ test.addExpectedVectorization("LShiftVI", 5);
+ test.addExpectedVectorization("RShiftVI", 3);
+ test.addExpectedVectorization("URShiftVI", 3);
+ test.run();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/c2/cr7200264/TestSSE4IntVect.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 7200264
+ * @summary 7192963 changes disabled shift vectors
+ * @requires vm.cpu.features ~= ".*sse4\\.1.*" & vm.debug & vm.flavor == "server"
+ * @requires !vm.emulatedClient
+ * @library /test/lib /
+ * @run driver compiler.c2.cr7200264.TestSSE4IntVect
+ */
+
+package compiler.c2.cr7200264;
+
+public class TestSSE4IntVect {
+ public static void main(String[] args) throws Throwable {
+ TestDriver test = new TestDriver();
+ test.addExpectedVectorization("MulVI", 2);
+ test.run();
+ }
+}
--- a/hotspot/test/compiler/ciReplay/TestVMNoCompLevel.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/ciReplay/TestVMNoCompLevel.java Thu Feb 09 23:15:52 2017 +0100
@@ -65,7 +65,11 @@
throw new Error("Failed to read/write replay data: " + ioe, ioe);
}
if (CLIENT_VM_AVAILABLE) {
- negativeTest(CLIENT_VM_OPTION);
+ if (SERVER_VM_AVAILABLE) {
+ negativeTest(CLIENT_VM_OPTION);
+ } else {
+ positiveTest(CLIENT_VM_OPTION);
+ }
}
if (SERVER_VM_AVAILABLE) {
positiveTest(TIERED_DISABLED_VM_OPTION, SERVER_VM_OPTION);
--- a/hotspot/test/compiler/codecache/cli/TestSegmentedCodeCacheOption.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/codecache/cli/TestSegmentedCodeCacheOption.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
*
* @run driver compiler.codecache.cli.TestSegmentedCodeCacheOption
*/
--- a/hotspot/test/compiler/codecache/cli/codeheapsize/TestCodeHeapSizeOptions.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/codecache/cli/codeheapsize/TestCodeHeapSizeOptions.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
*
* @run driver/timeout=240 compiler.codecache.cli.codeheapsize.TestCodeHeapSizeOptions
*/
--- a/hotspot/test/compiler/codecache/cli/printcodecache/TestPrintCodeCacheOption.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/codecache/cli/printcodecache/TestPrintCodeCacheOption.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
*
* @run main/timeout=240 compiler.codecache.cli.printcodecache.TestPrintCodeCacheOption
*/
--- a/hotspot/test/compiler/codecache/stress/OverloadCompileQueueTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/codecache/stress/OverloadCompileQueueTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -65,9 +65,9 @@
AVAILABLE_LEVELS = IntStream
.rangeClosed(LEVEL_SIMPLE, TIERED_STOP_AT_LEVEL)
.toArray();
- } else if (Platform.isServer()) {
+ } else if (Platform.isServer() && !Platform.isEmulatedClient()) {
AVAILABLE_LEVELS = new int[] { LEVEL_FULL_OPTIMIZATION };
- } else if (Platform.isClient() || Platform.isMinimal()) {
+ } else if (Platform.isClient() || Platform.isMinimal() || Platform.isEmulatedClient()) {
AVAILABLE_LEVELS = new int[] { LEVEL_SIMPLE };
} else {
throw new Error("TESTBUG: unknown VM: " + Platform.vmName);
--- a/hotspot/test/compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java Thu Feb 09 23:15:52 2017 +0100
@@ -75,7 +75,7 @@
prepareArguments(prepareBooleanFlag(AESIntrinsicsBase
.USE_AES, true)));
final String errorMessage = "Case testUseAES failed";
- if (Platform.isServer()) {
+ if (Platform.isServer() && !Platform.isEmulatedClient()) {
verifyOutput(new String[]{AESIntrinsicsBase.CIPHER_INTRINSIC,
AESIntrinsicsBase.AES_INTRINSIC}, null, errorMessage,
outputAnalyzer);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/gcbarriers/TestMembarDependencies.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2017, 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 TestMembarDependencies
+ * @bug 8172850
+ * @summary Tests correct scheduling of memory loads around MembarVolatile emitted by GC barriers.
+ * @library /test/lib /
+ * @modules java.base/jdk.internal.misc
+ * java.management
+ * @run driver compiler.membars.TestMembarDependencies
+ */
+
+package compiler.membars;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class TestMembarDependencies {
+ private static TestMembarDependencies f1;
+ private static TestMembarDependencies f2;
+
+ public static void main(String args[]) throws Exception {
+ if (args.length == 0) {
+ // For debugging, add "-XX:+TraceOptoPipelining"
+ OutputAnalyzer oa = ProcessTools.executeTestJvm("-XX:+IgnoreUnrecognizedVMOptions",
+ "-XX:-TieredCompilation", "-XX:-BackgroundCompilation", "-XX:+PrintOpto",
+ "-XX:CompileCommand=compileonly,compiler.membars.TestMembarDependencies::test*",
+ "-XX:CompileCommand=dontinline,compiler.membars.TestMembarDependencies::test_m1",
+ TestMembarDependencies.class.getName(), "run");
+ // C2 should not crash or bail out from compilation
+ oa.shouldHaveExitValue(0);
+ oa.shouldNotMatch("Bailout: Recompile without subsuming loads");
+ System.out.println(oa.getOutput());
+ } else {
+ f2 = new TestMembarDependencies();
+ // Trigger compilation of test1 and test2
+ for (int i = 0; i < 10_000; ++i) {
+ f2.test1(f2);
+ f2.test2(f2);
+ }
+ }
+ }
+
+ public void test_m1() { }
+ public void test_m2() { }
+
+ public void test1(TestMembarDependencies obj) {
+ // Try/catch/finally is used to create a CFG block without a test + jmpCon
+ // allowing GCM to schedule the testN_mem_reg0 instruction into that block.
+ try {
+ // Method call defines memory state that is then
+ // used by subsequent instructions/blocks (see below).
+ test_m1();
+ } catch (Exception e) {
+
+ } finally {
+ // Oop write to field emits a GC post-barrier with a MembarVolatile
+ // which has a wide memory effect (kills all memory). This creates an
+ // anti-dependency on all surrounding memory loads.
+ f1 = obj;
+ }
+ // The empty method m2 is inlined but the null check of f2 remains. It is encoded
+ // as CmpN(LoadN(MEM), NULL) where MEM is the memory after the call to test_m1().
+ // This is matched to testN_mem_reg0 on x86 which is scheduled before the barrier
+ // in the try/catch block due to the anti-dependency on the MembarVolatile.
+ // C2 crashes in the register allocator when trying to spill the flag register
+ // to keep the result of the testN instruction live from the try/catch block
+ // until it is here.
+ f2.test_m2();
+ }
+
+ public void test2(TestMembarDependencies obj) {
+ // Same as test1 but without try/catch/finally.
+ // This causes C2 to bail out in block local scheduling because testN_mem_reg0 is
+ // scheduled into a block that already contains another test + jmpCon instruction.
+ test_m1();
+ f1 = obj;
+ f2.test_m2();
+ }
+}
--- a/hotspot/test/compiler/intrinsics/IntrinsicAvailableTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/intrinsics/IntrinsicAvailableTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -114,7 +114,7 @@
public void test() throws Exception {
Executable intrinsicMethod = testCase.getExecutable();
- if (Platform.isServer() && (TIERED_STOP_AT_LEVEL == COMP_LEVEL_FULL_OPTIMIZATION)) {
+ if (Platform.isServer() && !Platform.isEmulatedClient() && (TIERED_STOP_AT_LEVEL == COMP_LEVEL_FULL_OPTIMIZATION)) {
if (TIERED_COMPILATION) {
checkIntrinsicForCompilationLevel(intrinsicMethod, COMP_LEVEL_SIMPLE);
}
--- a/hotspot/test/compiler/intrinsics/IntrinsicDisabledTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/intrinsics/IntrinsicDisabledTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -197,7 +197,8 @@
}
public static void main(String args[]) {
- if (Platform.isServer() && (TIERED_STOP_AT_LEVEL == CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION)) {
+ if (Platform.isServer() && !Platform.isEmulatedClient() &&
+ (TIERED_STOP_AT_LEVEL == CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION)) {
if (TIERED_COMPILATION) {
test(CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE);
}
--- a/hotspot/test/compiler/intrinsics/bigInteger/MontgomeryMultiplyTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/intrinsics/bigInteger/MontgomeryMultiplyTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @test
* @bug 8130150 8131779 8139907
* @summary Verify that the Montgomery multiply and square intrinsic works and correctly checks their arguments.
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
* @modules java.base/jdk.internal.misc:open
* @modules java.base/java.math:open
* @library /test/lib /
@@ -314,8 +314,8 @@
}
public static void main(String args[]) {
- if (!Platform.isServer()) {
- throw new Error("TESTBUG: Not server VM");
+ if (!Platform.isServer() || Platform.isEmulatedClient()) {
+ throw new Error("TESTBUG: Not server mode");
}
if (wb.isIntrinsicAvailable(getExecutable(true), CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION) &&
wb.isIntrinsicAvailable(getExecutable(false), CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION)) {
--- a/hotspot/test/compiler/intrinsics/bmi/verifycode/AndnTestI.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/AndnTestI.java Thu Feb 09 23:15:52 2017 +0100
@@ -24,7 +24,7 @@
/*
* @test
* @bug 8031321
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
--- a/hotspot/test/compiler/intrinsics/bmi/verifycode/AndnTestL.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/AndnTestL.java Thu Feb 09 23:15:52 2017 +0100
@@ -24,7 +24,7 @@
/*
* @test
* @bug 8031321
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
--- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestI.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestI.java Thu Feb 09 23:15:52 2017 +0100
@@ -24,7 +24,7 @@
/*
* @test
* @bug 8031321
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
--- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestL.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestL.java Thu Feb 09 23:15:52 2017 +0100
@@ -24,7 +24,7 @@
/*
* @test
* @bug 8031321
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
--- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestI.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestI.java Thu Feb 09 23:15:52 2017 +0100
@@ -24,7 +24,7 @@
/*
* @test
* @bug 8031321
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
--- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestL.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestL.java Thu Feb 09 23:15:52 2017 +0100
@@ -24,7 +24,7 @@
/*
* @test
* @bug 8031321
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
--- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestI.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestI.java Thu Feb 09 23:15:52 2017 +0100
@@ -24,7 +24,7 @@
/*
* @test
* @bug 8031321
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
--- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestL.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestL.java Thu Feb 09 23:15:52 2017 +0100
@@ -24,7 +24,7 @@
/*
* @test
* @bug 8031321
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
--- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BmiIntrinsicBase.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BmiIntrinsicBase.java Thu Feb 09 23:15:52 2017 +0100
@@ -78,7 +78,7 @@
System.out.println(testCase.name());
- if (TIERED_COMPILATION && TIERED_STOP_AT_LEVEL != CompilerWhiteBoxTest.COMP_LEVEL_MAX) {
+ if (TIERED_COMPILATION && TIERED_STOP_AT_LEVEL != CompilerWhiteBoxTest.COMP_LEVEL_MAX || Platform.isEmulatedClient()) {
System.out.println("TieredStopAtLevel value (" + TIERED_STOP_AT_LEVEL + ") is too low, test SKIPPED");
return;
}
--- a/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestI.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestI.java Thu Feb 09 23:15:52 2017 +0100
@@ -24,7 +24,7 @@
/*
* @test
* @bug 8031321
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
--- a/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestL.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestL.java Thu Feb 09 23:15:52 2017 +0100
@@ -24,7 +24,7 @@
/*
* @test
* @bug 8031321
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
--- a/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestI.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestI.java Thu Feb 09 23:15:52 2017 +0100
@@ -24,7 +24,7 @@
/*
* @test
* @bug 8031321
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
--- a/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestL.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestL.java Thu Feb 09 23:15:52 2017 +0100
@@ -24,7 +24,7 @@
/*
* @test
* @bug 8031321
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
--- a/hotspot/test/compiler/intrinsics/klass/CastNullCheckDroppingsTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/intrinsics/klass/CastNullCheckDroppingsTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -25,7 +25,7 @@
* @test NullCheckDroppingsTest
* @bug 8054492
* @summary Casting can result in redundant null checks in generated code
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
@@ -84,8 +84,8 @@
int[] asink;
public static void main(String[] args) throws Exception {
- if (!Platform.isServer()) {
- throw new Error("TESTBUG: Not server VM");
+ if (!Platform.isServer() || Platform.isEmulatedClient()) {
+ throw new Error("TESTBUG: Not server mode");
}
// Make sure background compilation is disabled
if (WHITE_BOX.getBooleanVMFlag("BackgroundCompilation")) {
--- a/hotspot/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/IntrinsicBase.java Thu Feb 09 23:15:52 2017 +0100
@@ -50,7 +50,7 @@
int expectedIntrinsicCount = 0;
- if (Platform.isServer()) {
+ if (Platform.isServer() && !Platform.isEmulatedClient()) {
if (TIERED_COMPILATION) {
int max_level = TIERED_STOP_AT_LEVEL;
expectedIntrinsicCount = (max_level == COMP_LEVEL_MAX) ? 1 : 0;
--- a/hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java Thu Feb 09 23:15:52 2017 +0100
@@ -48,8 +48,12 @@
return CTVM.getExceptionTableStart((HotSpotResolvedJavaMethodImpl)method);
}
- public static boolean canInlineMethod(HotSpotResolvedJavaMethod method) {
- return CTVM.canInlineMethod((HotSpotResolvedJavaMethodImpl)method);
+ public static boolean isCompilable(HotSpotResolvedJavaMethod method) {
+ return CTVM.isCompilable((HotSpotResolvedJavaMethodImpl)method);
+ }
+
+ public static boolean hasNeverInlineDirective(HotSpotResolvedJavaMethod method) {
+ return CTVM.hasNeverInlineDirective((HotSpotResolvedJavaMethodImpl)method);
}
public static boolean shouldInlineMethod(HotSpotResolvedJavaMethod method) {
--- a/hotspot/test/compiler/jvmci/compilerToVM/CanInlineMethodTest.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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 8136421
- * @requires vm.jvmci
- * @library /test/lib /
- * @library ../common/patches
- * @modules java.base/jdk.internal.misc
- * @modules java.base/jdk.internal.org.objectweb.asm
- * java.base/jdk.internal.org.objectweb.asm.tree
- * jdk.vm.ci/jdk.vm.ci.hotspot
- * jdk.vm.ci/jdk.vm.ci.code
- *
- * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper sun.hotspot.WhiteBox
- * @run driver ClassFileInstaller sun.hotspot.WhiteBox
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm -Xbootclasspath/a:.
- * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
- * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
- * compiler.jvmci.compilerToVM.CanInlineMethodTest
- */
-
-package compiler.jvmci.compilerToVM;
-
-import compiler.jvmci.common.CTVMUtilities;
-import jdk.test.lib.Asserts;
-import jdk.vm.ci.hotspot.CompilerToVMHelper;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
-import sun.hotspot.WhiteBox;
-
-import java.lang.reflect.Executable;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-public class CanInlineMethodTest {
-
- private static final WhiteBox WB = WhiteBox.getWhiteBox();
-
- public static void main(String[] args) {
- List<Executable> testCases = createTestCases();
- testCases.forEach(CanInlineMethodTest::runSanityTest);
- }
-
- private static void runSanityTest(Executable aMethod) {
- HotSpotResolvedJavaMethod method = CTVMUtilities
- .getResolvedMethod(aMethod);
- boolean canInline = CompilerToVMHelper.canInlineMethod(method);
- boolean expectedCanInline = !WB.testSetDontInlineMethod(aMethod,
- true);
- Asserts.assertEQ(canInline, expectedCanInline, "Unexpected initial " +
- "value of property 'can inline'");
-
- canInline = CompilerToVMHelper.canInlineMethod(method);
- Asserts.assertFalse(canInline, aMethod + "Unexpected value of " +
- "property 'can inline' after setting 'do not inline' to true");
- WB.testSetDontInlineMethod(aMethod, false);
- canInline = CompilerToVMHelper.canInlineMethod(method);
- Asserts.assertTrue(canInline, "Unexpected value of " +
- "property 'can inline' after setting 'do not inline' to false");
- }
-
- private static List<Executable> createTestCases() {
- List<Executable> testCases = new ArrayList<>();
-
- Class<?> aClass = DummyClass.class;
- testCases.addAll(Arrays.asList(aClass.getDeclaredMethods()));
- testCases.addAll(Arrays.asList(aClass.getDeclaredConstructors()));
- return testCases;
- }
-}
--- a/hotspot/test/compiler/jvmci/compilerToVM/DoNotInlineOrCompileTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/jvmci/compilerToVM/DoNotInlineOrCompileTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -67,13 +67,13 @@
private static void runSanityTest(Executable aMethod) {
HotSpotResolvedJavaMethod method = CTVMUtilities
.getResolvedMethod(aMethod);
- boolean canInline = CompilerToVMHelper.canInlineMethod(method);
- Asserts.assertTrue(canInline, "Unexpected initial " +
- "value of property 'can inline'");
+ boolean hasNeverInlineDirective = CompilerToVMHelper.hasNeverInlineDirective(method);
+ Asserts.assertFalse(hasNeverInlineDirective, "Unexpected initial " +
+ "value of property 'hasNeverInlineDirective'");
CompilerToVMHelper.doNotInlineOrCompile(method);
- canInline = CompilerToVMHelper.canInlineMethod(method);
- Asserts.assertFalse(canInline, aMethod
- + " : can be inlined even after doNotInlineOrCompile'");
+ hasNeverInlineDirective = CompilerToVMHelper.hasNeverInlineDirective(method);
+ Asserts.assertTrue(hasNeverInlineDirective, aMethod
+ + " : hasNeverInlineDirective is false even after doNotInlineOrCompile'");
}
private static List<Executable> createTestCases() {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/HasNeverInlineDirectiveTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 8136421
+ * @requires vm.jvmci
+ * @library /test/lib /
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * java.base/jdk.internal.org.objectweb.asm.tree
+ * jdk.vm.ci/jdk.vm.ci.hotspot
+ * jdk.vm.ci/jdk.vm.ci.code
+ *
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:.
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * compiler.jvmci.compilerToVM.HasNeverInlineDirectiveTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.CTVMUtilities;
+import jdk.test.lib.Asserts;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
+import sun.hotspot.WhiteBox;
+
+import java.lang.reflect.Executable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class HasNeverInlineDirectiveTest {
+
+ private static final WhiteBox WB = WhiteBox.getWhiteBox();
+
+ public static void main(String[] args) {
+ List<Executable> testCases = createTestCases();
+ testCases.forEach(HasNeverInlineDirectiveTest::runSanityTest);
+ }
+
+ private static void runSanityTest(Executable aMethod) {
+ HotSpotResolvedJavaMethod method = CTVMUtilities
+ .getResolvedMethod(aMethod);
+ boolean hasNeverInlineDirective = CompilerToVMHelper.hasNeverInlineDirective(method);
+ boolean expected = WB.testSetDontInlineMethod(aMethod, true);
+ Asserts.assertEQ(hasNeverInlineDirective, expected, "Unexpected initial " +
+ "value of property 'hasNeverInlineDirective'");
+
+ hasNeverInlineDirective = CompilerToVMHelper.hasNeverInlineDirective(method);
+ Asserts.assertTrue(hasNeverInlineDirective, aMethod + "Unexpected value of " +
+ "property 'hasNeverInlineDirective' after setting 'do not inline' to true");
+ WB.testSetDontInlineMethod(aMethod, false);
+ hasNeverInlineDirective = CompilerToVMHelper.hasNeverInlineDirective(method);
+ Asserts.assertFalse(hasNeverInlineDirective, "Unexpected value of " +
+ "property 'hasNeverInlineDirective' after setting 'do not inline' to false");
+ }
+
+ private static List<Executable> createTestCases() {
+ List<Executable> testCases = new ArrayList<>();
+
+ Class<?> aClass = DummyClass.class;
+ testCases.addAll(Arrays.asList(aClass.getDeclaredMethods()));
+ testCases.addAll(Arrays.asList(aClass.getDeclaredConstructors()));
+ return testCases;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/IsCompilableTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 8136421
+ * @requires vm.jvmci
+ * @library /test/lib /
+ * @library ../common/patches
+ * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * java.base/jdk.internal.org.objectweb.asm.tree
+ * jdk.vm.ci/jdk.vm.ci.hotspot
+ * jdk.vm.ci/jdk.vm.ci.code
+ *
+ * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:.
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:+UseJVMCICompiler
+ * compiler.jvmci.compilerToVM.IsCompilableTest
+ * @run main/othervm -Xbootclasspath/a:.
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
+ * compiler.jvmci.compilerToVM.IsCompilableTest
+ */
+
+package compiler.jvmci.compilerToVM;
+
+import compiler.jvmci.common.CTVMUtilities;
+import jdk.test.lib.Asserts;
+import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
+import sun.hotspot.WhiteBox;
+
+import java.lang.reflect.Executable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class IsCompilableTest {
+
+ private static final WhiteBox WB = WhiteBox.getWhiteBox();
+
+ public static void main(String[] args) {
+ List<Executable> testCases = createTestCases();
+ testCases.forEach(IsCompilableTest::runSanityTest);
+ }
+
+ private static void runSanityTest(Executable aMethod) {
+ boolean UseJVMCICompiler = (Boolean) WB.getVMFlag("UseJVMCICompiler");
+ HotSpotResolvedJavaMethod method = CTVMUtilities
+ .getResolvedMethod(aMethod);
+ boolean isCompilable = CompilerToVMHelper.isCompilable(method);
+ boolean expected = UseJVMCICompiler || WB.isMethodCompilable(aMethod);
+ Asserts.assertEQ(isCompilable, expected, "Unexpected initial " +
+ "value of property 'compilable'");
+
+ if (!UseJVMCICompiler) {
+ WB.makeMethodNotCompilable(aMethod);
+ isCompilable = CompilerToVMHelper.isCompilable(method);
+ Asserts.assertFalse(isCompilable, aMethod + "Unexpected value of " +
+ "property 'isCompilable' after setting 'compilable' to false");
+ }
+ }
+
+ private static List<Executable> createTestCases() {
+ List<Executable> testCases = new ArrayList<>();
+
+ Class<?> aClass = DummyClass.class;
+ testCases.addAll(Arrays.asList(aClass.getDeclaredMethods()));
+ testCases.addAll(Arrays.asList(aClass.getDeclaredConstructors()));
+ return testCases;
+ }
+}
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/DebugInfoTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/DebugInfoTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -25,6 +25,8 @@
import jdk.vm.ci.code.BytecodeFrame;
import jdk.vm.ci.code.DebugInfo;
import jdk.vm.ci.code.Location;
+import jdk.vm.ci.code.RegisterValue;
+import jdk.vm.ci.code.StackSlot;
import jdk.vm.ci.code.VirtualObject;
import jdk.vm.ci.hotspot.HotSpotReferenceMap;
import jdk.vm.ci.meta.JavaKind;
@@ -32,6 +34,9 @@
import jdk.vm.ci.meta.ResolvedJavaMethod;
import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
/**
* Test code installation with debug information.
@@ -54,11 +59,43 @@
int numStack = slotKinds.length - numLocals;
JavaValue[] values = new JavaValue[slotKinds.length];
test(asm -> {
+ /*
+ * Ensure that any objects mentioned in the VirtualObjects are also in the OopMap.
+ */
+ List<Location> newLocations = new ArrayList<Location>(Arrays.asList(objects));
+ List<Location> newDerived = new ArrayList<Location>(Arrays.asList(derivedBase));
+ int[] newSizeInBytes = sizeInBytes;
VirtualObject[] vobjs = compiler.compile(asm, values);
+ if (vobjs != null) {
+ for (VirtualObject obj : vobjs) {
+ JavaValue[] objValues = obj.getValues();
+ for (int i = 0; i < objValues.length; i++) {
+ if (obj.getSlotKind(i) == JavaKind.Object) {
+ Location oopLocation = null;
+ int bytes = -1;
+ if (objValues[i] instanceof RegisterValue) {
+ RegisterValue reg = (RegisterValue) objValues[i];
+ oopLocation = Location.register(reg.getRegister());
+ bytes = reg.getValueKind().getPlatformKind().getSizeInBytes();
+ } else if (objValues[i] instanceof StackSlot) {
+ StackSlot slot = (StackSlot) objValues[i];
+ oopLocation = Location.stack(asm.getOffset(slot));
+ bytes = slot.getValueKind().getPlatformKind().getSizeInBytes();
+ }
+ if (oopLocation != null && !newLocations.contains(oopLocation)) {
+ newLocations.add(oopLocation);
+ newDerived.add(null);
+ newSizeInBytes = Arrays.copyOf(newSizeInBytes, newSizeInBytes.length + 1);
+ newSizeInBytes[newSizeInBytes.length - 1] = bytes;
+ }
+ }
+ }
+ }
+ }
BytecodeFrame frame = new BytecodeFrame(null, resolvedMethod, bci, false, false, values, slotKinds, numLocals, numStack, 0);
DebugInfo info = new DebugInfo(frame, vobjs);
- info.setReferenceMap(new HotSpotReferenceMap(objects, derivedBase, sizeInBytes, 8));
+ info.setReferenceMap(new HotSpotReferenceMap(newLocations.toArray(new Location[0]), newDerived.toArray(new Location[0]), newSizeInBytes, 8));
asm.emitTrap(info);
}, method);
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestAssembler.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestAssembler.java Thu Feb 09 23:15:52 2017 +0100
@@ -256,6 +256,10 @@
return StackSlot.get(new TestValueKind(kind), -curStackSlot, true);
}
+ public int getOffset(StackSlot slot) {
+ return slot.getOffset(frameSize);
+ }
+
protected void growFrame(int sizeInBytes) {
curStackSlot += sizeInBytes;
if (curStackSlot > frameSize) {
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/VirtualObjectDebugInfoTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/VirtualObjectDebugInfoTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -103,6 +103,12 @@
return new TestClass();
}
+ public static TestClass buildObjectStack() {
+ return new TestClass();
+ }
+
+ boolean storeToStack;
+
private VirtualObject[] compileBuildObject(TestAssembler asm, JavaValue[] values) {
TestClass template = new TestClass();
ArrayList<VirtualObject> vobjs = new ArrayList<>();
@@ -135,7 +141,11 @@
} else if (template.arrayField[i] instanceof String) {
String value = (String) template.arrayField[i];
Register reg = asm.emitLoadPointer((HotSpotConstant) constantReflection.forString(value));
- arrayContent[i] = reg.asValue(asm.getValueKind(JavaKind.Object));
+ if (storeToStack) {
+ arrayContent[i] = asm.emitPointerToStack(reg);
+ } else {
+ arrayContent[i] = reg.asValue(asm.getValueKind(JavaKind.Object));
+ }
} else {
Assert.fail("unexpected value");
}
@@ -174,6 +184,13 @@
@Test
public void testBuildObject() {
+ storeToStack = false;
test(this::compileBuildObject, getMethod("buildObject"), 7, JavaKind.Object);
}
+
+ @Test
+ public void testBuildObjectStack() {
+ storeToStack = true;
+ test(this::compileBuildObject, getMethod("buildObjectStack"), 7, JavaKind.Object);
+ }
}
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java Thu Feb 09 23:15:52 2017 +0100
@@ -466,6 +466,7 @@
"getProfilingInfo",
"reprofile",
"getCompilerStorage",
+ "hasNeverInlineDirective",
"canBeInlined",
"shouldBeInlined",
"getLineNumberTable",
--- a/hotspot/test/compiler/loopopts/TestCountedLoopSafepointBackedge.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/loopopts/TestCountedLoopSafepointBackedge.java Thu Feb 09 23:15:52 2017 +0100
@@ -24,7 +24,7 @@
/**
* @test
* @bug 8161147
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
* @summary Safepoint on backedge breaks UseCountedLoopSafepoints
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:+UseCountedLoopSafepoints TestCountedLoopSafepointBackedge
*
--- a/hotspot/test/compiler/loopopts/UseCountedLoopSafepointsTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/loopopts/UseCountedLoopSafepointsTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,8 @@
* @bug 6869327
* @summary Test that C2 flag UseCountedLoopSafepoints ensures a safepoint is kept in a CountedLoop
* @library /test/lib /
- * @requires vm.compMode != "Xint" & vm.flavor == "server" & (vm.opt.TieredStopAtLevel == null | vm.opt.TieredStopAtLevel == 4)
+ * @requires vm.compMode != "Xint" & vm.flavor == "server" & (vm.opt.TieredStopAtLevel == null | vm.opt.TieredStopAtLevel == 4) & vm.debug == true
+ * @requires !vm.emulatedClient
* @modules java.base/jdk.internal.misc
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
@@ -37,6 +38,7 @@
package compiler.loopopts;
+import jdk.test.lib.Platform;
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.process.OutputAnalyzer;
import java.util.List;
--- a/hotspot/test/compiler/rangechecks/TestExplicitRangeChecks.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/rangechecks/TestExplicitRangeChecks.java Thu Feb 09 23:15:52 2017 +0100
@@ -445,7 +445,7 @@
success = false;
}
// Only perform these additional checks if C2 is available
- if (Platform.isServer() &&
+ if (Platform.isServer() && !Platform.isEmulatedClient() &&
TIERED_STOP_AT_LEVEL == CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION) {
if (deoptimize && WHITE_BOX.isMethodCompiled(m)) {
System.out.println(name + " not deoptimized on invalid access");
--- a/hotspot/test/compiler/testlibrary/CompilerUtils.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/testlibrary/CompilerUtils.java Thu Feb 09 23:15:52 2017 +0100
@@ -53,10 +53,10 @@
"TieredStopAtLevel has value out of int capacity");
return IntStream.rangeClosed(1, maxLevel).toArray();
} else {
- if (Platform.isServer()) {
+ if (Platform.isServer() && !Platform.isEmulatedClient()) {
return new int[]{4};
}
- if (Platform.isClient() || Platform.isMinimal()) {
+ if (Platform.isClient() || Platform.isMinimal() || Platform.isEmulatedClient()) {
return new int[]{1};
}
}
--- a/hotspot/test/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java Thu Feb 09 23:15:52 2017 +0100
@@ -55,7 +55,7 @@
"TieredStopAtLevel");
boolean maxLevelIsReachable = (tieredMaxLevel
== IntrinsicPredicates.TIERED_MAX_LEVEL);
- return Platform.isServer() && (!isTiered || maxLevelIsReachable);
+ return Platform.isServer() && !Platform.isEmulatedClient() && (!isTiered || maxLevelIsReachable);
};
public static final BooleanSupplier SHA1_INSTRUCTION_AVAILABLE
--- a/hotspot/test/compiler/tiered/NonTieredLevelsTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/tiered/NonTieredLevelsTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -47,13 +47,12 @@
private static final int AVAILABLE_COMP_LEVEL;
private static final IntPredicate IS_AVAILABLE_COMPLEVEL;
static {
- if (Platform.isServer()) {
+ if (Platform.isServer() && !Platform.isEmulatedClient()) {
AVAILABLE_COMP_LEVEL = COMP_LEVEL_FULL_OPTIMIZATION;
IS_AVAILABLE_COMPLEVEL = x -> x == COMP_LEVEL_FULL_OPTIMIZATION;
- } else if (Platform.isClient() || Platform.isMinimal()) {
+ } else if (Platform.isClient() || Platform.isMinimal() || Platform.isEmulatedClient()) {
AVAILABLE_COMP_LEVEL = COMP_LEVEL_SIMPLE;
- IS_AVAILABLE_COMPLEVEL = x -> x >= COMP_LEVEL_SIMPLE
- && x <= COMP_LEVEL_FULL_PROFILE;
+ IS_AVAILABLE_COMPLEVEL = x -> x == COMP_LEVEL_SIMPLE;
} else {
throw new Error("TESTBUG: unknown VM: " + Platform.vmName);
}
--- a/hotspot/test/compiler/types/correctness/CorrectnessTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/types/correctness/CorrectnessTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -25,7 +25,7 @@
* @test CorrectnessTest
* @bug 8038418
* @summary Tests correctness of type usage with type profiling and speculations
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
@@ -88,8 +88,8 @@
private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
public static void main(String[] args) {
- if (!Platform.isServer()) {
- throw new Error("TESTBUG: Not server VM");
+ if (!Platform.isServer() || Platform.isEmulatedClient()) {
+ throw new Error("TESTBUG: Not server mode");
}
Asserts.assertGTE(args.length, 1);
ProfilingType profilingType = ProfilingType.valueOf(args[0]);
--- a/hotspot/test/compiler/uncommontrap/TestUnstableIfTrap.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/uncommontrap/TestUnstableIfTrap.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,7 @@
* java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
*
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
@@ -206,7 +206,7 @@
boolean isMethodCompiledAtMaxTier
= WB.getMethodCompilationLevel(m) == MAX_TIER;
- return Platform.isServer() && isMethodCompiled
+ return Platform.isServer() && !Platform.isEmulatedClient() && isMethodCompiled
&& (!isTiered || isMethodCompiledAtMaxTier);
}
--- a/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java Thu Feb 09 23:15:52 2017 +0100
@@ -28,7 +28,7 @@
* @summary tests on constant folding of unsafe get operations
* @library /test/lib
*
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
*
* @modules java.base/jdk.internal.org.objectweb.asm
* java.base/jdk.internal.vm.annotation
@@ -93,8 +93,8 @@
static final Unsafe U = Unsafe.getUnsafe();
public static void main(String[] args) {
- if (!Platform.isServer()) {
- throw new Error("TESTBUG: Not server VM");
+ if (!Platform.isServer() || Platform.isEmulatedClient()) {
+ throw new Error("TESTBUG: Not server mode");
}
testUnsafeGetAddress();
testUnsafeGetField();
--- a/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java Thu Feb 09 23:15:52 2017 +0100
@@ -28,7 +28,7 @@
* @summary tests on constant folding of unsafe get operations from stable arrays
* @library /test/lib
*
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
*
* @modules java.base/jdk.internal.vm.annotation
* java.base/jdk.internal.misc
@@ -332,8 +332,8 @@
}
public static void main(String[] args) throws Exception {
- if (!Platform.isServer()) {
- throw new Error("TESTBUG: Not server VM");
+ if (!Platform.isServer() || Platform.isEmulatedClient()) {
+ throw new Error("TESTBUG: Not server mode");
}
testUnsafeAccess();
System.out.println("TEST PASSED");
--- a/hotspot/test/compiler/whitebox/IsMethodCompilableTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/compiler/whitebox/IsMethodCompilableTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -25,7 +25,8 @@
* @test IsMethodCompilableTest
* @bug 8007270 8006683 8007288 8022832
* @summary testing of WB::isMethodCompilable()
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & (vm.opt.TieredStopAtLevel == null | vm.opt.TieredStopAtLevel == 4)
+ * @requires !vm.emulatedClient
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
@@ -82,8 +83,8 @@
protected void test() throws Exception {
// Only c2 compilations can be disabled through PerMethodRecompilationCutoff
- if (!Platform.isServer()) {
- throw new Error("TESTBUG: Not server VM");
+ if (!Platform.isServer() || Platform.isEmulatedClient()) {
+ throw new Error("TESTBUG: Not server mode");
}
if (skipXcompOSR()) {
--- a/hotspot/test/gc/g1/TestHumongousShrinkHeap.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/gc/g1/TestHumongousShrinkHeap.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,7 @@
* @requires vm.gc.G1
* @summary Verify that heap shrinks after GC in the presence of fragmentation
* due to humongous objects
- * @library /test/lib
+ * @library /test/lib /
* @modules java.base/jdk.internal.misc
* @modules java.management/sun.management
* @run main/othervm -XX:-ExplicitGCInvokesConcurrent -XX:MinHeapFreeRatio=10
@@ -40,6 +40,8 @@
import java.lang.management.MemoryUsage;
import java.util.ArrayList;
import java.util.List;
+import java.text.NumberFormat;
+import gc.testlibrary.Helpers;
import static jdk.test.lib.Asserts.*;
public class TestHumongousShrinkHeap {
@@ -70,9 +72,9 @@
System.out.format("Running with %s initial heap size of %s maximum heap size. "
+ "Will allocate humongous object of %s size %d times.%n",
- MemoryUsagePrinter.humanReadableByteCount(TOTAL_MEMORY, false),
- MemoryUsagePrinter.humanReadableByteCount(MAX_MEMORY, false),
- MemoryUsagePrinter.humanReadableByteCount(HUMON_SIZE, false),
+ MemoryUsagePrinter.NF.format(TOTAL_MEMORY),
+ MemoryUsagePrinter.NF.format(MAX_MEMORY),
+ MemoryUsagePrinter.NF.format(HUMON_SIZE),
HUMON_COUNT
);
new TestHumongousShrinkHeap().test();
@@ -134,24 +136,16 @@
*/
class MemoryUsagePrinter {
- public static String humanReadableByteCount(long bytes, boolean si) {
- int unit = si ? 1000 : 1024;
- if (bytes < unit) {
- return bytes + " B";
- }
- int exp = (int) (Math.log(bytes) / Math.log(unit));
- String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i");
- return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
- }
+ public static final NumberFormat NF = Helpers.numberFormatter();
public static void printMemoryUsage(String label) {
MemoryUsage memusage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
float freeratio = 1f - (float) memusage.getUsed() / memusage.getCommitted();
System.out.format("[%-24s] init: %-7s, used: %-7s, comm: %-7s, freeRatio ~= %.1f%%%n",
label,
- humanReadableByteCount(memusage.getInit(), false),
- humanReadableByteCount(memusage.getUsed(), false),
- humanReadableByteCount(memusage.getCommitted(), false),
+ NF.format(memusage.getInit()),
+ NF.format(memusage.getUsed()),
+ NF.format(memusage.getCommitted()),
freeratio * 100
);
}
--- a/hotspot/test/gc/g1/TestShrinkDefragmentedHeap.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/gc/g1/TestShrinkDefragmentedHeap.java Thu Feb 09 23:15:52 2017 +0100
@@ -31,7 +31,7 @@
* "..................................H"
* 3. invoke gc and check that memory returned to the system (amount of committed memory got down)
*
- * @library /test/lib
+ * @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management/sun.management
*/
@@ -39,10 +39,12 @@
import java.lang.management.MemoryUsage;
import java.util.ArrayList;
import java.util.List;
+import java.text.NumberFormat;
import static jdk.test.lib.Asserts.*;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import com.sun.management.HotSpotDiagnosticMXBean;
+import gc.testlibrary.Helpers;
public class TestShrinkDefragmentedHeap {
// Since we store all the small objects, they become old and old regions are also allocated at the bottom of the heap
@@ -114,8 +116,8 @@
private void allocate() {
System.out.format("Will allocate objects of small size = %s and humongous size = %s",
- MemoryUsagePrinter.humanReadableByteCount(SMALL_OBJS_SIZE, false),
- MemoryUsagePrinter.humanReadableByteCount(HUMONG_OBJS_SIZE, false)
+ MemoryUsagePrinter.NF.format(SMALL_OBJS_SIZE),
+ MemoryUsagePrinter.NF.format(HUMONG_OBJS_SIZE)
);
for (int i = 0; i < ALLOCATE_COUNT; i++) {
@@ -170,24 +172,16 @@
*/
static class MemoryUsagePrinter {
- public static String humanReadableByteCount(long bytes, boolean si) {
- int unit = si ? 1000 : 1024;
- if (bytes < unit) {
- return bytes + " B";
- }
- int exp = (int) (Math.log(bytes) / Math.log(unit));
- String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i");
- return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
- }
+ public static final NumberFormat NF = Helpers.numberFormatter();
public static void printMemoryUsage(String label) {
MemoryUsage memusage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
float freeratio = 1f - (float) memusage.getUsed() / memusage.getCommitted();
System.out.format("[%-24s] init: %-7s, used: %-7s, comm: %-7s, freeRatio ~= %.1f%%%n",
label,
- humanReadableByteCount(memusage.getInit(), false),
- humanReadableByteCount(memusage.getUsed(), false),
- humanReadableByteCount(memusage.getCommitted(), false),
+ NF.format(memusage.getInit()),
+ NF.format(memusage.getUsed()),
+ NF.format(memusage.getCommitted()),
freeratio * 100
);
}
--- a/hotspot/test/gc/metaspace/TestMetaspacePerfCounters.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/gc/metaspace/TestMetaspacePerfCounters.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management/sun.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:+UsePerfData -XX:+UseSerialGC TestMetaspacePerfCounters
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:+UsePerfData -XX:+UseParallelGC -XX:+UseParallelOldGC TestMetaspacePerfCounters
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:+UsePerfData -XX:+UseG1GC TestMetaspacePerfCounters
--- a/hotspot/test/gc/metaspace/TestPerfCountersAndMemoryPools.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/gc/metaspace/TestPerfCountersAndMemoryPools.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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 @@
* report the same data.
* @modules java.base/jdk.internal.misc
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:+UseSerialGC -XX:+UsePerfData -Xint TestPerfCountersAndMemoryPools
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:+UseSerialGC -XX:+UsePerfData -Xint TestPerfCountersAndMemoryPools
*/
--- a/hotspot/test/gc/parallel/TestDynShrinkHeap.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/gc/parallel/TestDynShrinkHeap.java Thu Feb 09 23:15:52 2017 +0100
@@ -28,15 +28,17 @@
* @summary Verify that the heap shrinks after full GC according to the current values of the Min/MaxHeapFreeRatio flags
* @modules java.base/jdk.internal.misc
* @modules jdk.management
- * @library /test/lib
+ * @library /test/lib /
* @run main/othervm -XX:+UseAdaptiveSizePolicyWithSystemGC -XX:+UseParallelGC -XX:MinHeapFreeRatio=0 -XX:MaxHeapFreeRatio=100 -Xmx1g -verbose:gc TestDynShrinkHeap
*/
import jdk.test.lib.DynamicVMOption;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryUsage;
import java.util.ArrayList;
+import java.text.NumberFormat;
import static jdk.test.lib.Asserts.assertLessThan;
import com.sun.management.HotSpotDiagnosticMXBean;
+import gc.testlibrary.Helpers;
public class TestDynShrinkHeap {
@@ -101,24 +103,16 @@
*/
class MemoryUsagePrinter {
- public static String humanReadableByteCount(long bytes, boolean si) {
- int unit = si ? 1000 : 1024;
- if (bytes < unit) {
- return bytes + " B";
- }
- int exp = (int) (Math.log(bytes) / Math.log(unit));
- String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i");
- return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
- }
+ public static final NumberFormat NF = Helpers.numberFormatter();
public static void printMemoryUsage(String label) {
MemoryUsage memusage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
float freeratio = 1f - (float) memusage.getUsed() / memusage.getCommitted();
System.out.format("[%-24s] init: %-7s, used: %-7s, comm: %-7s, freeRatio ~= %.1f%%%n",
label,
- humanReadableByteCount(memusage.getInit(), true),
- humanReadableByteCount(memusage.getUsed(), true),
- humanReadableByteCount(memusage.getCommitted(), true),
+ NF.format(memusage.getInit()),
+ NF.format(memusage.getUsed()),
+ NF.format(memusage.getCommitted()),
freeratio * 100
);
}
--- a/hotspot/test/gc/stress/TestStressG1Humongous.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/gc/stress/TestStressG1Humongous.java Thu Feb 09 23:15:52 2017 +0100
@@ -28,14 +28,9 @@
* @summary Stress G1 by humongous allocations in situation near OOM
* @requires vm.gc.G1
* @requires !vm.flightRecorder
- * @run main/othervm/timeout=200 -Xlog:gc=debug -Xmx1g -XX:+UseG1GC -XX:G1HeapRegionSize=4m
- * -Dtimeout=120 -Dthreads=3 -Dhumongoussize=1.1 -Dregionsize=4 TestStressG1Humongous
- * @run main/othervm/timeout=200 -Xlog:gc=debug -Xmx1g -XX:+UseG1GC -XX:G1HeapRegionSize=16m
- * -Dtimeout=120 -Dthreads=5 -Dhumongoussize=2.1 -Dregionsize=16 TestStressG1Humongous
- * @run main/othervm/timeout=200 -Xlog:gc=debug -Xmx1g -XX:+UseG1GC -XX:G1HeapRegionSize=32m
- * -Dtimeout=120 -Dthreads=4 -Dhumongoussize=0.6 -Dregionsize=32 TestStressG1Humongous
- * @run main/othervm/timeout=700 -Xlog:gc=debug -Xmx1g -XX:+UseG1GC -XX:G1HeapRegionSize=1m
- * -Dtimeout=600 -Dthreads=7 -Dhumongoussize=0.6 -Dregionsize=1 TestStressG1Humongous
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @run driver/timeout=1300 TestStressG1Humongous
*/
import java.util.ArrayList;
@@ -44,8 +39,45 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
-public class TestStressG1Humongous {
+import jdk.test.lib.Platform;
+import jdk.test.lib.Utils;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+
+public class TestStressG1Humongous{
+
+ public static void main(String[] args) throws Exception {
+ // Limit heap size on 32-bit platforms
+ int heapSize = Platform.is32bit() ? 512 : 1024;
+ // Heap size, region size, threads, humongous size, timeout
+ run(heapSize, 4, 3, 1.1, 120);
+ run(heapSize, 16, 5, 2.1, 120);
+ run(heapSize, 32, 4, 0.6, 120);
+ run(heapSize, 1, 7, 0.6, 600);
+ }
+ private static void run(int heapSize, int regionSize, int threads, double humongousSize, int timeout)
+ throws Exception {
+ ArrayList<String> options = new ArrayList<>();
+ Collections.addAll(options, Utils.getTestJavaOpts());
+ Collections.addAll(options,
+ "-Xlog:gc=debug",
+ "-Xmx" + heapSize + "m",
+ "-XX:+UseG1GC",
+ "-XX:G1HeapRegionSize=" + regionSize + "m",
+ "-Dtimeout=" + timeout,
+ "-Dthreads=" + threads,
+ "-Dhumongoussize=" + humongousSize,
+ "-Dregionsize=" + regionSize,
+ TestStressG1HumongousImpl.class.getName()
+ );
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(options.toArray(new String[options.size()]));
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldHaveExitValue(0);
+ }
+}
+
+class TestStressG1HumongousImpl {
// Timeout in seconds
private static final int TIMEOUT = Integer.getInteger("timeout", 60);
private static final int THREAD_COUNT = Integer.getInteger("threads", 2);
@@ -60,10 +92,10 @@
public static final List<Object> GARBAGE = Collections.synchronizedList(new ArrayList<>());
public static void main(String[] args) throws InterruptedException {
- new TestStressG1Humongous().run();
+ new TestStressG1HumongousImpl().run();
}
- public TestStressG1Humongous() {
+ public TestStressG1HumongousImpl() {
isRunning = true;
threads = new Thread[THREAD_COUNT];
alocatedObjectsCount = new AtomicInteger(0);
--- a/hotspot/test/gc/stress/gcbasher/TestGCBasherWithCMS.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/gc/stress/gcbasher/TestGCBasherWithCMS.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,9 +29,9 @@
* @key gc
* @key stress
* @requires vm.gc.ConcMarkSweep
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
* @summary Stress the CMS GC by trying to make old objects more likely to be garbage than young objects.
- * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx128m -server -XX:+UseConcMarkSweepGC TestGCBasherWithCMS 120000
+ * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx256m -server -XX:+UseConcMarkSweepGC TestGCBasherWithCMS 120000
*/
public class TestGCBasherWithCMS {
public static void main(String[] args) throws IOException {
--- a/hotspot/test/gc/stress/gcbasher/TestGCBasherWithG1.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/gc/stress/gcbasher/TestGCBasherWithG1.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,9 +29,9 @@
* @key gc
* @key stress
* @requires vm.gc.G1
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
* @summary Stress the G1 GC by trying to make old objects more likely to be garbage than young objects.
- * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx128m -server -XX:+UseG1GC TestGCBasherWithG1 120000
+ * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx256m -server -XX:+UseG1GC TestGCBasherWithG1 120000
*/
public class TestGCBasherWithG1 {
public static void main(String[] args) throws IOException {
--- a/hotspot/test/gc/stress/gcbasher/TestGCBasherWithParallel.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/gc/stress/gcbasher/TestGCBasherWithParallel.java Thu Feb 09 23:15:52 2017 +0100
@@ -29,7 +29,7 @@
* @key gc
* @key stress
* @requires vm.gc.Parallel
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
* @summary Stress the Parallel GC by trying to make old objects more likely to be garbage than young objects.
* @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx256m -server -XX:+UseParallelGC -XX:-UseGCOverheadLimit TestGCBasherWithParallel 120000
*/
--- a/hotspot/test/gc/stress/gcbasher/TestGCBasherWithSerial.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/gc/stress/gcbasher/TestGCBasherWithSerial.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,9 +29,9 @@
* @key gc
* @key stress
* @requires vm.gc.Serial
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
* @summary Stress the Serial GC by trying to make old objects more likely to be garbage than young objects.
- * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx128m -server -XX:+UseSerialGC TestGCBasherWithSerial 120000
+ * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx256m -server -XX:+UseSerialGC TestGCBasherWithSerial 120000
*/
public class TestGCBasherWithSerial {
public static void main(String[] args) throws IOException {
--- a/hotspot/test/gc/testlibrary/Helpers.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/gc/testlibrary/Helpers.java Thu Feb 09 23:15:52 2017 +0100
@@ -31,6 +31,9 @@
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.NumberFormat;
public class Helpers {
@@ -320,4 +323,16 @@
}
}
+ /**
+ * @return a number formatter instance which prints numbers in a human
+ * readable form, like 9_223_372_036_854_775_807.
+ */
+ public static NumberFormat numberFormatter() {
+ DecimalFormat df = new DecimalFormat();
+ DecimalFormatSymbols dfs = df.getDecimalFormatSymbols();
+ dfs.setGroupingSeparator('_');
+ dfs.setDecimalSeparator('.');
+ df.setDecimalFormatSymbols(dfs);
+ return df;
+ }
}
--- a/hotspot/test/gc/whitebox/TestConcMarkCycleWB.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/gc/whitebox/TestConcMarkCycleWB.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @build sun.hotspot.WhiteBox
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
--- a/hotspot/test/native/code/test_dependencyContext.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/native/code/test_dependencyContext.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -86,7 +86,7 @@
NOT_PRODUCT(ASSERT_FALSE(depContext.is_dependent_nmethod(nm)));
}
-TEST(code, dependency_context) {
+TEST_VM(code, dependency_context) {
test_remove_dependent_nmethod(0, false);
test_remove_dependent_nmethod(1, false);
test_remove_dependent_nmethod(2, false);
--- a/hotspot/test/native/gc/g1/test_workerDataArray.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/native/gc/g1/test_workerDataArray.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -123,19 +123,19 @@
}
};
-TEST_F(BasicWorkerDataArrayTest, sum_test) {
+TEST_VM_F(BasicWorkerDataArrayTest, sum_test) {
ASSERT_EQ(15u, array.sum());
}
-TEST_F(BasicWorkerDataArrayTest, average_test) {
+TEST_VM_F(BasicWorkerDataArrayTest, average_test) {
ASSERT_NEAR(5.0, array.average(), epsilon);
}
-TEST_F(BasicWorkerDataArrayTest, print_summary_on_test) {
+TEST_VM_F(BasicWorkerDataArrayTest, print_summary_on_test) {
ASSERT_STREQ(print_expected_summary(), print_summary());
}
-TEST_F(BasicWorkerDataArrayTest, print_details_on_test) {
+TEST_VM_F(BasicWorkerDataArrayTest, print_details_on_test) {
ASSERT_STREQ(print_expected_details(), print_details());
}
@@ -161,19 +161,19 @@
}
};
-TEST_F(AddWorkerDataArrayTest, sum_test) {
+TEST_VM_F(AddWorkerDataArrayTest, sum_test) {
ASSERT_EQ(18u, array.sum());
}
-TEST_F(AddWorkerDataArrayTest, average_test) {
+TEST_VM_F(AddWorkerDataArrayTest, average_test) {
ASSERT_NEAR(6.0, array.average(), epsilon);
}
-TEST_F(AddWorkerDataArrayTest, print_summary_on_test) {
+TEST_VM_F(AddWorkerDataArrayTest, print_summary_on_test) {
ASSERT_STREQ(print_expected_summary(), print_summary());
}
-TEST_F(AddWorkerDataArrayTest, print_details_on_test) {
+TEST_VM_F(AddWorkerDataArrayTest, print_details_on_test) {
ASSERT_STREQ(print_expected_details(), print_details());
}
@@ -195,19 +195,19 @@
}
};
-TEST_F(UninitializedElementWorkerDataArrayTest, sum_test) {
+TEST_VM_F(UninitializedElementWorkerDataArrayTest, sum_test) {
ASSERT_EQ(12u, array.sum());
}
-TEST_F(UninitializedElementWorkerDataArrayTest, average_test) {
+TEST_VM_F(UninitializedElementWorkerDataArrayTest, average_test) {
ASSERT_NEAR(6.0, array.average(), epsilon);
}
-TEST_F(UninitializedElementWorkerDataArrayTest, print_summary_on_test) {
+TEST_VM_F(UninitializedElementWorkerDataArrayTest, print_summary_on_test) {
ASSERT_STREQ(print_expected_summary(), print_summary());
}
-TEST_F(UninitializedElementWorkerDataArrayTest, print_details_on_test) {
+TEST_VM_F(UninitializedElementWorkerDataArrayTest, print_details_on_test) {
ASSERT_STREQ(print_expected_details(), print_details());
}
@@ -229,19 +229,19 @@
}
};
-TEST_F(UninitializedWorkerDataArrayTest, sum_test) {
+TEST_VM_F(UninitializedWorkerDataArrayTest, sum_test) {
ASSERT_EQ(0u, array.sum());
}
-TEST_F(UninitializedWorkerDataArrayTest, average_test) {
+TEST_VM_F(UninitializedWorkerDataArrayTest, average_test) {
ASSERT_NEAR(0.0, array.average(), epsilon);
}
-TEST_F(UninitializedWorkerDataArrayTest, print_summary_on_test) {
+TEST_VM_F(UninitializedWorkerDataArrayTest, print_summary_on_test) {
ASSERT_STREQ(print_expected_summary(), print_summary());
}
-TEST_F(UninitializedWorkerDataArrayTest, print_details_on_test) {
+TEST_VM_F(UninitializedWorkerDataArrayTest, print_details_on_test) {
ASSERT_STREQ(print_expected_details(), print_details());
}
@@ -265,18 +265,18 @@
}
};
-TEST_F(UninitializedDoubleElementWorkerDataArrayTest, sum_test) {
+TEST_VM_F(UninitializedDoubleElementWorkerDataArrayTest, sum_test) {
ASSERT_NEAR(12.3 / MILLIUNITS, array.sum(), epsilon);
}
-TEST_F(UninitializedDoubleElementWorkerDataArrayTest, average_test) {
+TEST_VM_F(UninitializedDoubleElementWorkerDataArrayTest, average_test) {
ASSERT_NEAR(6.15 / MILLIUNITS, array.average(), epsilon);
}
-TEST_F(UninitializedDoubleElementWorkerDataArrayTest, print_summary_on_test) {
+TEST_VM_F(UninitializedDoubleElementWorkerDataArrayTest, print_summary_on_test) {
ASSERT_STREQ(print_expected_summary(), print_summary());
}
-TEST_F(UninitializedDoubleElementWorkerDataArrayTest, print_details_on_test) {
+TEST_VM_F(UninitializedDoubleElementWorkerDataArrayTest, print_details_on_test) {
ASSERT_STREQ(print_expected_details(), print_details());
}
--- a/hotspot/test/native/logging/test_log.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/native/logging/test_log.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -41,14 +41,14 @@
}
#ifdef ASSERT // 'test' tag is debug only
-TEST_F(LogTest, prefix) {
+TEST_VM_F(LogTest, prefix) {
set_log_config(TestLogFileName, "logging+test=trace");
log_trace(logging, test)(LOG_LINE_STR);
EXPECT_TRUE(file_contains_substring(TestLogFileName, LOG_PREFIX_STR LOG_LINE_STR));
}
#endif
-TEST_F(LogTest, large_message) {
+TEST_VM_F(LogTest, large_message) {
char big_msg[4096] = {0};
char Xchar = '~';
@@ -68,7 +68,7 @@
EXPECT_EQ(sizeof(big_msg) - 1, count);
}
-TEST_F(LogTest, enabled_logtarget) {
+TEST_VM_F(LogTest, enabled_logtarget) {
set_log_config(TestLogFileName, "gc=debug");
LogTarget(Debug, gc) log;
@@ -80,7 +80,7 @@
EXPECT_TRUE(file_contains_substring(TestLogFileName, LOG_TEST_STRING_LITERAL));
}
-TEST_F(LogTest, disabled_logtarget) {
+TEST_VM_F(LogTest, disabled_logtarget) {
set_log_config(TestLogFileName, "gc=info");
LogTarget(Debug, gc) log;
@@ -95,7 +95,7 @@
EXPECT_FALSE(file_contains_substring(TestLogFileName, LOG_TEST_STRING_LITERAL));
}
-TEST_F(LogTest, enabled_loghandle) {
+TEST_VM_F(LogTest, enabled_loghandle) {
set_log_config(TestLogFileName, "gc=debug");
Log(gc) log;
@@ -109,7 +109,7 @@
EXPECT_TRUE(file_contains_substring(TestLogFileName, "3 workers"));
}
-TEST_F(LogTest, disabled_loghandle) {
+TEST_VM_F(LogTest, disabled_loghandle) {
set_log_config(TestLogFileName, "gc=info");
Log(gc) log;
@@ -126,7 +126,7 @@
EXPECT_FALSE(file_contains_substring(TestLogFileName, "3 workers"));
}
-TEST_F(LogTest, enabled_logtargethandle) {
+TEST_VM_F(LogTest, enabled_logtargethandle) {
set_log_config(TestLogFileName, "gc=debug");
LogTarget(Debug, gc) log;
@@ -140,7 +140,7 @@
EXPECT_TRUE(file_contains_substring(TestLogFileName, "3 workers"));
}
-TEST_F(LogTest, disabled_logtargethandle) {
+TEST_VM_F(LogTest, disabled_logtargethandle) {
set_log_config(TestLogFileName, "gc=info");
LogTarget(Debug, gc) log;
--- a/hotspot/test/native/logging/test_logConfiguration.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/native/logging/test_logConfiguration.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -297,7 +297,7 @@
}
}
-TEST_F(LogConfigurationTest, configure_stdout) {
+TEST_VM_F(LogConfigurationTest, configure_stdout) {
// Start out with all logging disabled
LogConfiguration::disable_logging();
@@ -355,7 +355,7 @@
Test_logconfiguration_subscribe_triggered++;
}
-TEST_F(LogConfigurationTest, subscribe) {
+TEST_VM_F(LogConfigurationTest, subscribe) {
ResourceMark rm;
Log(logging) log;
set_log_config("stdout", "logging*=trace");
--- a/hotspot/test/native/logging/test_logMessageTest.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/native/logging/test_logMessageTest.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -65,7 +65,7 @@
// Verify that messages with multiple levels are written
// to outputs configured for all the corresponding levels
-TEST_F(LogMessageTest, level_inclusion) {
+TEST_VM_F(LogMessageTest, level_inclusion) {
const size_t message_count = 10;
LogMessageBuffer msg[message_count];
@@ -119,7 +119,7 @@
}
// Verify that messages are logged in the order they are added to the log message
-TEST_F(LogMessageTest, line_order) {
+TEST_VM_F(LogMessageTest, line_order) {
LogMessageBuffer msg;
msg.info("info line").error("error line").trace("trace line")
.error("another error").warning("warning line").debug("debug line");
@@ -131,7 +131,7 @@
<< "output missing or in incorrect order";
}
-TEST_F(LogMessageTest, long_message) {
+TEST_VM_F(LogMessageTest, long_message) {
// Write 10K bytes worth of log data
LogMessageBuffer msg;
const size_t size = 10 * K;
@@ -155,7 +155,7 @@
FREE_C_HEAP_ARRAY(char, data);
}
-TEST_F(LogMessageTest, message_with_many_lines) {
+TEST_VM_F(LogMessageTest, message_with_many_lines) {
const size_t lines = 100;
const size_t line_length = 16;
@@ -188,7 +188,7 @@
return prefix_len;
}
-TEST_F(LogMessageTest, prefixing) {
+TEST_VM_F(LogMessageTest, prefixing) {
LogMessageBuffer msg;
msg.set_prefix(dummy_prefixer);
for (int i = 0; i < 3; i++) {
@@ -209,7 +209,7 @@
<< "error in prefixed output";
}
-TEST_F(LogMessageTest, scoped_messages) {
+TEST_VM_F(LogMessageTest, scoped_messages) {
{
LogMessage(logging) msg;
msg.info("scoped info");
@@ -223,7 +223,7 @@
<< "missing output from scoped log message";
}
-TEST_F(LogMessageTest, scoped_flushing) {
+TEST_VM_F(LogMessageTest, scoped_flushing) {
{
LogMessage(logging) msg;
msg.info("manual flush info");
@@ -236,7 +236,7 @@
<< "log file contains duplicate lines from single scoped log message";
}
-TEST_F(LogMessageTest, scoped_reset) {
+TEST_VM_F(LogMessageTest, scoped_reset) {
{
LogMessage(logging) msg, partial;
msg.info("%s", "info reset msg");
--- a/hotspot/test/native/logging/test_logTagSetDescriptions.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/native/logging/test_logTagSetDescriptions.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -30,7 +30,7 @@
#include "unittest.hpp"
#include "utilities/ostream.hpp"
-TEST(LogTagSetDescriptions, describe) {
+TEST_VM(LogTagSetDescriptions, describe) {
for (LogTagSetDescription* d = tagset_descriptions; d->tagset != NULL; d++) {
char expected[1 * K];
d->tagset->label(expected, sizeof(expected), "+");
@@ -46,7 +46,7 @@
}
}
-TEST(LogTagSetDescriptions, command_line_help) {
+TEST_VM(LogTagSetDescriptions, command_line_help) {
const char* filename = "logtagset_descriptions";
FILE* fp = fopen(filename, "w+");
ASSERT_NE((void*)NULL, fp);
--- a/hotspot/test/runtime/CDSCompressedKPtrs/XShareAuto.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/runtime/CDSCompressedKPtrs/XShareAuto.java Thu Feb 09 23:15:52 2017 +0100
@@ -48,8 +48,9 @@
"-server", "-XX:+UnlockDiagnosticVMOptions",
"-XX:SharedArchiveFile=./XShareAuto.jsa", "-version");
output = new OutputAnalyzer(pb.start());
+ String outputString = output.getOutput();
// We asked for server but it could be aliased to something else
- if (output.getOutput().contains("Server VM")) {
+ if (outputString.contains("Server VM") && !outputString.contains("emulated-client")) {
// In server case we don't expect to see sharing flag
output.shouldNotContain("sharing");
output.shouldHaveExitValue(0);
--- a/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -28,7 +28,7 @@
* @modules java.base/jdk.internal.misc
* java.management
* jdk.attach/sun.tools.attach
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run main/othervm/timeout=900 TestOptionsWithRanges
*/
--- a/hotspot/test/runtime/ErrorHandling/CreateCoredumpOnCrash.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/runtime/ErrorHandling/CreateCoredumpOnCrash.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run driver CreateCoredumpOnCrash
*/
--- a/hotspot/test/runtime/ErrorHandling/ProblematicFrameTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/runtime/ErrorHandling/ProblematicFrameTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run driver ProblematicFrameTest
*/
--- a/hotspot/test/runtime/RedefineTests/RedefinePreviousVersions.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/runtime/RedefineTests/RedefinePreviousVersions.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -48,20 +48,23 @@
public static String newRunning =
"class RedefinePreviousVersions$Running {" +
" public static volatile boolean stop = true;" +
+ " public static volatile boolean running = true;" +
" static void localSleep() { }" +
" public static void infinite() { }" +
"}";
static class Running {
public static volatile boolean stop = false;
+ public static volatile boolean running = false;
static void localSleep() {
try{
- Thread.currentThread().sleep(10);//sleep for 10 ms
+ Thread.sleep(10); // sleep for 10 ms
} catch(InterruptedException ie) {
}
}
public static void infinite() {
+ running = true;
while (!stop) { localSleep(); }
}
}
@@ -70,8 +73,6 @@
if (args.length > 0) {
- String jarFile = System.getProperty("test.src") + "/testcase.jar";
-
// java -javaagent:redefineagent.jar -Xlog:stuff RedefinePreviousVersions
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-javaagent:redefineagent.jar",
"-Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace",
@@ -100,6 +101,10 @@
}
}.start();
+ while (!Running.running) {
+ Thread.sleep(10); // sleep for 10 ms
+ }
+
// Since a method of newRunning is running, this class should be added to the previous_version_list
// of Running, and _has_previous_versions should return true at class unloading.
RedefineClassHelper.redefineClass(Running.class, newRunning);
--- a/hotspot/test/runtime/ReservedStack/ReservedStackTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/runtime/ReservedStack/ReservedStackTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -199,7 +199,9 @@
// corruptions are still possible.
boolean supportedPlatform =
Platform.isAix() ||
- (Platform.isLinux() && (Platform.isPPC() || Platform.isX64() || Platform.isX86())) ||
+ (Platform.isLinux() &&
+ (Platform.isPPC() || Platform.isS390x() || Platform.isX64() ||
+ Platform.isX86() || Platform.isAArch64())) ||
Platform.isOSX() ||
Platform.isSolaris();
if (supportedPlatform && !result.contains("PASSED")) {
--- a/hotspot/test/runtime/ReservedStack/ReservedStackTestCompiler.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/runtime/ReservedStack/ReservedStackTestCompiler.java Thu Feb 09 23:15:52 2017 +0100
@@ -24,7 +24,7 @@
/*
* @test ReservedStackTestCompiler
* @summary Run ReservedStackTest with dedicated compilers C1 and C2.
- * @requires vm.flavor == "server"
+ * @requires vm.flavor == "server" & !vm.emulatedClient
* @library /test/lib
* @modules java.base/jdk.internal.misc
* @modules java.base/jdk.internal.vm.annotation
--- a/hotspot/test/runtime/SharedArchiveFile/BootAppendTests.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/runtime/SharedArchiveFile/BootAppendTests.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,7 @@
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @compile javax/sound/sampled/MyClass.jasm
* @compile org/omg/CORBA/Context.jasm
* @compile nonjdk/myPackage/MyClass.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/modules/AccessCheck/AccessExportTwice.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2017, 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
+ * @summary Class p1.c1 in an unnamed module cannot read p2.c2 in module second_mod,
+ * even after p2 is exported to all unnamed. Ensures constant
+ * access check answers when not accessible due to exportedness.
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.module
+ * @compile myloaders/MySameClassLoader.java
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @run main/othervm AccessExportTwice
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MySameClassLoader;
+
+//
+// ClassLoader1 --> defines first_mod --> no packages
+// defines second_mod --> packages p2
+//
+// first_mod can read second_mod
+// package p2 in second_mod is exported to first_mod
+//
+// class p1.c1 defined in an unnamed module tries to access p2.c2 defined in second_mod
+// Access is not allowed, even after p2 is exported to all unnamed modules.
+
+public class AccessExportTwice {
+
+ // Create a Layer over the boot layer.
+ // Define modules within this layer to test access between
+ // publicly defined classes within packages of those modules.
+ public void createLayerOnBoot() throws Throwable {
+
+ // Define module: first_mod
+ // Can read: java.base, second_mod
+ // Packages: none
+ // Packages exported: none
+ ModuleDescriptor descriptor_first_mod =
+ ModuleDescriptor.module("first_mod")
+ .requires("java.base")
+ .requires("second_mod")
+ .build();
+
+ // Define module: second_mod
+ // Can read: java.base
+ // Packages: p2
+ // Packages exported: p2 is exported to first_mod
+ ModuleDescriptor descriptor_second_mod =
+ ModuleDescriptor.module("second_mod")
+ .requires("java.base")
+ .exports("p2", Set.of("first_mod"))
+ .build();
+
+ // Set up a ModuleFinder containing all modules for this layer
+ ModuleFinder finder = ModuleLibrary.of(descriptor_first_mod, descriptor_second_mod);
+
+ // Resolves "first_mod"
+ Configuration cf = Layer.boot()
+ .configuration()
+ .resolveRequires(finder, ModuleFinder.of(), Set.of("first_mod"));
+
+ // Map each module to the same class loader
+ Map<String, ClassLoader> map = new HashMap<>();
+ map.put("first_mod", MySameClassLoader.loader1);
+ map.put("second_mod", MySameClassLoader.loader1);
+
+ // Create Layer that contains first_mod & second_mod
+ Layer layer = Layer.boot().defineModules(cf, map::get);
+
+ assertTrue(layer.findLoader("first_mod") == MySameClassLoader.loader1);
+ assertTrue(layer.findLoader("second_mod") == MySameClassLoader.loader1);
+ assertTrue(layer.findLoader("java.base") == null);
+
+ Class p2_c2_class = MySameClassLoader.loader1.loadClass("p2.c2");
+ // Use the same loader to load class p1.c1
+ Class p1_c1_class = MySameClassLoader.loader1.loadClass("p1.c1");
+ // First access check for p1.c1
+ try {
+ p1_c1_class.newInstance();
+ throw new RuntimeException("Test Failed, the unnamed module should not have access to public type p2.c2");
+ } catch (IllegalAccessError e) {
+ String message = e.getMessage();
+ if (!(message.contains("cannot access") &&
+ message.contains("because module second_mod does not export p2 to unnamed module"))) {
+ throw new RuntimeException("Wrong message: " + message);
+ } else {
+ System.out.println("Test Succeeded at attempt #1");
+ }
+ }
+
+ // Export second_mod/p2 to all unnamed modules.
+ Module second_mod = p2_c2_class.getModule();
+ jdk.internal.module.Modules.addExportsToAllUnnamed(second_mod, "p2");
+
+ // Second access check for p1.c1, should have same result as first
+ try {
+ p1_c1_class.newInstance();
+ throw new RuntimeException("Test Failed, access should have been cached above");
+ } catch (IllegalAccessError e) {
+ String message = e.getMessage();
+ if (!(message.contains("cannot access") &&
+ message.contains("because module second_mod does not export p2 to unnamed module"))) {
+ throw new RuntimeException("Wrong message: " + message);
+ } else {
+ System.out.println("Test Succeeded at attempt #2");
+ }
+ }
+ }
+
+ public static void main(String args[]) throws Throwable {
+ AccessExportTwice test = new AccessExportTwice();
+ test.createLayerOnBoot();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/modules/AccessCheck/AccessReadTwice.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2017, 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
+ * @summary Class p1.c1 in module first_mod cannot read p2.c2 in module second_mod,
+ * even after a read edge is added between first_mod and second_mod.
+ * Ensures constant access check answers when not accessible due to readability.
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.module
+ * @compile p2/c2.java
+ * @compile p1/c1.java
+ * @compile p4/c4.java
+ * @run main/othervm AccessReadTwice
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+//
+// ClassLoader1 --> defines first_mod --> packages p1, p4
+// defines second_mod --> package p2
+//
+// package p2 in second_mod is exported to first_mod
+//
+// class p1.c1 defined in first_mod tries to access p2.c2 defined in second_mod
+// Access is not allowed, even after a read edge is added between first_mod and second_mod.
+
+public class AccessReadTwice {
+
+ // Create a Layer over the boot layer.
+ // Define modules within this layer to test access between
+ // publicly defined classes within packages of those modules.
+ public void createLayerOnBoot() throws Throwable {
+
+ // Define module: first_mod
+ // Can read: java.base
+ // Packages: p1, p4
+ // Packages exported: none
+ ModuleDescriptor descriptor_first_mod =
+ ModuleDescriptor.module("first_mod")
+ .requires("java.base")
+ .contains(Set.of("p1", "p4"))
+ .build();
+
+ // Define module: second_mod
+ // Can read: java.base
+ // Packages: p2
+ // Packages exported: p2 is exported to first_mod
+ ModuleDescriptor descriptor_second_mod =
+ ModuleDescriptor.module("second_mod")
+ .requires("java.base")
+ .exports("p2", Set.of("first_mod"))
+ .build();
+
+ // Set up a ModuleFinder containing all modules for this layer
+ ModuleFinder finder = ModuleLibrary.of(descriptor_first_mod, descriptor_second_mod);
+
+ // Resolves "first_mod" and "second_mod"
+ Configuration cf = Layer.boot()
+ .configuration()
+ .resolveRequires(finder, ModuleFinder.of(), Set.of("first_mod", "second_mod"));
+
+ // Map each module to this class loader
+ Map<String, ClassLoader> map = new HashMap<>();
+ ClassLoader loader = AccessReadTwice.class.getClassLoader();
+ map.put("first_mod", loader);
+ map.put("second_mod", loader);
+
+ // Create Layer that contains first_mod & second_mod
+ Layer layer = Layer.boot().defineModules(cf, map::get);
+
+ assertTrue(layer.findLoader("first_mod") == loader);
+ assertTrue(layer.findLoader("second_mod") == loader);
+ assertTrue(layer.findLoader("java.base") == null);
+
+ Class p2_c2_class = loader.loadClass("p2.c2");
+ Class p1_c1_class = loader.loadClass("p1.c1");
+ Class p4_c4_class = loader.loadClass("p4.c4");
+
+ Module first_mod = p1_c1_class.getModule();
+ Module second_mod = p2_c2_class.getModule();
+
+ // Export first_mod/p1 and first_mod/p4 to all unnamed modules so that
+ // this test can use them
+ jdk.internal.module.Modules.addExportsToAllUnnamed(first_mod, "p1");
+ jdk.internal.module.Modules.addExportsToAllUnnamed(first_mod, "p4");
+
+ // First access check for p1.c1
+ try {
+ p1_c1_class.newInstance();
+ throw new RuntimeException("Test Failed, module first_mod should not have access to p2.c2");
+ } catch (IllegalAccessError e) {
+ String message = e.getMessage();
+ if (!(message.contains("cannot access") &&
+ message.contains("because module first_mod does not read module second_mod"))) {
+ throw new RuntimeException("Wrong message: " + message);
+ } else {
+ System.out.println("Test Succeeded at attempt #1");
+ }
+ }
+
+ // Add a read edge from p4/c4's module (first_mod) to second_mod
+ p4.c4 c4_obj = new p4.c4();
+ c4_obj.addReads(second_mod);
+
+ // Second access check for p1.c1, should have same result as first
+ try {
+ p1_c1_class.newInstance();
+ throw new RuntimeException("Test Failed, access should have been cached above");
+ } catch (IllegalAccessError e) {
+ String message = e.getMessage();
+ if (!(message.contains("cannot access") &&
+ message.contains("because module first_mod does not read module second_mod"))) {
+ throw new RuntimeException("Wrong message: " + message);
+ } else {
+ System.out.println("Test Succeeded at attempt #2");
+ }
+ }
+ }
+
+ public static void main(String args[]) throws Throwable {
+ AccessReadTwice test = new AccessReadTwice();
+ test.createLayerOnBoot();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/modules/AccessCheck/p4/c4.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+// Small class used by multiple hotspot/runtime/modules/AccessCheck/* tests.
+
+package p4;
+
+import java.lang.reflect.Module;
+
+public class c4 {
+ // Add a read edge from c4's module to given module m
+ public void addReads(Module m) {
+ c4.class.getModule().addReads(m);
+ }
+}
--- a/hotspot/test/runtime/modules/JVMAddModulePackage.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/runtime/modules/JVMAddModulePackage.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -84,11 +84,11 @@
// Expected
}
- // Existing package, expect an IAE
+ // Existing package, expect an ISE
try {
ModuleHelper.AddModulePackage(module1, "yourpackage");
- throw new RuntimeException("Failed to get the expected IAE");
- } catch(IllegalArgumentException e) {
+ throw new RuntimeException("Failed to get the expected ISE");
+ } catch(IllegalStateException e) {
// Expected
}
--- a/hotspot/test/runtime/modules/JVMDefineModule.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/runtime/modules/JVMDefineModule.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -127,27 +127,27 @@
}
}
- // Duplicate module name, expect an IAE
- m = ModuleHelper.ModuleObject("module.name", cl, new String[] { "mypackage6" });
+ // Duplicate module name, expect an ISE
+ m = ModuleHelper.ModuleObject("Module_A", cl, new String[] { "mypackage6" });
assertNotNull(m, "Module should not be null");
ModuleHelper.DefineModule(m, "9.0", "module.name/here", new String[] { "mypackage6" });
try {
ModuleHelper.DefineModule(m, "9.0", "module.name/here", new String[] { "mypackage6a" });
- throw new RuntimeException("Failed to get IAE for duplicate module");
- } catch(IllegalArgumentException e) {
- if (!e.getMessage().contains("Module module.name is already defined")) {
- throw new RuntimeException("Failed to get expected IAE message for duplicate module: " + e.getMessage());
+ throw new RuntimeException("Failed to get ISE for duplicate module");
+ } catch(IllegalStateException e) {
+ if (!e.getMessage().contains("Module Module_A is already defined")) {
+ throw new RuntimeException("Failed to get expected ISE message for duplicate module: " + e.getMessage());
}
}
- // Package is already defined for class loader, expect an IAE
+ // Package is already defined for class loader, expect an ISE
m = ModuleHelper.ModuleObject("dupl.pkg.module", cl, new String[] { "mypackage6b" });
try {
ModuleHelper.DefineModule(m, "9.0", "module.name/here", new String[] { "mypackage6" });
- throw new RuntimeException("Failed to get IAE for existing package");
- } catch(IllegalArgumentException e) {
- if (!e.getMessage().contains("Package mypackage6 for module dupl.pkg.module already exists for class loader")) {
- throw new RuntimeException("Failed to get expected IAE message for duplicate package: " + e.getMessage());
+ throw new RuntimeException("Failed to get ISE for existing package");
+ } catch(IllegalStateException e) {
+ if (!e.getMessage().contains("Package mypackage6 for module dupl.pkg.module is already in another module, Module_A, defined to the class loader")) {
+ throw new RuntimeException("Failed to get expected ISE message for duplicate package: " + e.getMessage());
}
}
--- a/hotspot/test/serviceability/attach/AttachSetGetFlag.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/attach/AttachSetGetFlag.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,7 @@
* java.compiler
* java.management
* jdk.attach/sun.tools.attach
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run main AttachSetGetFlag
*/
--- a/hotspot/test/serviceability/dcmd/compiler/CodeCacheTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/dcmd/compiler/CodeCacheTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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
@@ -28,7 +28,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng/othervm -XX:+SegmentedCodeCache CodeCacheTest
* @run testng/othervm -XX:-SegmentedCodeCache CodeCacheTest
* @run testng/othervm -Xint -XX:+SegmentedCodeCache CodeCacheTest
--- a/hotspot/test/serviceability/dcmd/compiler/CodelistTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/dcmd/compiler/CodelistTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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
@@ -28,7 +28,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
--- a/hotspot/test/serviceability/dcmd/compiler/CompilerDirectivesDCMDTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/dcmd/compiler/CompilerDirectivesDCMDTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -49,7 +49,7 @@
public void run(CommandExecutor executor) {
- if (Platform.isServer()) {
+ if (Platform.isServer() && !Platform.isEmulatedClient()) {
filename = System.getProperty("test.src", ".") + File.separator + "control2.txt";
} else {
filename = System.getProperty("test.src", ".") + File.separator + "control1.txt";
--- a/hotspot/test/serviceability/dcmd/compiler/CompilerQueueTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/dcmd/compiler/CompilerQueueTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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
@@ -28,7 +28,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @summary Test of diagnostic command Compiler.queue
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
--- a/hotspot/test/serviceability/dcmd/framework/HelpTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/dcmd/framework/HelpTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -36,7 +36,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng/othervm -XX:+UsePerfData HelpTest
*/
public class HelpTest {
--- a/hotspot/test/serviceability/dcmd/framework/InvalidCommandTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/dcmd/framework/InvalidCommandTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -36,7 +36,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng/othervm -XX:+UsePerfData InvalidCommandTest
*/
public class InvalidCommandTest {
--- a/hotspot/test/serviceability/dcmd/framework/VMVersionTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/dcmd/framework/VMVersionTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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,7 +37,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng/othervm -XX:+UsePerfData VMVersionTest
*/
public class VMVersionTest {
--- a/hotspot/test/serviceability/dcmd/gc/ClassHistogramAllTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/dcmd/gc/ClassHistogramAllTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -28,7 +28,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng ClassHistogramAllTest
*/
public class ClassHistogramAllTest extends ClassHistogramTest {
--- a/hotspot/test/serviceability/dcmd/gc/ClassHistogramTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/dcmd/gc/ClassHistogramTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -36,7 +36,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng ClassHistogramTest
*/
public class ClassHistogramTest {
--- a/hotspot/test/serviceability/dcmd/gc/HeapDumpAllTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/dcmd/gc/HeapDumpAllTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -28,7 +28,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng HeapDumpAllTest
*/
public class HeapDumpAllTest extends HeapDumpTest {
--- a/hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng HeapDumpTest
*/
public class HeapDumpTest {
--- a/hotspot/test/serviceability/dcmd/gc/RunFinalizationTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/dcmd/gc/RunFinalizationTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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,7 +34,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @build FinalizationRunner
* @run main RunFinalizationTest
*/
--- a/hotspot/test/serviceability/dcmd/gc/RunGCTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/dcmd/gc/RunGCTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -40,7 +40,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng/othervm -Xlog:gc=debug:RunGC.gclog -XX:-ExplicitGCInvokesConcurrent RunGCTest
*/
public class RunGCTest {
--- a/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -41,7 +41,7 @@
* java.compiler
* java.instrument
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @build SimpleJvmtiAgent
* @run main ClassFileInstaller SimpleJvmtiAgent
* @run testng LoadAgentDcmdTest
--- a/hotspot/test/serviceability/dcmd/thread/PrintConcurrentLocksTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/dcmd/thread/PrintConcurrentLocksTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -28,7 +28,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng PrintConcurrentLocksTest
*/
public class PrintConcurrentLocksTest extends PrintTest {
--- a/hotspot/test/serviceability/dcmd/thread/PrintTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/dcmd/thread/PrintTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -41,7 +41,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng PrintTest
*/
public class PrintTest {
--- a/hotspot/test/serviceability/dcmd/vm/ClassHierarchyTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/dcmd/vm/ClassHierarchyTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -28,7 +28,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng ClassHierarchyTest
*/
--- a/hotspot/test/serviceability/dcmd/vm/ClassLoaderStatsTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/dcmd/vm/ClassLoaderStatsTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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
@@ -28,7 +28,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng ClassLoaderStatsTest
*/
--- a/hotspot/test/serviceability/dcmd/vm/CommandLineTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/dcmd/vm/CommandLineTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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,7 +34,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+ThereShouldNotBeAnyVMOptionNamedLikeThis CommandLineTest
*/
public class CommandLineTest {
--- a/hotspot/test/serviceability/dcmd/vm/DynLibsTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/dcmd/vm/DynLibsTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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
@@ -36,7 +36,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng DynLibsTest
*/
--- a/hotspot/test/serviceability/dcmd/vm/FlagsTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/dcmd/vm/FlagsTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -33,7 +33,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng/othervm -Xmx129m -XX:+UnlockDiagnosticVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+ThereShouldNotBeAnyVMOptionNamedLikeThis_Right -XX:-TieredCompilation FlagsTest
*/
public class FlagsTest {
--- a/hotspot/test/serviceability/dcmd/vm/SystemPropertiesTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/dcmd/vm/SystemPropertiesTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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,7 +34,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng SystemPropertiesTest
*/
public class SystemPropertiesTest {
--- a/hotspot/test/serviceability/dcmd/vm/UptimeTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/dcmd/vm/UptimeTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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,7 +38,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @run testng UptimeTest
*/
public class UptimeTest {
--- a/hotspot/test/serviceability/jvmti/GetObjectSizeClass.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/jvmti/GetObjectSizeClass.java Thu Feb 09 23:15:52 2017 +0100
@@ -35,7 +35,7 @@
* java.compiler
* java.instrument
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @build GetObjectSizeClassAgent
* @run main ClassFileInstaller GetObjectSizeClassAgent
* @run main GetObjectSizeClass
--- a/hotspot/test/serviceability/jvmti/GetObjectSizeOverflow.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/jvmti/GetObjectSizeOverflow.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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
@@ -36,7 +36,7 @@
* java.compiler
* java.instrument
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @build GetObjectSizeOverflowAgent
* @run main ClassFileInstaller GetObjectSizeOverflowAgent
* @run main GetObjectSizeOverflow
--- a/hotspot/test/serviceability/jvmti/TestRedefineWithUnresolvedClass.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/jvmti/TestRedefineWithUnresolvedClass.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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,7 +31,7 @@
* java.instrument
* java.management
* jdk.jartool/sun.tools.jar
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @build UnresolvedClassAgent
* @run main TestRedefineWithUnresolvedClass
*/
--- a/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapProc.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapProc.java Thu Feb 09 23:15:52 2017 +0100
@@ -21,12 +21,9 @@
* questions.
*/
-import java.lang.management.ManagementFactory;
-import java.lang.management.RuntimeMXBean;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
+import jdk.test.lib.process.ProcessTools;
import sun.management.VMManagement;
@@ -38,7 +35,7 @@
buildLargeHeap(args);
// Print our pid on stdout
- System.out.println("PID[" + getProcessId() + "]");
+ System.out.println("PID[" + ProcessTools.getProcessId() + "]");
// Wait for input before termination
System.in.read();
@@ -50,22 +47,4 @@
}
}
- public static int getProcessId() throws Exception {
-
- // Get the current process id using a reflection hack
- RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
- Field jvm = runtime.getClass().getDeclaredField("jvm");
-
- jvm.setAccessible(true);
- VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime);
-
- Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId");
-
- pid_method.setAccessible(true);
-
- int pid = (Integer) pid_method.invoke(mgmt);
-
- return pid;
- }
-
}
--- a/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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
@@ -46,7 +46,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management/sun.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @build JMapHProfLargeHeapProc
* @run main JMapHProfLargeHeapTest
*/
@@ -90,6 +90,9 @@
try (Scanner largeHeapScanner = new Scanner(
largeHeapProc.getInputStream());) {
String pidstring = null;
+ if (!largeHeapScanner.hasNext()) {
+ throw new RuntimeException ("Test failed: could not open largeHeapScanner.");
+ }
while ((pidstring = largeHeapScanner.findInLine("PID\\[[0-9].*\\]")) == null) {
Thread.sleep(500);
}
--- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java Thu Feb 09 23:15:52 2017 +0100
@@ -59,6 +59,8 @@
OUT = os;
}
+ boolean passed = false;
+
try {
try {
if (ManagementFactory.getCompilationMXBean() == null) {
@@ -84,10 +86,10 @@
PathHandler.getClassCount(),
Compiler.getMethodCount(),
System.currentTimeMillis() - start);
+ passed = true;
} finally {
- if (os != null) {
- os.close();
- }
+ // <clinit> might have started new threads
+ System.exit(passed ? 0 : 1);
}
}
--- a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java Thu Feb 09 23:15:52 2017 +0100
@@ -101,10 +101,12 @@
INITIAL_COMP_LEVEL = 1;
} else {
String vmName = System.getProperty("java.vm.name");
- if (Utils.endsWithIgnoreCase(vmName, " Server VM")) {
+ String vmInfo = System.getProperty("java.vm.info");
+ boolean isEmulatedClient = (vmInfo != null) && vmInfo.contains("emulated-client");
+ if (Utils.endsWithIgnoreCase(vmName, " Server VM") && !isEmulatedClient) {
INITIAL_COMP_LEVEL = 4;
} else if (Utils.endsWithIgnoreCase(vmName, " Client VM")
- || Utils.endsWithIgnoreCase(vmName, " Minimal VM")) {
+ || Utils.endsWithIgnoreCase(vmName, " Minimal VM") || isEmulatedClient) {
INITIAL_COMP_LEVEL = 1;
} else {
throw new RuntimeException("Unknown VM: " + vmName);
--- a/hotspot/test/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java Thu Feb 09 23:15:52 2017 +0100
@@ -50,7 +50,7 @@
OS("isAix", "isLinux", "isOSX", "isSolaris", "isWindows"),
VM_TYPE("isClient", "isServer", "isGraal", "isMinimal", "isZero", "isEmbedded"),
MODE("isInt", "isMixed", "isComp"),
- IGNORED("isDebugBuild", "isFastDebugBuild", "isSlowDebugBuild",
+ IGNORED("isEmulatedClient", "isDebugBuild", "isFastDebugBuild", "isSlowDebugBuild",
"shouldSAAttach", "canPtraceAttachLinux", "canAttachOSX",
"isTieredSupported");
--- a/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -30,11 +30,11 @@
* java.base/jdk.internal.reflect
* java.management
* @build sun.hotspot.WhiteBox Foo Bar
- * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main ClassesDirTest prepare
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld classes
- * @run main ClassesDirTest check ctw.log
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run driver ClassesDirTest prepare
+ * @run driver ClassesDirTest compile classes
+ * @run driver ClassesDirTest check
* @summary testing of CompileTheWorld :: classes in directory
* @author igor.ignatyev@oracle.com
*/
--- a/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -30,11 +30,11 @@
* java.base/jdk.internal.reflect
* java.management
* @build sun.hotspot.WhiteBox Foo Bar
- * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main ClassesListTest prepare
- * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld classes.lst
- * @run main ClassesListTest check ctw.log
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run driver ClassesListTest prepare
+ * @run driver/timeout=600 ClassesListTest compile classes.lst
+ * @run driver ClassesListTest check
* @summary testing of CompileTheWorld :: list of classes in file
* @author igor.ignatyev@oracle.com
*/
--- a/hotspot/test/testlibrary_tests/ctw/CtwTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/testlibrary_tests/ctw/CtwTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -21,6 +21,7 @@
* questions.
*/
+import java.util.Arrays;
import java.util.List;
import java.util.Collections;
import java.util.ArrayList;
@@ -38,8 +39,20 @@
import jdk.test.lib.JDKToolFinder;
import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
public abstract class CtwTest {
+ private static final String LOG_FILE = "ctw.log";
+ private static final String[] CTW_COMMAND = {
+ "-Xbootclasspath/a:.",
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:+WhiteBoxAPI",
+ "-Dsun.hotspot.tools.ctw.logfile=" + LOG_FILE,
+ "--add-exports", "java.base/jdk.internal.jimage=ALL-UNNAMED",
+ "--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED",
+ "--add-exports", "java.base/jdk.internal.reflect=ALL-UNNAMED",
+ sun.hotspot.tools.ctw.CompileTheWorld.class.getName(),
+ };
protected final String[] shouldContain;
protected CtwTest(String[] shouldContain) {
this.shouldContain = shouldContain;
@@ -54,7 +67,10 @@
prepare();
break;
case "check":
- check(args);
+ check();
+ break;
+ case "compile":
+ compile(args);
break;
default:
throw new Error("unregonized action -- " + args[0]);
@@ -63,20 +79,27 @@
protected void prepare() throws Exception { }
- protected void check(String[] args) throws Exception {
- if (args.length < 2) {
- throw new Error("logfile isn't specified");
- }
- String logfile = args[1];
- try (BufferedReader r = Files.newBufferedReader(Paths.get(logfile),
+ protected void check() throws Exception {
+ try (BufferedReader r = Files.newBufferedReader(Paths.get(LOG_FILE),
Charset.defaultCharset())) {
OutputAnalyzer output = readOutput(r);
- for (String test : shouldContain) {
+ for (String test : shouldContain) {
output.shouldContain(test);
}
}
}
+ protected void compile(String[] args) throws Exception {
+ // concat CTW_COMMAND and args w/o 0th element
+ String[] cmd = Arrays.copyOf(CTW_COMMAND, CTW_COMMAND.length + args.length - 1);
+ System.arraycopy(args, 1, cmd, CTW_COMMAND.length, args.length - 1);
+
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmd);
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ dump(output, "compile");
+ output.shouldHaveExitValue(0);
+ }
+
private static OutputAnalyzer readOutput(BufferedReader reader)
throws IOException {
StringBuilder builder = new StringBuilder();
--- a/hotspot/test/testlibrary_tests/ctw/JarDirTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/testlibrary_tests/ctw/JarDirTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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,13 +30,13 @@
* java.base/jdk.internal.reflect
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @build sun.hotspot.WhiteBox Foo Bar
- * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main JarDirTest prepare
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld jars/*
- * @run main JarDirTest check ctw.log
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run driver JarDirTest prepare
+ * @run driver JarDirTest compile jars/*
+ * @run driver JarDirTest check
* @summary testing of CompileTheWorld :: jars in directory
* @author igor.ignatyev@oracle.com
*/
--- a/hotspot/test/testlibrary_tests/ctw/JarsTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/testlibrary_tests/ctw/JarsTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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,13 +30,13 @@
* java.base/jdk.internal.reflect
* java.compiler
* java.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @build sun.hotspot.WhiteBox Foo Bar
- * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main JarsTest prepare
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld foo.jar bar.jar
- * @run main JarsTest check ctw.log
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run driver JarsTest prepare
+ * @run driver JarsTest compile foo.jar bar.jar
+ * @run driver JarsTest check
* @summary testing of CompileTheWorld :: jars
* @author igor.ignatyev@oracle.com
*/
--- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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
@@ -28,7 +28,7 @@
* @modules java.base/jdk.internal.misc
* java.compiler
* java.management/sun.management
- * jdk.jvmstat/sun.jvmstat.monitor
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
* @build sun.hotspot.WhiteBox
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
--- a/jaxp/.hgtags Thu Feb 02 05:26:20 2017 -0800
+++ b/jaxp/.hgtags Thu Feb 09 23:15:52 2017 +0100
@@ -396,3 +396,5 @@
13c6906bfc861d99dc35a19c80b7a99f0b0ac58d jdk-9+151
7e3da313b1746578da648155e37dd8526e83153d jdk-9+152
1384504d2cd0e55c5e0becaeaf40ab05cae959d6 jdk-9+153
+7fa738305436d14c0926df0f04892890cacc766b jdk-9+154
+48fa77af153288b08ba794e1616a7b0685f3b67e jdk-9+155
--- a/jaxp/src/java.xml/share/classes/com/sun/xml/internal/stream/EventFilterSupport.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jaxp/src/java.xml/share/classes/com/sun/xml/internal/stream/EventFilterSupport.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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,7 +64,7 @@
}
public XMLEvent nextEvent()throws XMLStreamException{
- if(super.hasNext()){
+ while (super.hasNext()) {
//get the next event by calling XMLEventReader
XMLEvent event = super.nextEvent();
@@ -72,27 +72,19 @@
if(fEventFilter.accept(event)){
return event;
}
- else{
- return nextEvent();
- }
- }else{
- throw new NoSuchElementException();
}
+ throw new NoSuchElementException();
}//nextEvent()
public XMLEvent nextTag() throws XMLStreamException{
- if(super.hasNext()){
+ while (super.hasNext()) {
XMLEvent event = super.nextTag();
//if the filter accepts this event return this event.
if(fEventFilter.accept(event)){
return event;
}
- else{
- return nextTag();
- }
- }else{
- throw new NoSuchElementException();
}
+ throw new NoSuchElementException();
}
public XMLEvent peek() throws XMLStreamException{
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/Util.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/Util.java Thu Feb 09 23:15:52 2017 +0100
@@ -149,14 +149,6 @@
CatalogMessages.reportIAE(CatalogMessages.ERR_URI_NOTVALIDURL,
new Object[]{uri}, null);
}
-
- // verify the resource exists where possible
- if (isFileUri(uri)) {
- if (!isFileUriExist(uri, false)) {
- CatalogMessages.reportIAE(CatalogMessages.ERR_URI_NOTVALIDURL,
- new Object[]{uri}, null);
- }
- }
}
/**
--- a/jaxp/test/ProblemList.txt Thu Feb 02 05:26:20 2017 -0800
+++ b/jaxp/test/ProblemList.txt Thu Feb 09 23:15:52 2017 +0100
@@ -1,6 +1,6 @@
###########################################################################
#
-# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -22,5 +22,3 @@
# questions.
#
###########################################################################
-
-javax/xml/jaxp/isolatedjdk/catalog/PropertiesTest.sh 8169827 generic-all
--- a/jaxp/test/javax/xml/jaxp/isolatedjdk/IsolatedJDK.sh Thu Feb 02 05:26:20 2017 -0800
+++ b/jaxp/test/javax/xml/jaxp/isolatedjdk/IsolatedJDK.sh Thu Feb 09 23:15:52 2017 +0100
@@ -1,6 +1,6 @@
#!/bin/sh
-# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2015, 2017, 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,11 +21,6 @@
# or visit www.oracle.com if you need additional information or have any
# questions.
-if [ $# = 0 ]; then
- echo "The suffix of ISOLATED_JDK is mandatory"
- exit 1
-fi
-
checkVariable() {
variable='$'$1
@@ -42,20 +37,33 @@
done
}
-# Check essential variables
-checkVariables TESTJAVA TESTSRC TESTCLASSES TESTCLASSPATH
+# Script needs parameters
+if [ $# = 0 ]; then
+ echo "Syntax: IsolatedJDK.sh <Suffix> [remove]"
+ exit 1
+fi
-echo "TESTJAVA=${TESTJAVA}"
-echo "TESTSRC=${TESTSRC}"
-echo "TESTCLASSES=${TESTCLASSES}"
-echo "TESTCLASSPATH=${TESTCLASSPATH}"
+# Is it the call to remove ?
+if [ $# = 2 ]; then
+ if [ "$2" = "remove" ]; then
+ removeIsolatedJdk=1
+ fi
+fi
+
+# Check essential variables
+checkVariables TESTJAVA
+ISOLATED_JDK="./ISOLATED_JDK_$1"
+
+# Remove isolated copy
+if [ "$removeIsolatedJdk" = "1" ]; then
+ echo "Removing ${ISOLATED_JDK}..."
+ rm -rf ${ISOLATED_JDK}
+ echo "Removed."
+ exit 0
+fi
# Make an isolated copy of the testing JDK
-ISOLATED_JDK="./ISOLATED_JDK_$1"
-echo "ISOLATED_JDK=${ISOLATED_JDK}"
-
-echo "Copy testing JDK started"
+echo "Copying test JDK: ${TESTJAVA} -> ${ISOLATED_JDK}..."
cp -H -R ${TESTJAVA} ${ISOLATED_JDK} || exit 1
chmod -R +w ${ISOLATED_JDK} || exit 1
-echo "Copy testing JDK ended"
-
+echo "Copy done."
--- a/jaxp/test/javax/xml/jaxp/isolatedjdk/catalog/PropertiesTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jaxp/test/javax/xml/jaxp/isolatedjdk/catalog/PropertiesTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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,20 +37,95 @@
import static catalog.CatalogTestUtils.generateJAXPProps;
import static catalog.CatalogTestUtils.getCatalogPath;
+import java.io.BufferedReader;
import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import javax.xml.catalog.CatalogResolver;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
/*
- * This case tests if the properties FILES, DEFER, PREFER, RESOLVE in
- * jaxp.properties and system properties could be cared.
+ * @test
+ * @library /javax/xml/jaxp/libs /javax/xml/jaxp/isolatedjdk
+ * @run shell/timeout=600 ../IsolatedJDK.sh JAXP_PROPS
+ * @run testng catalog.PropertiesTest
+ * @run shell/timeout=600 ../IsolatedJDK.sh JAXP_PROPS remove
+ * @summary This test case tests if the properties FILES, DEFER, PREFER,
+ * RESOLVE in jaxp.properties and system properties are used.
+ * It needs to run in a copied JDK as it modifies the JDK's
+ * jaxp.properties file.
+ * @bug 8077931
*/
public class PropertiesTest {
private static final String CATALOG_PROPERTIES = "properties.xml";
+ @Test
+ /*
+ * Run main in a child process as it will modify the JDK.
+ */
+ public void test() throws Exception {
+ // get required properties and do some assertions
+ String javaclasspath = System.getProperty("java.class.path");
+ Assert.assertNotNull(javaclasspath, "Test class path is null");
+ String testclasspath = System.getProperty("test.class.path");
+ Assert.assertNotNull(testclasspath, "Test class path is null");
+ String testsourcepath = System.getProperty("test.src");
+ Assert.assertNotNull(testsourcepath, "Test source path is null");
+
+ // start the child process
+ List<String> testCall = new ArrayList<>(6);
+ testCall.add(Paths.get("ISOLATED_JDK_JAXP_PROPS", "/bin", "java").toString());
+ testCall.add("-cp");
+ testCall.add(javaclasspath);
+ testCall.add("-Dtest.class.path=" + testclasspath);
+ testCall.add("-Dtest.src=" + testsourcepath);
+ testCall.add("catalog.PropertiesTest");
+ System.out.println("Starting child process: " + Arrays.toString(testCall.toArray()));
+ Process test = new ProcessBuilder(testCall).start();
+
+ // wait for it to finish
+ boolean interrupted = false;
+ do {
+ try {
+ test.waitFor();
+ interrupted = false;
+ } catch (InterruptedException ie) {
+ interrupted = true;
+ }
+ } while (interrupted);
+
+ // trace system.out of child process
+ System.out.println("Proccess Out:");
+ BufferedReader br = new BufferedReader(new InputStreamReader(test.getInputStream()));
+ String line;
+ while ((line = br.readLine()) != null) {
+ System.out.println(line);
+ }
+ br.close();
+
+ // trace system.err of child process
+ System.out.println("Proccess Err:");
+ br = new BufferedReader(new InputStreamReader(test.getErrorStream()));
+ while ((line = br.readLine()) != null) {
+ System.out.println(line);
+ }
+ br.close();
+
+ // trace exit value and assert 0
+ int exitValue = test.exitValue();
+ System.out.println("Process Exit code: " + exitValue);
+ Assert.assertEquals(exitValue, 0, "PropertiesTest returned nonzero exit code.");
+ }
+
public static void main(String[] args) throws Exception {
System.out.println("testJAXPProperties started");
testJAXPProperties();
@@ -64,7 +139,8 @@
}
/*
- * Tests how does jaxp.properties affects the resolution.
+ * Tests how jaxp.properties affects the resolution.
+ * Be careful: This test modifies jaxp.properties in the used JDK.
*/
private static void testJAXPProperties() throws IOException {
generateJAXPProps(createJAXPPropsContent());
@@ -73,7 +149,7 @@
}
/*
- * Tests how does system properties affects the resolution.
+ * Tests how system properties affects the resolution.
*/
private static void testSystemProperties() {
setSystemProperties();
@@ -104,7 +180,7 @@
// The properties in jaxp.properties don't use default values
private static String createJAXPPropsContent() {
Map<String, String> props = new HashMap<>();
- props.put(FEATURE_FILES, getCatalogPath(CATALOG_PROPERTIES));
+ props.put(FEATURE_FILES, getCatalogPath(CATALOG_PROPERTIES).toString());
props.put(FEATURE_DEFER, DEFER_FALSE);
props.put(FEATURE_PREFER, PREFER_SYSTEM);
props.put(FEATURE_RESOLVE, RESOLVE_CONTINUE);
@@ -113,7 +189,7 @@
// The system properties don't use default values
private static void setSystemProperties() {
- System.setProperty(FEATURE_FILES, getCatalogPath(CATALOG_PROPERTIES));
+ System.setProperty(FEATURE_FILES, getCatalogPath(CATALOG_PROPERTIES).toString());
System.setProperty(FEATURE_DEFER, DEFER_FALSE);
System.setProperty(FEATURE_PREFER, PREFER_SYSTEM);
System.setProperty(FEATURE_RESOLVE, RESOLVE_CONTINUE);
--- a/jaxp/test/javax/xml/jaxp/isolatedjdk/catalog/PropertiesTest.sh Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-#!/bin/sh
-
-# Copyright (c) 2015, 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 8077931
-# @summary This case tests if the properties FILES, DEFER, PREFER, RESOLVE in
-# jaxp.properties and system properties could be used.
-# @key intermittent
-# @library ../../libs/
-# @build catalog.CatalogTestUtils
-# @build PropertiesTest
-# @run shell/timeout=600 ../IsolatedJDK.sh JAXP_PROPS
-# @run shell/timeout=600 PropertiesTest.sh
-
-echo "Copies properties.xml to class path"
-TEST_CATALOG_PATH=${TESTCLASSES}/catalog/catalogFiles
-echo "TEST_CATALOG_PATH=${TEST_CATALOG_PATH}"
-mkdir -p ${TEST_CATALOG_PATH}
-cp ${TESTSRC}/catalogFiles/properties.xml ${TEST_CATALOG_PATH}/properties.xml
-
-# Execute test
-ISOLATED_JDK=./ISOLATED_JDK_JAXP_PROPS
-echo "Executes PropertiesTest"
-${ISOLATED_JDK}/bin/java -Dtest.src="${TESTSRC}/.." ${TESTVMOPTS} -cp "${TESTCLASSPATH}" catalog.PropertiesTest
-exitCode=$?
-
-# Cleanup ISOLATED_JDK
-rm -rf ${ISOLATED_JDK}
-
-# Results
-echo ''
-if [ $exitCode -gt 0 ]; then
- echo "PropertiesTest failed";
-else
- echo "PropertiesTest passed";
-fi
-exit $exitCode
-
--- a/jaxp/test/javax/xml/jaxp/libs/catalog/CatalogTestUtils.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jaxp/test/javax/xml/jaxp/libs/catalog/CatalogTestUtils.java Thu Feb 09 23:15:52 2017 +0100
@@ -69,12 +69,6 @@
private static final String JAXP_PROPS = "jaxp.properties";
private static final String JAXP_PROPS_BAK = JAXP_PROPS + ".bak";
- /*
- * Force using slash as File separator as we always use cygwin to test in
- * Windows platform.
- */
- private static final String FILE_SEP = "/";
-
private CatalogTestUtils() { }
/* ********** create resolver ********** */
@@ -133,11 +127,14 @@
/* ********** jaxp.properties ********** */
/*
- * Generates the jaxp.properties with the specified content.
+ * Generates jaxp.properties with the specified content,
+ * takes a backup if possible.
*/
static void generateJAXPProps(String content) throws IOException {
Path filePath = getJAXPPropsPath();
Path bakPath = filePath.resolveSibling(JAXP_PROPS_BAK);
+ System.out.println("Creating new file " + filePath +
+ ", saving old version to " + bakPath + ".");
if (Files.exists(filePath) && !Files.exists(bakPath)) {
Files.move(filePath, bakPath);
}
@@ -146,14 +143,16 @@
}
/*
- * Deletes the jaxp.properties.
+ * Deletes jaxp.properties, restoring backup if possible.
*/
static void deleteJAXPProps() throws IOException {
Path filePath = getJAXPPropsPath();
+ Path bakPath = filePath.resolveSibling(JAXP_PROPS_BAK);
+ System.out.println("Removing file " + filePath +
+ ", restoring old version from " + bakPath + ".");
Files.delete(filePath);
- Path bakFilePath = filePath.resolveSibling(JAXP_PROPS_BAK);
- if (Files.exists(bakFilePath)) {
- Files.move(bakFilePath, filePath);
+ if (Files.exists(bakPath)) {
+ Files.move(bakPath, filePath);
}
}
--- a/jaxp/test/javax/xml/jaxp/libs/jaxp/library/JAXPTestUtilities.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jaxp/test/javax/xml/jaxp/libs/jaxp/library/JAXPTestUtilities.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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
@@ -85,13 +85,13 @@
* A map storing every test's current test file pointer. File number should
* be incremental and it's a thread-safe reading on this file number.
*/
- private static final ConcurrentHashMap<Class, Integer> currentFileNumber
+ private static final ConcurrentHashMap<Class<?>, Integer> currentFileNumber
= new ConcurrentHashMap<>();
/**
* BOM table for storing BOM header.
*/
- private final static Map<String, byte[]> bom = new HashMap();
+ private final static Map<String, byte[]> bom = new HashMap<>();
/**
* Initialize all BOM headers.
@@ -313,7 +313,7 @@
* @param clazz test class.
* @return next test output file name.
*/
- public static String getNextFile(Class clazz) {
+ public static String getNextFile(Class<?> clazz) {
int nextNumber = currentFileNumber.contains(clazz)
? currentFileNumber.get(clazz) + 1 : 1;
Integer i = currentFileNumber.putIfAbsent(clazz, nextNumber);
@@ -332,7 +332,7 @@
* path.
* @return a string represents the full path of accessing path.
*/
- public static String getPathByClassName(Class clazz, String relativeDir) {
+ public static String getPathByClassName(Class<?> clazz, String relativeDir) {
String javaSourcePath = System.getProperty("test.src").replaceAll("\\" + File.separator, FILE_SEP);
String normalizedPath = Paths.get(javaSourcePath, relativeDir).normalize().
toAbsolutePath().toString();
@@ -435,7 +435,7 @@
*/
public static void runWithTmpPermission(Runnable r, Permission... ps) {
JAXPPolicyManager policyManager = JAXPPolicyManager.getJAXPPolicyManager(false);
- List<Integer> tmpPermissionIndexes = new ArrayList();
+ List<Integer> tmpPermissionIndexes = new ArrayList<>();
if (policyManager != null) {
for (Permission p : ps)
tmpPermissionIndexes.add(policyManager.addTmpPermission(p));
@@ -459,7 +459,7 @@
*/
public static <T> T runWithTmpPermission(Supplier<T> s, Permission... ps) {
JAXPPolicyManager policyManager = JAXPPolicyManager.getJAXPPolicyManager(false);
- List<Integer> tmpPermissionIndexes = new ArrayList();
+ List<Integer> tmpPermissionIndexes = new ArrayList<>();
if (policyManager != null) {
for (Permission p : ps)
tmpPermissionIndexes.add(policyManager.addTmpPermission(p));
@@ -483,7 +483,7 @@
*/
public static void tryRunWithTmpPermission(RunnableWithException r, Permission... ps) throws Exception {
JAXPPolicyManager policyManager = JAXPPolicyManager.getJAXPPolicyManager(false);
- List<Integer> tmpPermissionIndexes = new ArrayList();
+ List<Integer> tmpPermissionIndexes = new ArrayList<>();
if (policyManager != null) {
for (Permission p : ps)
tmpPermissionIndexes.add(policyManager.addTmpPermission(p));
--- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogFileInputTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogFileInputTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -222,6 +222,8 @@
String catalogUri = getClass().getResource("catalog_invalid.xml").toExternalForm();
return new Object[][]{
{catalogUri, "-//W3C//DTD XHTML 1.0 Strict//EN",
+ "The catalog is invalid, attempting to match the public entry shall return null."},
+ {"file:/../../..", "-//W3C//DTD XHTML 1.0 Strict//EN",
"The catalog is invalid, attempting to match the public entry shall return null."}
};
}
@@ -239,7 +241,6 @@
return new Object[][]{
{""},
{"file:a/b\\c"},
- {"file:/../../.."},
{"c:/te:t"},
{"c:/te?t"},
{"c/te*t"},
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/stream/EventsTest/EventFilterSupportTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2017, 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 stream.EventsTest;
+
+import java.io.IOException;
+import java.io.InputStream;
+import javax.xml.stream.EventFilter;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.XMLEvent;
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+
+/**
+ * @test
+ * @bug 8173111
+ * @summary tests that filtering out nested elements doesn't end up in
+ * a StackOverflowException
+ * @run testng/othervm stream.EventsTest.EventFilterSupportTest
+ * @author danielfuchs
+ */
+public class EventFilterSupportTest {
+ static final String ROOT = "xml";
+ static final String NEXT = "foo";
+ static final String SMOKE = "<?xml version=\"1.0\" encoding=\"US-ASCII\"?>"
+ + "<xml><foo><foo><foo></foo></foo></foo></xml>";
+ // A number high enough to trigger StackOverflowException before the fix.
+ static final int MAX = 100_000;
+
+ public static void main(String[] args)
+ throws XMLStreamException, IOException {
+ smokeTest();
+ testNextEvent(MAX);
+ testNextTag(MAX);
+ System.out.println("Tests passed...");
+ }
+
+ // The smoke test just verifies that our TestInputStream works as
+ // expected and produces the expected stream of characters.
+ // Here we test it with 4 nested elements.
+ @Test
+ public static void smokeTest() throws IOException {
+ System.out.println("\nSmoke test...");
+ StringBuilder sb = new StringBuilder();
+ try (InputStream ts = new TestInputStream(4)) {
+ int c;
+ while ((c = ts.read()) != -1) {
+ System.out.print((char)c);
+ sb.append((char)c);
+ }
+ }
+ assertEquals(sb.toString(), SMOKE, "Smoke test failed");
+ System.out.println("\nSmoke test passed\n");
+ }
+
+ // Test calling XMLEventReader.nextEvent()
+ @Test
+ public static void testNextEvent() throws IOException, XMLStreamException {
+ testNextEvent(MAX);
+ }
+
+ // Without the fix, will cause a StackOverflowException if 'max' is high
+ // enough
+ private static void testNextEvent(int max)
+ throws IOException, XMLStreamException {
+ System.out.println("\nTest nextEvent (" + max + ")...");
+ XMLEventReader reader = createXmlReader(max);
+ XMLEvent event;
+ do {
+ event = reader.nextEvent();
+ System.out.println(event);
+ } while (event.getEventType() != XMLEvent.END_DOCUMENT);
+ System.out.println("nextEvent passed\n");
+ }
+
+ // Test calling XMLEventReader.nextTag()
+ @Test
+ public static void testNextTag() throws IOException, XMLStreamException {
+ testNextTag(MAX);
+ }
+
+ // Without the fix, will cause a StackOverflowException if 'max' is high
+ // enough
+ private static void testNextTag(int max)
+ throws IOException, XMLStreamException {
+ System.out.println("\nTest nextTag (" + max + ")...");
+ XMLEventReader reader = createXmlReader(max);
+ XMLEvent event;
+ do {
+ event = reader.nextTag();
+ System.out.println(event);
+ if (event.getEventType() == XMLEvent.END_ELEMENT
+ && event.asEndElement().getName().getLocalPart().equals(ROOT)) {
+ break;
+ }
+ } while (true);
+ System.out.println("nextTag passed\n");
+ }
+
+ private static XMLEventReader createXmlReader(int max)
+ throws XMLStreamException {
+ TestInputStream ts = new TestInputStream(max);
+ XMLInputFactory xif = XMLInputFactory.newInstance();
+ XMLEventReader reader = xif.createXMLEventReader(ts);
+ return xif.createFilteredReader(reader, new TagFilter(max));
+ }
+
+ // An input stream that pretends to contain 'max - 1' nested NEXT tags
+ // within a ROOT element:
+ // <?xml version="1.0" encoding="US-ASCII"?>
+ // <ROOT><NEXT><NEXT>...</NEXT></NEXT></ROOT>
+ // (1 ROOT element + max-1 nested NEXT elements)
+ public static class TestInputStream extends InputStream {
+
+ int open = 0;
+ int i = 0;
+ int n = 0;
+ final int max;
+
+ public TestInputStream(int max) {
+ this.max = max;
+ }
+
+ String tag() {
+ if (n == 0) {
+ // opening first element - includes the XML processing instruction.
+ return "?xml version=\"1.0\" encoding=\"US-ASCII\"?><" + ROOT;
+ }
+ if (n == 2 * max -1) {
+ // closing the first element
+ // we have 'max' opening tags (0..max-1) followed by
+ // 'max' closing tags (max..2*max-1)
+ // for n in [0..max-1] we open the tags,
+ // for n in [max..2*max-1] we close them (in reverse order)
+ return ROOT;
+ }
+ // everything between [1..max-2] is a NEXT element tag (opening
+ // or closing)
+ return NEXT;
+ }
+
+ @Override
+ public int read() throws IOException {
+ if (n >= 2 * max) return -1;
+ if (open == 0) {
+ open = 1;
+ return '<';
+ }
+ if (open == 1 && n >= max) {
+ // we have opened the ROOT element + n-1 nested NEXT elements,
+ // so now we need to start closing them all in reverse order.
+ open = 2;
+ return '/';
+ }
+ String tag = tag();
+ if (open > 0 && i < tag.length()) {
+ return tag.charAt(i++);
+ }
+ if (open > 0 && i == tag.length()) {
+ open = 0; i = 0; n++;
+ return '>';
+ }
+ return -1;
+ }
+ }
+
+ public static final class TagFilter implements EventFilter {
+ int count;
+ final int max;
+
+ public TagFilter(int max) {
+ this.max = max;
+ }
+
+ // Filters everything except the ROOT element.
+ @Override
+ public boolean accept(XMLEvent event) {
+ int type = event.getEventType();
+ if (type == XMLEvent.START_ELEMENT) {
+ String loc = event.asStartElement().getName().getLocalPart();
+ if (count == 0 || count == 1) System.out.println("<" + loc + ">");
+ count++;
+ return ROOT.equals(loc);
+ }
+ if (type == XMLEvent.END_ELEMENT) {
+ if (count == max) System.out.println("Got " + count + " elements");
+ String loc = event.asEndElement().getName().getLocalPart();
+ count--;
+ if (count == 0 || count == 1) System.out.println("</" + loc + ">");
+ return ROOT.equals(loc);
+ }
+ if (type == XMLEvent.PROCESSING_INSTRUCTION) return true;
+ if (type == XMLEvent.START_DOCUMENT) return true;
+ if (type == XMLEvent.END_DOCUMENT) return true;
+ return false;
+ }
+ }
+
+}
--- a/jaxp/test/javax/xml/jaxp/unittest/transform/TransformerTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jaxp/test/javax/xml/jaxp/unittest/transform/TransformerTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -24,32 +24,32 @@
package transform;
import static jaxp.library.JAXPTestUtilities.getSystemProperty;
-import static jaxp.library.JAXPTestUtilities.tryRunWithTmpPermission;
-import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
import java.io.IOException;
-import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stax.StAXSource;
import javax.xml.transform.stream.StreamResult;
-import javax.xml.transform.stream.StreamSource;
import org.testng.Assert;
import org.testng.AssertJUnit;
+import org.testng.annotations.DataProvider;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
import org.w3c.dom.Document;
@@ -67,8 +67,7 @@
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.AttributesImpl;
-import com.sun.org.apache.xml.internal.serialize.OutputFormat;
-import com.sun.org.apache.xml.internal.serialize.XMLSerializer;
+import transform.util.TransformerTestTemplate;
/*
* @test
@@ -91,250 +90,241 @@
private static final String NAMESPACE_PREFIXES =
"http://xml.org/sax/features/namespace-prefixes";
- private static abstract class TestTemplate {
- protected void printSnippet(String title, String snippet) {
- StringBuilder div = new StringBuilder();
- for (int i = 0; i < title.length(); i++)
- div.append("=");
- System.out.println(title + "\n" + div + "\n" + snippet + "\n");
- }
- }
+ public static class Test6272879 extends TransformerTestTemplate {
- /**
- * Reads the contents of the given file into a string.
- * WARNING: this method adds a final line feed even if the last line of the file doesn't contain one.
- *
- * @param f
- * The file to read
- * @return The content of the file as a string, with line terminators as \"n"
- * for all platforms
- * @throws IOException
- * If there was an error reading
- */
- private String getFileContentAsString(File f) throws IOException {
- try (BufferedReader reader = new BufferedReader(new FileReader(f))) {
- String line;
- StringBuilder sb = new StringBuilder();
- while ((line = reader.readLine()) != null) {
- sb.append(line).append("\n");
- }
- return sb.toString();
- }
- }
+ private static String XSL_INPUT =
+ "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" + LINE_SEPARATOR +
+ "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">" + LINE_SEPARATOR +
+ "<xsl:output method=\"xml\" indent=\"no\" encoding=\"ISO-8859-1\"/>" + LINE_SEPARATOR +
+ "<xsl:template match=\"/\">" + LINE_SEPARATOR +
+ "<xsl:element name=\"TransformateurXML\">" + LINE_SEPARATOR +
+ " <xsl:for-each select=\"XMLUtils/test\">" + LINE_SEPARATOR +
+ " <xsl:element name=\"test2\">" + LINE_SEPARATOR +
+ " <xsl:element name=\"valeur2\">" + LINE_SEPARATOR +
+ " <xsl:attribute name=\"attribut2\">" + LINE_SEPARATOR +
+ " <xsl:value-of select=\"valeur/@attribut\"/>" + LINE_SEPARATOR +
+ " </xsl:attribute>" + LINE_SEPARATOR +
+ " <xsl:value-of select=\"valeur\"/>" + LINE_SEPARATOR +
+ " </xsl:element>" + LINE_SEPARATOR +
+ " </xsl:element>" + LINE_SEPARATOR +
+ " </xsl:for-each>" + LINE_SEPARATOR +
+ "</xsl:element>" + LINE_SEPARATOR +
+ "</xsl:template>" + LINE_SEPARATOR +
+ "</xsl:stylesheet>";
- private class XMLReaderFor6305029 implements XMLReader {
- private boolean namespaces = true;
- private boolean namespacePrefixes = false;
- private EntityResolver resolver;
- private DTDHandler dtdHandler;
- private ContentHandler contentHandler;
- private ErrorHandler errorHandler;
+ private static String XML_INPUT =
+ "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" + LINE_SEPARATOR +
+ // "<!DOCTYPE XMLUtils [" + LINE_SEPARATOR +
+ // "<!ELEMENT XMLUtils (test*)>" + LINE_SEPARATOR +
+ // "<!ELEMENT test (valeur*)>" + LINE_SEPARATOR +
+ // "<!ELEMENT valeur (#PCDATA)>" + LINE_SEPARATOR +
+ // "<!ATTLIST valeur attribut CDATA #REQUIRED>]>" +
+ // LINE_SEPARATOR +
+ "<XMLUtils>" + LINE_SEPARATOR +
+ " <test>" + LINE_SEPARATOR +
+ " <valeur attribut=\"Attribut 1\">Valeur 1</valeur>" + LINE_SEPARATOR +
+ " </test>" + LINE_SEPARATOR +
+ " <test>" + LINE_SEPARATOR +
+ " <valeur attribut=\"Attribut 2\">Valeur 2</valeur>" + LINE_SEPARATOR +
+ " </test>" + LINE_SEPARATOR +
+ "</XMLUtils>";
- public boolean getFeature(final String name) throws SAXNotRecognizedException, SAXNotSupportedException {
- if (name.equals(NAMESPACES)) {
- return namespaces;
- } else if (name.equals(NAMESPACE_PREFIXES)) {
- return namespacePrefixes;
- } else {
- throw new SAXNotRecognizedException();
- }
- }
-
- public void setFeature(final String name, final boolean value) throws SAXNotRecognizedException, SAXNotSupportedException {
- if (name.equals(NAMESPACES)) {
- namespaces = value;
- } else if (name.equals(NAMESPACE_PREFIXES)) {
- namespacePrefixes = value;
- } else {
- throw new SAXNotRecognizedException();
- }
+ public Test6272879() {
+ super(XSL_INPUT, XML_INPUT);
}
- public Object getProperty(final String name) throws SAXNotRecognizedException, SAXNotSupportedException {
- return null;
- }
-
- public void setProperty(final String name, final Object value) throws SAXNotRecognizedException, SAXNotSupportedException {
- }
-
- public void setEntityResolver(final EntityResolver theResolver) {
- this.resolver = theResolver;
- }
-
- public EntityResolver getEntityResolver() {
- return resolver;
- }
-
- public void setDTDHandler(final DTDHandler theHandler) {
- dtdHandler = theHandler;
- }
-
- public DTDHandler getDTDHandler() {
- return dtdHandler;
- }
-
- public void setContentHandler(final ContentHandler handler) {
- contentHandler = handler;
- }
+ /*
+ * @bug 6272879
+ * @summary Test for JDK-6272879
+ * DomResult had truncated Strings in some places
+ */
+ @Test
+ public void run() throws TransformerException, ClassNotFoundException, InstantiationException,
+ IllegalAccessException, ClassCastException
+ {
+ // print input
+ printSnippet("Stylesheet:", getXsl());
+ printSnippet("Source before transformation:", getSourceXml());
- public ContentHandler getContentHandler() {
- return contentHandler;
- }
-
- public void setErrorHandler(final ErrorHandler handler) {
- errorHandler = handler;
- }
+ // transform to DOM result
+ Transformer t = getTransformer();
+ DOMResult result = new DOMResult();
+ t.transform(getStreamSource(), result);
- public ErrorHandler getErrorHandler() {
- return errorHandler;
- }
-
- public void parse(final InputSource input) throws IOException, SAXException {
- parse();
- }
+ // print output
+ printSnippet("Result after transformation:", prettyPrintDOMResult(result));
- public void parse(final String systemId) throws IOException, SAXException {
- parse();
- }
-
- private void parse() throws SAXException {
- contentHandler.startDocument();
- contentHandler.startPrefixMapping("prefix", "namespaceUri");
-
- AttributesImpl atts = new AttributesImpl();
- if (namespacePrefixes) {
- atts.addAttribute("", "xmlns:prefix", "xmlns:prefix", "CDATA", "namespaceUri");
+ // do some assertions
+ Document document = (Document)result.getNode();
+ NodeList nodes = document.getElementsByTagName("valeur2");
+ for (int i = 0; i < nodes.getLength(); i++) {
+ Node node = nodes.item(i);
+ AssertJUnit.assertEquals("Node value mismatch",
+ "Valeur " + (i + 1),
+ node.getFirstChild().getNodeValue());
+ AssertJUnit.assertEquals("Node attribute mismatch",
+ "Attribut " + (i + 1),
+ node.getAttributes().item(0).getNodeValue());
}
-
- contentHandler.startElement("namespaceUri", "localName", namespacePrefixes ? "prefix:localName" : "", atts);
- contentHandler.endElement("namespaceUri", "localName", namespacePrefixes ? "prefix:localName" : "");
- contentHandler.endPrefixMapping("prefix");
- contentHandler.endDocument();
}
}
- /*
- * @bug 6272879
- * @summary Test for JDK-6272879
- */
- @Test
- public final void testBug6272879() throws Exception {
- final String xsl =
- "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" + LINE_SEPARATOR +
- "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">" + LINE_SEPARATOR +
- "<xsl:output method=\"xml\" indent=\"no\" encoding=\"ISO-8859-1\"/>" + LINE_SEPARATOR +
- "<xsl:template match=\"/\">" + LINE_SEPARATOR +
- "<xsl:element name=\"TransformateurXML\">" + LINE_SEPARATOR +
- " <xsl:for-each select=\"XMLUtils/test\">" + LINE_SEPARATOR +
- " <xsl:element name=\"test2\">" + LINE_SEPARATOR +
- " <xsl:element name=\"valeur2\">" + LINE_SEPARATOR +
- " <xsl:attribute name=\"attribut2\">" + LINE_SEPARATOR +
- " <xsl:value-of select=\"valeur/@attribut\"/>" + LINE_SEPARATOR +
- " </xsl:attribute>" + LINE_SEPARATOR +
- " <xsl:value-of select=\"valeur\"/>" + LINE_SEPARATOR +
- " </xsl:element>" + LINE_SEPARATOR +
- " </xsl:element>" + LINE_SEPARATOR +
- " </xsl:for-each>" + LINE_SEPARATOR +
- "</xsl:element>" + LINE_SEPARATOR +
- "</xsl:template>" + LINE_SEPARATOR +
- "</xsl:stylesheet>";
+ public static class Test6305029 extends TransformerTestTemplate {
+
+ private static String XML_INPUT =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<prefix:localName xmlns:prefix=\"namespaceUri\"/>";
+
+ // custom XMLReader representing XML_INPUT
+ private class MyXMLReader implements XMLReader {
+ private boolean namespaces = true;
+ private boolean namespacePrefixes = false;
+ private EntityResolver resolver;
+ private DTDHandler dtdHandler;
+ private ContentHandler contentHandler;
+ private ErrorHandler errorHandler;
+
+ public boolean getFeature(final String name) throws SAXNotRecognizedException, SAXNotSupportedException {
+ if (name.equals(NAMESPACES)) {
+ return namespaces;
+ } else if (name.equals(NAMESPACE_PREFIXES)) {
+ return namespacePrefixes;
+ } else {
+ throw new SAXNotRecognizedException();
+ }
+ }
+
+ public void setFeature(final String name, final boolean value) throws SAXNotRecognizedException, SAXNotSupportedException {
+ if (name.equals(NAMESPACES)) {
+ namespaces = value;
+ } else if (name.equals(NAMESPACE_PREFIXES)) {
+ namespacePrefixes = value;
+ } else {
+ throw new SAXNotRecognizedException();
+ }
+ }
+
+ public Object getProperty(final String name) throws SAXNotRecognizedException, SAXNotSupportedException {
+ return null;
+ }
+
+ public void setProperty(final String name, final Object value) throws SAXNotRecognizedException, SAXNotSupportedException {
+ }
+
+ public void setEntityResolver(final EntityResolver theResolver) {
+ this.resolver = theResolver;
+ }
+
+ public EntityResolver getEntityResolver() {
+ return resolver;
+ }
+
+ public void setDTDHandler(final DTDHandler theHandler) {
+ dtdHandler = theHandler;
+ }
+
+ public DTDHandler getDTDHandler() {
+ return dtdHandler;
+ }
+
+ public void setContentHandler(final ContentHandler handler) {
+ contentHandler = handler;
+ }
- final String sourceXml =
- "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" + LINE_SEPARATOR +
- // "<!DOCTYPE XMLUtils [" + LINE_SEPARATOR +
- // "<!ELEMENT XMLUtils (test*)>" + LINE_SEPARATOR +
- // "<!ELEMENT test (valeur*)>" + LINE_SEPARATOR +
- // "<!ELEMENT valeur (#PCDATA)>" + LINE_SEPARATOR +
- // "<!ATTLIST valeur attribut CDATA #REQUIRED>]>" +
- // LINE_SEPARATOR +
- "<XMLUtils>" + LINE_SEPARATOR +
- " <test>" + LINE_SEPARATOR +
- " <valeur attribut=\"Attribut 1\">Valeur 1</valeur>" + LINE_SEPARATOR +
- " </test>" + LINE_SEPARATOR +
- " <test>" + LINE_SEPARATOR +
- " <valeur attribut=\"Attribut 2\">Valeur 2</valeur>" + LINE_SEPARATOR +
- " </test>" + LINE_SEPARATOR +
- "</XMLUtils>";
+ public ContentHandler getContentHandler() {
+ return contentHandler;
+ }
+
+ public void setErrorHandler(final ErrorHandler handler) {
+ errorHandler = handler;
+ }
+
+ public ErrorHandler getErrorHandler() {
+ return errorHandler;
+ }
- System.out.println("Stylesheet:");
- System.out.println("=============================");
- System.out.println(xsl);
- System.out.println();
+ public void parse(final InputSource input) throws IOException, SAXException {
+ parse();
+ }
+
+ public void parse(final String systemId) throws IOException, SAXException {
+ parse();
+ }
- System.out.println("Source before transformation:");
- System.out.println("=============================");
- System.out.println(sourceXml);
- System.out.println();
+ private void parse() throws SAXException {
+ contentHandler.startDocument();
+ contentHandler.startPrefixMapping("prefix", "namespaceUri");
+
+ AttributesImpl atts = new AttributesImpl();
+ if (namespacePrefixes) {
+ atts.addAttribute("", "xmlns:prefix", "xmlns:prefix", "CDATA", "namespaceUri");
+ }
- // transform to DOM result
- TransformerFactory tf = TransformerFactory.newInstance();
- Transformer t = tf.newTransformer(new StreamSource(new ByteArrayInputStream(xsl.getBytes())));
- DOMResult result = new DOMResult();
- t.transform(new StreamSource(new ByteArrayInputStream(sourceXml.getBytes())), result);
- Document document = (Document)result.getNode();
+ contentHandler.startElement("namespaceUri", "localName", namespacePrefixes ? "prefix:localName" : "", atts);
+ contentHandler.endElement("namespaceUri", "localName", namespacePrefixes ? "prefix:localName" : "");
+ contentHandler.endPrefixMapping("prefix");
+ contentHandler.endDocument();
+ }
+ }
+
+ public Test6305029() {
+ super(null, XML_INPUT);
+ }
- System.out.println("Result after transformation:");
- System.out.println("============================");
- tryRunWithTmpPermission(() -> {
- OutputFormat format = new OutputFormat();
- format.setIndenting(true);
- new XMLSerializer(System.out, format).serialize(document);
- }, new RuntimePermission("accessClassInPackage.com.sun.org.apache.xml.internal.serialize"));
- System.out.println();
+ /*
+ * @bug 6305029
+ * @summary Test for JDK-6305029
+ * Test identity transformation
+ */
+ @Test
+ public void run() throws TransformerFactoryConfigurationError, TransformerException {
+ // get Identity transformer
+ Transformer t = getTransformer();
- System.out.println("Node content for element valeur2:");
- System.out.println("=================================");
- NodeList nodes = document.getElementsByTagName("valeur2");
- for (int i = 0; i < nodes.getLength(); i++) {
- Node node = nodes.item(i);
- System.out.println(" Node value: " + node.getFirstChild().getNodeValue());
- System.out.println(" Node attribute: " + node.getAttributes().item(0).getNodeValue());
+ // test SAXSource from custom XMLReader
+ SAXSource saxSource = new SAXSource(new MyXMLReader(), new InputSource());
+ StringWriter resultWriter = new StringWriter();
+ t.transform(saxSource, new StreamResult(resultWriter));
+ String resultString = resultWriter.toString();
+ printSnippet("Result after transformation from custom SAXSource:", resultString);
+ AssertJUnit.assertEquals("Identity transform of SAXSource", getSourceXml(), resultString);
- AssertJUnit.assertEquals("Node value mismatch", "Valeur " + (i + 1), node.getFirstChild().getNodeValue());
- AssertJUnit.assertEquals("Node attribute mismatch", "Attribut " + (i + 1), node.getAttributes().item(0).getNodeValue());
+ // test StreamSource
+ printSnippet("Source before transformation of StreamSource:", getSourceXml());
+ resultWriter = new StringWriter();
+ t.transform(getStreamSource(), new StreamResult(resultWriter));
+ resultString = resultWriter.toString();
+ printSnippet("Result after transformation of StreamSource:", resultString);
+ AssertJUnit.assertEquals("Identity transform of StreamSource", getSourceXml(), resultString);
}
}
- /*
- * @bug 6305029
- * @summary Test for JDK-6305029
- */
- @Test
- public final void testBug6305029() throws TransformerException {
- final String XML_DOCUMENT = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<prefix:localName xmlns:prefix=\"namespaceUri\"/>";
+ public static class Test6505031 extends TransformerTestTemplate {
+
+ public Test6505031() throws IOException {
+ super();
+ setXsl(fromInputStream(getClass().getResourceAsStream("transform.xsl")));
+ setSourceXml(fromInputStream(getClass().getResourceAsStream("template.xml")));
+ }
- // test SAXSource
- SAXSource saxSource = new SAXSource(new XMLReaderFor6305029(), new InputSource());
- StringWriter resultWriter = new StringWriter();
- TransformerFactory tf = TransformerFactory.newInstance();
- tf.newTransformer().transform(saxSource, new StreamResult(resultWriter));
- AssertJUnit.assertEquals("Identity transform of SAXSource", XML_DOCUMENT, resultWriter.toString());
-
- // test StreamSource
- StreamSource streamSource = new StreamSource(new StringReader(XML_DOCUMENT));
- resultWriter = new StringWriter();
- tf.newTransformer().transform(streamSource, new StreamResult(resultWriter));
- AssertJUnit.assertEquals("Identity transform of StreamSource", XML_DOCUMENT, resultWriter.toString());
+ /*
+ * @bug 6505031
+ * @summary Test transformer parses keys and their values coming from different xml documents.
+ */
+ @Test
+ public void run() throws TransformerFactoryConfigurationError, TransformerException {
+ Transformer t = getTransformer();
+ t.setParameter("config", getClass().getResource("config.xml").toString());
+ t.setParameter("mapsFile", getClass().getResource("maps.xml").toString());
+ StringWriter resultWriter = new StringWriter();
+ t.transform(getStreamSource(), new StreamResult(resultWriter));
+ String resultString = resultWriter.toString();
+ Assert.assertTrue(resultString.contains("map1key1value") && resultString.contains("map2key1value"));
+ }
}
- /*
- * @bug 6505031
- * @summary Test transformer parses keys and their values coming from different xml documents.
- */
- @Test
- public final void testBug6505031() throws TransformerException {
- TransformerFactory tf = TransformerFactory.newInstance();
- Transformer t = tf.newTransformer(new StreamSource(getClass().getResource("transform.xsl").toString()));
- t.setParameter("config", getClass().getResource("config.xml").toString());
- t.setParameter("mapsFile", getClass().getResource("maps.xml").toString());
- StringWriter sw = new StringWriter();
- t.transform(new StreamSource(getClass().getResource("template.xml").toString()), new StreamResult(sw));
- String s = sw.toString();
- Assert.assertTrue(s.contains("map1key1value") && s.contains("map2key1value"));
- }
+ public static class Test8169631 extends TransformerTestTemplate {
- private static class Test8169631 extends TestTemplate {
- private final static String xsl =
+ private static String XSL_INPUT =
"<?xml version=\"1.0\"?>" + LINE_SEPARATOR +
"<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">" + LINE_SEPARATOR +
" <xsl:template match=\"/\">" + LINE_SEPARATOR +
@@ -345,7 +335,7 @@
" </xsl:template>" + LINE_SEPARATOR +
"</xsl:stylesheet>" + LINE_SEPARATOR;
- private final static String sourceXml =
+ private static String XML_INPUT =
"<?xml version=\"1.0\"?>" + LINE_SEPARATOR +
"<envelope xmlns=\"http://www.sap.com/myns\" xmlns:sap=\"http://www.sap.com/myns\">" + LINE_SEPARATOR +
" <sap:row sap:attrib=\"a\">1</sap:row>" + LINE_SEPARATOR +
@@ -353,6 +343,10 @@
" <row sap:attrib=\"c\">3</row>" + LINE_SEPARATOR +
"</envelope>" + LINE_SEPARATOR;
+ public Test8169631() {
+ super(XSL_INPUT, XML_INPUT);
+ }
+
/**
* Utility method to print out transformation result and check values.
*
@@ -380,103 +374,104 @@
type + " should have count of "+ attribCount + " attributes.");
}
- public void run() throws IOException, TransformerException,
- SAXException, ParserConfigurationException
+ @DataProvider(name = "testdata8169631")
+ public Object[][] testData()
+ throws TransformerConfigurationException, SAXException, IOException,
+ ParserConfigurationException, XMLStreamException
{
- printSnippet("Source:", sourceXml);
-
- printSnippet("Stylesheet:", xsl);
-
- // create default transformer (namespace aware)
- TransformerFactory tf1 = TransformerFactory.newInstance();
- ByteArrayInputStream bais = new ByteArrayInputStream(xsl.getBytes());
- Transformer t1 = tf1.newTransformer(new StreamSource(bais));
+ // get Transformers
+ TransformerFactory tf = TransformerFactory.newInstance();
+ Transformer t = getTransformer(tf);
+ Transformer tFromTemplates = getTemplates(tf).newTransformer();
- // test transformation from stream source with namespace support
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- bais = new ByteArrayInputStream(sourceXml.getBytes());
- t1.transform(new StreamSource(bais), new StreamResult(baos));
- verifyResult("StreamSource with namespace support", baos.toString(), 0, 1);
+ // get DOMSource objects
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DOMSource domSourceWithoutNS = getDOMSource(dbf);
+ dbf.setNamespaceAware(true);
+ DOMSource domSourceWithNS = getDOMSource(dbf);
- // test transformation from DOM source with namespace support
- bais.reset();
- baos.reset();
- DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
- dbf.setNamespaceAware(true);
- Document doc = dbf.newDocumentBuilder().parse(new InputSource(bais));
- t1.transform(new DOMSource(doc), new StreamResult(baos));
- verifyResult("DOMSource with namespace support", baos.toString(), 0, 1);
+ // get SAXSource objects
+ SAXParserFactory spf = SAXParserFactory.newInstance();
+ SAXSource saxSourceWithoutNS = getSAXSource(spf);
+ spf.setNamespaceAware(true);
+ SAXSource saxSourceWithNS = getSAXSource(spf);
+
+ // get StAXSource objects
+ XMLInputFactory xif = XMLInputFactory.newInstance();
+ StAXSource staxSourceWithNS = getStAXSource(xif);
- // test transformation from DOM source without namespace support
- bais.reset();
- baos.reset();
- dbf.setNamespaceAware(false);
- doc = dbf.newDocumentBuilder().parse(new InputSource(bais));
- t1.transform(new DOMSource(doc), new StreamResult(baos));
- verifyResult("DOMSource without namespace support", baos.toString(), 3, 3);
+ // print XML/XSL snippets to ease understanding of result
+ printSnippet("Source:", getSourceXml());
+ printSnippet("Stylesheet:", getXsl());
- // test transformation from SAX source with namespace support
- bais.reset();
- baos.reset();
- SAXParserFactory spf = SAXParserFactory.newInstance();
- spf.setNamespaceAware(true);
- XMLReader xmlr = spf.newSAXParser().getXMLReader();
- SAXSource saxS = new SAXSource(xmlr, new InputSource(bais));
- t1.transform(saxS, new StreamResult(baos));
- verifyResult("SAXSource with namespace support", baos.toString(), 0, 1);
+ return new Object[][] {
+ // test StreamSource input with all transformers
+ // namespace awareness is set by transformer
+ {t, getStreamSource(), "StreamSource with namespace support", 0, 1},
+ {tFromTemplates, getStreamSource(), "StreamSource with namespace support using templates", 0, 1},
+ // now test DOMSource, SAXSource and StAXSource
+ // with rotating use of created transformers
+ // namespace awareness is set by source objects
+ {t, domSourceWithNS, "DOMSource with namespace support", 0, 1},
+ {t, domSourceWithoutNS, "DOMSource without namespace support", 3, 3},
+ {tFromTemplates, saxSourceWithNS, "SAXSource with namespace support", 0, 1},
+ {tFromTemplates, saxSourceWithoutNS, "SAXSource without namespace support", 3, 3},
+ {t, staxSourceWithNS, "StAXSource with namespace support", 0, 1}
+ };
+ }
- // test transformation from SAX source without namespace support
- bais.reset();
- baos.reset();
- spf.setNamespaceAware(false);
- xmlr = spf.newSAXParser().getXMLReader();
- saxS = new SAXSource(xmlr, new InputSource(bais));
- t1.transform(saxS, new StreamResult(baos));
- verifyResult("SAXSource without namespace support", baos.toString(), 3, 3);
+ /*
+ * @bug 8169631
+ * @summary Test combinations of namespace awareness settings on
+ * XSL transformations
+ */
+ @Test(dataProvider = "testdata8169631")
+ public void run(Transformer t, Source s, String label, int elementcount, int attributecount)
+ throws TransformerException
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ t.transform(s, new StreamResult(baos));
+ verifyResult(label, baos.toString(), elementcount, attributecount);
}
}
- /*
- * @bug 8169631
- * @summary Test combinations of namespace awareness settings on
- * XSL transformations
- */
- @Test
- public final void testBug8169631() throws IOException, SAXException,
- TransformerException, ParserConfigurationException
- {
- new Test8169631().run();
+ public static class Test8150704 extends TransformerTestTemplate {
+
+ public Test8150704() {
+ super();
+ }
+
+ @DataProvider(name = "testdata8150704")
+ public Object[][] testData() {
+ return new Object[][] {
+ {"Bug8150704-1.xsl", "Bug8150704-1.xml", "Bug8150704-1.ref"},
+ {"Bug8150704-2.xsl", "Bug8150704-2.xml", "Bug8150704-2.ref"}
+ };
+ }
+
+ /*
+ * @bug 8150704
+ * @summary Test that XSL transformation with lots of temporary result
+ * trees will not run out of DTM IDs.
+ */
+ @Test(dataProvider = "testdata8150704")
+ public void run(String xsl, String xml, String ref) throws IOException, TransformerException {
+ System.out.println("Testing transformation of " + xml + "...");
+ setXsl(fromInputStream(getClass().getResourceAsStream(xsl)));
+ setSourceXml(fromInputStream(getClass().getResourceAsStream(xml)));
+ Transformer t = getTransformer();
+ StringWriter resultWriter = new StringWriter();
+ t.transform(getStreamSource(), new StreamResult(resultWriter));
+ String resultString = resultWriter.toString().replaceAll("\\r\\n", "\n").replaceAll("\\r", "\n").trim();
+ String reference = fromInputStream(getClass().getResourceAsStream(ref)).trim();
+ Assert.assertEquals(resultString, reference, "Output of transformation of " + xml + " does not match reference");
+ System.out.println("Passed.");
+ }
}
- /*
- * @bug 8150704
- * @summary Test that XSL transformation with lots of temporary result
- * trees will not run out of DTM IDs.
- */
- @Test
- public final void testBug8150704() throws TransformerException, IOException {
- System.out.println("Testing transformation of Bug8150704-1.xml...");
- TransformerFactory tf = TransformerFactory.newInstance();
- Transformer t = tf.newTransformer(new StreamSource(getClass().getResource("Bug8150704-1.xsl").toString()));
- StringWriter sw = new StringWriter();
- t.transform(new StreamSource(getClass().getResource("Bug8150704-1.xml").toString()), new StreamResult(sw));
- String resultstring = sw.toString().replaceAll("\\r\\n", "\n").replaceAll("\\r", "\n");
- String reference = getFileContentAsString(new File(getClass().getResource("Bug8150704-1.ref").getPath()));
- Assert.assertEquals(resultstring, reference, "Output of transformation of Bug8150704-1.xml does not match reference");
- System.out.println("Passed.");
+ public static class Test8162598 extends TransformerTestTemplate {
- System.out.println("Testing transformation of Bug8150704-2.xml...");
- t = tf.newTransformer(new StreamSource(getClass().getResource("Bug8150704-2.xsl").toString()));
- sw = new StringWriter();
- t.transform(new StreamSource(getClass().getResource("Bug8150704-2.xml").toString()), new StreamResult(sw));
- resultstring = sw.toString().replaceAll("\\r\\n", "\n").replaceAll("\\r", "\n");
- reference = getFileContentAsString(new File(getClass().getResource("Bug8150704-2.ref").getPath()));
- Assert.assertEquals(resultstring, reference, "Output of transformation of Bug8150704-2.xml does not match reference");
- System.out.println("Passed.");
- }
-
- private static class Test8162598 extends TestTemplate {
- private static final String xsl =
+ private static String XSL_INPUT =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + LINE_SEPARATOR +
"<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">" + LINE_SEPARATOR +
" <xsl:template match=\"/\">" + LINE_SEPARATOR +
@@ -494,8 +489,13 @@
" </xsl:template>" + LINE_SEPARATOR +
"</xsl:stylesheet>";
- private static final String sourceXml =
+ private static String XML_INPUT =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><aaa></aaa>" + LINE_SEPARATOR;
+
+ public Test8162598() {
+ super(XSL_INPUT, XML_INPUT);
+ }
+
/**
* Utility method for testBug8162598().
* Provides a convenient way to check/assert the expected namespaces
@@ -510,7 +510,6 @@
* @param nsc
* Expected namespace of the first sibling of the first sibling
*/
-
private void checkNodeNS(Node test, String nstest, String nsb, String nsc) {
String testNodeName = test.getNodeName();
if (nstest == null) {
@@ -532,29 +531,27 @@
}
}
+ /*
+ * @bug 8162598
+ * @summary Test XSLTC handling of namespaces, especially empty namespace
+ * definitions to reset the default namespace
+ */
+ @Test
public void run() throws Exception {
- printSnippet("Source:", sourceXml);
-
- printSnippet("Stylesheet:", xsl);
+ // print input
+ printSnippet("Source:", getSourceXml());
+ printSnippet("Stylesheet:", getXsl());
// transform to DOM result
- TransformerFactory tf = TransformerFactory.newInstance();
- ByteArrayInputStream bais = new ByteArrayInputStream(xsl.getBytes());
- Transformer t = tf.newTransformer(new StreamSource(bais));
+ Transformer t = getTransformer();
DOMResult result = new DOMResult();
- bais = new ByteArrayInputStream(sourceXml.getBytes());
- t.transform(new StreamSource(bais), result);
- Document document = (Document)result.getNode();
+ t.transform(getStreamSource(), result);
- System.out.println("Result after transformation:");
- System.out.println("============================");
- tryRunWithTmpPermission(() -> {
- OutputFormat format = new OutputFormat();
- format.setIndenting(true);
- new XMLSerializer(System.out, format).serialize(document);
- }, new RuntimePermission("accessClassInPackage.com.sun.org.apache.xml.internal.serialize"));
- System.out.println();
+ // print output
+ printSnippet("Result after transformation:", prettyPrintDOMResult(result));
+ // do some verifications
+ Document document = (Document)result.getNode();
checkNodeNS(document.getElementsByTagName("test1").item(0), "ns2", "ns2", null);
checkNodeNS(document.getElementsByTagName("test2").item(0), "ns1", "ns2", null);
checkNodeNS(document.getElementsByTagName("test3").item(0), null, null, null);
@@ -565,68 +562,74 @@
}
}
- /*
- * @bug 8162598
- * @summary Test XSLTC handling of namespaces, especially empty namespace
- * definitions to reset the default namespace
- */
- @Test
- public final void testBug8162598() throws Exception {
- new Test8162598().run();
- }
+ public static class Test8169112 extends TransformerTestTemplate{
+
+ public static String XML_INPUT =
+ "<?xml version=\"1.0\"?><DOCROOT/>";
+
+ public Test8169112() throws IOException {
+ super();
+ setXsl(fromInputStream(getClass().getResourceAsStream("Bug8169112.xsl")));
+ setSourceXml(XML_INPUT);
+ }
- /**
- * @bug 8169112
- * @summary Test compilation of large xsl file with outlining.
- *
- * This test merely compiles a large xsl file and tests if its bytecode
- * passes verification by invoking the transform() method for
- * dummy content. The test succeeds if no Exception is thrown
- */
- @Test
- public final void testBug8169112() throws FileNotFoundException,
- TransformerException
- {
- TransformerFactory tf = TransformerFactory.newInstance();
- String xslFile = getClass().getResource("Bug8169112.xsl").toString();
- Transformer t = tf.newTransformer(new StreamSource(xslFile));
- String xmlIn = "<?xml version=\"1.0\"?><DOCROOT/>";
- ByteArrayInputStream bis = new ByteArrayInputStream(xmlIn.getBytes());
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- t.transform(new StreamSource(bis), new StreamResult(bos));
+ /**
+ * @throws TransformerException
+ * @bug 8169112
+ * @summary Test compilation of large xsl file with outlining.
+ *
+ * This test merely compiles a large xsl file and tests if its bytecode
+ * passes verification by invoking the transform() method for
+ * dummy content. The test succeeds if no Exception is thrown
+ */
+ @Test
+ public void run() throws TransformerException {
+ Transformer t = getTransformer();
+ t.transform(getStreamSource(), new StreamResult(new ByteArrayOutputStream()));
+ }
}
- /**
- * @bug 8169772
- * @summary Test transformation of DOM with null valued text node
- *
- * This test would throw a NullPointerException during transform when the
- * fix was not present.
- */
- @Test
- public final void testBug8169772() throws ParserConfigurationException,
- SAXException, IOException, TransformerException
- {
- // create a small DOM
- Document doc = DocumentBuilderFactory.newInstance().
- newDocumentBuilder().parse(
- new ByteArrayInputStream(
- "<?xml version=\"1.0\"?><DOCROOT/>".getBytes()
- )
- );
+ public static class Test8169772 extends TransformerTestTemplate {
+
+ public Test8169772() {
+ super();
+ }
+
+ private Document getDOMWithBadElement() throws SAXException, IOException, ParserConfigurationException {
+ // create a small DOM
+ Document doc = DocumentBuilderFactory.newInstance().
+ newDocumentBuilder().parse(
+ new ByteArrayInputStream(
+ "<?xml version=\"1.0\"?><DOCROOT/>".getBytes()
+ )
+ );
+
+ // insert a bad element
+ Element e = doc.createElement("ERROR");
+ e.appendChild(doc.createTextNode(null));
+ doc.getDocumentElement().appendChild(e);
- // insert a bad element
- Element e = doc.createElement("ERROR");
- e.appendChild(doc.createTextNode(null));
- doc.getDocumentElement().appendChild(e);
+ return doc;
+ }
- // transform
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- TransformerFactory.newInstance().newTransformer().transform(
- new DOMSource(doc.getDocumentElement()), new StreamResult(bos)
- );
- System.out.println("Transformation result (DOM with null text node):");
- System.out.println("================================================");
- System.out.println(bos);
+ /**
+ * @throws ParserConfigurationException
+ * @throws IOException
+ * @throws SAXException
+ * @throws TransformerException
+ * @bug 8169772
+ * @summary Test transformation of DOM with null valued text node
+ *
+ * This test would throw a NullPointerException during transform when the
+ * fix was not present.
+ */
+ @Test
+ public void run() throws SAXException, IOException, ParserConfigurationException, TransformerException {
+ Transformer t = getTransformer();
+ StringWriter resultWriter = new StringWriter();
+ DOMSource d = new DOMSource(getDOMWithBadElement().getDocumentElement());
+ t.transform(d, new StreamResult(resultWriter));
+ printSnippet("Transformation result (DOM with null text node):", resultWriter.toString());
+ }
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/transform/util/TransformerTestTemplate.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2014, 2017, 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 transform.util;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.stream.Collectors;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.transform.Templates;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stax.StAXSource;
+import javax.xml.transform.stream.StreamSource;
+
+import org.w3c.dom.bootstrap.DOMImplementationRegistry;
+import org.w3c.dom.ls.DOMImplementationLS;
+import org.w3c.dom.ls.LSOutput;
+import org.w3c.dom.ls.LSSerializer;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/*
+ * Template for Transformer tests
+ */
+public abstract class TransformerTestTemplate {
+ private String xsl = null;
+ private String sourceXml = null;
+
+ public TransformerTestTemplate() {
+ super();
+ }
+
+ public TransformerTestTemplate(String xsl, String sourceXml) {
+ super();
+ this.xsl = xsl;
+ this.sourceXml = sourceXml;
+ }
+
+ public String getXsl() {
+ return xsl;
+ }
+
+ public void setXsl(String xsl) {
+ this.xsl = xsl;
+ }
+
+ public String getSourceXml() {
+ return sourceXml;
+ }
+
+ public void setSourceXml(String sourceXml) {
+ this.sourceXml = sourceXml;
+ }
+
+ public String fromInputStream(InputStream is) throws IOException {
+ try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
+ return br.lines().collect(Collectors.joining("\n"));
+ }
+ }
+
+ // print an XML Snippet under a given title
+ public void printSnippet(String title, String snippet) {
+ StringBuilder div = new StringBuilder();
+ for (int i = 0; i < title.length(); i++)
+ div.append("=");
+ System.out.println(title + "\n" + div + "\n" + snippet + "\n");
+ }
+
+ // pretty print a DOMResult
+ public String prettyPrintDOMResult(DOMResult dr) throws ClassNotFoundException, InstantiationException,
+ IllegalAccessException, ClassCastException
+ {
+ DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
+ DOMImplementationLS domImplementationLS = (DOMImplementationLS)registry.getDOMImplementation("LS");
+ StringWriter writer = new StringWriter();
+ LSOutput formattedOutput = domImplementationLS.createLSOutput();
+ formattedOutput.setCharacterStream(writer);
+ LSSerializer domSerializer = domImplementationLS.createLSSerializer();
+ domSerializer.getDomConfig().setParameter("format-pretty-print", true);
+ domSerializer.getDomConfig().setParameter("xml-declaration", false);
+ domSerializer.write(dr.getNode(), formattedOutput);
+ return writer.toString();
+ }
+
+ public Transformer getTransformer() throws TransformerConfigurationException {
+ return getTransformer(null);
+ }
+
+ // utility to obtain Transformer from TransformerFactory
+ public Transformer getTransformer(TransformerFactory tf)
+ throws TransformerConfigurationException
+ {
+ if (tf == null) {
+ tf = TransformerFactory.newInstance();
+ }
+
+ if (xsl == null) {
+ return tf.newTransformer();
+ } else {
+ return tf.newTransformer(
+ new StreamSource(new ByteArrayInputStream(xsl.getBytes()))
+ );
+ }
+ }
+
+ // utility to obtain Templates from TransformerFactory
+ public Templates getTemplates(TransformerFactory tf)
+ throws TransformerConfigurationException
+ {
+ return tf.newTemplates(
+ new StreamSource(new ByteArrayInputStream(xsl.getBytes()))
+ );
+ }
+
+ // utility to construct StreamSource
+ public StreamSource getStreamSource() {
+ return new StreamSource(
+ new ByteArrayInputStream(sourceXml.getBytes())
+ );
+ }
+
+ // utility to construct DOMSource from DocumentBuilderFactory
+ public DOMSource getDOMSource(DocumentBuilderFactory dbf)
+ throws SAXException, IOException, ParserConfigurationException
+ {
+ return new DOMSource(
+ dbf.newDocumentBuilder().parse(
+ new InputSource(
+ new ByteArrayInputStream(sourceXml.getBytes())
+ )
+ )
+ );
+ }
+
+ // utility to construct SAXSource from SAXParserFactory
+ public SAXSource getSAXSource(SAXParserFactory spf)
+ throws SAXException, ParserConfigurationException
+ {
+ return new SAXSource(
+ spf.newSAXParser().getXMLReader(),
+ new InputSource(new ByteArrayInputStream(sourceXml.getBytes()))
+ );
+ }
+
+ // utility to construct StAXSource from XMLInputFactory
+ public StAXSource getStAXSource(XMLInputFactory xif)
+ throws XMLStreamException
+ {
+ return new StAXSource(
+ xif.createXMLStreamReader(new StringReader(sourceXml))
+ );
+ }
+}
--- a/jaxws/.hgtags Thu Feb 02 05:26:20 2017 -0800
+++ b/jaxws/.hgtags Thu Feb 09 23:15:52 2017 +0100
@@ -399,3 +399,5 @@
c48b4d4768b1c2b8fe5d1a844ca13732e5dfbe2a jdk-9+151
6f8fb1cf7e5f61c40dcc3654f9a623c505f6de1f jdk-9+152
7a532a9a227137155b905341d4b99939db51220e jdk-9+153
+34af95c7dbff74f3448fcdb7d745524e8a1cc88a jdk-9+154
+9b9918656c97724fd89c04a8547043bbd37f5935 jdk-9+155
--- a/jaxws/src/java.annotations.common/share/classes/javax/annotation/Generated.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2005, 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.
- */
-
-package javax.annotation;
-import java.lang.annotation.*;
-import static java.lang.annotation.ElementType.*;
-import static java.lang.annotation.RetentionPolicy.*;
-
-/**
- * The Generated annotation is used to mark source code that has been generated.
- * It can also be used to differentiate user written code from generated code
- * in a single file. When used, the value element must have the name of the
- * code generator. The recommended convention is to use the fully qualified
- * name of the code generator in the value field .
- * <p>For example: com.company.package.classname.
- * The date element is used to indicate the date the source was generated.
- * The date element must follow the ISO 8601 standard. For example the date
- * element would have the following value 2001-07-04T12:08:56.235-0700
- * which represents 2001-07-04 12:08:56 local time in the U.S. Pacific
- * Time time zone.</p>
- * <p>The comment element is a place holder for any comments that the code
- * generator may want to include in the generated code.</p>
- *
- * @since 1.6, Common Annotations 1.0
- */
-
-@Documented
-@Retention(SOURCE)
-@Target({PACKAGE, TYPE, ANNOTATION_TYPE, METHOD, CONSTRUCTOR, FIELD,
- LOCAL_VARIABLE, PARAMETER})
-public @interface Generated {
- /**
- * The value element MUST have the name of the code generator.
- * The recommended convention is to use the fully qualified name of the
- * code generator. For example: com.acme.generator.CodeGen.
- */
- String[] value();
-
- /**
- * Date when the source was generated.
- */
- String date() default "";
-
- /**
- * A place holder for any comments that the code generator may want to
- * include in the generated code.
- */
- String comments() default "";
-}
--- a/jaxws/src/java.annotations.common/share/classes/javax/annotation/PostConstruct.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2005, 2015, 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 javax.annotation;
-
-import java.lang.annotation.*;
-import static java.lang.annotation.ElementType.*;
-import static java.lang.annotation.RetentionPolicy.*;
-
-/**
- * The PostConstruct annotation is used on a method that needs to be executed
- * after dependency injection is done to perform any initialization. This
- * method MUST be invoked before the class is put into service. This
- * annotation MUST be supported on all classes that support dependency
- * injection. The method annotated with PostConstruct MUST be invoked even
- * if the class does not request any resources to be injected. Only one
- * method can be annotated with this annotation. The method on which the
- * PostConstruct annotation is applied MUST fulfill all of the following
- * criteria:
- * <ul>
- * <li>The method MUST NOT have any parameters except in the case of
- * interceptors in which case it takes an InvocationContext object as
- * defined by the Interceptors specification.</li>
- * <li>The method defined on an interceptor class MUST HAVE one of the
- * following signatures:
- * <p>
- * void <METHOD>(InvocationContext)
- * <p>
- * Object <METHOD>(InvocationContext) throws Exception
- * <p>
- * <i>Note: A PostConstruct interceptor method must not throw application
- * exceptions, but it may be declared to throw checked exceptions including
- * the java.lang.Exception if the same interceptor method interposes on
- * business or timeout methods in addition to lifecycle events. If a
- * PostConstruct interceptor method returns a value, it is ignored by
- * the container.</i>
- * </li>
- * <li>The method defined on a non-interceptor class MUST HAVE the
- * following signature:
- * <p>
- * void <METHOD>()
- * </li>
- * <li>The method on which PostConstruct is applied MAY be public, protected,
- * package private or private.</li>
- * <li>The method MUST NOT be static except for the application client.</li>
- * <li>The method MAY be final.</li>
- * <li>If the method throws an unchecked exception the class MUST NOT be put into
- * service except in the case of EJBs where the EJB can handle exceptions and
- * even recover from them.</li></ul>
- *
- * @see javax.annotation.PreDestroy
- * @see javax.annotation.Resource
- * @since 1.6, Common Annotations 1.0
- */
-@Documented
-@Retention (RUNTIME)
-@Target(METHOD)
-public @interface PostConstruct {
-}
--- a/jaxws/src/java.annotations.common/share/classes/javax/annotation/PreDestroy.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2005, 2015, 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 javax.annotation;
-
-import java.lang.annotation.*;
-import static java.lang.annotation.ElementType.*;
-import static java.lang.annotation.RetentionPolicy.*;
-
-/**
- * The PreDestroy annotation is used on methods as a callback notification to
- * signal that the instance is in the process of being removed by the
- * container. The method annotated with PreDestroy is typically used to
- * release resources that it has been holding. This annotation MUST be
- * supported by all container managed objects that support PostConstruct
- * except the application client container in Java EE 5. The method on which
- * the PreDestroy annotation is applied MUST fulfill all of the following
- * criteria:
- * <ul>
- * <li>The method MUST NOT have any parameters except in the case of
- * interceptors in which case it takes an InvocationContext object as
- * defined by the Interceptors specification.</li>
- * <li>The method defined on an interceptor class MUST HAVE one of the
- * following signatures:
- * <p>
- * void <METHOD>(InvocationContext)
- * <p>
- * Object <METHOD>(InvocationContext) throws Exception
- * <p>
- * <i>Note: A PreDestroy interceptor method must not throw application
- * exceptions, but it may be declared to throw checked exceptions including
- * the java.lang.Exception if the same interceptor method interposes on
- * business or timeout methods in addition to lifecycle events. If a
- * PreDestroy interceptor method returns a value, it is ignored by
- * the container.</i>
- * </li>
- * <li>The method defined on a non-interceptor class MUST HAVE the
- * following signature:
- * <p>
- * void <METHOD>()
- * </li>
- * <li>The method on which PreDestroy is applied MAY be public, protected,
- * package private or private.</li>
- * <li>The method MUST NOT be static.</li>
- * <li>The method MAY be final.</li>
- * <li>If the method throws an unchecked exception it is ignored except in the
- * case of EJBs where the EJB can handle exceptions.</li>
- * </ul>
- *
- * @see javax.annotation.PostConstruct
- * @see javax.annotation.Resource
- * @since 1.6, Common Annotations 1.0
- */
-
-@Documented
-@Retention (RUNTIME)
-@Target(METHOD)
-public @interface PreDestroy {
-}
--- a/jaxws/src/java.annotations.common/share/classes/javax/annotation/Resource.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2005, 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.
- */
-
-package javax.annotation;
-
-import java.lang.annotation.*;
-import static java.lang.annotation.ElementType.*;
-import static java.lang.annotation.RetentionPolicy.*;
-
-/**
- * The Resource annotation marks a resource that is needed
- * by the application. This annotation may be applied to an
- * application component class, or to fields or methods of the
- * component class. When the annotation is applied to a
- * field or method, the container will inject an instance
- * of the requested resource into the application component
- * when the component is initialized. If the annotation is
- * applied to the component class, the annotation declares a
- * resource that the application will look up at runtime. <p>
- *
- * Even though this annotation is not marked Inherited, deployment
- * tools are required to examine all superclasses of any component
- * class to discover all uses of this annotation in all superclasses.
- * All such annotation instances specify resources that are needed
- * by the application component. Note that this annotation may
- * appear on private fields and methods of superclasses; the container
- * is required to perform injection in these cases as well.
- *
- * @since 1.6, Common Annotations 1.0
- */
-@Target({TYPE, FIELD, METHOD})
-@Retention(RUNTIME)
-public @interface Resource {
- /**
- * The JNDI name of the resource. For field annotations,
- * the default is the field name. For method annotations,
- * the default is the JavaBeans property name corresponding
- * to the method. For class annotations, there is no default
- * and this must be specified.
- */
- String name() default "";
-
- /**
- * The name of the resource that the reference points to. It can
- * link to any compatible resource using the global JNDI names.
- *
- * @since 1.7, Common Annotations 1.1
- */
-
- String lookup() default "";
-
- /**
- * The Java type of the resource. For field annotations,
- * the default is the type of the field. For method annotations,
- * the default is the type of the JavaBeans property.
- * For class annotations, there is no default and this must be
- * specified.
- */
- Class<?> type() default java.lang.Object.class;
-
- /**
- * The two possible authentication types for a resource.
- */
- enum AuthenticationType {
- CONTAINER,
- APPLICATION
- }
-
- /**
- * The authentication type to use for this resource.
- * This may be specified for resources representing a
- * connection factory of any supported type, and must
- * not be specified for resources of other types.
- */
- AuthenticationType authenticationType() default AuthenticationType.CONTAINER;
-
- /**
- * Indicates whether this resource can be shared between
- * this component and other components.
- * This may be specified for resources representing a
- * connection factory of any supported type, and must
- * not be specified for resources of other types.
- */
- boolean shareable() default true;
-
- /**
- * A product specific name that this resource should be mapped to.
- * The name of this resource, as defined by the <code>name</code>
- * element or defaulted, is a name that is local to the application
- * component using the resource. (It's a name in the JNDI
- * <code>java:comp/env</code> namespace.) Many application servers
- * provide a way to map these local names to names of resources
- * known to the application server. This mapped name is often a
- * <i>global</i> JNDI name, but may be a name of any form. <p>
- *
- * Application servers are not required to support any particular
- * form or type of mapped name, nor the ability to use mapped names.
- * The mapped name is product-dependent and often installation-dependent.
- * No use of a mapped name is portable.
- */
- String mappedName() default "";
-
- /**
- * Description of this resource. The description is expected
- * to be in the default language of the system on which the
- * application is deployed. The description can be presented
- * to the Deployer to help in choosing the correct resource.
- */
- String description() default "";
-}
--- a/jaxws/src/java.annotations.common/share/classes/javax/annotation/Resources.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2005, 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.
- */
-
-package javax.annotation;
-import java.lang.annotation.*;
-import static java.lang.annotation.ElementType.*;
-import static java.lang.annotation.RetentionPolicy.*;
-
-/**
- * This class is used to allow multiple resources declarations.
- *
- * @see javax.annotation.Resource
- * @since 1.6, Common Annotations 1.0
- */
-
-@Documented
-@Retention(RUNTIME)
-@Target(TYPE)
-public @interface Resources {
- /**
- * Array used for multiple resource declarations.
- */
- Resource[] value();
-}
--- a/jaxws/src/java.annotations.common/share/classes/module-info.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * Defines a subset of the Common Annotations API to support programs running
- * on the Java SE Platform.
- */
-module java.annotations.common {
- exports javax.annotation;
-}
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/java.xml.ws.annotation/share/classes/javax/annotation/Generated.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2005, 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.
+ */
+
+package javax.annotation;
+import java.lang.annotation.*;
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+/**
+ * The Generated annotation is used to mark source code that has been generated.
+ * It can also be used to differentiate user written code from generated code
+ * in a single file. When used, the value element must have the name of the
+ * code generator. The recommended convention is to use the fully qualified
+ * name of the code generator in the value field .
+ * <p>For example: com.company.package.classname.
+ * The date element is used to indicate the date the source was generated.
+ * The date element must follow the ISO 8601 standard. For example the date
+ * element would have the following value 2001-07-04T12:08:56.235-0700
+ * which represents 2001-07-04 12:08:56 local time in the U.S. Pacific
+ * Time time zone.</p>
+ * <p>The comment element is a place holder for any comments that the code
+ * generator may want to include in the generated code.</p>
+ *
+ * @since 1.6, Common Annotations 1.0
+ */
+
+@Documented
+@Retention(SOURCE)
+@Target({PACKAGE, TYPE, ANNOTATION_TYPE, METHOD, CONSTRUCTOR, FIELD,
+ LOCAL_VARIABLE, PARAMETER})
+public @interface Generated {
+ /**
+ * The value element MUST have the name of the code generator.
+ * The recommended convention is to use the fully qualified name of the
+ * code generator. For example: com.acme.generator.CodeGen.
+ */
+ String[] value();
+
+ /**
+ * Date when the source was generated.
+ */
+ String date() default "";
+
+ /**
+ * A place holder for any comments that the code generator may want to
+ * include in the generated code.
+ */
+ String comments() default "";
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/java.xml.ws.annotation/share/classes/javax/annotation/PostConstruct.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2005, 2015, 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 javax.annotation;
+
+import java.lang.annotation.*;
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+/**
+ * The PostConstruct annotation is used on a method that needs to be executed
+ * after dependency injection is done to perform any initialization. This
+ * method MUST be invoked before the class is put into service. This
+ * annotation MUST be supported on all classes that support dependency
+ * injection. The method annotated with PostConstruct MUST be invoked even
+ * if the class does not request any resources to be injected. Only one
+ * method can be annotated with this annotation. The method on which the
+ * PostConstruct annotation is applied MUST fulfill all of the following
+ * criteria:
+ * <ul>
+ * <li>The method MUST NOT have any parameters except in the case of
+ * interceptors in which case it takes an InvocationContext object as
+ * defined by the Interceptors specification.</li>
+ * <li>The method defined on an interceptor class MUST HAVE one of the
+ * following signatures:
+ * <p>
+ * void <METHOD>(InvocationContext)
+ * <p>
+ * Object <METHOD>(InvocationContext) throws Exception
+ * <p>
+ * <i>Note: A PostConstruct interceptor method must not throw application
+ * exceptions, but it may be declared to throw checked exceptions including
+ * the java.lang.Exception if the same interceptor method interposes on
+ * business or timeout methods in addition to lifecycle events. If a
+ * PostConstruct interceptor method returns a value, it is ignored by
+ * the container.</i>
+ * </li>
+ * <li>The method defined on a non-interceptor class MUST HAVE the
+ * following signature:
+ * <p>
+ * void <METHOD>()
+ * </li>
+ * <li>The method on which PostConstruct is applied MAY be public, protected,
+ * package private or private.</li>
+ * <li>The method MUST NOT be static except for the application client.</li>
+ * <li>The method MAY be final.</li>
+ * <li>If the method throws an unchecked exception the class MUST NOT be put into
+ * service except in the case of EJBs where the EJB can handle exceptions and
+ * even recover from them.</li></ul>
+ *
+ * @see javax.annotation.PreDestroy
+ * @see javax.annotation.Resource
+ * @since 1.6, Common Annotations 1.0
+ */
+@Documented
+@Retention (RUNTIME)
+@Target(METHOD)
+public @interface PostConstruct {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/java.xml.ws.annotation/share/classes/javax/annotation/PreDestroy.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2005, 2015, 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 javax.annotation;
+
+import java.lang.annotation.*;
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+/**
+ * The PreDestroy annotation is used on methods as a callback notification to
+ * signal that the instance is in the process of being removed by the
+ * container. The method annotated with PreDestroy is typically used to
+ * release resources that it has been holding. This annotation MUST be
+ * supported by all container managed objects that support PostConstruct
+ * except the application client container in Java EE 5. The method on which
+ * the PreDestroy annotation is applied MUST fulfill all of the following
+ * criteria:
+ * <ul>
+ * <li>The method MUST NOT have any parameters except in the case of
+ * interceptors in which case it takes an InvocationContext object as
+ * defined by the Interceptors specification.</li>
+ * <li>The method defined on an interceptor class MUST HAVE one of the
+ * following signatures:
+ * <p>
+ * void <METHOD>(InvocationContext)
+ * <p>
+ * Object <METHOD>(InvocationContext) throws Exception
+ * <p>
+ * <i>Note: A PreDestroy interceptor method must not throw application
+ * exceptions, but it may be declared to throw checked exceptions including
+ * the java.lang.Exception if the same interceptor method interposes on
+ * business or timeout methods in addition to lifecycle events. If a
+ * PreDestroy interceptor method returns a value, it is ignored by
+ * the container.</i>
+ * </li>
+ * <li>The method defined on a non-interceptor class MUST HAVE the
+ * following signature:
+ * <p>
+ * void <METHOD>()
+ * </li>
+ * <li>The method on which PreDestroy is applied MAY be public, protected,
+ * package private or private.</li>
+ * <li>The method MUST NOT be static.</li>
+ * <li>The method MAY be final.</li>
+ * <li>If the method throws an unchecked exception it is ignored except in the
+ * case of EJBs where the EJB can handle exceptions.</li>
+ * </ul>
+ *
+ * @see javax.annotation.PostConstruct
+ * @see javax.annotation.Resource
+ * @since 1.6, Common Annotations 1.0
+ */
+
+@Documented
+@Retention (RUNTIME)
+@Target(METHOD)
+public @interface PreDestroy {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/java.xml.ws.annotation/share/classes/javax/annotation/Resource.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2005, 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.
+ */
+
+package javax.annotation;
+
+import java.lang.annotation.*;
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+/**
+ * The Resource annotation marks a resource that is needed
+ * by the application. This annotation may be applied to an
+ * application component class, or to fields or methods of the
+ * component class. When the annotation is applied to a
+ * field or method, the container will inject an instance
+ * of the requested resource into the application component
+ * when the component is initialized. If the annotation is
+ * applied to the component class, the annotation declares a
+ * resource that the application will look up at runtime. <p>
+ *
+ * Even though this annotation is not marked Inherited, deployment
+ * tools are required to examine all superclasses of any component
+ * class to discover all uses of this annotation in all superclasses.
+ * All such annotation instances specify resources that are needed
+ * by the application component. Note that this annotation may
+ * appear on private fields and methods of superclasses; the container
+ * is required to perform injection in these cases as well.
+ *
+ * @since 1.6, Common Annotations 1.0
+ */
+@Target({TYPE, FIELD, METHOD})
+@Retention(RUNTIME)
+public @interface Resource {
+ /**
+ * The JNDI name of the resource. For field annotations,
+ * the default is the field name. For method annotations,
+ * the default is the JavaBeans property name corresponding
+ * to the method. For class annotations, there is no default
+ * and this must be specified.
+ */
+ String name() default "";
+
+ /**
+ * The name of the resource that the reference points to. It can
+ * link to any compatible resource using the global JNDI names.
+ *
+ * @since 1.7, Common Annotations 1.1
+ */
+
+ String lookup() default "";
+
+ /**
+ * The Java type of the resource. For field annotations,
+ * the default is the type of the field. For method annotations,
+ * the default is the type of the JavaBeans property.
+ * For class annotations, there is no default and this must be
+ * specified.
+ */
+ Class<?> type() default java.lang.Object.class;
+
+ /**
+ * The two possible authentication types for a resource.
+ */
+ enum AuthenticationType {
+ CONTAINER,
+ APPLICATION
+ }
+
+ /**
+ * The authentication type to use for this resource.
+ * This may be specified for resources representing a
+ * connection factory of any supported type, and must
+ * not be specified for resources of other types.
+ */
+ AuthenticationType authenticationType() default AuthenticationType.CONTAINER;
+
+ /**
+ * Indicates whether this resource can be shared between
+ * this component and other components.
+ * This may be specified for resources representing a
+ * connection factory of any supported type, and must
+ * not be specified for resources of other types.
+ */
+ boolean shareable() default true;
+
+ /**
+ * A product specific name that this resource should be mapped to.
+ * The name of this resource, as defined by the <code>name</code>
+ * element or defaulted, is a name that is local to the application
+ * component using the resource. (It's a name in the JNDI
+ * <code>java:comp/env</code> namespace.) Many application servers
+ * provide a way to map these local names to names of resources
+ * known to the application server. This mapped name is often a
+ * <i>global</i> JNDI name, but may be a name of any form. <p>
+ *
+ * Application servers are not required to support any particular
+ * form or type of mapped name, nor the ability to use mapped names.
+ * The mapped name is product-dependent and often installation-dependent.
+ * No use of a mapped name is portable.
+ */
+ String mappedName() default "";
+
+ /**
+ * Description of this resource. The description is expected
+ * to be in the default language of the system on which the
+ * application is deployed. The description can be presented
+ * to the Deployer to help in choosing the correct resource.
+ */
+ String description() default "";
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/java.xml.ws.annotation/share/classes/javax/annotation/Resources.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2005, 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.
+ */
+
+package javax.annotation;
+import java.lang.annotation.*;
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+/**
+ * This class is used to allow multiple resources declarations.
+ *
+ * @see javax.annotation.Resource
+ * @since 1.6, Common Annotations 1.0
+ */
+
+@Documented
+@Retention(RUNTIME)
+@Target(TYPE)
+public @interface Resources {
+ /**
+ * Array used for multiple resource declarations.
+ */
+ Resource[] value();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/java.xml.ws.annotation/share/classes/module-info.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, 2017, 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.
+ */
+
+/**
+ * Defines a subset of the Common Annotations API to support programs running
+ * on the Java SE Platform.
+ */
+module java.xml.ws.annotation {
+ exports javax.annotation;
+}
+
--- a/jaxws/src/java.xml.ws/share/classes/module-info.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jaxws/src/java.xml.ws/share/classes/module-info.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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,7 +31,7 @@
requires transitive java.activation;
requires transitive java.xml;
requires transitive java.xml.bind;
- requires java.annotations.common;
+ requires java.xml.ws.annotation;
requires java.desktop;
requires java.logging;
requires java.management;
--- a/jdk/.hgtags Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/.hgtags Thu Feb 09 23:15:52 2017 +0100
@@ -397,3 +397,4 @@
a20f2cf90762673e1bc4980fd6597e70a2578045 jdk-9+152
1c4411322327aea3f91011ec3977a12a05b09629 jdk-9+153
c97e7a8b8da062b9070df442f9cf308e10845fb7 jdk-9+154
+e170c858888e83d5c0994504599b6ed7a1fb0cfc jdk-9+155
--- a/jdk/make/copy/Copy-java.management.gmk Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-#
-# 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 CopyCommon.gmk
-
-################################################################################
-
-MGMT_CONF_DIR := $(CONF_DST_DIR)/management
-MGMT_CONF_SRC := $(JDK_TOPDIR)/src/java.management/share/conf
-MGMT_SRC_FILES := $(wildcard $(MGMT_CONF_SRC)/*)
-MGMT_TARGET_FILES := $(subst $(MGMT_CONF_SRC),$(MGMT_CONF_DIR),$(MGMT_SRC_FILES))
-
-$(MGMT_CONF_DIR)/management.properties: $(MGMT_CONF_SRC)/management.properties
- $(call install-file)
- $(CHMOD) 644 $@
-
-# this file has different permissions...don't know why...
-$(MGMT_CONF_DIR)/jmxremote.access: $(MGMT_CONF_SRC)/jmxremote.access
- $(call install-file)
- $(CHMOD) 644 $@
-
-$(MGMT_CONF_DIR)/%: $(MGMT_CONF_SRC)/%
- $(call install-file)
- $(CHMOD) 444 $@
-
-TARGETS := $(MGMT_TARGET_FILES)
-
-################################################################################
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/copy/Copy-jdk.management.agent.gmk Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,50 @@
+#
+# 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 CopyCommon.gmk
+
+################################################################################
+
+MGMT_CONF_DIR := $(CONF_DST_DIR)/management
+MGMT_CONF_SRC := $(JDK_TOPDIR)/src/jdk.management.agent/share/conf
+MGMT_SRC_FILES := $(wildcard $(MGMT_CONF_SRC)/*)
+MGMT_TARGET_FILES := $(subst $(MGMT_CONF_SRC),$(MGMT_CONF_DIR),$(MGMT_SRC_FILES))
+
+$(MGMT_CONF_DIR)/management.properties: $(MGMT_CONF_SRC)/management.properties
+ $(call install-file)
+ $(CHMOD) 644 $@
+
+# this file has different permissions...don't know why...
+$(MGMT_CONF_DIR)/jmxremote.access: $(MGMT_CONF_SRC)/jmxremote.access
+ $(call install-file)
+ $(CHMOD) 644 $@
+
+$(MGMT_CONF_DIR)/%: $(MGMT_CONF_SRC)/%
+ $(call install-file)
+ $(CHMOD) 444 $@
+
+TARGETS := $(MGMT_TARGET_FILES)
+
+################################################################################
--- a/jdk/make/gensrc/Gensrc-java.management.gmk Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-#
-# Copyright (c) 2011, 2015, 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 GensrcCommon.gmk
-
-# Hook to include the corresponding custom file, if present.
-$(eval $(call IncludeCustomExtension, jdk, gensrc/Gensrc-java.management.gmk))
-
-################################################################################
-
-include GensrcProperties.gmk
-
-$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
- SRC_DIRS := $(JDK_TOPDIR)/src/java.management/share/classes/sun/management/resources, \
- CLASS := ListResourceBundle, \
-))
-
-TARGETS += $(COMPILE_PROPERTIES)
-
-################################################################################
-
-all: $(TARGETS)
-
-.PHONY: all
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/gensrc/Gensrc-jdk.management.agent.gmk Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,43 @@
+#
+# Copyright (c) 2011, 2015, 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 GensrcCommon.gmk
+
+################################################################################
+
+include GensrcProperties.gmk
+
+$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
+ SRC_DIRS := $(JDK_TOPDIR)/src/jdk.management.agent/share/classes/jdk/internal/agent/resources, \
+ CLASS := ListResourceBundle, \
+))
+
+TARGETS += $(COMPILE_PROPERTIES)
+
+################################################################################
+
+all: $(TARGETS)
+
+.PHONY: all
--- a/jdk/make/lib/Lib-java.management.gmk Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/make/lib/Lib-java.management.gmk Thu Feb 09 23:15:52 2017 +0100
@@ -30,8 +30,7 @@
################################################################################
-LIBMANAGEMENT_SRC += $(JDK_TOPDIR)/src/java.management/share/native/libmanagement \
- $(JDK_TOPDIR)/src/java.management/$(OPENJDK_TARGET_OS_TYPE)/native/libmanagement
+LIBMANAGEMENT_SRC += $(JDK_TOPDIR)/src/java.management/share/native/libmanagement
LIBMANAGEMENT_CFLAGS := -I$(JDK_TOPDIR)/src/java.management/share/native/include \
$(addprefix -I,$(LIBMANAGEMENT_SRC)) \
-I$(SUPPORT_OUTPUTDIR)/headers/java.management \
--- a/jdk/make/lib/Lib-java.security.jgss.gmk Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/make/lib/Lib-java.security.jgss.gmk Thu Feb 09 23:15:52 2017 +0100
@@ -53,7 +53,7 @@
################################################################################
-ifneq ($(BUILD_CRYPTO), no)
+ifneq ($(BUILD_CRYPTO), false)
BUILD_LIBKRB5_NAME :=
ifeq ($(OPENJDK_TARGET_OS), windows)
BUILD_LIBKRB5_NAME := w2k_lsa_auth
--- a/jdk/make/lib/Lib-jdk.crypto.ec.gmk Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/make/lib/Lib-jdk.crypto.ec.gmk Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,7 @@
################################################################################
-ifeq ($(ENABLE_INTREE_EC), yes)
+ifeq ($(ENABLE_INTREE_EC), true)
LIBSUNEC_SRC := $(JDK_TOPDIR)/src/jdk.crypto.ec/share/native/libsunec
BUILD_LIBSUNEC_FLAGS := $(addprefix -I, $(SUNEC_SRC))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/lib/Lib-jdk.management.agent.gmk Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,59 @@
+#
+# Copyright (c) 2017, 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 LibCommon.gmk
+
+################################################################################
+
+LIBMANAGEMENT_AGENT_SRC += $(JDK_TOPDIR)/src/jdk.management.agent/$(OPENJDK_TARGET_OS_TYPE)/native/libmanagement_agent
+LIBMANAGEMENT_AGENT_CFLAGS := $(addprefix -I,$(LIBMANAGEMENT_AGENT_SRC)) \
+ -I$(SUPPORT_OUTPUTDIR)/headers/jdk.management.agent \
+ $(LIBJAVA_HEADER_FLAGS) \
+ #
+
+$(eval $(call SetupNativeCompilation,BUILD_LIBMANAGEMENT_AGENT, \
+ LIBRARY := management_agent, \
+ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
+ SRC := $(LIBMANAGEMENT_AGENT_SRC), \
+ OPTIMIZATION := LOW, \
+ CFLAGS := $(CFLAGS_JDKLIB) $(LIBMANAGEMENT_AGENT_CFLAGS), \
+ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libmanagement_agent/mapfile-vers, \
+ LDFLAGS := $(LDFLAGS_JDKLIB) \
+ $(call SET_SHARED_LIBRARY_ORIGIN), \
+ LIBS := $(JDKLIB_LIBS), \
+ LIBS_windows := $(WIN_JAVA_LIB) advapi32.lib, \
+ VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
+ RC_FLAGS := $(RC_FLAGS) \
+ -D "JDK_FNAME=management_agent.dll" \
+ -D "JDK_INTERNAL_NAME=management_agent" \
+ -D "JDK_FTYPE=0x2L", \
+ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libmanagement_agent, \
+))
+
+$(BUILD_LIBMANAGEMENT_AGENT): $(call FindLib, java.base, java)
+
+TARGETS += $(BUILD_LIBMANAGEMENT_AGENT)
+
+################################################################################
--- a/jdk/make/lib/NetworkingLibraries.gmk Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/make/lib/NetworkingLibraries.gmk Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -44,8 +44,9 @@
LIBS_linux := $(LIBDL) -lpthread, \
LIBS_solaris := -lnsl -lsocket $(LIBDL) -lc, \
LIBS_aix := $(LIBDL),\
- LIBS_windows := ws2_32.lib jvm.lib secur32.lib iphlpapi.lib \
+ LIBS_windows := ws2_32.lib jvm.lib secur32.lib iphlpapi.lib winhttp.lib \
delayimp.lib $(WIN_JAVA_LIB) advapi32.lib, \
+ LIBS_macosx := -framework CoreFoundation -framework CoreServices, \
VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
RC_FLAGS := $(RC_FLAGS) \
-D "JDK_FNAME=net.dll" \
--- a/jdk/make/mapfiles/libmanagement/mapfile-vers Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/make/mapfiles/libmanagement/mapfile-vers Thu Feb 09 23:15:52 2017 +0100
@@ -28,7 +28,6 @@
SUNWprivate_1.1 {
global:
Java_sun_management_ClassLoadingImpl_setVerboseClass;
- Java_sun_management_FileSystemImpl_isAccessUserOnly0;
Java_sun_management_GarbageCollectorImpl_getCollectionCount;
Java_sun_management_GarbageCollectorImpl_getCollectionTime;
Java_sun_management_HotspotThread_getInternalThreadCount;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/mapfiles/libmanagement_agent/mapfile-vers Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 2017, 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.
+#
+
+# Define library interface.
+
+SUNWprivate_1.1 {
+ global:
+ Java_jdk_internal_agent_FileSystemImpl_isAccessUserOnly0;
+ JNI_OnLoad;
+ local:
+ *;
+};
--- a/jdk/make/mapfiles/libnet/mapfile-vers Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/make/mapfiles/libnet/mapfile-vers Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2017, 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
@@ -97,7 +97,7 @@
Java_sun_net_sdp_SdpSupport_convert0;
Java_sun_net_sdp_SdpSupport_create0;
Java_sun_net_spi_DefaultProxySelector_init;
- Java_sun_net_spi_DefaultProxySelector_getSystemProxy;
+ Java_sun_net_spi_DefaultProxySelector_getSystemProxies;
NET_SockaddrToInetAddress;
NET_SockaddrEqualsInetAddress;
NET_InetAddressToSockaddr;
--- a/jdk/make/mapfiles/libunpack/mapfile-vers-unpack200-solaris-sparc Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/make/mapfiles/libunpack/mapfile-vers-unpack200-solaris-sparc Thu Feb 09 23:15:52 2017 +0100
@@ -28,6 +28,7 @@
SUNWprivate_1.1 {
global:
# These are needed by the c runtime in SS12u4
+ environ;
_environ;
__environ_lock;
___Argv;
--- a/jdk/make/rmic/Rmic-java.management.gmk Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-#
-# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-default: all
-
-include RmicCommon.gmk
-
-##########################################################################################
-#
-# Generate RMI stubs
-#
-
-JMX_RMI_CLASSES := javax.management.remote.rmi.RMIConnectionImpl \
- javax.management.remote.rmi.RMIServerImpl
-
-# Generate into gensrc dir where sources get picked up for javadoc, then move the classes
-# into the stub classes dir.
-$(eval $(call SetupRMICompilation,RMI_GEN, \
- CLASSES := $(JMX_RMI_CLASSES), \
- CLASSES_DIR := $(CLASSES_DIR)/java.management, \
- STUB_CLASSES_DIR := $(RMIC_GENSRC_DIR)/java.management, \
- RUN_V12 := true, \
- KEEP_GENERATED := true, \
-))
-
-# Find all classes generated and move them from the gensrc dir to the stub classes dir
-$(RMIC_GENSRC_DIR)/_classes.moved: $(RMI_GEN)
- $(eval classfiles := $(shell $(FIND) $(RMIC_GENSRC_DIR) -name "*.class"))
- $(foreach src, $(classfiles), \
- $(eval target := $(patsubst $(RMIC_GENSRC_DIR)/%, \
- $(STUB_CLASSES_DIR)/%, $(src))) \
- $(MKDIR) -p $(dir $(target)) ; \
- $(MV) $(src) $(target) $(NEWLINE))
- $(TOUCH) $@
-
-##########################################################################################
-
-all: $(RMIC_GENSRC_DIR)/_classes.moved $(RMI_GEN)
-
-.PHONY: all
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/rmic/Rmic-java.management.rmi.gmk Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,62 @@
+#
+# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+default: all
+
+include RmicCommon.gmk
+
+##########################################################################################
+#
+# Generate RMI stubs
+#
+
+JMX_RMI_CLASSES := javax.management.remote.rmi.RMIConnectionImpl \
+ javax.management.remote.rmi.RMIServerImpl
+
+# Generate into gensrc dir where sources get picked up for javadoc, then move the classes
+# into the stub classes dir.
+$(eval $(call SetupRMICompilation,RMI_GEN, \
+ CLASSES := $(JMX_RMI_CLASSES), \
+ CLASSES_DIR := $(CLASSES_DIR)/java.management.rmi, \
+ STUB_CLASSES_DIR := $(RMIC_GENSRC_DIR)/java.management.rmi, \
+ RUN_V12 := true, \
+ KEEP_GENERATED := true, \
+))
+
+# Find all classes generated and move them from the gensrc dir to the stub classes dir
+$(RMIC_GENSRC_DIR)/_classes.moved: $(RMI_GEN)
+ $(eval classfiles := $(shell $(FIND) $(RMIC_GENSRC_DIR) -name "*.class"))
+ $(foreach src, $(classfiles), \
+ $(eval target := $(patsubst $(RMIC_GENSRC_DIR)/%, \
+ $(STUB_CLASSES_DIR)/%, $(src))) \
+ $(MKDIR) -p $(dir $(target)) ; \
+ $(MV) $(src) $(target) $(NEWLINE))
+ $(TOUCH) $@
+
+##########################################################################################
+
+all: $(RMIC_GENSRC_DIR)/_classes.moved $(RMI_GEN)
+
+.PHONY: all
--- a/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/make/src/classes/build/tools/jigsaw/GenGraphs.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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
@@ -126,7 +126,7 @@
ranks.add(Set.of("java.compiler", "java.instrument"));
ranks.add(Set.of("java.desktop", "java.management"));
ranks.add(Set.of("java.corba", "java.xml.ws"));
- ranks.add(Set.of("java.xml.bind", "java.annotations.common"));
+ ranks.add(Set.of("java.xml.bind", "java.xml.ws.annotation"));
}
--- a/jdk/make/src/classes/build/tools/jigsaw/technology-summary.html Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/make/src/classes/build/tools/jigsaw/technology-summary.html Thu Feb 09 23:15:52 2017 +0100
@@ -588,7 +588,7 @@
<td>Common Annotations</td>
<td><a href="https://jcp.org/en/jsr/detail?id=250">250</a></td>
<td>Java SE,EE</td>
-<td><a href="module-summary.html#java.annotations.common">java.annotations.common</a></td>
+<td><a href="module-summary.html#java.xml.ws.annotation">java.xml.ws.annotation</a></td>
<td>Original JSR</td>
<td>Formerly a <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/standards/#standalone-technologies">Standalone Technology</a> (unlisted)</td>
<td>SE</td>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/aix/classes/sun/nio/fs/DefaultFileSystemProvider.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.fs;
+
+import java.nio.file.spi.FileSystemProvider;
+
+/**
+ * Creates this platform's default FileSystemProvider.
+ */
+
+public class DefaultFileSystemProvider {
+ private DefaultFileSystemProvider() { }
+
+ /**
+ * Returns the default FileSystemProvider.
+ */
+ public static FileSystemProvider create() {
+ return new AixFileSystemProvider();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/linux/classes/sun/nio/fs/DefaultFileSystemProvider.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.fs;
+
+import java.nio.file.spi.FileSystemProvider;
+
+/**
+ * Creates this platform's default FileSystemProvider.
+ */
+
+public class DefaultFileSystemProvider {
+ private DefaultFileSystemProvider() { }
+
+ /**
+ * Returns the default FileSystemProvider.
+ */
+ public static FileSystemProvider create() {
+ return new LinuxFileSystemProvider();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/macosx/classes/sun/nio/fs/DefaultFileSystemProvider.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.fs;
+
+import java.nio.file.spi.FileSystemProvider;
+
+/**
+ * Creates this platform's default FileSystemProvider.
+ */
+
+public class DefaultFileSystemProvider {
+ private DefaultFileSystemProvider() { }
+
+ /**
+ * Returns the default FileSystemProvider.
+ */
+ public static FileSystemProvider create() {
+ return new MacOSXFileSystemProvider();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/macosx/native/libnet/DefaultProxySelector.c Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017 SAP SE. 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 <string.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreServices/CoreServices.h>
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "jvm_md.h"
+
+#include "proxy_util.h"
+
+#include "sun_net_spi_DefaultProxySelector.h"
+
+
+/**
+ * For more information on how to use the APIs in "CFProxySupport.h" see:
+ * https://developer.apple.com/legacy/library/samplecode/CFProxySupportTool/Introduction/Intro.html
+ */
+
+#define kResolveProxyRunLoopMode CFSTR("sun.net.spi.DefaultProxySelector")
+
+#define BUFFER_SIZE 1024
+
+/* Callback for CFNetworkExecuteProxyAutoConfigurationURL. */
+static void proxyUrlCallback(void * client, CFArrayRef proxies, CFErrorRef error) {
+ /* client is a pointer to a CFTypeRef and holds either proxies or an error. */
+ CFTypeRef* resultPtr = (CFTypeRef *)client;
+
+ if (error != NULL) {
+ *resultPtr = CFRetain(error);
+ } else {
+ *resultPtr = CFRetain(proxies);
+ }
+ CFRunLoopStop(CFRunLoopGetCurrent());
+}
+
+/*
+ * Returns a new array of proxies containing all the given non-PAC proxies as
+ * well as the results of executing all the given PAC-based proxies, for the
+ * specified URL. 'proxies' is a list that may contain both PAC and non-PAC
+ * proxies.
+ */
+static CFArrayRef createExpandedProxiesArray(CFArrayRef proxies, CFURLRef url) {
+
+ CFIndex count;
+ CFIndex index;
+ CFMutableArrayRef expandedProxiesArray;
+
+ expandedProxiesArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ if (expandedProxiesArray == NULL)
+ return NULL;
+
+ /* Iterate over the array of proxies */
+ count = CFArrayGetCount(proxies);
+ for (index = 0; index < count ; index++) {
+ CFDictionaryRef currentProxy;
+ CFStringRef proxyType;
+
+ currentProxy = (CFDictionaryRef) CFArrayGetValueAtIndex(proxies, index);
+ if(currentProxy == NULL) {
+ CFRelease(expandedProxiesArray);
+ return NULL;
+ }
+ proxyType = (CFStringRef) CFDictionaryGetValue(currentProxy, kCFProxyTypeKey);
+ if (proxyType == NULL) {
+ CFRelease(expandedProxiesArray);
+ return NULL;
+ }
+
+ if (!CFEqual(proxyType, kCFProxyTypeAutoConfigurationURL)) {
+ /* Non-PAC entry, just copy it to the new array */
+ CFArrayAppendValue(expandedProxiesArray, currentProxy);
+ } else {
+ /* PAC-based URL, execute its script append its results */
+ CFRunLoopSourceRef runLoop;
+ CFURLRef scriptURL;
+ CFTypeRef result = NULL;
+ CFStreamClientContext context = { 0, &result, NULL, NULL, NULL };
+ CFTimeInterval timeout = 5;
+
+ scriptURL = CFDictionaryGetValue(currentProxy, kCFProxyAutoConfigurationURLKey);
+
+ runLoop = CFNetworkExecuteProxyAutoConfigurationURL(scriptURL, url, proxyUrlCallback,
+ &context);
+ if (runLoop != NULL) {
+ /*
+ * Despite the fact that CFNetworkExecuteProxyAutoConfigurationURL has
+ * neither a "Create" nor a "Copy" in the name, we are required to
+ * release the return CFRunLoopSourceRef <rdar://problem/5533931>.
+ */
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoop, kResolveProxyRunLoopMode);
+ CFRunLoopRunInMode(kResolveProxyRunLoopMode, timeout, false);
+ CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runLoop, kResolveProxyRunLoopMode);
+
+ /*
+ * Once the runloop returns, there will be either an error result or
+ * a proxies array result. Do the appropriate thing with that result.
+ */
+ if (result != NULL) {
+ if (CFGetTypeID(result) == CFArrayGetTypeID()) {
+ /*
+ * Append the new array from the PAC list - it contains
+ * only non-PAC entries.
+ */
+ CFArrayAppendArray(expandedProxiesArray, result,
+ CFRangeMake(0, CFArrayGetCount(result)));
+ }
+ CFRelease(result);
+ }
+ CFRelease(runLoop);
+ }
+ }
+ }
+ return expandedProxiesArray;
+}
+
+
+/*
+ * Class: sun_net_spi_DefaultProxySelector
+ * Method: init
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_sun_net_spi_DefaultProxySelector_init(JNIEnv *env, jclass clazz) {
+ if (!initJavaClass(env)) {
+ return JNI_FALSE;
+ }
+ return JNI_TRUE;
+}
+
+
+/*
+ * Class: sun_net_spi_DefaultProxySelector
+ * Method: getSystemProxies
+ * Signature: ([Ljava/lang/String;Ljava/lang/String;)[Ljava/net/Proxy;
+ */
+JNIEXPORT jobjectArray JNICALL
+Java_sun_net_spi_DefaultProxySelector_getSystemProxies(JNIEnv *env,
+ jobject this,
+ jstring proto,
+ jstring host)
+{
+ CFDictionaryRef proxyDicRef = NULL;
+ CFURLRef urlRef = NULL;
+ bool proxyFound = false;
+ jobjectArray proxyArray = NULL;
+ const char *cproto;
+ const char *chost;
+
+ /* Get system proxy settings */
+ proxyDicRef = CFNetworkCopySystemProxySettings();
+ if (proxyDicRef == NULL) {
+ return NULL;
+ }
+
+ /* Create CFURLRef from proto and host */
+ cproto = (*env)->GetStringUTFChars(env, proto, NULL);
+ if (cproto != NULL) {
+ chost = (*env)->GetStringUTFChars(env, host, NULL);
+ if (chost != NULL) {
+ char* uri = NULL;
+ size_t protoLen = 0;
+ size_t hostLen = 0;
+
+ protoLen = strlen(cproto);
+ hostLen = strlen(chost);
+
+ /* Construct the uri, cproto + "://" + chost */
+ uri = malloc(protoLen + hostLen + 4);
+ if (uri != NULL) {
+ memcpy(uri, cproto, protoLen);
+ memcpy(uri + protoLen, "://", 3);
+ memcpy(uri + protoLen + 3, chost, hostLen + 1);
+
+ urlRef = CFURLCreateWithBytes(NULL, (const UInt8 *) uri, strlen(uri),
+ kCFStringEncodingUTF8, NULL);
+ free(uri);
+ }
+ (*env)->ReleaseStringUTFChars(env, host, chost);
+ }
+ (*env)->ReleaseStringUTFChars(env, proto, cproto);
+ }
+ if (urlRef != NULL) {
+ CFArrayRef urlProxyArrayRef = CFNetworkCopyProxiesForURL(urlRef, proxyDicRef);
+ if (urlProxyArrayRef != NULL) {
+ CFIndex count;
+ CFIndex index;
+
+ CFArrayRef expandedProxyArray = createExpandedProxiesArray(urlProxyArrayRef, urlRef);
+ CFRelease(urlProxyArrayRef);
+
+ if (expandedProxyArray == NULL) {
+ CFRelease(urlRef);
+ CFRelease(proxyDicRef);
+ return NULL;
+ }
+
+ count = CFArrayGetCount(expandedProxyArray);
+
+ proxyArray = (*env)->NewObjectArray(env, count, proxy_class, NULL);
+ if (proxyArray != NULL || (*env)->ExceptionCheck(env)) {
+ /* Iterate over the expanded array of proxies */
+ for (index = 0; index < count ; index++) {
+ CFDictionaryRef currentProxy;
+ CFStringRef proxyType;
+ jobject proxy = NULL;
+
+ currentProxy = (CFDictionaryRef) CFArrayGetValueAtIndex(expandedProxyArray,
+ index);
+ proxyType = (CFStringRef) CFDictionaryGetValue(currentProxy, kCFProxyTypeKey);
+ if (CFEqual(proxyType, kCFProxyTypeNone)) {
+ /* This entry states no proxy, therefore just add a NO_PROXY object. */
+ proxy = (*env)->GetStaticObjectField(env, proxy_class, pr_no_proxyID);
+ } else {
+ /*
+ * Create a proxy object for this entry.
+ * Differentiate between SOCKS and HTTP type.
+ */
+ jfieldID typeID = ptype_httpID;
+ if (CFEqual(proxyType, kCFProxyTypeSOCKS)) {
+ typeID = ptype_socksID;
+ }
+ CFNumberRef portNumberRef = (CFNumberRef)CFDictionaryGetValue(currentProxy,
+ (const void*)kCFProxyPortNumberKey);
+ if (portNumberRef != NULL) {
+ int port = 0;
+ if (CFNumberGetValue(portNumberRef, kCFNumberSInt32Type, &port)) {
+ CFStringRef hostNameRef = (CFStringRef)CFDictionaryGetValue(
+ currentProxy, (const void*)kCFProxyHostNameKey);
+ if (hostNameRef != NULL) {
+ char hostNameBuffer[BUFFER_SIZE];
+ if (CFStringGetCString(hostNameRef, hostNameBuffer,
+ BUFFER_SIZE, kCFStringEncodingUTF8)) {
+ proxy = createProxy(env, typeID, &hostNameBuffer[0], port);
+ }
+ }
+ }
+ }
+ }
+ if (proxy == NULL || (*env)->ExceptionCheck(env)) {
+ proxyArray = NULL;
+ break;
+ }
+ (*env)->SetObjectArrayElement(env, proxyArray, index, proxy);
+ if ((*env)->ExceptionCheck(env)) {
+ proxyArray = NULL;
+ break;
+ }
+ }
+ }
+ CFRelease(expandedProxyArray);
+ }
+ CFRelease(urlRef);
+ }
+ CFRelease(proxyDicRef);
+
+ return proxyArray;
+}
--- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/OutputFeedback.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/OutputFeedback.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -162,11 +162,11 @@
for (int i = 0; i < numBytes; i++) {
cipher[i + cipherOffset] =
(byte)(k[i] ^ plain[i + plainOffset]);
- if (nShift != 0) {
- System.arraycopy(register, numBytes, register, 0, nShift);
- }
- System.arraycopy(k, 0, register, nShift, numBytes);
}
+ if (nShift != 0) {
+ System.arraycopy(register, numBytes, register, 0, nShift);
+ }
+ System.arraycopy(k, 0, register, nShift, numBytes);
}
return plainLen;
}
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/HostnameVerifier.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/HostnameVerifier.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, 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,9 +38,8 @@
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.HostnameVerifier} and
* {@link javax.net.ssl.CertificateHostnameVerifier}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public interface HostnameVerifier {
/**
* Verify that the hostname from the URL is an acceptable
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/HttpsURLConnection.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -44,9 +44,8 @@
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.HttpsURLConnection}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public abstract
class HttpsURLConnection extends HttpURLConnection
{
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/KeyManager.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/KeyManager.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, 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
@@ -36,8 +36,7 @@
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.KeyManager}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public interface KeyManager {
}
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/KeyManagerFactory.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/KeyManagerFactory.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, 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
@@ -39,9 +39,8 @@
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.KeyManagerFactory}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public class KeyManagerFactory {
// The provider
private Provider provider;
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/KeyManagerFactorySpi.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/KeyManagerFactorySpi.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -41,9 +41,8 @@
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.KeyManagerFactorySpi}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public abstract class KeyManagerFactorySpi {
/**
* Initializes this factory with a source of key material. The
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLContext.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLContext.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -44,9 +44,8 @@
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.SSLContext}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public class SSLContext {
private Provider provider;
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLContextSpi.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLContextSpi.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, 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
@@ -43,9 +43,8 @@
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.SSLContextSpi}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public abstract class SSLContextSpi {
/**
* Initializes this context.
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLPermission.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/SSLPermission.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, 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
@@ -97,9 +97,8 @@
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.SSLPermission}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public final class SSLPermission extends BasicPermission {
private static final long serialVersionUID = -2583684302506167542L;
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/TrustManager.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/TrustManager.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, 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
@@ -36,8 +36,7 @@
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.TrustManager}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public interface TrustManager {
}
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/TrustManagerFactory.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/TrustManagerFactory.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, 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
@@ -39,9 +39,8 @@
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.TrustManagerFactory}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public class TrustManagerFactory {
// The provider
private Provider provider;
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/TrustManagerFactorySpi.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/TrustManagerFactorySpi.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -41,9 +41,8 @@
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.TrustManagerFactorySpi}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public abstract class TrustManagerFactorySpi {
/**
* Initializes this factory with a source of certificate
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/X509KeyManager.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/X509KeyManager.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -41,9 +41,8 @@
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.X509KeyManager}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public interface X509KeyManager extends KeyManager {
/**
* Get the matching aliases for authenticating the client side of a secure
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/X509TrustManager.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/X509TrustManager.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, 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
@@ -40,9 +40,8 @@
*
* @deprecated As of JDK 1.4, this implementation-specific class was
* replaced by {@link javax.net.ssl.X509TrustManager}.
- * This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public interface X509TrustManager extends TrustManager {
/**
* Given the partial or complete certificate chain
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/ssl/Provider.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/ssl/Provider.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, 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,10 +31,8 @@
* Main class for the SunJSSE provider. The actual code was moved to the
* class sun.security.ssl.SunJSSE, but for backward compatibility we
* continue to use this class as the main Provider class.
- *
- * @deprecated This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public final class Provider extends SunJSSE {
private static final long serialVersionUID = 3231825739635378733L;
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/ssl/X509ExtendedTrustManager.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/ssl/X509ExtendedTrustManager.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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
@@ -54,9 +54,8 @@
*
* @since 1.6
* @author Xuelei Fan
- * @deprecated This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public abstract class X509ExtendedTrustManager implements X509TrustManager {
/**
* Constructor used by subclasses only.
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/DelegateHttpsURLConnection.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/DelegateHttpsURLConnection.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, 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
@@ -52,9 +52,8 @@
* of protocol implementation (this one)
* com.sun.net.ssl.HttpURLConnection is used in the com.sun version.
*
- * @deprecated This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
@SuppressWarnings("deprecation") // HttpsURLConnection is deprecated
public class DelegateHttpsURLConnection extends AbstractDelegateHttpsURLConnection {
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/Handler.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/Handler.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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,9 +34,8 @@
* only. The HTTPS implementation can now be found in
* sun.net.www.protocol.https.
*
- * @deprecated This class is subject to removal in a future version of JDK.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public class Handler extends sun.net.www.protocol.https.Handler {
public Handler() {
--- a/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -60,13 +60,12 @@
* needs to implement all public methods in it's super class and all
* the way to Object.
*
- * @deprecated This class is subject to removal in a future version of JDK.
*/
// For both copies of the file, uncomment one line and comment the other
// public class HttpsURLConnectionImpl
// extends javax.net.ssl.HttpsURLConnection {
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
@SuppressWarnings("deprecation") // HttpsURLConnection is deprecated
public class HttpsURLConnectionOldImpl
extends com.sun.net.ssl.HttpsURLConnection {
--- a/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java Thu Feb 09 23:15:52 2017 +0100
@@ -25,11 +25,13 @@
package java.lang;
import jdk.internal.reflect.MethodAccessor;
+import jdk.internal.reflect.ConstructorAccessor;
import java.lang.StackWalker.Option;
import java.lang.StackWalker.StackFrame;
import java.lang.annotation.Native;
import java.lang.reflect.Method;
+import java.lang.reflect.Constructor;
import java.util.HashSet;
import java.util.NoSuchElementException;
import java.util.Objects;
@@ -922,7 +924,8 @@
*/
final void setBatch(int depth, int startIndex, int endIndex) {
if (startIndex <= 0 || endIndex <= 0)
- throw new IllegalArgumentException("startIndex=" + startIndex + " endIndex=" + endIndex);
+ throw new IllegalArgumentException("startIndex=" + startIndex
+ + " endIndex=" + endIndex);
this.origin = startIndex;
this.fence = endIndex;
@@ -980,13 +983,18 @@
private static boolean isReflectionFrame(Class<?> c) {
if (c.getName().startsWith("jdk.internal.reflect") &&
- !MethodAccessor.class.isAssignableFrom(c)) {
- throw new InternalError("Not jdk.internal.reflect.MethodAccessor: " + c.toString());
+ !MethodAccessor.class.isAssignableFrom(c) &&
+ !ConstructorAccessor.class.isAssignableFrom(c)) {
+ throw new InternalError("Not jdk.internal.reflect.MethodAccessor"
+ + " or jdk.internal.reflect.ConstructorAccessor: "
+ + c.toString());
}
// ## should filter all @Hidden frames?
return c == Method.class ||
- MethodAccessor.class.isAssignableFrom(c) ||
- c.getName().startsWith("java.lang.invoke.LambdaForm");
+ c == Constructor.class ||
+ MethodAccessor.class.isAssignableFrom(c) ||
+ ConstructorAccessor.class.isAssignableFrom(c) ||
+ c.getName().startsWith("java.lang.invoke.LambdaForm");
}
}
--- a/jdk/src/java.base/share/classes/java/lang/StackWalker.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/lang/StackWalker.java Thu Feb 09 23:15:52 2017 +0100
@@ -29,6 +29,7 @@
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
+import java.util.function.Predicate;
import java.util.stream.Stream;
/**
@@ -207,13 +208,23 @@
/**
* Shows all reflection frames.
*
- * <p>By default, reflection frames are hidden. This includes the
- * {@link java.lang.reflect.Method#invoke} method
- * and the reflection implementation classes. A {@code StackWalker} with
- * this {@code SHOW_REFLECT_FRAMES} option will show all reflection frames.
- * The {@link #SHOW_HIDDEN_FRAMES} option can also be used to show all
+ * <p>By default, reflection frames are hidden. A {@code StackWalker}
+ * configured with this {@code SHOW_REFLECT_FRAMES} option
+ * will show all reflection frames that
+ * include {@link java.lang.reflect.Method#invoke} and
+ * {@link java.lang.reflect.Constructor#newInstance(Object...)}
+ * and their reflection implementation classes.
+ *
+ * <p>The {@link #SHOW_HIDDEN_FRAMES} option can also be used to show all
* reflection frames and it will also show other hidden frames that
* are implementation-specific.
+ *
+ * @apiNote
+ * This option includes the stack frames representing the invocation of
+ * {@code Method} and {@code Constructor}. Any utility methods that
+ * are equivalent to calling {@code Method.invoke} or
+ * {@code Constructor.newInstance} such as {@code Class.newInstance}
+ * are not filtered or controlled by any stack walking option.
*/
SHOW_REFLECT_FRAMES,
/**
@@ -468,8 +479,9 @@
* Gets the {@code Class} object of the caller invoking the method
* that calls this {@code getCallerClass} method.
*
- * <p> Reflection frames, {@link java.lang.invoke.MethodHandle}, and
- * hidden frames are filtered regardless of the
+ * <p> This method filters {@linkplain Option#SHOW_REFLECT_FRAMES reflection
+ * frames}, {@link java.lang.invoke.MethodHandle}, and
+ * {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} regardless of the
* {@link Option#SHOW_REFLECT_FRAMES SHOW_REFLECT_FRAMES}
* and {@link Option#SHOW_HIDDEN_FRAMES SHOW_HIDDEN_FRAMES} options
* this {@code StackWalker} has been configured with.
--- a/jdk/src/java.base/share/classes/java/net/doc-files/net-properties.html Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/net/doc-files/net-properties.html Thu Feb 09 23:15:52 2017 +0100
@@ -149,7 +149,7 @@
the <B>user.name</B> property will be used with no password.</P>
</UL>
<LI><P><B>java.net.useSystemProxies</B> (default: false)<BR>
- On recent Windows systems and on Gnome 2.x systems it is possible to
+ On Windows systems, macOS systems and on Gnome systems it is possible to
tell the java.net stack, setting this property to <B>true</B>, to use
the system proxy settings (both these systems let you set proxies
globally through their user interface). Note that this property is
--- a/jdk/src/java.base/share/classes/java/security/Certificate.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/security/Certificate.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -60,10 +60,9 @@
* This Certificate interface is entirely deprecated and
* is here to allow for a smooth transition to the new
* package.
- * This class is subject to removal in a future version of Java SE.
* @see java.security.cert.Certificate
*/
-@Deprecated(since="1.2", forRemoval=true)
+@Deprecated(since="1.2")
public interface Certificate {
/**
--- a/jdk/src/java.base/share/classes/java/security/Identity.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/security/Identity.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -52,12 +52,11 @@
*
* @author Benjamin Renaud
* @deprecated This class is no longer used. Its functionality has been
- * replaced by {@link java.security.KeyStore}, the
- * {@link java.security.cert} package, and
- * {@link java.security.Principal}.
- * This class is subject to removal in a future version of Java SE.
+ * replaced by {@code java.security.KeyStore}, the
+ * {@code java.security.cert} package, and
+ * {@code java.security.Principal}.
*/
-@Deprecated(since="1.2", forRemoval=true)
+@Deprecated(since="1.2")
public abstract class Identity implements Principal, Serializable {
/** use serialVersionUID from JDK 1.1.x for interoperability */
--- a/jdk/src/java.base/share/classes/java/security/IdentityScope.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/security/IdentityScope.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -57,15 +57,11 @@
* @author Benjamin Renaud
*
* @deprecated This class is no longer used. Its functionality has been
- * replaced by {@link java.security.KeyStore}, the
- * {@link java.security.cert} package, and
- * {@link java.security.Principal}.
- * This class is subject to removal in a future version of Java SE.
- *
- * Note that the security property {@code policy.ignoreIdentityScope}
- * is only applicable to these APIs and is also a candidate for removal.
+ * replaced by {@code java.security.KeyStore}, the
+ * {@code java.security.cert} package, and
+ * {@code java.security.Principal}.
*/
-@Deprecated(since="1.2", forRemoval=true)
+@Deprecated(since="1.2")
public abstract
class IdentityScope extends Identity {
--- a/jdk/src/java.base/share/classes/java/security/Signer.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/security/Signer.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -40,12 +40,11 @@
* @author Benjamin Renaud
*
* @deprecated This class is no longer used. Its functionality has been
- * replaced by {@link java.security.KeyStore}, the
- * {@link java.security.cert} package, and
- * {@link java.security.Principal}.
- * This class is subject to removal in a future version of Java SE.
+ * replaced by {@code java.security.KeyStore}, the
+ * {@code java.security.cert} package, and
+ * {@code java.security.Principal}.
*/
-@Deprecated(since="1.2", forRemoval=true)
+@Deprecated(since="1.2")
public abstract class Signer extends Identity {
private static final long serialVersionUID = -1763464102261361480L;
--- a/jdk/src/java.base/share/classes/java/security/acl/Acl.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/security/acl/Acl.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -85,10 +85,9 @@
*
* @deprecated This package has been replaced by {@code java.security.Policy}
* and related classes since 1.2.
- * This class is subject to removal in a future version of Java SE.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public interface Acl extends Owner {
/**
--- a/jdk/src/java.base/share/classes/java/security/acl/AclEntry.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/security/acl/AclEntry.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -53,9 +53,8 @@
*
* @deprecated This package has been replaced by {@code java.security.Policy}
* and related classes since 1.2.
- * This class is subject to removal in a future version of Java SE.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public interface AclEntry extends Cloneable {
/**
--- a/jdk/src/java.base/share/classes/java/security/acl/AclNotFoundException.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/security/acl/AclNotFoundException.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -33,9 +33,8 @@
*
* @deprecated This package has been replaced by {@code java.security.Policy}
* and related classes since 1.2.
- * This class is subject to removal in a future version of Java SE.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public class AclNotFoundException extends Exception {
private static final long serialVersionUID = 5684295034092681791L;
--- a/jdk/src/java.base/share/classes/java/security/acl/Group.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/security/acl/Group.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,9 +42,8 @@
*
* @deprecated This package has been replaced by {@code java.security.Policy}
* and related classes since 1.2.
- * This class is subject to removal in a future version of Java SE.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public interface Group extends Principal {
/**
--- a/jdk/src/java.base/share/classes/java/security/acl/LastOwnerException.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/security/acl/LastOwnerException.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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,9 +35,8 @@
*
* @deprecated This package has been replaced by {@code java.security.Policy}
* and related classes since 1.2.
- * This class is subject to removal in a future version of Java SE.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public class LastOwnerException extends Exception {
private static final long serialVersionUID = -5141997548211140359L;
--- a/jdk/src/java.base/share/classes/java/security/acl/NotOwnerException.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/security/acl/NotOwnerException.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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,9 +34,8 @@
*
* @deprecated This package has been replaced by {@code java.security.Policy}
* and related classes since 1.2.
- * This class is subject to removal in a future version of Java SE.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public class NotOwnerException extends Exception {
private static final long serialVersionUID = -5555597911163362399L;
--- a/jdk/src/java.base/share/classes/java/security/acl/Owner.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/security/acl/Owner.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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,9 +38,8 @@
*
* @deprecated This package has been replaced by {@code java.security.Policy}
* and related classes since 1.2.
- * This class is subject to removal in a future version of Java SE.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public interface Owner {
/**
--- a/jdk/src/java.base/share/classes/java/security/acl/Permission.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/security/acl/Permission.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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,9 +34,8 @@
*
* @deprecated This package has been replaced by {@code java.security.Policy}
* and related classes since 1.2.
- * This class is subject to removal in a future version of Java SE.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public interface Permission {
/**
--- a/jdk/src/java.base/share/classes/java/security/acl/package-info.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/security/acl/package-info.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,8 +27,7 @@
* The classes and interfaces in this package have been deprecated. New
* classes should not be added to this package. The {@code java.security}
* package contains suitable replacements. See {@link java.security.Policy}
- * and related classes for details. This package is subject to removal in a
- * future version of Java SE.
+ * and related classes for details.
*
* @since 1.1
*/
--- a/jdk/src/java.base/share/classes/java/util/PriorityQueue.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/PriorityQueue.java Thu Feb 09 23:15:52 2017 +0100
@@ -734,12 +734,12 @@
@SuppressWarnings("unchecked")
private void heapify() {
final Object[] es = queue;
- final int half = (size >>> 1) - 1;
+ int i = (size >>> 1) - 1;
if (comparator == null)
- for (int i = half; i >= 0; i--)
+ for (; i >= 0; i--)
siftDownComparable(i, (E) es[i]);
else
- for (int i = half; i >= 0; i--)
+ for (; i >= 0; i--)
siftDownUsingComparator(i, (E) es[i]);
}
--- a/jdk/src/java.base/share/classes/java/util/ResourceBundle.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/ResourceBundle.java Thu Feb 09 23:15:52 2017 +0100
@@ -61,7 +61,10 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.jar.JarEntry;
+import java.util.spi.ResourceBundleControlProvider;
import java.util.spi.ResourceBundleProvider;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import jdk.internal.loader.BootLoader;
import jdk.internal.misc.JavaUtilResourceBundleAccess;
@@ -232,6 +235,8 @@
* <li>{@code ResourceBundle.Control} is <em>not</em> supported in named modules.
* If the {@code getBundle} method with a {@code ResourceBundle.Control} is called
* in a named module, the method will throw an {@code UnsupportedOperationException}.
+ * Any service providers of {@link ResourceBundleControlProvider} are ignored in
+ * named modules.
* </li>
* </ul>
*
@@ -262,6 +267,18 @@
* {@link #getBundle(String, Locale, ClassLoader, Control) getBundle}
* factory method for details.
*
+ * <p><a name="modify_default_behavior">For the {@code getBundle} factory</a>
+ * methods that take no {@link Control} instance, their <a
+ * href="#default_behavior"> default behavior</a> of resource bundle loading
+ * can be modified with custom {@link
+ * ResourceBundleControlProvider} implementations.
+ * If any of the
+ * providers provides a {@link Control} for the given base name, that {@link
+ * Control} will be used instead of the default {@link Control}. If there is
+ * more than one service provider for supporting the same base name,
+ * the first one returned from {@link ServiceLoader} will be used.
+ * A custom {@link Control} implementation is ignored by named modules.
+ *
* <h3>Cache Management</h3>
*
* Resource bundle instances created by the <code>getBundle</code> factory
@@ -367,7 +384,8 @@
public ResourceBundle getBundle(String baseName, Locale locale, Module module) {
// use the given module as the caller to bypass the access check
return getBundleImpl(module, module,
- baseName, locale, Control.INSTANCE);
+ baseName, locale,
+ getDefaultControl(module, baseName));
}
@Override
@@ -815,7 +833,7 @@
{
Class<?> caller = Reflection.getCallerClass();
return getBundleImpl(baseName, Locale.getDefault(),
- caller, Control.INSTANCE);
+ caller, getDefaultControl(caller, baseName));
}
/**
@@ -889,7 +907,7 @@
{
Class<?> caller = Reflection.getCallerClass();
return getBundleImpl(baseName, locale,
- caller, Control.INSTANCE);
+ caller, getDefaultControl(caller, baseName));
}
/**
@@ -925,7 +943,8 @@
@CallerSensitive
public static ResourceBundle getBundle(String baseName, Module module) {
return getBundleFromModule(Reflection.getCallerClass(), module, baseName,
- Locale.getDefault(), Control.INSTANCE);
+ Locale.getDefault(),
+ getDefaultControl(module, baseName));
}
/**
@@ -953,7 +972,9 @@
* equivalent to calling {@link #getBundle(String, Locale, ClassLoader)
* getBundle(baseName, targetLocale, module.getClassLoader()} to load
* resource bundles that are visible to the class loader of the given
- * unnamed module.
+ * unnamed module. Custom {@link java.util.spi.ResourceBundleControlProvider}
+ * implementations, if present, will only be invoked if the specified
+ * module is an unnamed module.
*
* @param baseName the base name of the resource bundle,
* a fully qualified class name
@@ -974,7 +995,7 @@
@CallerSensitive
public static ResourceBundle getBundle(String baseName, Locale targetLocale, Module module) {
return getBundleFromModule(Reflection.getCallerClass(), module, baseName, targetLocale,
- Control.INSTANCE);
+ getDefaultControl(module, baseName));
}
/**
@@ -1030,7 +1051,10 @@
*
* <p>This method behaves the same as calling
* {@link #getBundle(String, Locale, ClassLoader, Control)} passing a
- * default instance of {@link Control}.
+ * default instance of {@link Control} unless another {@link Control} is
+ * provided with the {@link ResourceBundleControlProvider} SPI. Refer to the
+ * description of <a href="#modify_default_behavior">modifying the default
+ * behavior</a>.
*
* <p><a name="default_behavior">The following describes the default
* behavior</a>.
@@ -1228,7 +1252,7 @@
throw new NullPointerException();
}
Class<?> caller = Reflection.getCallerClass();
- return getBundleImpl(baseName, locale, caller, loader, Control.INSTANCE);
+ return getBundleImpl(baseName, locale, caller, loader, getDefaultControl(caller, baseName));
}
/**
@@ -1453,6 +1477,39 @@
return getBundleImpl(baseName, targetLocale, caller, loader, control);
}
+ private static Control getDefaultControl(Class<?> caller, String baseName) {
+ return getDefaultControl(caller.getModule(), baseName);
+ }
+
+ private static Control getDefaultControl(Module targetModule, String baseName) {
+ return targetModule.isNamed() ?
+ Control.INSTANCE :
+ ResourceBundleControlProviderHolder.getControl(baseName);
+ }
+
+ private static class ResourceBundleControlProviderHolder {
+ private static final PrivilegedAction<List<ResourceBundleControlProvider>> pa =
+ () -> {
+ return Collections.unmodifiableList(
+ ServiceLoader.load(ResourceBundleControlProvider.class,
+ ClassLoader.getSystemClassLoader()).stream()
+ .map(ServiceLoader.Provider::get)
+ .collect(Collectors.toList()));
+ };
+
+ private static final List<ResourceBundleControlProvider> CONTROL_PROVIDERS =
+ AccessController.doPrivileged(pa);
+
+ private static Control getControl(String baseName) {
+ return CONTROL_PROVIDERS.isEmpty() ?
+ Control.INSTANCE :
+ CONTROL_PROVIDERS.stream()
+ .flatMap(provider -> Stream.ofNullable(provider.getControl(baseName)))
+ .findFirst()
+ .orElse(Control.INSTANCE);
+ }
+ }
+
private static void checkNamedModule(Class<?> caller) {
if (caller.getModule().isNamed()) {
throw new UnsupportedOperationException(
@@ -2414,7 +2471,8 @@
* @apiNote <a name="note">{@code ResourceBundle.Control} is not supported
* in named modules.</a> If the {@code ResourceBundle.getBundle} method with
* a {@code ResourceBundle.Control} is called in a named module, the method
- * will throw an {@link UnsupportedOperationException}.
+ * will throw an {@link UnsupportedOperationException}. Any service providers
+ * of {@link ResourceBundleControlProvider} are ignored in named modules.
*
* @since 1.6
* @see java.util.spi.ResourceBundleProvider
--- a/jdk/src/java.base/share/classes/java/util/Vector.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/Vector.java Thu Feb 09 23:15:52 2017 +0100
@@ -307,8 +307,9 @@
if (newSize > elementData.length)
grow(newSize);
final Object[] es = elementData;
- for (int to = elementCount, i = elementCount = newSize; i < to; i++)
+ for (int to = elementCount, i = newSize; i < to; i++)
es[i] = null;
+ elementCount = newSize;
}
/**
@@ -1443,9 +1444,8 @@
@SuppressWarnings("unchecked")
public boolean tryAdvance(Consumer<? super E> action) {
+ Objects.requireNonNull(action);
int i;
- if (action == null)
- throw new NullPointerException();
if (getFence() > (i = index)) {
index = i + 1;
action.accept((E)array[i]);
@@ -1458,8 +1458,7 @@
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> action) {
- if (action == null)
- throw new NullPointerException();
+ Objects.requireNonNull(action);
final int hi = getFence();
final Object[] a = array;
int i;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java Thu Feb 09 23:15:52 2017 +0100
@@ -72,9 +72,8 @@
* generally decreases throughput but reduces variability and avoids
* starvation.
*
- * <p>This class and its iterator implement all of the
- * <em>optional</em> methods of the {@link Collection} and {@link
- * Iterator} interfaces.
+ * <p>This class and its iterator implement all of the <em>optional</em>
+ * methods of the {@link Collection} and {@link Iterator} interfaces.
*
* <p>This class is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java Thu Feb 09 23:15:52 2017 +0100
@@ -67,12 +67,12 @@
* asynchronous nature of these deques, determining the current number
* of elements requires a traversal of the elements, and so may report
* inaccurate results if this collection is modified during traversal.
- * Additionally, the bulk operations {@code addAll},
- * {@code removeAll}, {@code retainAll}, {@code containsAll},
- * and {@code toArray} are <em>not</em> guaranteed
- * to be performed atomically. For example, an iterator operating
- * concurrently with an {@code addAll} operation might view only some
- * of the added elements.
+ *
+ * <p>Bulk operations that add, remove, or examine multiple elements,
+ * such as {@link #addAll}, {@link #removeIf} or {@link #forEach},
+ * are <em>not</em> guaranteed to be performed atomically.
+ * For example, a {@code forEach} traversal concurrent with an {@code
+ * addAll} operation might observe only some of the added elements.
*
* <p>This class and its iterator implement all of the <em>optional</em>
* methods of the {@link Deque} and {@link Iterator} interfaces.
@@ -683,8 +683,9 @@
*/
final Node<E> succ(Node<E> p) {
// TODO: should we skip deleted nodes here?
- Node<E> q = p.next;
- return (p == q) ? first() : q;
+ if (p == (p = p.next))
+ p = first();
+ return p;
}
/**
@@ -1416,65 +1417,55 @@
boolean exhausted; // true when no more nodes
public Spliterator<E> trySplit() {
- Node<E> p;
- int b = batch;
- int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
- if (!exhausted &&
- ((p = current) != null || (p = first()) != null)) {
- if (p.item == null && p == (p = p.next))
- current = p = first();
- if (p != null && p.next != null) {
- Object[] a = new Object[n];
- int i = 0;
- do {
- if ((a[i] = p.item) != null)
- ++i;
- if (p == (p = p.next))
- p = first();
- } while (p != null && i < n);
- if ((current = p) == null)
- exhausted = true;
- if (i > 0) {
- batch = i;
- return Spliterators.spliterator
- (a, 0, i, (Spliterator.ORDERED |
- Spliterator.NONNULL |
- Spliterator.CONCURRENT));
- }
+ Node<E> p, q;
+ if ((p = current()) == null || (q = p.next) == null)
+ return null;
+ int i = 0, n = batch = Math.min(batch + 1, MAX_BATCH);
+ Object[] a = null;
+ do {
+ final E e;
+ if ((e = p.item) != null) {
+ if (a == null)
+ a = new Object[n];
+ a[i++] = e;
}
- }
- return null;
+ if (p == (p = q))
+ p = first();
+ } while (p != null && (q = p.next) != null && i < n);
+ setCurrent(p);
+ return (i == 0) ? null :
+ Spliterators.spliterator(a, 0, i, (Spliterator.ORDERED |
+ Spliterator.NONNULL |
+ Spliterator.CONCURRENT));
}
public void forEachRemaining(Consumer<? super E> action) {
+ Objects.requireNonNull(action);
Node<E> p;
- if (action == null) throw new NullPointerException();
- if (!exhausted &&
- ((p = current) != null || (p = first()) != null)) {
+ if ((p = current()) != null) {
+ current = null;
exhausted = true;
do {
- E e = p.item;
+ final E e;
+ if ((e = p.item) != null)
+ action.accept(e);
if (p == (p = p.next))
p = first();
- if (e != null)
- action.accept(e);
} while (p != null);
}
}
public boolean tryAdvance(Consumer<? super E> action) {
+ Objects.requireNonNull(action);
Node<E> p;
- if (action == null) throw new NullPointerException();
- if (!exhausted &&
- ((p = current) != null || (p = first()) != null)) {
+ if ((p = current()) != null) {
E e;
do {
e = p.item;
if (p == (p = p.next))
p = first();
} while (e == null && p != null);
- if ((current = p) == null)
- exhausted = true;
+ setCurrent(p);
if (e != null) {
action.accept(e);
return true;
@@ -1483,11 +1474,24 @@
return false;
}
+ private void setCurrent(Node<E> p) {
+ if ((current = p) == null)
+ exhausted = true;
+ }
+
+ private Node<E> current() {
+ Node<E> p;
+ if ((p = current) == null && !exhausted)
+ setCurrent(p = first());
+ return p;
+ }
+
public long estimateSize() { return Long.MAX_VALUE; }
public int characteristics() {
- return Spliterator.ORDERED | Spliterator.NONNULL |
- Spliterator.CONCURRENT;
+ return (Spliterator.ORDERED |
+ Spliterator.NONNULL |
+ Spliterator.CONCURRENT);
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java Thu Feb 09 23:15:52 2017 +0100
@@ -81,12 +81,12 @@
* asynchronous nature of these queues, determining the current number
* of elements requires a traversal of the elements, and so may report
* inaccurate results if this collection is modified during traversal.
- * Additionally, the bulk operations {@code addAll},
- * {@code removeAll}, {@code retainAll}, {@code containsAll},
- * and {@code toArray} are <em>not</em> guaranteed
- * to be performed atomically. For example, an iterator operating
- * concurrently with an {@code addAll} operation might view only some
- * of the added elements.
+ *
+ * <p>Bulk operations that add, remove, or examine multiple elements,
+ * such as {@link #addAll}, {@link #removeIf} or {@link #forEach},
+ * are <em>not</em> guaranteed to be performed atomically.
+ * For example, a {@code forEach} traversal concurrent with an {@code
+ * addAll} operation might observe only some of the added elements.
*
* <p>This class and its iterator implement all of the <em>optional</em>
* methods of the {@link Queue} and {@link Iterator} interfaces.
@@ -184,16 +184,30 @@
static final class Node<E> {
volatile E item;
volatile Node<E> next;
- }
+
+ /**
+ * Constructs a node holding item. Uses relaxed write because
+ * item can only be seen after piggy-backing publication via CAS.
+ */
+ Node(E item) {
+ ITEM.set(this, item);
+ }
+
+ /** Constructs a dead dummy node. */
+ Node() {}
- /**
- * Returns a new node holding item. Uses relaxed write because item
- * can only be seen after piggy-backing publication via CAS.
- */
- static <E> Node<E> newNode(E item) {
- Node<E> node = new Node<E>();
- ITEM.set(node, item);
- return node;
+ void appendRelaxed(Node<E> next) {
+ // assert next != null;
+ // assert this.next == null;
+ NEXT.set(this, next);
+ }
+
+ boolean casItem(E cmp, E val) {
+ // assert item == cmp || item == null;
+ // assert cmp != null;
+ // assert val == null;
+ return ITEM.compareAndSet(this, cmp, val);
+ }
}
/**
@@ -220,7 +234,7 @@
* - tail.item may or may not be null.
* - it is permitted for tail to lag behind head, that is, for tail
* to not be reachable from head!
- * - tail.next may or may not be self-pointing to tail.
+ * - tail.next may or may not be self-linked.
*/
private transient volatile Node<E> tail;
@@ -228,7 +242,7 @@
* Creates a {@code ConcurrentLinkedQueue} that is initially empty.
*/
public ConcurrentLinkedQueue() {
- head = tail = newNode(null);
+ head = tail = new Node<E>();
}
/**
@@ -243,16 +257,14 @@
public ConcurrentLinkedQueue(Collection<? extends E> c) {
Node<E> h = null, t = null;
for (E e : c) {
- Node<E> newNode = newNode(Objects.requireNonNull(e));
+ Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
if (h == null)
h = t = newNode;
- else {
- NEXT.set(t, newNode);
- t = newNode;
- }
+ else
+ t.appendRelaxed(t = newNode);
}
if (h == null)
- h = t = newNode(null);
+ h = t = new Node<E>();
head = h;
tail = t;
}
@@ -287,14 +299,17 @@
* stale pointer that is now off the list.
*/
final Node<E> succ(Node<E> p) {
- Node<E> next = p.next;
- return (p == next) ? head : next;
+ if (p == (p = p.next))
+ p = head;
+ return p;
}
/**
* Tries to CAS pred.next (or head, if pred is null) from c to p.
+ * Caller must ensure that we're not unlinking the trailing node.
*/
private boolean tryCasSuccessor(Node<E> pred, Node<E> c, Node<E> p) {
+ // assert p != null;
// assert c.item == null;
// assert c != p;
if (pred != null)
@@ -307,6 +322,29 @@
}
/**
+ * Collapse dead nodes between pred and q.
+ * @param pred the last known live node, or null if none
+ * @param c the first dead node
+ * @param p the last dead node
+ * @param q p.next: the next live node, or null if at end
+ * @return either old pred or p if pred dead or CAS failed
+ */
+ private Node<E> skipDeadNodes(Node<E> pred, Node<E> c, Node<E> p, Node<E> q) {
+ // assert pred != c;
+ // assert p != q;
+ // assert c.item == null;
+ // assert p.item == null;
+ if (q == null) {
+ // Never unlink trailing node.
+ if (c == p) return pred;
+ q = p;
+ }
+ return (tryCasSuccessor(pred, c, q)
+ && (pred == null || ITEM.get(pred) != null))
+ ? pred : p;
+ }
+
+ /**
* Inserts the specified element at the tail of this queue.
* As the queue is unbounded, this method will never return {@code false}.
*
@@ -314,7 +352,7 @@
* @throws NullPointerException if the specified element is null
*/
public boolean offer(E e) {
- final Node<E> newNode = newNode(Objects.requireNonNull(e));
+ final Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
for (Node<E> t = tail, p = t;;) {
Node<E> q = p.next;
@@ -346,8 +384,7 @@
restartFromHead: for (;;) {
for (Node<E> h = head, p = h, q;; p = q) {
final E item;
- if ((item = p.item) != null
- && ITEM.compareAndSet(p, item, null)) {
+ if ((item = p.item) != null && p.casItem(item, null)) {
// Successful CAS is the linearization point
// for item to be removed from this queue.
if (p != h) // hop two nodes at a time
@@ -451,19 +488,20 @@
public boolean contains(Object o) {
if (o == null) return false;
restartFromHead: for (;;) {
- for (Node<E> p = head, c = p, pred = null, q; p != null; p = q) {
+ for (Node<E> p = head, pred = null; p != null; ) {
+ Node<E> q = p.next;
final E item;
- if ((item = p.item) != null && o.equals(item))
- return true;
- if (c != p && tryCasSuccessor(pred, c, p))
- c = p;
- q = p.next;
- if (item != null || c != p) {
- pred = p;
- c = q;
+ if ((item = p.item) != null) {
+ if (o.equals(item))
+ return true;
+ pred = p; p = q; continue;
}
- else if (p == q)
- continue restartFromHead;
+ for (Node<E> c = p;; q = p.next) {
+ if (q == null || q.item != null) {
+ pred = skipDeadNodes(pred, c, p, q); p = q; break;
+ }
+ if (p == (p = q)) continue restartFromHead;
+ }
}
return false;
}
@@ -483,23 +521,22 @@
public boolean remove(Object o) {
if (o == null) return false;
restartFromHead: for (;;) {
- for (Node<E> p = head, c = p, pred = null, q; p != null; p = q) {
+ for (Node<E> p = head, pred = null; p != null; ) {
+ Node<E> q = p.next;
final E item;
- final boolean removed =
- (item = p.item) != null
- && o.equals(item)
- && ITEM.compareAndSet(p, item, null);
- if (c != p && tryCasSuccessor(pred, c, p))
- c = p;
- if (removed)
- return true;
- q = p.next;
- if (item != null || c != p) {
- pred = p;
- c = q;
+ if ((item = p.item) != null) {
+ if (o.equals(item) && p.casItem(item, null)) {
+ skipDeadNodes(pred, p, p, q);
+ return true;
+ }
+ pred = p; p = q; continue;
}
- else if (p == q)
- continue restartFromHead;
+ for (Node<E> c = p;; q = p.next) {
+ if (q == null || q.item != null) {
+ pred = skipDeadNodes(pred, c, p, q); p = q; break;
+ }
+ if (p == (p = q)) continue restartFromHead;
+ }
}
return false;
}
@@ -525,13 +562,11 @@
// Copy c into a private chain of Nodes
Node<E> beginningOfTheEnd = null, last = null;
for (E e : c) {
- Node<E> newNode = newNode(Objects.requireNonNull(e));
+ Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
if (beginningOfTheEnd == null)
beginningOfTheEnd = last = newNode;
- else {
- NEXT.set(last, newNode);
- last = newNode;
- }
+ else
+ last.appendRelaxed(last = newNode);
}
if (beginningOfTheEnd == null)
return false;
@@ -677,7 +712,7 @@
*/
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
- if (a == null) throw new NullPointerException();
+ Objects.requireNonNull(a);
return (T[]) toArrayInternal(a);
}
@@ -757,6 +792,8 @@
}
}
+ // Default implementation of forEachRemaining is "good enough".
+
public void remove() {
Node<E> l = lastRet;
if (l == null) throw new IllegalStateException();
@@ -806,16 +843,14 @@
Node<E> h = null, t = null;
for (Object item; (item = s.readObject()) != null; ) {
@SuppressWarnings("unchecked")
- Node<E> newNode = newNode((E) item);
+ Node<E> newNode = new Node<E>((E) item);
if (h == null)
h = t = newNode;
- else {
- NEXT.set(t, newNode);
- t = newNode;
- }
+ else
+ t.appendRelaxed(t = newNode);
}
if (h == null)
- h = t = newNode(null);
+ h = t = new Node<E>();
head = h;
tail = t;
}
@@ -828,62 +863,49 @@
boolean exhausted; // true when no more nodes
public Spliterator<E> trySplit() {
- Node<E> p;
- int b = batch;
- int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
- if (!exhausted &&
- ((p = current) != null || (p = first()) != null) &&
- p.next != null) {
- Object[] a = new Object[n];
- int i = 0;
- do {
- if ((a[i] = p.item) != null)
- ++i;
- if (p == (p = p.next))
- p = first();
- } while (p != null && i < n);
- if ((current = p) == null)
- exhausted = true;
- if (i > 0) {
- batch = i;
- return Spliterators.spliterator
- (a, 0, i, (Spliterator.ORDERED |
- Spliterator.NONNULL |
- Spliterator.CONCURRENT));
+ Node<E> p, q;
+ if ((p = current()) == null || (q = p.next) == null)
+ return null;
+ int i = 0, n = batch = Math.min(batch + 1, MAX_BATCH);
+ Object[] a = null;
+ do {
+ final E e;
+ if ((e = p.item) != null) {
+ if (a == null)
+ a = new Object[n];
+ a[i++] = e;
}
- }
- return null;
+ if (p == (p = q))
+ p = first();
+ } while (p != null && (q = p.next) != null && i < n);
+ setCurrent(p);
+ return (i == 0) ? null :
+ Spliterators.spliterator(a, 0, i, (Spliterator.ORDERED |
+ Spliterator.NONNULL |
+ Spliterator.CONCURRENT));
}
public void forEachRemaining(Consumer<? super E> action) {
- Node<E> p;
- if (action == null) throw new NullPointerException();
- if (!exhausted &&
- ((p = current) != null || (p = first()) != null)) {
+ Objects.requireNonNull(action);
+ final Node<E> p;
+ if ((p = current()) != null) {
+ current = null;
exhausted = true;
- do {
- E e = p.item;
- if (p == (p = p.next))
- p = first();
- if (e != null)
- action.accept(e);
- } while (p != null);
+ forEachFrom(action, p);
}
}
public boolean tryAdvance(Consumer<? super E> action) {
+ Objects.requireNonNull(action);
Node<E> p;
- if (action == null) throw new NullPointerException();
- if (!exhausted &&
- ((p = current) != null || (p = first()) != null)) {
+ if ((p = current()) != null) {
E e;
do {
e = p.item;
if (p == (p = p.next))
p = first();
} while (e == null && p != null);
- if ((current = p) == null)
- exhausted = true;
+ setCurrent(p);
if (e != null) {
action.accept(e);
return true;
@@ -892,11 +914,24 @@
return false;
}
+ private void setCurrent(Node<E> p) {
+ if ((current = p) == null)
+ exhausted = true;
+ }
+
+ private Node<E> current() {
+ Node<E> p;
+ if ((p = current) == null && !exhausted)
+ setCurrent(p = first());
+ return p;
+ }
+
public long estimateSize() { return Long.MAX_VALUE; }
public int characteristics() {
- return Spliterator.ORDERED | Spliterator.NONNULL |
- Spliterator.CONCURRENT;
+ return (Spliterator.ORDERED |
+ Spliterator.NONNULL |
+ Spliterator.CONCURRENT);
}
}
@@ -963,22 +998,22 @@
// c will be CASed to collapse intervening dead nodes between
// pred (or head if null) and p.
for (Node<E> p = head, c = p, pred = null, q; p != null; p = q) {
+ q = p.next;
final E item; boolean pAlive;
if (pAlive = ((item = p.item) != null)) {
if (filter.test(item)) {
- if (ITEM.compareAndSet(p, item, null))
+ if (p.casItem(item, null))
removed = true;
pAlive = false;
}
}
- if ((q = p.next) == null || pAlive || --hops == 0) {
+ if (pAlive || q == null || --hops == 0) {
// p might already be self-linked here, but if so:
// - CASing head will surely fail
// - CASing pred's next will be useless but harmless.
- if (c != p && tryCasSuccessor(pred, c, p))
- c = p;
- // if c != p, CAS failed, so abandon old pred
- if (pAlive || c != p) {
+ if ((c != p && !tryCasSuccessor(pred, c, c = p))
+ || pAlive) {
+ // if CAS failed or alive, abandon old pred
hops = MAX_HOPS;
pred = p;
c = q;
@@ -991,34 +1026,39 @@
}
/**
+ * Runs action on each element found during a traversal starting at p.
+ * If p is null, the action is not run.
+ */
+ void forEachFrom(Consumer<? super E> action, Node<E> p) {
+ for (Node<E> pred = null; p != null; ) {
+ Node<E> q = p.next;
+ final E item;
+ if ((item = p.item) != null) {
+ action.accept(item);
+ pred = p; p = q; continue;
+ }
+ for (Node<E> c = p;; q = p.next) {
+ if (q == null || q.item != null) {
+ pred = skipDeadNodes(pred, c, p, q); p = q; break;
+ }
+ if (p == (p = q)) { pred = null; p = head; break; }
+ }
+ }
+ }
+
+ /**
* @throws NullPointerException {@inheritDoc}
*/
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
- restartFromHead: for (;;) {
- for (Node<E> p = head, c = p, pred = null, q; p != null; p = q) {
- final E item;
- if ((item = p.item) != null)
- action.accept(item);
- if (c != p && tryCasSuccessor(pred, c, p))
- c = p;
- q = p.next;
- if (item != null || c != p) {
- pred = p;
- c = q;
- }
- else if (p == q)
- continue restartFromHead;
- }
- return;
- }
+ forEachFrom(action, head);
}
// VarHandle mechanics
private static final VarHandle HEAD;
private static final VarHandle TAIL;
- private static final VarHandle ITEM;
- private static final VarHandle NEXT;
+ static final VarHandle ITEM;
+ static final VarHandle NEXT;
static {
try {
MethodHandles.Lookup l = MethodHandles.lookup();
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java Thu Feb 09 23:15:52 2017 +0100
@@ -72,12 +72,12 @@
* asynchronous nature of these sets, determining the current number
* of elements requires a traversal of the elements, and so may report
* inaccurate results if this collection is modified during traversal.
- * Additionally, the bulk operations {@code addAll},
- * {@code removeAll}, {@code retainAll}, {@code containsAll},
- * {@code equals}, and {@code toArray} are <em>not</em> guaranteed
- * to be performed atomically. For example, an iterator operating
- * concurrently with an {@code addAll} operation might view only some
- * of the added elements.
+ *
+ * <p>Bulk operations that add, remove, or examine multiple elements,
+ * such as {@link #addAll}, {@link #removeIf} or {@link #forEach},
+ * are <em>not</em> guaranteed to be performed atomically.
+ * For example, a {@code forEach} traversal concurrent with an {@code
+ * addAll} operation might observe only some of the added elements.
*
* <p>This class and its iterators implement all of the
* <em>optional</em> methods of the {@link Set} and {@link Iterator}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java Thu Feb 09 23:15:52 2017 +0100
@@ -797,7 +797,7 @@
* @throws NullPointerException {@inheritDoc}
*/
public void forEach(Consumer<? super E> action) {
- if (action == null) throw new NullPointerException();
+ Objects.requireNonNull(action);
for (Object x : getArray()) {
@SuppressWarnings("unchecked") E e = (E) x;
action.accept(e);
@@ -808,7 +808,7 @@
* @throws NullPointerException {@inheritDoc}
*/
public boolean removeIf(Predicate<? super E> filter) {
- if (filter == null) throw new NullPointerException();
+ Objects.requireNonNull(filter);
return bulkRemove(filter);
}
@@ -865,7 +865,7 @@
}
public void replaceAll(UnaryOperator<E> operator) {
- if (operator == null) throw new NullPointerException();
+ Objects.requireNonNull(operator);
synchronized (lock) {
replaceAll(operator, 0, getArray().length);
}
@@ -1329,7 +1329,7 @@
}
public void forEach(Consumer<? super E> action) {
- if (action == null) throw new NullPointerException();
+ Objects.requireNonNull(action);
int i, end; final Object[] es;
synchronized (l.lock) {
es = getArrayChecked();
@@ -1341,7 +1341,7 @@
}
public void replaceAll(UnaryOperator<E> operator) {
- if (operator == null) throw new NullPointerException();
+ Objects.requireNonNull(operator);
synchronized (l.lock) {
checkForComodification();
l.replaceAll(operator, offset, offset + size);
--- a/jdk/src/java.base/share/classes/java/util/concurrent/DelayQueue.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/DelayQueue.java Thu Feb 09 23:15:52 2017 +0100
@@ -41,6 +41,7 @@
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
+import java.util.Objects;
import java.util.PriorityQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
@@ -59,11 +60,11 @@
* returns the count of both expired and unexpired elements.
* This queue does not permit null elements.
*
- * <p>This class and its iterator implement all of the
- * <em>optional</em> methods of the {@link Collection} and {@link
- * Iterator} interfaces. The Iterator provided in method {@link
- * #iterator()} is <em>not</em> guaranteed to traverse the elements of
- * the DelayQueue in any particular order.
+ * <p>This class and its iterator implement all of the <em>optional</em>
+ * methods of the {@link Collection} and {@link Iterator} interfaces.
+ * The Iterator provided in method {@link #iterator()} is <em>not</em>
+ * guaranteed to traverse the elements of the DelayQueue in any
+ * particular order.
*
* <p>This class is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
@@ -339,8 +340,7 @@
* @throws IllegalArgumentException {@inheritDoc}
*/
public int drainTo(Collection<? super E> c) {
- if (c == null)
- throw new NullPointerException();
+ Objects.requireNonNull(c);
if (c == this)
throw new IllegalArgumentException();
final ReentrantLock lock = this.lock;
@@ -365,8 +365,7 @@
* @throws IllegalArgumentException {@inheritDoc}
*/
public int drainTo(Collection<? super E> c, int maxElements) {
- if (c == null)
- throw new NullPointerException();
+ Objects.requireNonNull(c);
if (c == this)
throw new IllegalArgumentException();
if (maxElements <= 0)
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java Thu Feb 09 23:15:52 2017 +0100
@@ -40,6 +40,7 @@
import java.lang.invoke.VarHandle;
import java.security.AccessController;
import java.security.AccessControlContext;
+import java.security.Permission;
import java.security.Permissions;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
@@ -132,24 +133,30 @@
* </tr>
* </table>
*
- * <p>The common pool is by default constructed with default
- * parameters, but these may be controlled by setting the following
- * {@linkplain System#getProperty system properties}:
+ * <p>The parameters used to construct the common pool may be controlled by
+ * setting the following {@linkplain System#getProperty system properties}:
* <ul>
* <li>{@code java.util.concurrent.ForkJoinPool.common.parallelism}
* - the parallelism level, a non-negative integer
* <li>{@code java.util.concurrent.ForkJoinPool.common.threadFactory}
- * - the class name of a {@link ForkJoinWorkerThreadFactory}
+ * - the class name of a {@link ForkJoinWorkerThreadFactory}.
+ * The {@linkplain ClassLoader#getSystemClassLoader() system class loader}
+ * is used to load this class.
* <li>{@code java.util.concurrent.ForkJoinPool.common.exceptionHandler}
- * - the class name of a {@link UncaughtExceptionHandler}
+ * - the class name of a {@link UncaughtExceptionHandler}.
+ * The {@linkplain ClassLoader#getSystemClassLoader() system class loader}
+ * is used to load this class.
* <li>{@code java.util.concurrent.ForkJoinPool.common.maximumSpares}
* - the maximum number of allowed extra threads to maintain target
* parallelism (default 256).
* </ul>
- * If a {@link SecurityManager} is present and no factory is
- * specified, then the default pool uses a factory supplying
- * threads that have no {@link Permissions} enabled.
- * The system class loader is used to load these classes.
+ * If no thread factory is supplied via a system property, then the
+ * common pool uses a factory that uses the system class loader as the
+ * {@linkplain Thread#getContextClassLoader() thread context class loader}.
+ * In addition, if a {@link SecurityManager} is present, then
+ * the common pool uses a factory supplying threads that have no
+ * {@link Permissions} enabled.
+ *
* Upon any error in establishing these settings, default parameters
* are used. It is possible to disable or limit the use of threads in
* the common pool by setting the parallelism property to zero, and/or
@@ -638,20 +645,38 @@
*
* @param pool the pool this thread works in
* @return the new worker thread, or {@code null} if the request
- * to create a thread is rejected.
+ * to create a thread is rejected
* @throws NullPointerException if the pool is null
*/
public ForkJoinWorkerThread newThread(ForkJoinPool pool);
}
+ static AccessControlContext contextWithPermissions(Permission ... perms) {
+ Permissions permissions = new Permissions();
+ for (Permission perm : perms)
+ permissions.add(perm);
+ return new AccessControlContext(
+ new ProtectionDomain[] { new ProtectionDomain(null, permissions) });
+ }
+
/**
* Default ForkJoinWorkerThreadFactory implementation; creates a
- * new ForkJoinWorkerThread.
+ * new ForkJoinWorkerThread using the system class loader as the
+ * thread context class loader.
*/
private static final class DefaultForkJoinWorkerThreadFactory
implements ForkJoinWorkerThreadFactory {
+ private static final AccessControlContext ACC = contextWithPermissions(
+ new RuntimePermission("getClassLoader"),
+ new RuntimePermission("setContextClassLoader"));
+
public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
- return new ForkJoinWorkerThread(pool);
+ return AccessController.doPrivileged(
+ new PrivilegedAction<>() {
+ public ForkJoinWorkerThread run() {
+ return new ForkJoinWorkerThread(
+ pool, ClassLoader.getSystemClassLoader()); }},
+ ACC);
}
}
@@ -3244,26 +3269,20 @@
* An ACC to restrict permissions for the factory itself.
* The constructed workers have no permissions set.
*/
- private static final AccessControlContext INNOCUOUS_ACC;
- static {
- Permissions innocuousPerms = new Permissions();
- innocuousPerms.add(modifyThreadPermission);
- innocuousPerms.add(new RuntimePermission(
- "enableContextClassLoaderOverride"));
- innocuousPerms.add(new RuntimePermission(
- "modifyThreadGroup"));
- INNOCUOUS_ACC = new AccessControlContext(new ProtectionDomain[] {
- new ProtectionDomain(null, innocuousPerms)
- });
- }
+ private static final AccessControlContext ACC = contextWithPermissions(
+ modifyThreadPermission,
+ new RuntimePermission("enableContextClassLoaderOverride"),
+ new RuntimePermission("modifyThreadGroup"),
+ new RuntimePermission("getClassLoader"),
+ new RuntimePermission("setContextClassLoader"));
public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
- return AccessController.doPrivileged(new PrivilegedAction<>() {
- public ForkJoinWorkerThread run() {
- return new ForkJoinWorkerThread.
- InnocuousForkJoinWorkerThread(pool);
- }}, INNOCUOUS_ACC);
+ return AccessController.doPrivileged(
+ new PrivilegedAction<>() {
+ public ForkJoinWorkerThread run() {
+ return new ForkJoinWorkerThread.
+ InnocuousForkJoinWorkerThread(pool); }},
+ ACC);
}
}
-
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java Thu Feb 09 23:15:52 2017 +0100
@@ -36,6 +36,8 @@
package java.util.concurrent;
import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
/**
@@ -88,11 +90,26 @@
}
/**
+ * Version for use by the default pool. Supports setting the
+ * context class loader. This is a separate constructor to avoid
+ * affecting the protected constructor.
+ */
+ ForkJoinWorkerThread(ForkJoinPool pool, ClassLoader ccl) {
+ super("aForkJoinWorkerThread");
+ super.setContextClassLoader(ccl);
+ this.pool = pool;
+ this.workQueue = pool.registerWorker(this);
+ }
+
+ /**
* Version for InnocuousForkJoinWorkerThread.
*/
- ForkJoinWorkerThread(ForkJoinPool pool, ThreadGroup threadGroup,
+ ForkJoinWorkerThread(ForkJoinPool pool,
+ ClassLoader ccl,
+ ThreadGroup threadGroup,
AccessControlContext acc) {
super(threadGroup, null, "aForkJoinWorkerThread");
+ super.setContextClassLoader(ccl);
ThreadLocalRandom.setInheritedAccessControlContext(this, acc);
ThreadLocalRandom.eraseThreadLocals(this); // clear before registering
this.pool = pool;
@@ -179,20 +196,21 @@
/**
* A worker thread that has no permissions, is not a member of any
- * user-defined ThreadGroup, and erases all ThreadLocals after
+ * user-defined ThreadGroup, uses the system class loader as
+ * thread context class loader, and erases all ThreadLocals after
* running each top-level task.
*/
static final class InnocuousForkJoinWorkerThread extends ForkJoinWorkerThread {
/** The ThreadGroup for all InnocuousForkJoinWorkerThreads */
private static final ThreadGroup innocuousThreadGroup =
- java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction<>() {
- public ThreadGroup run() {
- ThreadGroup group = Thread.currentThread().getThreadGroup();
- for (ThreadGroup p; (p = group.getParent()) != null; )
- group = p;
- return new ThreadGroup(group, "InnocuousForkJoinWorkerThreadGroup");
- }});
+ java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction<>() {
+ public ThreadGroup run() {
+ ThreadGroup group = Thread.currentThread().getThreadGroup();
+ for (ThreadGroup p; (p = group.getParent()) != null; )
+ group = p;
+ return new ThreadGroup(group, "InnocuousForkJoinWorkerThreadGroup");
+ }});
/** An AccessControlContext supporting no privileges */
private static final AccessControlContext INNOCUOUS_ACC =
@@ -202,7 +220,10 @@
});
InnocuousForkJoinWorkerThread(ForkJoinPool pool) {
- super(pool, innocuousThreadGroup, INNOCUOUS_ACC);
+ super(pool,
+ ClassLoader.getSystemClassLoader(),
+ innocuousThreadGroup,
+ INNOCUOUS_ACC);
}
@Override // to erase ThreadLocals
@@ -210,11 +231,6 @@
ThreadLocalRandom.eraseThreadLocals(this);
}
- @Override // to always report system loader
- public ClassLoader getContextClassLoader() {
- return ClassLoader.getSystemClassLoader();
- }
-
@Override // to silently fail
public void setUncaughtExceptionHandler(UncaughtExceptionHandler x) { }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java Thu Feb 09 23:15:52 2017 +0100
@@ -45,6 +45,7 @@
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
+import java.util.function.Predicate;
/**
* An optionally-bounded {@linkplain BlockingDeque blocking deque} based on
@@ -63,9 +64,8 @@
* contains}, {@link #iterator iterator.remove()}, and the bulk
* operations, all of which run in linear time.
*
- * <p>This class and its iterator implement all of the
- * <em>optional</em> methods of the {@link Collection} and {@link
- * Iterator} interfaces.
+ * <p>This class and its iterator implement all of the <em>optional</em>
+ * methods of the {@link Collection} and {@link Iterator} interfaces.
*
* <p>This class is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
@@ -195,18 +195,7 @@
*/
public LinkedBlockingDeque(Collection<? extends E> c) {
this(Integer.MAX_VALUE);
- final ReentrantLock lock = this.lock;
- lock.lock(); // Never contended, but necessary for visibility
- try {
- for (E e : c) {
- if (e == null)
- throw new NullPointerException();
- if (!linkLast(new Node<E>(e)))
- throw new IllegalStateException("Deque full");
- }
- } finally {
- lock.unlock();
- }
+ addAll(c);
}
@@ -299,6 +288,7 @@
*/
void unlink(Node<E> x) {
// assert lock.isHeldByCurrentThread();
+ // assert x.item != null;
Node<E> p = x.prev;
Node<E> n = x.next;
if (p == null) {
@@ -834,46 +824,65 @@
}
}
- /*
- * TODO: Add support for more efficient bulk operations.
+ /**
+ * Appends all of the elements in the specified collection to the end of
+ * this deque, in the order that they are returned by the specified
+ * collection's iterator. Attempts to {@code addAll} of a deque to
+ * itself result in {@code IllegalArgumentException}.
*
- * We don't want to acquire the lock for every iteration, but we
- * also want other threads a chance to interact with the
- * collection, especially when count is close to capacity.
+ * @param c the elements to be inserted into this deque
+ * @return {@code true} if this deque changed as a result of the call
+ * @throws NullPointerException if the specified collection or any
+ * of its elements are null
+ * @throws IllegalArgumentException if the collection is this deque
+ * @throws IllegalStateException if this deque is full
+ * @see #add(Object)
*/
+ public boolean addAll(Collection<? extends E> c) {
+ if (c == this)
+ // As historically specified in AbstractQueue#addAll
+ throw new IllegalArgumentException();
-// /**
-// * Adds all of the elements in the specified collection to this
-// * queue. Attempts to addAll of a queue to itself result in
-// * {@code IllegalArgumentException}. Further, the behavior of
-// * this operation is undefined if the specified collection is
-// * modified while the operation is in progress.
-// *
-// * @param c collection containing elements to be added to this queue
-// * @return {@code true} if this queue changed as a result of the call
-// * @throws ClassCastException {@inheritDoc}
-// * @throws NullPointerException {@inheritDoc}
-// * @throws IllegalArgumentException {@inheritDoc}
-// * @throws IllegalStateException if this deque is full
-// * @see #add(Object)
-// */
-// public boolean addAll(Collection<? extends E> c) {
-// if (c == null)
-// throw new NullPointerException();
-// if (c == this)
-// throw new IllegalArgumentException();
-// final ReentrantLock lock = this.lock;
-// lock.lock();
-// try {
-// boolean modified = false;
-// for (E e : c)
-// if (linkLast(e))
-// modified = true;
-// return modified;
-// } finally {
-// lock.unlock();
-// }
-// }
+ // Copy c into a private chain of Nodes
+ Node<E> beg = null, end = null;
+ int n = 0;
+ for (E e : c) {
+ Objects.requireNonNull(e);
+ n++;
+ Node<E> newNode = new Node<E>(e);
+ if (beg == null)
+ beg = end = newNode;
+ else {
+ end.next = newNode;
+ newNode.prev = end;
+ end = newNode;
+ }
+ }
+ if (beg == null)
+ return false;
+
+ // Atomically append the chain at the end
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ if (count + n <= capacity) {
+ beg.prev = last;
+ if (first == null)
+ first = beg;
+ else
+ last.next = beg;
+ last = end;
+ count += n;
+ notEmpty.signalAll();
+ return true;
+ }
+ } finally {
+ lock.unlock();
+ }
+ // Fall back to historic non-atomic implementation, failing
+ // with IllegalStateException when the capacity is exceeded.
+ return super.addAll(c);
+ }
/**
* Returns an array containing all of the elements in this deque, in
@@ -992,7 +1001,9 @@
* - (possibly multiple) interior removed nodes (p.item == null)
*/
Node<E> succ(Node<E> p) {
- return (p == (p = p.next)) ? first : p;
+ if (p == (p = p.next))
+ p = first;
+ return p;
}
/**
@@ -1049,7 +1060,9 @@
abstract Node<E> nextNode(Node<E> n);
private Node<E> succ(Node<E> p) {
- return (p == (p = nextNode(p))) ? firstNode() : p;
+ if (p == (p = nextNode(p)))
+ p = firstNode();
+ return p;
}
AbstractItr() {
@@ -1096,7 +1109,7 @@
lastRet = p;
next = null;
final ReentrantLock lock = LinkedBlockingDeque.this.lock;
- final int batchSize = 32;
+ final int batchSize = 64;
Object[] es = null;
int n, len = 1;
do {
@@ -1175,11 +1188,10 @@
public Spliterator<E> trySplit() {
Node<E> h;
- int b = batch;
- int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
if (!exhausted &&
((h = current) != null || (h = first) != null)
&& h.next != null) {
+ int n = batch = Math.min(batch + 1, MAX_BATCH);
Object[] a = new Object[n];
final ReentrantLock lock = LinkedBlockingDeque.this.lock;
int i = 0;
@@ -1199,13 +1211,11 @@
}
else if ((est -= i) < 0L)
est = 0L;
- if (i > 0) {
- batch = i;
+ if (i > 0)
return Spliterators.spliterator
(a, 0, i, (Spliterator.ORDERED |
Spliterator.NONNULL |
Spliterator.CONCURRENT));
- }
}
return null;
}
@@ -1223,7 +1233,8 @@
e = p.item;
p = succ(p);
} while (e == null && p != null);
- exhausted = ((current = p) == null);
+ if ((current = p) == null)
+ exhausted = true;
} finally {
lock.unlock();
}
@@ -1288,7 +1299,7 @@
// Extract batches of elements while holding the lock; then
// run the action on the elements while not
final ReentrantLock lock = this.lock;
- final int batchSize = 32; // max number of elements per batch
+ final int batchSize = 64; // max number of elements per batch
Object[] es = null; // container for batch of elements
int n, len = 0;
do {
@@ -1315,6 +1326,83 @@
}
/**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean removeIf(Predicate<? super E> filter) {
+ Objects.requireNonNull(filter);
+ return bulkRemove(filter);
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean removeAll(Collection<?> c) {
+ Objects.requireNonNull(c);
+ return bulkRemove(e -> c.contains(e));
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean retainAll(Collection<?> c) {
+ Objects.requireNonNull(c);
+ return bulkRemove(e -> !c.contains(e));
+ }
+
+ /** Implementation of bulk remove methods. */
+ @SuppressWarnings("unchecked")
+ private boolean bulkRemove(Predicate<? super E> filter) {
+ boolean removed = false;
+ Node<E> p = null;
+ final ReentrantLock lock = this.lock;
+ Node<E>[] nodes = null;
+ int n, len = 0;
+ do {
+ // 1. Extract batch of up to 64 elements while holding the lock.
+ long deathRow = 0; // "bitset" of size 64
+ lock.lock();
+ try {
+ if (nodes == null) {
+ if (p == null) p = first;
+ for (Node<E> q = p; q != null; q = succ(q))
+ if (q.item != null && ++len == 64)
+ break;
+ nodes = (Node<E>[]) new Node<?>[len];
+ }
+ for (n = 0; p != null && n < len; p = succ(p))
+ nodes[n++] = p;
+ } finally {
+ lock.unlock();
+ }
+
+ // 2. Run the filter on the elements while lock is free.
+ for (int i = 0; i < n; i++) {
+ final E e;
+ if ((e = nodes[i].item) != null && filter.test(e))
+ deathRow |= 1L << i;
+ }
+
+ // 3. Remove any filtered elements while holding the lock.
+ if (deathRow != 0) {
+ lock.lock();
+ try {
+ for (int i = 0; i < n; i++) {
+ final Node<E> q;
+ if ((deathRow & (1L << i)) != 0L
+ && (q = nodes[i]).item != null) {
+ unlink(q);
+ removed = true;
+ }
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+ } while (n > 0 && p != null);
+ return removed;
+ }
+
+ /**
* Saves this deque to a stream (that is, serializes it).
*
* @param s the stream
--- a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java Thu Feb 09 23:15:52 2017 +0100
@@ -46,6 +46,7 @@
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
+import java.util.function.Predicate;
/**
* An optionally-bounded {@linkplain BlockingQueue blocking queue} based on
@@ -66,9 +67,8 @@
* dynamically created upon each insertion unless this would bring the
* queue above capacity.
*
- * <p>This class and its iterator implement all of the
- * <em>optional</em> methods of the {@link Collection} and {@link
- * Iterator} interfaces.
+ * <p>This class and its iterator implement all of the <em>optional</em>
+ * methods of the {@link Collection} and {@link Iterator} interfaces.
*
* <p>This class is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
@@ -507,17 +507,17 @@
}
/**
- * Unlinks interior Node p with predecessor trail.
+ * Unlinks interior Node p with predecessor pred.
*/
- void unlink(Node<E> p, Node<E> trail) {
+ void unlink(Node<E> p, Node<E> pred) {
// assert putLock.isHeldByCurrentThread();
// assert takeLock.isHeldByCurrentThread();
// p.next is not changed, to allow iterators that are
// traversing p to maintain their weak-consistency guarantee.
p.item = null;
- trail.next = p.next;
+ pred.next = p.next;
if (last == p)
- last = trail;
+ last = pred;
if (count.getAndDecrement() == capacity)
notFull.signal();
}
@@ -537,11 +537,11 @@
if (o == null) return false;
fullyLock();
try {
- for (Node<E> trail = head, p = trail.next;
+ for (Node<E> pred = head, p = pred.next;
p != null;
- trail = p, p = p.next) {
+ pred = p, p = p.next) {
if (o.equals(p.item)) {
- unlink(p, trail);
+ unlink(p, pred);
return true;
}
}
@@ -740,7 +740,9 @@
* - (possibly multiple) interior removed nodes (p.item == null)
*/
Node<E> succ(Node<E> p) {
- return (p == (p = p.next)) ? head.next : p;
+ if (p == (p = p.next))
+ p = head.next;
+ return p;
}
/**
@@ -756,16 +758,18 @@
return new Itr();
}
+ /**
+ * Weakly-consistent iterator.
+ *
+ * Lazily updated ancestor field provides expected O(1) remove(),
+ * but still O(n) in the worst case, whenever the saved ancestor
+ * is concurrently deleted.
+ */
private class Itr implements Iterator<E> {
- /*
- * Basic weakly-consistent iterator. At all times hold the next
- * item to hand out so that if hasNext() reports true, we will
- * still have it to return even if lost race with a take etc.
- */
-
- private Node<E> next;
- private E nextItem;
+ private Node<E> next; // Node holding nextItem
+ private E nextItem; // next item to hand out
private Node<E> lastRet;
+ private Node<E> ancestor; // Helps unlink lastRet on remove()
Itr() {
fullyLock();
@@ -807,7 +811,7 @@
if ((p = next) == null) return;
lastRet = p;
next = null;
- final int batchSize = 32;
+ final int batchSize = 64;
Object[] es = null;
int n, len = 1;
do {
@@ -840,19 +844,17 @@
}
public void remove() {
- if (lastRet == null)
+ Node<E> p = lastRet;
+ if (p == null)
throw new IllegalStateException();
+ lastRet = null;
fullyLock();
try {
- Node<E> node = lastRet;
- lastRet = null;
- for (Node<E> trail = head, p = trail.next;
- p != null;
- trail = p, p = p.next) {
- if (p == node) {
- unlink(p, trail);
- break;
- }
+ if (p.item != null) {
+ if (ancestor == null)
+ ancestor = head;
+ ancestor = findPred(p, ancestor);
+ unlink(p, ancestor);
}
} finally {
fullyUnlock();
@@ -877,11 +879,10 @@
public Spliterator<E> trySplit() {
Node<E> h;
- int b = batch;
- int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
if (!exhausted &&
((h = current) != null || (h = head.next) != null)
&& h.next != null) {
+ int n = batch = Math.min(batch + 1, MAX_BATCH);
Object[] a = new Object[n];
int i = 0;
Node<E> p = current;
@@ -900,13 +901,11 @@
}
else if ((est -= i) < 0L)
est = 0L;
- if (i > 0) {
- batch = i;
+ if (i > 0)
return Spliterators.spliterator
(a, 0, i, (Spliterator.ORDERED |
Spliterator.NONNULL |
Spliterator.CONCURRENT));
- }
}
return null;
}
@@ -923,7 +922,8 @@
e = p.item;
p = succ(p);
} while (e == null && p != null);
- exhausted = ((current = p) == null);
+ if ((current = p) == null)
+ exhausted = true;
} finally {
fullyUnlock();
}
@@ -987,7 +987,7 @@
void forEachFrom(Consumer<? super E> action, Node<E> p) {
// Extract batches of elements while holding the lock; then
// run the action on the elements while not
- final int batchSize = 32; // max number of elements per batch
+ final int batchSize = 64; // max number of elements per batch
Object[] es = null; // container for batch of elements
int n, len = 0;
do {
@@ -1014,6 +1014,97 @@
}
/**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean removeIf(Predicate<? super E> filter) {
+ Objects.requireNonNull(filter);
+ return bulkRemove(filter);
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean removeAll(Collection<?> c) {
+ Objects.requireNonNull(c);
+ return bulkRemove(e -> c.contains(e));
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean retainAll(Collection<?> c) {
+ Objects.requireNonNull(c);
+ return bulkRemove(e -> !c.contains(e));
+ }
+
+ /**
+ * Returns the predecessor of live node p, given a node that was
+ * once a live ancestor of p (or head); allows unlinking of p.
+ */
+ Node<E> findPred(Node<E> p, Node<E> ancestor) {
+ // assert p.item != null;
+ if (ancestor.item == null)
+ ancestor = head;
+ // Fails with NPE if precondition not satisfied
+ for (Node<E> q; (q = ancestor.next) != p; )
+ ancestor = q;
+ return ancestor;
+ }
+
+ /** Implementation of bulk remove methods. */
+ @SuppressWarnings("unchecked")
+ private boolean bulkRemove(Predicate<? super E> filter) {
+ boolean removed = false;
+ Node<E> p = null, ancestor = head;
+ Node<E>[] nodes = null;
+ int n, len = 0;
+ do {
+ // 1. Extract batch of up to 64 elements while holding the lock.
+ long deathRow = 0; // "bitset" of size 64
+ fullyLock();
+ try {
+ if (nodes == null) {
+ if (p == null) p = head.next;
+ for (Node<E> q = p; q != null; q = succ(q))
+ if (q.item != null && ++len == 64)
+ break;
+ nodes = (Node<E>[]) new Node<?>[len];
+ }
+ for (n = 0; p != null && n < len; p = succ(p))
+ nodes[n++] = p;
+ } finally {
+ fullyUnlock();
+ }
+
+ // 2. Run the filter on the elements while lock is free.
+ for (int i = 0; i < n; i++) {
+ final E e;
+ if ((e = nodes[i].item) != null && filter.test(e))
+ deathRow |= 1L << i;
+ }
+
+ // 3. Remove any filtered elements while holding the lock.
+ if (deathRow != 0) {
+ fullyLock();
+ try {
+ for (int i = 0; i < n; i++) {
+ final Node<E> q;
+ if ((deathRow & (1L << i)) != 0L
+ && (q = nodes[i]).item != null) {
+ ancestor = findPred(q, ancestor);
+ unlink(q, ancestor);
+ removed = true;
+ }
+ }
+ } finally {
+ fullyUnlock();
+ }
+ }
+ } while (n > 0 && p != null);
+ return removed;
+ }
+
+ /**
* Saves this queue to a stream (that is, serializes it).
*
* @param s the stream
--- a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java Thu Feb 09 23:15:52 2017 +0100
@@ -42,11 +42,13 @@
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
+import java.util.Objects;
import java.util.Queue;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.concurrent.locks.LockSupport;
import java.util.function.Consumer;
+import java.util.function.Predicate;
/**
* An unbounded {@link TransferQueue} based on linked nodes.
@@ -61,16 +63,15 @@
* asynchronous nature of these queues, determining the current number
* of elements requires a traversal of the elements, and so may report
* inaccurate results if this collection is modified during traversal.
- * Additionally, the bulk operations {@code addAll},
- * {@code removeAll}, {@code retainAll}, {@code containsAll},
- * and {@code toArray} are <em>not</em> guaranteed
- * to be performed atomically. For example, an iterator operating
- * concurrently with an {@code addAll} operation might view only some
- * of the added elements.
*
- * <p>This class and its iterator implement all of the
- * <em>optional</em> methods of the {@link Collection} and {@link
- * Iterator} interfaces.
+ * <p>Bulk operations that add, remove, or examine multiple elements,
+ * such as {@link #addAll}, {@link #removeIf} or {@link #forEach},
+ * are <em>not</em> guaranteed to be performed atomically.
+ * For example, a {@code forEach} traversal concurrent with an {@code
+ * addAll} operation might observe only some of the added elements.
+ *
+ * <p>This class and its iterator implement all of the <em>optional</em>
+ * methods of the {@link Collection} and {@link Iterator} interfaces.
*
* <p>Memory consistency effects: As with other concurrent
* collections, actions in a thread prior to placing an object into a
@@ -158,9 +159,8 @@
* correctly perform enqueue and dequeue operations by traversing
* from a pointer to the initial node; CASing the item of the
* first unmatched node on match and CASing the next field of the
- * trailing node on appends. (Plus some special-casing when
- * initially empty). While this would be a terrible idea in
- * itself, it does have the benefit of not requiring ANY atomic
+ * trailing node on appends. While this would be a terrible idea
+ * in itself, it does have the benefit of not requiring ANY atomic
* updates on head/tail fields.
*
* We introduce here an approach that lies between the extremes of
@@ -196,15 +196,15 @@
* with a given probability per traversal step.
*
* In any strategy along these lines, because CASes updating
- * fields may fail, the actual slack may exceed targeted
- * slack. However, they may be retried at any time to maintain
- * targets. Even when using very small slack values, this
- * approach works well for dual queues because it allows all
- * operations up to the point of matching or appending an item
- * (hence potentially allowing progress by another thread) to be
- * read-only, thus not introducing any further contention. As
- * described below, we implement this by performing slack
- * maintenance retries only after these points.
+ * fields may fail, the actual slack may exceed targeted slack.
+ * However, they may be retried at any time to maintain targets.
+ * Even when using very small slack values, this approach works
+ * well for dual queues because it allows all operations up to the
+ * point of matching or appending an item (hence potentially
+ * allowing progress by another thread) to be read-only, thus not
+ * introducing any further contention. As described below, we
+ * implement this by performing slack maintenance retries only
+ * after these points.
*
* As an accompaniment to such techniques, traversal overhead can
* be further reduced without increasing contention of head
@@ -223,7 +223,7 @@
* (Similar issues arise in non-GC environments.) To cope with
* this in our implementation, upon CASing to advance the head
* pointer, we set the "next" link of the previous head to point
- * only to itself; thus limiting the length of connected dead lists.
+ * only to itself; thus limiting the length of chains of dead nodes.
* (We also take similar care to wipe out possibly garbage
* retaining values held in other Node fields.) However, doing so
* adds some further complexity to traversal: If any "next"
@@ -266,15 +266,6 @@
* interior nodes) except in the case of cancellation/removal (see
* below).
*
- * We allow both the head and tail fields to be null before any
- * nodes are enqueued; initializing upon first append. This
- * simplifies some other logic, as well as providing more
- * efficient explicit control paths instead of letting JVMs insert
- * implicit NullPointerExceptions when they are null. While not
- * currently fully implemented, we also leave open the possibility
- * of re-nulling these fields when empty (which is complicated to
- * arrange, for little benefit.)
- *
* All enqueue/dequeue operations are handled by the single method
* "xfer" with parameters indicating whether to act as some form
* of offer, put, poll, take, or transfer (each possibly with
@@ -282,44 +273,40 @@
* method outweighs the code bulk and maintenance problems of
* using separate methods for each case.
*
- * Operation consists of up to three phases. The first is
- * implemented within method xfer, the second in tryAppend, and
- * the third in method awaitMatch.
+ * Operation consists of up to two phases. The first is implemented
+ * in method xfer, the second in method awaitMatch.
*
- * 1. Try to match an existing node
+ * 1. Traverse until matching or appending (method xfer)
*
- * Starting at head, skip already-matched nodes until finding
- * an unmatched node of opposite mode, if one exists, in which
- * case matching it and returning, also if necessary updating
- * head to one past the matched node (or the node itself if the
- * list has no other unmatched nodes). If the CAS misses, then
- * a loop retries advancing head by two steps until either
- * success or the slack is at most two. By requiring that each
- * attempt advances head by two (if applicable), we ensure that
- * the slack does not grow without bound. Traversals also check
- * if the initial head is now off-list, in which case they
- * start at the new head.
+ * Conceptually, we simply traverse all nodes starting from head.
+ * If we encounter an unmatched node of opposite mode, we match
+ * it and return, also updating head (by at least 2 hops) to
+ * one past the matched node (or the node itself if it's the
+ * pinned trailing node). Traversals also check for the
+ * possibility of falling off-list, in which case they restart.
*
- * If no candidates are found and the call was untimed
- * poll/offer, (argument "how" is NOW) return.
- *
- * 2. Try to append a new node (method tryAppend)
+ * If the trailing node of the list is reached, a match is not
+ * possible. If this call was untimed poll or tryTransfer
+ * (argument "how" is NOW), return empty-handed immediately.
+ * Else a new node is CAS-appended. On successful append, if
+ * this call was ASYNC (e.g. offer), an element was
+ * successfully added to the end of the queue and we return.
*
- * Starting at current tail pointer, find the actual last node
- * and try to append a new node (or if head was null, establish
- * the first node). Nodes can be appended only if their
- * predecessors are either already matched or are of the same
- * mode. If we detect otherwise, then a new node with opposite
- * mode must have been appended during traversal, so we must
- * restart at phase 1. The traversal and update steps are
- * otherwise similar to phase 1: Retrying upon CAS misses and
- * checking for staleness. In particular, if a self-link is
- * encountered, then we can safely jump to a node on the list
- * by continuing the traversal at current head.
+ * Of course, this naive traversal is O(n) when no match is
+ * possible. We optimize the traversal by maintaining a tail
+ * pointer, which is expected to be "near" the end of the list.
+ * It is only safe to fast-forward to tail (in the presence of
+ * arbitrary concurrent changes) if it is pointing to a node of
+ * the same mode, even if it is dead (in this case no preceding
+ * node could still be matchable by this traversal). If we
+ * need to restart due to falling off-list, we can again
+ * fast-forward to tail, but only if it has changed since the
+ * last traversal (else we might loop forever). If tail cannot
+ * be used, traversal starts at head (but in this case we
+ * expect to be able to match near head). As with head, we
+ * CAS-advance the tail pointer by at least two hops.
*
- * On successful append, if the call was ASYNC, return.
- *
- * 3. Await match or cancellation (method awaitMatch)
+ * 2. Await match or cancellation (method awaitMatch)
*
* Wait for another thread to match node; instead cancelling if
* the current thread was interrupted or the wait timed out. On
@@ -373,12 +360,12 @@
* from, the head of list.
*
* Without taking these into account, it would be possible for an
- * unbounded number of supposedly removed nodes to remain
- * reachable. Situations leading to such buildup are uncommon but
- * can occur in practice; for example when a series of short timed
- * calls to poll repeatedly time out but never otherwise fall off
- * the list because of an untimed call to take at the front of the
- * queue.
+ * unbounded number of supposedly removed nodes to remain reachable.
+ * Situations leading to such buildup are uncommon but can occur
+ * in practice; for example when a series of short timed calls to
+ * poll repeatedly time out at the trailing node but otherwise
+ * never fall off the list because of an untimed call to take() at
+ * the front of the queue.
*
* When these cases arise, rather than always retraversing the
* entire list to find an actual predecessor to unlink (which
@@ -391,10 +378,9 @@
* We perform sweeps by the thread hitting threshold (rather than
* background threads or by spreading work to other threads)
* because in the main contexts in which removal occurs, the
- * caller is already timed-out, cancelled, or performing a
- * potentially O(n) operation (e.g. remove(x)), none of which are
- * time-critical enough to warrant the overhead that alternatives
- * would impose on other threads.
+ * caller is timed-out or cancelled, which are not time-critical
+ * enough to warrant the overhead that alternatives would impose
+ * on other threads.
*
* Because the sweepVotes estimate is conservative, and because
* nodes become unlinked "naturally" as they fall off the head of
@@ -406,6 +392,13 @@
* quiescent queues. The value defined below was chosen
* empirically to balance these under various timeout scenarios.
*
+ * Because traversal operations on the linked list of nodes are a
+ * natural opportunity to sweep dead nodes, we generally do so,
+ * including all the operations that might remove elements as they
+ * traverse, such as removeIf and Iterator.remove. This largely
+ * eliminates long chains of dead interior nodes, except from
+ * cancelled or timed out blocking operations.
+ *
* Note that we cannot self-link unlinked interior nodes during
* sweeps. However, the associated garbage chains terminate when
* some successor ultimately falls off the head of the list and is
@@ -446,54 +439,71 @@
/**
* Queue nodes. Uses Object, not E, for items to allow forgetting
- * them after use. Relies heavily on VarHandles to minimize
- * unnecessary ordering constraints: Writes that are intrinsically
- * ordered wrt other accesses or CASes use simple relaxed forms.
+ * them after use. Writes that are intrinsically ordered wrt
+ * other accesses or CASes use simple relaxed forms.
*/
static final class Node {
final boolean isData; // false if this is a request node
volatile Object item; // initially non-null if isData; CASed to match
volatile Node next;
- volatile Thread waiter; // null until waiting
+ volatile Thread waiter; // null when not waiting for a match
- // CAS methods for fields
+ /**
+ * Constructs a data node holding item if item is non-null,
+ * else a request node. Uses relaxed write because item can
+ * only be seen after piggy-backing publication via CAS.
+ */
+ Node(Object item) {
+ ITEM.set(this, item);
+ isData = (item != null);
+ }
+
+ /** Constructs a (matched data) dummy node. */
+ Node() {
+ isData = true;
+ }
+
final boolean casNext(Node cmp, Node val) {
+ // assert val != null;
return NEXT.compareAndSet(this, cmp, val);
}
final boolean casItem(Object cmp, Object val) {
- // assert cmp == null || cmp.getClass() != Node.class;
+ // assert isData == (cmp != null);
+ // assert isData == (val == null);
+ // assert !(cmp instanceof Node);
return ITEM.compareAndSet(this, cmp, val);
}
/**
- * Constructs a new node. Uses relaxed write because item can
- * only be seen after publication via casNext.
- */
- Node(Object item, boolean isData) {
- ITEM.set(this, item); // relaxed write
- this.isData = isData;
- }
-
- /**
* Links node to itself to avoid garbage retention. Called
* only after CASing head field, so uses relaxed write.
*/
- final void forgetNext() {
- NEXT.set(this, this);
+ final void selfLink() {
+ // assert isMatched();
+ NEXT.setRelease(this, this);
+ }
+
+ final void appendRelaxed(Node next) {
+ // assert next != null;
+ // assert this.next == null;
+ NEXT.set(this, next);
}
/**
- * Sets item to self and waiter to null, to avoid garbage
- * retention after matching or cancelling. Uses relaxed writes
- * because order is already constrained in the only calling
- * contexts: item is forgotten only after volatile/atomic
- * mechanics that extract items. Similarly, clearing waiter
- * follows either CAS or return from park (if ever parked;
- * else we don't care).
+ * Sets item (of a request node) to self and waiter to null,
+ * to avoid garbage retention after matching or cancelling.
+ * Uses relaxed writes because order is already constrained in
+ * the only calling contexts: item is forgotten only after
+ * volatile/atomic mechanics that extract items, and visitors
+ * of request nodes only ever check whether item is null.
+ * Similarly, clearing waiter follows either CAS or return
+ * from park (if ever parked; else we don't care).
*/
final void forgetContents() {
- ITEM.set(this, this);
+ // assert isMatched();
+ if (!isData)
+ ITEM.set(this, this);
WAITER.set(this, null);
}
@@ -502,15 +512,16 @@
* case of artificial matches due to cancellation.
*/
final boolean isMatched() {
- Object x = item;
- return (x == this) || ((x == null) == isData);
+ return isData == (item == null);
}
- /**
- * Returns true if this is an unmatched request node.
- */
- final boolean isUnmatchedRequest() {
- return !isData && item == null;
+ /** Tries to CAS-match this node; if successful, wakes waiter. */
+ final boolean tryMatch(Object cmp, Object val) {
+ if (casItem(cmp, val)) {
+ LockSupport.unpark(waiter);
+ return true;
+ }
+ return false;
}
/**
@@ -520,52 +531,46 @@
*/
final boolean cannotPrecede(boolean haveData) {
boolean d = isData;
- Object x;
- return d != haveData && (x = item) != this && (x != null) == d;
- }
-
- /**
- * Tries to artificially match a data node -- used by remove.
- */
- final boolean tryMatchData() {
- // assert isData;
- Object x = item;
- if (x != null && x != this && casItem(x, null)) {
- LockSupport.unpark(waiter);
- return true;
- }
- return false;
+ return d != haveData && d != (item == null);
}
private static final long serialVersionUID = -3375979862319811754L;
-
- // VarHandle mechanics
- private static final VarHandle ITEM;
- private static final VarHandle NEXT;
- private static final VarHandle WAITER;
- static {
- try {
- MethodHandles.Lookup l = MethodHandles.lookup();
- ITEM = l.findVarHandle(Node.class, "item", Object.class);
- NEXT = l.findVarHandle(Node.class, "next", Node.class);
- WAITER = l.findVarHandle(Node.class, "waiter", Thread.class);
- } catch (ReflectiveOperationException e) {
- throw new Error(e);
- }
- }
}
- /** head of the queue; null until first enqueue */
+ /**
+ * A node from which the first live (non-matched) node (if any)
+ * can be reached in O(1) time.
+ * Invariants:
+ * - all live nodes are reachable from head via .next
+ * - head != null
+ * - (tmp = head).next != tmp || tmp != head
+ * Non-invariants:
+ * - head may or may not be live
+ * - it is permitted for tail to lag behind head, that is, for tail
+ * to not be reachable from head!
+ */
transient volatile Node head;
- /** tail of the queue; null until first append */
+ /**
+ * A node from which the last node on list (that is, the unique
+ * node with node.next == null) can be reached in O(1) time.
+ * Invariants:
+ * - the last node is always reachable from tail via .next
+ * - tail != null
+ * Non-invariants:
+ * - tail may or may not be live
+ * - it is permitted for tail to lag behind head, that is, for tail
+ * to not be reachable from head!
+ * - tail.next may or may not be self-linked.
+ */
private transient volatile Node tail;
- /** The number of apparent failures to unsplice removed nodes */
+ /** The number of apparent failures to unsplice cancelled nodes */
private transient volatile int sweepVotes;
- // CAS methods for fields
private boolean casTail(Node cmp, Node val) {
+ // assert cmp != null;
+ // assert val != null;
return TAIL.compareAndSet(this, cmp, val);
}
@@ -573,13 +578,71 @@
return HEAD.compareAndSet(this, cmp, val);
}
- private boolean casSweepVotes(int cmp, int val) {
- return SWEEPVOTES.compareAndSet(this, cmp, val);
+ /** Atomic version of ++sweepVotes. */
+ private int incSweepVotes() {
+ return (int) SWEEPVOTES.getAndAdd(this, 1) + 1;
+ }
+
+ /**
+ * Tries to CAS pred.next (or head, if pred is null) from c to p.
+ * Caller must ensure that we're not unlinking the trailing node.
+ */
+ private boolean tryCasSuccessor(Node pred, Node c, Node p) {
+ // assert p != null;
+ // assert c.isData != (c.item != null);
+ // assert c != p;
+ if (pred != null)
+ return pred.casNext(c, p);
+ if (casHead(c, p)) {
+ c.selfLink();
+ return true;
+ }
+ return false;
}
- /*
- * Possible values for "how" argument in xfer method.
+ /**
+ * Collapses dead (matched) nodes between pred and q.
+ * @param pred the last known live node, or null if none
+ * @param c the first dead node
+ * @param p the last dead node
+ * @param q p.next: the next live node, or null if at end
+ * @return pred if pred still alive and CAS succeeded; else p
*/
+ private Node skipDeadNodes(Node pred, Node c, Node p, Node q) {
+ // assert pred != c;
+ // assert p != q;
+ // assert c.isMatched();
+ // assert p.isMatched();
+ if (q == null) {
+ // Never unlink trailing node.
+ if (c == p) return pred;
+ q = p;
+ }
+ return (tryCasSuccessor(pred, c, q)
+ && (pred == null || !pred.isMatched()))
+ ? pred : p;
+ }
+
+ /**
+ * Collapses dead (matched) nodes from h (which was once head) to p.
+ * Caller ensures all nodes from h up to and including p are dead.
+ */
+ private void skipDeadNodesNearHead(Node h, Node p) {
+ // assert h != null;
+ // assert h != p;
+ // assert p.isMatched();
+ for (;;) {
+ final Node q;
+ if ((q = p.next) == null) break;
+ else if (!q.isMatched()) { p = q; break; }
+ else if (p == (p = q)) return;
+ }
+ if (casHead(h, p))
+ h.selfLink();
+ }
+
+ /* Possible values for "how" argument in xfer method. */
+
private static final int NOW = 0; // for untimed poll, tryTransfer
private static final int ASYNC = 1; // for offer, put, add
private static final int SYNC = 2; // for transfer, take
@@ -595,84 +658,32 @@
* @return an item if matched, else e
* @throws NullPointerException if haveData mode but e is null
*/
+ @SuppressWarnings("unchecked")
private E xfer(E e, boolean haveData, int how, long nanos) {
if (haveData && (e == null))
throw new NullPointerException();
- Node s = null; // the node to append, if needed
- retry:
- for (;;) { // restart on append race
-
- for (Node h = head, p = h; p != null;) { // find & match first node
- boolean isData = p.isData;
- Object item = p.item;
- if (item != p && (item != null) == isData) { // unmatched
- if (isData == haveData) // can't match
- break;
- if (p.casItem(item, e)) { // match
- for (Node q = p; q != h;) {
- Node n = q.next; // update by 2 unless singleton
- if (head == h && casHead(h, n == null ? q : n)) {
- h.forgetNext();
- break;
- } // advance and retry
- if ((h = head) == null ||
- (q = h.next) == null || !q.isMatched())
- break; // unless slack < 2
- }
- LockSupport.unpark(p.waiter);
- @SuppressWarnings("unchecked") E itemE = (E) item;
- return itemE;
+ restart: for (Node s = null, t = null, h = null;;) {
+ for (Node p = (t != (t = tail) && t.isData == haveData) ? t
+ : (h = head);; ) {
+ final Node q; final Object item;
+ if (p.isData != haveData
+ && haveData == ((item = p.item) == null)) {
+ if (h == null) h = head;
+ if (p.tryMatch(item, e)) {
+ if (h != p) skipDeadNodesNearHead(h, p);
+ return (E) item;
}
}
- Node n = p.next;
- p = (p != n) ? n : (h = head); // Use head if p offlist
- }
-
- if (how != NOW) { // No matches available
- if (s == null)
- s = new Node(e, haveData);
- Node pred = tryAppend(s, haveData);
- if (pred == null)
- continue retry; // lost race vs opposite mode
- if (how != ASYNC)
- return awaitMatch(s, pred, e, (how == TIMED), nanos);
- }
- return e; // not waiting
- }
- }
-
- /**
- * Tries to append node s as tail.
- *
- * @param s the node to append
- * @param haveData true if appending in data mode
- * @return null on failure due to losing race with append in
- * different mode, else s's predecessor, or s itself if no
- * predecessor
- */
- private Node tryAppend(Node s, boolean haveData) {
- for (Node t = tail, p = t;;) { // move p to last node and append
- Node n, u; // temps for reads of next & tail
- if (p == null && (p = head) == null) {
- if (casHead(null, s))
- return s; // initialize
- }
- else if (p.cannotPrecede(haveData))
- return null; // lost race vs opposite mode
- else if ((n = p.next) != null) // not last; keep traversing
- p = p != t && t != (u = tail) ? (t = u) : // stale tail
- (p != n) ? n : null; // restart if off list
- else if (!p.casNext(null, s))
- p = p.next; // re-read on CAS failure
- else {
- if (p != t) { // update if slack now >= 2
- while ((tail != t || !casTail(t, s)) &&
- (t = tail) != null &&
- (s = t.next) != null && // advance and retry
- (s = s.next) != null && s != t);
+ if ((q = p.next) == null) {
+ if (how == NOW) return e;
+ if (s == null) s = new Node(e);
+ if (!p.casNext(null, s)) continue;
+ if (p != t) casTail(t, s);
+ if (how == ASYNC) return e;
+ return awaitMatch(s, p, e, (how == TIMED), nanos);
}
- return p;
+ if (p == (p = q)) continue restart;
}
}
}
@@ -681,9 +692,9 @@
* Spins/yields/blocks until node s is matched or caller gives up.
*
* @param s the waiting node
- * @param pred the predecessor of s, or s itself if it has no
- * predecessor, or null if unknown (the null case does not occur
- * in any current calls but may in possible future extensions)
+ * @param pred the predecessor of s, or null if unknown (the null
+ * case does not occur in any current calls but may in possible
+ * future extensions)
* @param e the comparison value for checking match
* @param timed if true, wait only until timeout elapses
* @param nanos timeout in nanosecs, used only if timed is true
@@ -696,17 +707,20 @@
ThreadLocalRandom randomYields = null; // bound if needed
for (;;) {
- Object item = s.item;
- if (item != e) { // matched
+ final Object item;
+ if ((item = s.item) != e) { // matched
// assert item != s;
s.forgetContents(); // avoid garbage
@SuppressWarnings("unchecked") E itemE = (E) item;
return itemE;
}
else if (w.isInterrupted() || (timed && nanos <= 0L)) {
- unsplice(pred, s); // try to unlink and cancel
- if (s.casItem(e, s)) // return normally if lost CAS
+ // try to cancel and unlink
+ if (s.casItem(e, s.isData ? null : s)) {
+ unsplice(pred, s);
return e;
+ }
+ // return normally if lost CAS
}
else if (spins < 0) { // establish spins at/near front
if ((spins = spinsFor(pred, s.isData)) > 0)
@@ -750,34 +764,33 @@
/* -------------- Traversal methods -------------- */
/**
- * Returns the successor of p, or the head node if p.next has been
- * linked to self, which will only be true if traversing with a
- * stale pointer that is now off the list.
- */
- final Node succ(Node p) {
- Node next = p.next;
- return (p == next) ? head : next;
- }
-
- /**
* Returns the first unmatched data node, or null if none.
- * Callers must recheck if the returned node's item field is null
- * or self-linked before using.
+ * Callers must recheck if the returned node is unmatched
+ * before using.
*/
final Node firstDataNode() {
+ Node first = null;
restartFromHead: for (;;) {
- for (Node p = head; p != null;) {
- Object item = p.item;
- if (p.isData) {
- if (item != null && item != p)
- return p;
+ Node h = head, p = h;
+ for (; p != null;) {
+ final Object item;
+ if ((item = p.item) != null) {
+ if (p.isData) {
+ first = p;
+ break;
+ }
}
- else if (item == null)
+ else if (!p.isData)
break;
- if (p == (p = p.next))
+ final Node q;
+ if ((q = p.next) == null)
+ break;
+ if (p == (p = q))
continue restartFromHead;
}
- return null;
+ if (p != h && casHead(h, p))
+ h.selfLink();
+ return first;
}
}
@@ -810,7 +823,7 @@
for (Node p = head; p != null;) {
Object item = p.item;
if (p.isData) {
- if (item != null && item != p) {
+ if (item != null) {
if (a == null)
a = new String[4];
else if (size == a.length)
@@ -839,7 +852,7 @@
for (Node p = head; p != null;) {
Object item = p.item;
if (p.isData) {
- if (item != null && item != p) {
+ if (item != null) {
if (x == null)
x = new Object[4];
else if (size == x.length)
@@ -918,76 +931,50 @@
*/
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
- if (a == null) throw new NullPointerException();
+ Objects.requireNonNull(a);
return (T[]) toArrayInternal(a);
}
+ /**
+ * Weakly-consistent iterator.
+ *
+ * Lazily updated ancestor is expected to be amortized O(1) remove(),
+ * but O(n) in the worst case, when lastRet is concurrently deleted.
+ */
final class Itr implements Iterator<E> {
private Node nextNode; // next node to return item for
private E nextItem; // the corresponding item
private Node lastRet; // last returned node, to support remove
- private Node lastPred; // predecessor to unlink lastRet
+ private Node ancestor; // Helps unlink lastRet on remove()
/**
- * Moves to next node after prev, or first node if prev null.
+ * Moves to next node after pred, or first node if pred null.
*/
- private void advance(Node prev) {
- /*
- * To track and avoid buildup of deleted nodes in the face
- * of calls to both Queue.remove and Itr.remove, we must
- * include variants of unsplice and sweep upon each
- * advance: Upon Itr.remove, we may need to catch up links
- * from lastPred, and upon other removes, we might need to
- * skip ahead from stale nodes and unsplice deleted ones
- * found while advancing.
- */
-
- Node r, b; // reset lastPred upon possible deletion of lastRet
- if ((r = lastRet) != null && !r.isMatched())
- lastPred = r; // next lastPred is old lastRet
- else if ((b = lastPred) == null || b.isMatched())
- lastPred = null; // at start of list
- else {
- Node s, n; // help with removal of lastPred.next
- while ((s = b.next) != null &&
- s != b && s.isMatched() &&
- (n = s.next) != null && n != s)
- b.casNext(s, n);
+ @SuppressWarnings("unchecked")
+ private void advance(Node pred) {
+ for (Node p = (pred == null) ? head : pred.next, c = p;
+ p != null; ) {
+ final Object item;
+ if ((item = p.item) != null && p.isData) {
+ nextNode = p;
+ nextItem = (E) item;
+ if (c != p)
+ tryCasSuccessor(pred, c, p);
+ return;
+ }
+ else if (!p.isData && item == null)
+ break;
+ if (c != p && !tryCasSuccessor(pred, c, c = p)) {
+ pred = p;
+ c = p = p.next;
+ }
+ else if (p == (p = p.next)) {
+ pred = null;
+ c = p = head;
+ }
}
-
- this.lastRet = prev;
-
- for (Node p = prev, s, n;;) {
- s = (p == null) ? head : p.next;
- if (s == null)
- break;
- else if (s == p) {
- p = null;
- continue;
- }
- Object item = s.item;
- if (s.isData) {
- if (item != null && item != s) {
- @SuppressWarnings("unchecked") E itemE = (E) item;
- nextItem = itemE;
- nextNode = s;
- return;
- }
- }
- else if (item == null)
- break;
- // assert s.isMatched();
- if (p == null)
- p = s;
- else if ((n = s.next) == null)
- break;
- else if (s == n)
- p = null;
- else
- p.casNext(s, n);
- }
+ nextItem = null;
nextNode = null;
- nextItem = null;
}
Itr() {
@@ -999,25 +986,67 @@
}
public final E next() {
- Node p = nextNode;
- if (p == null) throw new NoSuchElementException();
+ final Node p;
+ if ((p = nextNode) == null) throw new NoSuchElementException();
E e = nextItem;
- advance(p);
+ advance(lastRet = p);
return e;
}
+ public void forEachRemaining(Consumer<? super E> action) {
+ Objects.requireNonNull(action);
+ Node q = null;
+ for (Node p; (p = nextNode) != null; advance(q = p))
+ action.accept(nextItem);
+ if (q != null)
+ lastRet = q;
+ }
+
public final void remove() {
final Node lastRet = this.lastRet;
if (lastRet == null)
throw new IllegalStateException();
this.lastRet = null;
- if (lastRet.tryMatchData())
- unsplice(lastPred, lastRet);
+ if (lastRet.item == null) // already deleted?
+ return;
+ // Advance ancestor, collapsing intervening dead nodes
+ Node pred = ancestor;
+ for (Node p = (pred == null) ? head : pred.next, c = p, q;
+ p != null; ) {
+ if (p == lastRet) {
+ final Object item;
+ if ((item = p.item) != null)
+ p.tryMatch(item, null);
+ if ((q = p.next) == null) q = p;
+ if (c != q) tryCasSuccessor(pred, c, q);
+ ancestor = pred;
+ return;
+ }
+ final Object item; final boolean pAlive;
+ if (pAlive = ((item = p.item) != null && p.isData)) {
+ // exceptionally, nothing to do
+ }
+ else if (!p.isData && item == null)
+ break;
+ if ((c != p && !tryCasSuccessor(pred, c, c = p)) || pAlive) {
+ pred = p;
+ c = p = p.next;
+ }
+ else if (p == (p = p.next)) {
+ pred = null;
+ c = p = head;
+ }
+ }
+ // traversal failed to find lastRet; must have been deleted;
+ // leave ancestor at original location to avoid overshoot;
+ // better luck next time!
+
+ // assert lastRet.isMatched();
}
}
/** A customized variant of Spliterators.IteratorSpliterator */
- final class LTQSpliterator<E> implements Spliterator<E> {
+ final class LTQSpliterator implements Spliterator<E> {
static final int MAX_BATCH = 1 << 25; // max batch array size;
Node current; // current node; null until initialized
int batch; // batch size for splits
@@ -1025,79 +1054,90 @@
LTQSpliterator() {}
public Spliterator<E> trySplit() {
- Node p;
- int b = batch;
- int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
- if (!exhausted &&
- ((p = current) != null || (p = firstDataNode()) != null) &&
- p.next != null) {
- Object[] a = new Object[n];
- int i = 0;
- do {
- Object e = p.item;
- if (e != p && (a[i] = e) != null)
- ++i;
- if (p == (p = p.next))
- p = firstDataNode();
- } while (p != null && i < n && p.isData);
- if ((current = p) == null)
- exhausted = true;
- if (i > 0) {
- batch = i;
- return Spliterators.spliterator
- (a, 0, i, (Spliterator.ORDERED |
- Spliterator.NONNULL |
- Spliterator.CONCURRENT));
+ Node p, q;
+ if ((p = current()) == null || (q = p.next) == null)
+ return null;
+ int i = 0, n = batch = Math.min(batch + 1, MAX_BATCH);
+ Object[] a = null;
+ do {
+ final Object item = p.item;
+ if (p.isData) {
+ if (item != null) {
+ if (a == null)
+ a = new Object[n];
+ a[i++] = item;
+ }
+ } else if (item == null) {
+ p = null;
+ break;
}
- }
- return null;
+ if (p == (p = q))
+ p = firstDataNode();
+ } while (p != null && (q = p.next) != null && i < n);
+ setCurrent(p);
+ return (i == 0) ? null :
+ Spliterators.spliterator(a, 0, i, (Spliterator.ORDERED |
+ Spliterator.NONNULL |
+ Spliterator.CONCURRENT));
}
- @SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> action) {
- Node p;
- if (action == null) throw new NullPointerException();
- if (!exhausted &&
- ((p = current) != null || (p = firstDataNode()) != null)) {
+ Objects.requireNonNull(action);
+ final Node p;
+ if ((p = current()) != null) {
+ current = null;
exhausted = true;
- do {
- Object e = p.item;
- if (e != null && e != p)
- action.accept((E)e);
- if (p == (p = p.next))
- p = firstDataNode();
- } while (p != null && p.isData);
+ forEachFrom(action, p);
}
}
@SuppressWarnings("unchecked")
public boolean tryAdvance(Consumer<? super E> action) {
+ Objects.requireNonNull(action);
Node p;
- if (action == null) throw new NullPointerException();
- if (!exhausted &&
- ((p = current) != null || (p = firstDataNode()) != null)) {
- Object e;
+ if ((p = current()) != null) {
+ E e = null;
do {
- if ((e = p.item) == p)
- e = null;
+ final Object item = p.item;
+ final boolean isData = p.isData;
if (p == (p = p.next))
- p = firstDataNode();
- } while (e == null && p != null && p.isData);
- if ((current = p) == null)
- exhausted = true;
+ p = head;
+ if (isData) {
+ if (item != null) {
+ e = (E) item;
+ break;
+ }
+ }
+ else if (item == null)
+ p = null;
+ } while (p != null);
+ setCurrent(p);
if (e != null) {
- action.accept((E)e);
+ action.accept(e);
return true;
}
}
return false;
}
+ private void setCurrent(Node p) {
+ if ((current = p) == null)
+ exhausted = true;
+ }
+
+ private Node current() {
+ Node p;
+ if ((p = current) == null && !exhausted)
+ setCurrent(p = firstDataNode());
+ return p;
+ }
+
public long estimateSize() { return Long.MAX_VALUE; }
public int characteristics() {
- return Spliterator.ORDERED | Spliterator.NONNULL |
- Spliterator.CONCURRENT;
+ return (Spliterator.ORDERED |
+ Spliterator.NONNULL |
+ Spliterator.CONCURRENT);
}
}
@@ -1118,7 +1158,7 @@
* @since 1.8
*/
public Spliterator<E> spliterator() {
- return new LTQSpliterator<E>();
+ return new LTQSpliterator();
}
/* -------------- Removal methods -------------- */
@@ -1128,10 +1168,15 @@
* the given predecessor.
*
* @param pred a node that was at one time known to be the
- * predecessor of s, or null or s itself if s is/was at head
+ * predecessor of s
* @param s the node to be unspliced
*/
final void unsplice(Node pred, Node s) {
+ // assert pred != null;
+ // assert pred != s;
+ // assert s != null;
+ // assert s.isMatched();
+ // assert (SWEEP_THRESHOLD & (SWEEP_THRESHOLD - 1)) == 0;
s.waiter = null; // disable signals
/*
* See above for rationale. Briefly: if pred still points to
@@ -1140,13 +1185,13 @@
* nor s are head or offlist, add to sweepVotes, and if enough
* votes have accumulated, sweep.
*/
- if (pred != null && pred != s && pred.next == s) {
+ if (pred != null && pred.next == s) {
Node n = s.next;
if (n == null ||
(n != s && pred.casNext(s, n) && pred.isMatched())) {
for (;;) { // check if at, or could be, head
Node h = head;
- if (h == pred || h == s || h == null)
+ if (h == pred || h == s)
return; // at head or list empty
if (!h.isMatched())
break;
@@ -1154,21 +1199,12 @@
if (hn == null)
return; // now empty
if (hn != h && casHead(h, hn))
- h.forgetNext(); // advance head
+ h.selfLink(); // advance head
}
- if (pred.next != pred && s.next != s) { // recheck if offlist
- for (;;) { // sweep now if enough votes
- int v = sweepVotes;
- if (v < SWEEP_THRESHOLD) {
- if (casSweepVotes(v, v + 1))
- break;
- }
- else if (casSweepVotes(v, 0)) {
- sweep();
- break;
- }
- }
- }
+ // sweep every SWEEP_THRESHOLD votes
+ if (pred.next != pred && s.next != s // recheck if offlist
+ && (incSweepVotes() & (SWEEP_THRESHOLD - 1)) == 0)
+ sweep();
}
}
}
@@ -1193,35 +1229,10 @@
}
/**
- * Main implementation of remove(Object)
- */
- private boolean findAndRemove(Object e) {
- if (e != null) {
- for (Node pred = null, p = head; p != null; ) {
- Object item = p.item;
- if (p.isData) {
- if (item != null && item != p && e.equals(item) &&
- p.tryMatchData()) {
- unsplice(pred, p);
- return true;
- }
- }
- else if (item == null)
- break;
- pred = p;
- if ((p = p.next) == pred) { // stale
- pred = null;
- p = head;
- }
- }
- }
- return false;
- }
-
- /**
* Creates an initially empty {@code LinkedTransferQueue}.
*/
public LinkedTransferQueue() {
+ head = tail = new Node();
}
/**
@@ -1234,8 +1245,18 @@
* of its elements are null
*/
public LinkedTransferQueue(Collection<? extends E> c) {
- this();
- addAll(c);
+ Node h = null, t = null;
+ for (E e : c) {
+ Node newNode = new Node(Objects.requireNonNull(e));
+ if (h == null)
+ h = t = newNode;
+ else
+ t.appendRelaxed(t = newNode);
+ }
+ if (h == null)
+ h = t = new Node();
+ head = h;
+ tail = t;
}
/**
@@ -1367,15 +1388,12 @@
* @throws IllegalArgumentException {@inheritDoc}
*/
public int drainTo(Collection<? super E> c) {
- if (c == null)
- throw new NullPointerException();
+ Objects.requireNonNull(c);
if (c == this)
throw new IllegalArgumentException();
int n = 0;
- for (E e; (e = poll()) != null;) {
+ for (E e; (e = poll()) != null; n++)
c.add(e);
- ++n;
- }
return n;
}
@@ -1384,15 +1402,12 @@
* @throws IllegalArgumentException {@inheritDoc}
*/
public int drainTo(Collection<? super E> c, int maxElements) {
- if (c == null)
- throw new NullPointerException();
+ Objects.requireNonNull(c);
if (c == this)
throw new IllegalArgumentException();
int n = 0;
- for (E e; n < maxElements && (e = poll()) != null;) {
+ for (E e; n < maxElements && (e = poll()) != null; n++)
c.add(e);
- ++n;
- }
return n;
}
@@ -1414,7 +1429,7 @@
for (Node p = head; p != null;) {
Object item = p.item;
if (p.isData) {
- if (item != null && item != p) {
+ if (item != null) {
@SuppressWarnings("unchecked") E e = (E) item;
return e;
}
@@ -1442,7 +1457,7 @@
for (Node p = head; p != null;) {
Object item = p.item;
if (p.isData) {
- if (item != null && item != p)
+ if (item != null)
break;
}
else if (item == null)
@@ -1486,7 +1501,31 @@
* @return {@code true} if this queue changed as a result of the call
*/
public boolean remove(Object o) {
- return findAndRemove(o);
+ if (o == null) return false;
+ restartFromHead: for (;;) {
+ for (Node p = head, pred = null; p != null; ) {
+ Node q = p.next;
+ final Object item;
+ if ((item = p.item) != null) {
+ if (p.isData) {
+ if (o.equals(item) && p.tryMatch(item, null)) {
+ skipDeadNodes(pred, p, p, q);
+ return true;
+ }
+ pred = p; p = q; continue;
+ }
+ }
+ else if (!p.isData)
+ break;
+ for (Node c = p;; q = p.next) {
+ if (q == null || !q.isMatched()) {
+ pred = skipDeadNodes(pred, c, p, q); p = q; break;
+ }
+ if (p == (p = q)) continue restartFromHead;
+ }
+ }
+ return false;
+ }
}
/**
@@ -1498,18 +1537,29 @@
* @return {@code true} if this queue contains the specified element
*/
public boolean contains(Object o) {
- if (o != null) {
- for (Node p = head; p != null; p = succ(p)) {
- Object item = p.item;
- if (p.isData) {
- if (item != null && item != p && o.equals(item))
- return true;
+ if (o == null) return false;
+ restartFromHead: for (;;) {
+ for (Node p = head, pred = null; p != null; ) {
+ Node q = p.next;
+ final Object item;
+ if ((item = p.item) != null) {
+ if (p.isData) {
+ if (o.equals(item))
+ return true;
+ pred = p; p = q; continue;
+ }
}
- else if (item == null)
+ else if (!p.isData)
break;
+ for (Node c = p;; q = p.next) {
+ if (q == null || !q.isMatched()) {
+ pred = skipDeadNodes(pred, c, p, q); p = q; break;
+ }
+ if (p == (p = q)) continue restartFromHead;
+ }
}
+ return false;
}
- return false;
}
/**
@@ -1550,21 +1600,136 @@
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
- s.defaultReadObject();
- for (;;) {
+
+ // Read in elements until trailing null sentinel found
+ Node h = null, t = null;
+ for (Object item; (item = s.readObject()) != null; ) {
@SuppressWarnings("unchecked")
- E item = (E) s.readObject();
- if (item == null)
+ Node newNode = new Node((E) item);
+ if (h == null)
+ h = t = newNode;
+ else
+ t.appendRelaxed(t = newNode);
+ }
+ if (h == null)
+ h = t = new Node();
+ head = h;
+ tail = t;
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean removeIf(Predicate<? super E> filter) {
+ Objects.requireNonNull(filter);
+ return bulkRemove(filter);
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean removeAll(Collection<?> c) {
+ Objects.requireNonNull(c);
+ return bulkRemove(e -> c.contains(e));
+ }
+
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public boolean retainAll(Collection<?> c) {
+ Objects.requireNonNull(c);
+ return bulkRemove(e -> !c.contains(e));
+ }
+
+ public void clear() {
+ bulkRemove(e -> true);
+ }
+
+ /**
+ * Tolerate this many consecutive dead nodes before CAS-collapsing.
+ * Amortized cost of clear() is (1 + 1/MAX_HOPS) CASes per element.
+ */
+ private static final int MAX_HOPS = 8;
+
+ /** Implementation of bulk remove methods. */
+ @SuppressWarnings("unchecked")
+ private boolean bulkRemove(Predicate<? super E> filter) {
+ boolean removed = false;
+ restartFromHead: for (;;) {
+ int hops = MAX_HOPS;
+ // c will be CASed to collapse intervening dead nodes between
+ // pred (or head if null) and p.
+ for (Node p = head, c = p, pred = null, q; p != null; p = q) {
+ q = p.next;
+ final Object item; boolean pAlive;
+ if (pAlive = ((item = p.item) != null && p.isData)) {
+ if (filter.test((E) item)) {
+ if (p.tryMatch(item, null))
+ removed = true;
+ pAlive = false;
+ }
+ }
+ else if (!p.isData && item == null)
+ break;
+ if (pAlive || q == null || --hops == 0) {
+ // p might already be self-linked here, but if so:
+ // - CASing head will surely fail
+ // - CASing pred's next will be useless but harmless.
+ if ((c != p && !tryCasSuccessor(pred, c, c = p))
+ || pAlive) {
+ // if CAS failed or alive, abandon old pred
+ hops = MAX_HOPS;
+ pred = p;
+ c = q;
+ }
+ } else if (p == q)
+ continue restartFromHead;
+ }
+ return removed;
+ }
+ }
+
+ /**
+ * Runs action on each element found during a traversal starting at p.
+ * If p is null, the action is not run.
+ */
+ @SuppressWarnings("unchecked")
+ void forEachFrom(Consumer<? super E> action, Node p) {
+ for (Node pred = null; p != null; ) {
+ Node q = p.next;
+ final Object item;
+ if ((item = p.item) != null) {
+ if (p.isData) {
+ action.accept((E) item);
+ pred = p; p = q; continue;
+ }
+ }
+ else if (!p.isData)
break;
- else
- offer(item);
+ for (Node c = p;; q = p.next) {
+ if (q == null || !q.isMatched()) {
+ pred = skipDeadNodes(pred, c, p, q); p = q; break;
+ }
+ if (p == (p = q)) { pred = null; p = head; break; }
+ }
}
}
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public void forEach(Consumer<? super E> action) {
+ Objects.requireNonNull(action);
+ forEachFrom(action, head);
+ }
+
// VarHandle mechanics
private static final VarHandle HEAD;
private static final VarHandle TAIL;
private static final VarHandle SWEEPVOTES;
+ static final VarHandle ITEM;
+ static final VarHandle NEXT;
+ static final VarHandle WAITER;
static {
try {
MethodHandles.Lookup l = MethodHandles.lookup();
@@ -1574,6 +1739,9 @@
Node.class);
SWEEPVOTES = l.findVarHandle(LinkedTransferQueue.class, "sweepVotes",
int.class);
+ ITEM = l.findVarHandle(Node.class, "item", Object.class);
+ NEXT = l.findVarHandle(Node.class, "next", Node.class);
+ WAITER = l.findVarHandle(Node.class, "waiter", Thread.class);
} catch (ReflectiveOperationException e) {
throw new Error(e);
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java Thu Feb 09 23:15:52 2017 +0100
@@ -43,6 +43,7 @@
import java.util.Comparator;
import java.util.Iterator;
import java.util.NoSuchElementException;
+import java.util.Objects;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.SortedSet;
@@ -62,16 +63,15 @@
* non-comparable objects (doing so results in
* {@code ClassCastException}).
*
- * <p>This class and its iterator implement all of the
- * <em>optional</em> methods of the {@link Collection} and {@link
- * Iterator} interfaces. The Iterator provided in method {@link
- * #iterator()} and the Spliterator provided in method {@link #spliterator()}
- * are <em>not</em> guaranteed to traverse the elements of
- * the PriorityBlockingQueue in any particular order. If you need
- * ordered traversal, consider using
- * {@code Arrays.sort(pq.toArray())}. Also, method {@code drainTo}
- * can be used to <em>remove</em> some or all elements in priority
- * order and place them in another collection.
+ * <p>This class and its iterator implement all of the <em>optional</em>
+ * methods of the {@link Collection} and {@link Iterator} interfaces.
+ * The Iterator provided in method {@link #iterator()} and the
+ * Spliterator provided in method {@link #spliterator()} are <em>not</em>
+ * guaranteed to traverse the elements of the PriorityBlockingQueue in
+ * any particular order. If you need ordered traversal, consider using
+ * {@code Arrays.sort(pq.toArray())}. Also, method {@code drainTo} can
+ * be used to <em>remove</em> some or all elements in priority order and
+ * place them in another collection.
*
* <p>Operations on this class make no guarantees about the ordering
* of elements with equal priority. If you need to enforce an
@@ -437,15 +437,14 @@
*/
private void heapify() {
Object[] array = queue;
- int n = size;
- int half = (n >>> 1) - 1;
+ int n = size, i = (n >>> 1) - 1;
Comparator<? super E> cmp = comparator;
if (cmp == null) {
- for (int i = half; i >= 0; i--)
+ for (; i >= 0; i--)
siftDownComparable(i, (E) array[i], array, n);
}
else {
- for (int i = half; i >= 0; i--)
+ for (; i >= 0; i--)
siftDownUsingComparator(i, (E) array[i], array, n, cmp);
}
}
@@ -730,8 +729,7 @@
* @throws IllegalArgumentException {@inheritDoc}
*/
public int drainTo(Collection<? super E> c, int maxElements) {
- if (c == null)
- throw new NullPointerException();
+ Objects.requireNonNull(c);
if (c == this)
throw new IllegalArgumentException();
if (maxElements <= 0)
@@ -935,21 +933,22 @@
* Immutable snapshot spliterator that binds to elements "late".
*/
final class PBQSpliterator implements Spliterator<E> {
- Object[] array;
+ Object[] array; // null until late-bound-initialized
int index;
int fence;
+ PBQSpliterator() {}
+
PBQSpliterator(Object[] array, int index, int fence) {
this.array = array;
this.index = index;
this.fence = fence;
}
- final int getFence() {
- int hi;
- if ((hi = fence) < 0)
- hi = fence = (array = toArray()).length;
- return hi;
+ private int getFence() {
+ if (array == null)
+ fence = (array = toArray()).length;
+ return fence;
}
public PBQSpliterator trySplit() {
@@ -958,25 +957,19 @@
new PBQSpliterator(array, lo, index = mid);
}
- @SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> action) {
- Object[] a; int i, hi; // hoist accesses and checks from loop
- if (action == null)
- throw new NullPointerException();
- if ((a = array) == null)
- fence = (a = toArray()).length;
- if ((hi = fence) <= a.length &&
- (i = index) >= 0 && i < (index = hi)) {
- do { action.accept((E)a[i]); } while (++i < hi);
- }
+ Objects.requireNonNull(action);
+ final int hi = getFence(), lo = index;
+ final Object[] a = array;
+ index = hi; // ensure exhaustion
+ for (int i = lo; i < hi; i++)
+ action.accept((E) a[i]);
}
public boolean tryAdvance(Consumer<? super E> action) {
- if (action == null)
- throw new NullPointerException();
+ Objects.requireNonNull(action);
if (getFence() > index && index >= 0) {
- @SuppressWarnings("unchecked") E e = (E) array[index++];
- action.accept(e);
+ action.accept((E) array[index++]);
return true;
}
return false;
@@ -985,7 +978,9 @@
public long estimateSize() { return getFence() - index; }
public int characteristics() {
- return Spliterator.NONNULL | Spliterator.SIZED | Spliterator.SUBSIZED;
+ return (Spliterator.NONNULL |
+ Spliterator.SIZED |
+ Spliterator.SUBSIZED);
}
}
@@ -1007,7 +1002,7 @@
* @since 1.8
*/
public Spliterator<E> spliterator() {
- return new PBQSpliterator(null, 0, -1);
+ return new PBQSpliterator();
}
// VarHandle mechanics
--- a/jdk/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java Thu Feb 09 23:15:52 2017 +0100
@@ -42,6 +42,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
+import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.concurrent.locks.LockSupport;
@@ -75,9 +76,8 @@
* is not guaranteed. However, a queue constructed with fairness set
* to {@code true} grants threads access in FIFO order.
*
- * <p>This class and its iterator implement all of the
- * <em>optional</em> methods of the {@link Collection} and {@link
- * Iterator} interfaces.
+ * <p>This class and its iterator implement all of the <em>optional</em>
+ * methods of the {@link Collection} and {@link Iterator} interfaces.
*
* <p>This class is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
@@ -1112,15 +1112,12 @@
* @throws IllegalArgumentException {@inheritDoc}
*/
public int drainTo(Collection<? super E> c) {
- if (c == null)
- throw new NullPointerException();
+ Objects.requireNonNull(c);
if (c == this)
throw new IllegalArgumentException();
int n = 0;
- for (E e; (e = poll()) != null;) {
+ for (E e; (e = poll()) != null; n++)
c.add(e);
- ++n;
- }
return n;
}
@@ -1131,15 +1128,12 @@
* @throws IllegalArgumentException {@inheritDoc}
*/
public int drainTo(Collection<? super E> c, int maxElements) {
- if (c == null)
- throw new NullPointerException();
+ Objects.requireNonNull(c);
if (c == this)
throw new IllegalArgumentException();
int n = 0;
- for (E e; n < maxElements && (e = poll()) != null;) {
+ for (E e; n < maxElements && (e = poll()) != null; n++)
c.add(e);
- ++n;
- }
return n;
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java Thu Feb 09 23:15:52 2017 +0100
@@ -1059,17 +1059,17 @@
static {
try {
SEED = U.objectFieldOffset
- (Thread.class.getDeclaredField("threadLocalRandomSeed"));
+ (Thread.class.getDeclaredField("threadLocalRandomSeed"));
PROBE = U.objectFieldOffset
- (Thread.class.getDeclaredField("threadLocalRandomProbe"));
+ (Thread.class.getDeclaredField("threadLocalRandomProbe"));
SECONDARY = U.objectFieldOffset
- (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
+ (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
THREADLOCALS = U.objectFieldOffset
- (Thread.class.getDeclaredField("threadLocals"));
+ (Thread.class.getDeclaredField("threadLocals"));
INHERITABLETHREADLOCALS = U.objectFieldOffset
- (Thread.class.getDeclaredField("inheritableThreadLocals"));
+ (Thread.class.getDeclaredField("inheritableThreadLocals"));
INHERITEDACCESSCONTROLCONTEXT = U.objectFieldOffset
- (Thread.class.getDeclaredField("inheritedAccessControlContext"));
+ (Thread.class.getDeclaredField("inheritedAccessControlContext"));
} catch (ReflectiveOperationException e) {
throw new Error(e);
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java Thu Feb 09 23:15:52 2017 +0100
@@ -425,11 +425,11 @@
static {
try {
PARKBLOCKER = U.objectFieldOffset
- (Thread.class.getDeclaredField("parkBlocker"));
+ (Thread.class.getDeclaredField("parkBlocker"));
SECONDARY = U.objectFieldOffset
- (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
+ (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
TID = U.objectFieldOffset
- (Thread.class.getDeclaredField("tid"));
+ (Thread.class.getDeclaredField("tid"));
} catch (ReflectiveOperationException e) {
throw new Error(e);
--- a/jdk/src/java.base/share/classes/java/util/regex/CharPredicates.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/regex/CharPredicates.java Thu Feb 09 23:15:52 2017 +0100
@@ -32,164 +32,195 @@
class CharPredicates {
- static final CharPredicate ALPHABETIC = Character::isAlphabetic;
+ static final CharPredicate ALPHABETIC() {
+ return Character::isAlphabetic;
+ }
// \p{gc=Decimal_Number}
- static final CharPredicate DIGIT = Character::isDigit;
+ static final CharPredicate DIGIT() {
+ return Character::isDigit;
+ }
- static final CharPredicate LETTER = Character::isLetter;
+ static final CharPredicate LETTER() {
+ return Character::isLetter;
+ }
- static final CharPredicate IDEOGRAPHIC = Character::isIdeographic;
+ static final CharPredicate IDEOGRAPHIC() {
+ return Character::isIdeographic;
+ }
- static final CharPredicate LOWERCASE = Character::isLowerCase;
+ static final CharPredicate LOWERCASE() {
+ return Character::isLowerCase;
+ }
- static final CharPredicate UPPERCASE = Character::isUpperCase;
+ static final CharPredicate UPPERCASE() {
+ return Character::isUpperCase;
+ }
- static final CharPredicate TITLECASE = Character::isTitleCase;
+ static final CharPredicate TITLECASE() {
+ return Character::isTitleCase;
+ }
// \p{Whitespace}
- static final CharPredicate WHITE_SPACE = ch ->
- ((((1 << Character.SPACE_SEPARATOR) |
- (1 << Character.LINE_SEPARATOR) |
- (1 << Character.PARAGRAPH_SEPARATOR)) >> Character.getType(ch)) & 1)
- != 0 || (ch >= 0x9 && ch <= 0xd) || (ch == 0x85);
+ static final CharPredicate WHITE_SPACE() {
+ return ch ->
+ ((((1 << Character.SPACE_SEPARATOR) |
+ (1 << Character.LINE_SEPARATOR) |
+ (1 << Character.PARAGRAPH_SEPARATOR)) >> Character.getType(ch)) & 1)
+ != 0 || (ch >= 0x9 && ch <= 0xd) || (ch == 0x85);
+ }
// \p{gc=Control}
- static final CharPredicate CONTROL = ch ->
- Character.getType(ch) == Character.CONTROL;
+ static final CharPredicate CONTROL() {
+ return ch -> Character.getType(ch) == Character.CONTROL;
+ }
// \p{gc=Punctuation}
- static final CharPredicate PUNCTUATION = ch ->
- ((((1 << Character.CONNECTOR_PUNCTUATION) |
- (1 << Character.DASH_PUNCTUATION) |
- (1 << Character.START_PUNCTUATION) |
- (1 << Character.END_PUNCTUATION) |
- (1 << Character.OTHER_PUNCTUATION) |
- (1 << Character.INITIAL_QUOTE_PUNCTUATION) |
- (1 << Character.FINAL_QUOTE_PUNCTUATION)) >> Character.getType(ch)) & 1)
- != 0;
+ static final CharPredicate PUNCTUATION() {
+ return ch ->
+ ((((1 << Character.CONNECTOR_PUNCTUATION) |
+ (1 << Character.DASH_PUNCTUATION) |
+ (1 << Character.START_PUNCTUATION) |
+ (1 << Character.END_PUNCTUATION) |
+ (1 << Character.OTHER_PUNCTUATION) |
+ (1 << Character.INITIAL_QUOTE_PUNCTUATION) |
+ (1 << Character.FINAL_QUOTE_PUNCTUATION)) >> Character.getType(ch)) & 1)
+ != 0;
+ }
// \p{gc=Decimal_Number}
// \p{Hex_Digit} -> PropList.txt: Hex_Digit
- static final CharPredicate HEX_DIGIT = DIGIT.union(
- ch -> (ch >= 0x0030 && ch <= 0x0039) ||
- (ch >= 0x0041 && ch <= 0x0046) ||
- (ch >= 0x0061 && ch <= 0x0066) ||
- (ch >= 0xFF10 && ch <= 0xFF19) ||
- (ch >= 0xFF21 && ch <= 0xFF26) ||
- (ch >= 0xFF41 && ch <= 0xFF46));
+ static final CharPredicate HEX_DIGIT() {
+ return DIGIT().union(ch -> (ch >= 0x0030 && ch <= 0x0039) ||
+ (ch >= 0x0041 && ch <= 0x0046) ||
+ (ch >= 0x0061 && ch <= 0x0066) ||
+ (ch >= 0xFF10 && ch <= 0xFF19) ||
+ (ch >= 0xFF21 && ch <= 0xFF26) ||
+ (ch >= 0xFF41 && ch <= 0xFF46));
+ }
- static final CharPredicate ASSIGNED = ch ->
- Character.getType(ch) != Character.UNASSIGNED;
+ static final CharPredicate ASSIGNED() {
+ return ch -> Character.getType(ch) != Character.UNASSIGNED;
+ }
// PropList.txt:Noncharacter_Code_Point
- static final CharPredicate NONCHARACTER_CODE_POINT = ch ->
- (ch & 0xfffe) == 0xfffe || (ch >= 0xfdd0 && ch <= 0xfdef);
+ static final CharPredicate NONCHARACTER_CODE_POINT() {
+ return ch -> (ch & 0xfffe) == 0xfffe || (ch >= 0xfdd0 && ch <= 0xfdef);
+ }
// \p{alpha}
// \p{digit}
- static final CharPredicate ALNUM = ALPHABETIC.union(DIGIT);
+ static final CharPredicate ALNUM() {
+ return ALPHABETIC().union(DIGIT());
+ }
// \p{Whitespace} --
// [\N{LF} \N{VT} \N{FF} \N{CR} \N{NEL} -> 0xa, 0xb, 0xc, 0xd, 0x85
// \p{gc=Line_Separator}
// \p{gc=Paragraph_Separator}]
- static final CharPredicate BLANK = ch ->
- Character.getType(ch) == Character.SPACE_SEPARATOR ||
- ch == 0x9; // \N{HT}
+ static final CharPredicate BLANK() {
+ return ch ->
+ Character.getType(ch) == Character.SPACE_SEPARATOR ||
+ ch == 0x9; // \N{HT}
+ }
// [^
// \p{space}
// \p{gc=Control}
// \p{gc=Surrogate}
// \p{gc=Unassigned}]
- static final CharPredicate GRAPH = ch ->
- ((((1 << Character.SPACE_SEPARATOR) |
- (1 << Character.LINE_SEPARATOR) |
- (1 << Character.PARAGRAPH_SEPARATOR) |
- (1 << Character.CONTROL) |
- (1 << Character.SURROGATE) |
- (1 << Character.UNASSIGNED)) >> Character.getType(ch)) & 1)
- == 0;
+ static final CharPredicate GRAPH() {
+ return ch ->
+ ((((1 << Character.SPACE_SEPARATOR) |
+ (1 << Character.LINE_SEPARATOR) |
+ (1 << Character.PARAGRAPH_SEPARATOR) |
+ (1 << Character.CONTROL) |
+ (1 << Character.SURROGATE) |
+ (1 << Character.UNASSIGNED)) >> Character.getType(ch)) & 1)
+ == 0;
+ }
// \p{graph}
// \p{blank}
// -- \p{cntrl}
- static final CharPredicate PRINT = GRAPH.union(BLANK).and(CONTROL.negate());
+ static final CharPredicate PRINT() {
+ return GRAPH().union(BLANK()).and(CONTROL().negate());
+ }
// 200C..200D PropList.txt:Join_Control
- static final CharPredicate JOIN_CONTROL = ch -> ch == 0x200C || ch == 0x200D;
+ static final CharPredicate JOIN_CONTROL() {
+ return ch -> ch == 0x200C || ch == 0x200D;
+ }
// \p{alpha}
// \p{gc=Mark}
// \p{digit}
// \p{gc=Connector_Punctuation}
// \p{Join_Control} 200C..200D
- static final CharPredicate WORD =
- ALPHABETIC.union(ch -> ((((1 << Character.NON_SPACING_MARK) |
+ static final CharPredicate WORD() {
+ return ALPHABETIC().union(ch -> ((((1 << Character.NON_SPACING_MARK) |
(1 << Character.ENCLOSING_MARK) |
(1 << Character.COMBINING_SPACING_MARK) |
(1 << Character.DECIMAL_DIGIT_NUMBER) |
(1 << Character.CONNECTOR_PUNCTUATION))
>> Character.getType(ch)) & 1) != 0,
- JOIN_CONTROL);
+ JOIN_CONTROL());
+ }
/////////////////////////////////////////////////////////////////////////////
- private static final HashMap<String, CharPredicate> posix = new HashMap<>(12);
- private static final HashMap<String, CharPredicate> uprops = new HashMap<>(18);
-
- private static void defPosix(String name, CharPredicate p) {
- posix.put(name, p);
- }
- private static void defUProp(String name, CharPredicate p) {
- uprops.put(name, p);
+ private static CharPredicate getPosixPredicate(String name) {
+ switch (name) {
+ case "ALPHA": return ALPHABETIC();
+ case "LOWER": return LOWERCASE();
+ case "UPPER": return UPPERCASE();
+ case "SPACE": return WHITE_SPACE();
+ case "PUNCT": return PUNCTUATION();
+ case "XDIGIT": return HEX_DIGIT();
+ case "ALNUM": return ALNUM();
+ case "CNTRL": return CONTROL();
+ case "DIGIT": return DIGIT();
+ case "BLANK": return BLANK();
+ case "GRAPH": return GRAPH();
+ case "PRINT": return PRINT();
+ default: return null;
+ }
}
- static {
- defPosix("ALPHA", ALPHABETIC);
- defPosix("LOWER", LOWERCASE);
- defPosix("UPPER", UPPERCASE);
- defPosix("SPACE", WHITE_SPACE);
- defPosix("PUNCT", PUNCTUATION);
- defPosix("XDIGIT",HEX_DIGIT);
- defPosix("ALNUM", ALNUM);
- defPosix("CNTRL", CONTROL);
- defPosix("DIGIT", DIGIT);
- defPosix("BLANK", BLANK);
- defPosix("GRAPH", GRAPH);
- defPosix("PRINT", PRINT);
-
- defUProp("ALPHABETIC", ALPHABETIC);
- defUProp("ASSIGNED", ASSIGNED);
- defUProp("CONTROL", CONTROL);
- defUProp("HEXDIGIT", HEX_DIGIT);
- defUProp("IDEOGRAPHIC", IDEOGRAPHIC);
- defUProp("JOINCONTROL", JOIN_CONTROL);
- defUProp("LETTER", LETTER);
- defUProp("LOWERCASE", LOWERCASE);
- defUProp("NONCHARACTERCODEPOINT", NONCHARACTER_CODE_POINT);
- defUProp("TITLECASE", TITLECASE);
- defUProp("PUNCTUATION", PUNCTUATION);
- defUProp("UPPERCASE", UPPERCASE);
- defUProp("WHITESPACE", WHITE_SPACE);
- defUProp("WORD", WORD);
- defUProp("WHITE_SPACE", WHITE_SPACE);
- defUProp("HEX_DIGIT", HEX_DIGIT);
- defUProp("NONCHARACTER_CODE_POINT", NONCHARACTER_CODE_POINT);
- defUProp("JOIN_CONTROL", JOIN_CONTROL);
+ private static CharPredicate getUnicodePredicate(String name) {
+ switch (name) {
+ case "ALPHABETIC": return ALPHABETIC();
+ case "ASSIGNED": return ASSIGNED();
+ case "CONTROL": return CONTROL();
+ case "HEXDIGIT": return HEX_DIGIT();
+ case "IDEOGRAPHIC": return IDEOGRAPHIC();
+ case "JOINCONTROL": return JOIN_CONTROL();
+ case "LETTER": return LETTER();
+ case "LOWERCASE": return LOWERCASE();
+ case "NONCHARACTERCODEPOINT": return NONCHARACTER_CODE_POINT();
+ case "TITLECASE": return TITLECASE();
+ case "PUNCTUATION": return PUNCTUATION();
+ case "UPPERCASE": return UPPERCASE();
+ case "WHITESPACE": return WHITE_SPACE();
+ case "WORD": return WORD();
+ case "WHITE_SPACE": return WHITE_SPACE();
+ case "HEX_DIGIT": return HEX_DIGIT();
+ case "NONCHARACTER_CODE_POINT": return NONCHARACTER_CODE_POINT();
+ case "JOIN_CONTROL": return JOIN_CONTROL();
+ default: return null;
+ }
}
public static CharPredicate forUnicodeProperty(String propName) {
propName = propName.toUpperCase(Locale.ROOT);
- CharPredicate p = uprops.get(propName);
+ CharPredicate p = getUnicodePredicate(propName);
if (p != null)
return p;
- return posix.get(propName);
+ return getPosixPredicate(propName);
}
public static CharPredicate forPOSIXName(String propName) {
- return posix.get(propName.toUpperCase(Locale.ENGLISH));
+ return getPosixPredicate(propName.toUpperCase(Locale.ENGLISH));
}
/////////////////////////////////////////////////////////////////////////////
@@ -223,145 +254,130 @@
// unicode categories, aliases, properties, java methods ...
- private static final HashMap<String, CharPredicate> props = new HashMap<>(128);
-
- /**
- * Returns a predicate matching all characters in a named property.
- */
static CharPredicate forProperty(String name) {
- return props.get(name);
- }
-
- private static void defProp(String name, CharPredicate p) {
- props.put(name, p);
- }
-
- private static void defCategory(String name, final int typeMask) {
- CharPredicate p = ch -> (typeMask & (1 << Character.getType(ch))) != 0;
- props.put(name, p);
- }
-
- private static void defRange(String name, final int lower, final int upper) {
- BmpCharPredicate p = ch -> lower <= ch && ch <= upper;
- props.put(name, p);
- }
-
- private static void defCtype(String name, final int ctype) {
- BmpCharPredicate p = ch -> ch < 128 && ASCII.isType(ch, ctype);
- // PrintPattern.pmap.put(p, name);
- props.put(name, p);
- }
-
- static {
// Unicode character property aliases, defined in
// http://www.unicode.org/Public/UNIDATA/PropertyValueAliases.txt
- defCategory("Cn", 1<<Character.UNASSIGNED);
- defCategory("Lu", 1<<Character.UPPERCASE_LETTER);
- defCategory("Ll", 1<<Character.LOWERCASE_LETTER);
- defCategory("Lt", 1<<Character.TITLECASE_LETTER);
- defCategory("Lm", 1<<Character.MODIFIER_LETTER);
- defCategory("Lo", 1<<Character.OTHER_LETTER);
- defCategory("Mn", 1<<Character.NON_SPACING_MARK);
- defCategory("Me", 1<<Character.ENCLOSING_MARK);
- defCategory("Mc", 1<<Character.COMBINING_SPACING_MARK);
- defCategory("Nd", 1<<Character.DECIMAL_DIGIT_NUMBER);
- defCategory("Nl", 1<<Character.LETTER_NUMBER);
- defCategory("No", 1<<Character.OTHER_NUMBER);
- defCategory("Zs", 1<<Character.SPACE_SEPARATOR);
- defCategory("Zl", 1<<Character.LINE_SEPARATOR);
- defCategory("Zp", 1<<Character.PARAGRAPH_SEPARATOR);
- defCategory("Cc", 1<<Character.CONTROL);
- defCategory("Cf", 1<<Character.FORMAT);
- defCategory("Co", 1<<Character.PRIVATE_USE);
- defCategory("Cs", 1<<Character.SURROGATE);
- defCategory("Pd", 1<<Character.DASH_PUNCTUATION);
- defCategory("Ps", 1<<Character.START_PUNCTUATION);
- defCategory("Pe", 1<<Character.END_PUNCTUATION);
- defCategory("Pc", 1<<Character.CONNECTOR_PUNCTUATION);
- defCategory("Po", 1<<Character.OTHER_PUNCTUATION);
- defCategory("Sm", 1<<Character.MATH_SYMBOL);
- defCategory("Sc", 1<<Character.CURRENCY_SYMBOL);
- defCategory("Sk", 1<<Character.MODIFIER_SYMBOL);
- defCategory("So", 1<<Character.OTHER_SYMBOL);
- defCategory("Pi", 1<<Character.INITIAL_QUOTE_PUNCTUATION);
- defCategory("Pf", 1<<Character.FINAL_QUOTE_PUNCTUATION);
- defCategory("L", ((1<<Character.UPPERCASE_LETTER) |
- (1<<Character.LOWERCASE_LETTER) |
- (1<<Character.TITLECASE_LETTER) |
- (1<<Character.MODIFIER_LETTER) |
- (1<<Character.OTHER_LETTER)));
- defCategory("M", ((1<<Character.NON_SPACING_MARK) |
- (1<<Character.ENCLOSING_MARK) |
- (1<<Character.COMBINING_SPACING_MARK)));
- defCategory("N", ((1<<Character.DECIMAL_DIGIT_NUMBER) |
- (1<<Character.LETTER_NUMBER) |
- (1<<Character.OTHER_NUMBER)));
- defCategory("Z", ((1<<Character.SPACE_SEPARATOR) |
- (1<<Character.LINE_SEPARATOR) |
- (1<<Character.PARAGRAPH_SEPARATOR)));
- defCategory("C", ((1<<Character.CONTROL) |
- (1<<Character.FORMAT) |
- (1<<Character.PRIVATE_USE) |
- (1<<Character.SURROGATE) |
- (1<<Character.UNASSIGNED))); // Other
- defCategory("P", ((1<<Character.DASH_PUNCTUATION) |
- (1<<Character.START_PUNCTUATION) |
- (1<<Character.END_PUNCTUATION) |
- (1<<Character.CONNECTOR_PUNCTUATION) |
- (1<<Character.OTHER_PUNCTUATION) |
- (1<<Character.INITIAL_QUOTE_PUNCTUATION) |
- (1<<Character.FINAL_QUOTE_PUNCTUATION)));
- defCategory("S", ((1<<Character.MATH_SYMBOL) |
- (1<<Character.CURRENCY_SYMBOL) |
- (1<<Character.MODIFIER_SYMBOL) |
- (1<<Character.OTHER_SYMBOL)));
- defCategory("LC", ((1<<Character.UPPERCASE_LETTER) |
- (1<<Character.LOWERCASE_LETTER) |
- (1<<Character.TITLECASE_LETTER)));
- defCategory("LD", ((1<<Character.UPPERCASE_LETTER) |
- (1<<Character.LOWERCASE_LETTER) |
- (1<<Character.TITLECASE_LETTER) |
- (1<<Character.MODIFIER_LETTER) |
- (1<<Character.OTHER_LETTER) |
- (1<<Character.DECIMAL_DIGIT_NUMBER)));
- defRange("L1", 0x00, 0xFF); // Latin-1
- props.put("all", ch -> true);
+ switch (name) {
+ case "Cn": return category(1<<Character.UNASSIGNED);
+ case "Lu": return category(1<<Character.UPPERCASE_LETTER);
+ case "Ll": return category(1<<Character.LOWERCASE_LETTER);
+ case "Lt": return category(1<<Character.TITLECASE_LETTER);
+ case "Lm": return category(1<<Character.MODIFIER_LETTER);
+ case "Lo": return category(1<<Character.OTHER_LETTER);
+ case "Mn": return category(1<<Character.NON_SPACING_MARK);
+ case "Me": return category(1<<Character.ENCLOSING_MARK);
+ case "Mc": return category(1<<Character.COMBINING_SPACING_MARK);
+ case "Nd": return category(1<<Character.DECIMAL_DIGIT_NUMBER);
+ case "Nl": return category(1<<Character.LETTER_NUMBER);
+ case "No": return category(1<<Character.OTHER_NUMBER);
+ case "Zs": return category(1<<Character.SPACE_SEPARATOR);
+ case "Zl": return category(1<<Character.LINE_SEPARATOR);
+ case "Zp": return category(1<<Character.PARAGRAPH_SEPARATOR);
+ case "Cc": return category(1<<Character.CONTROL);
+ case "Cf": return category(1<<Character.FORMAT);
+ case "Co": return category(1<<Character.PRIVATE_USE);
+ case "Cs": return category(1<<Character.SURROGATE);
+ case "Pd": return category(1<<Character.DASH_PUNCTUATION);
+ case "Ps": return category(1<<Character.START_PUNCTUATION);
+ case "Pe": return category(1<<Character.END_PUNCTUATION);
+ case "Pc": return category(1<<Character.CONNECTOR_PUNCTUATION);
+ case "Po": return category(1<<Character.OTHER_PUNCTUATION);
+ case "Sm": return category(1<<Character.MATH_SYMBOL);
+ case "Sc": return category(1<<Character.CURRENCY_SYMBOL);
+ case "Sk": return category(1<<Character.MODIFIER_SYMBOL);
+ case "So": return category(1<<Character.OTHER_SYMBOL);
+ case "Pi": return category(1<<Character.INITIAL_QUOTE_PUNCTUATION);
+ case "Pf": return category(1<<Character.FINAL_QUOTE_PUNCTUATION);
+ case "L": return category(((1<<Character.UPPERCASE_LETTER) |
+ (1<<Character.LOWERCASE_LETTER) |
+ (1<<Character.TITLECASE_LETTER) |
+ (1<<Character.MODIFIER_LETTER) |
+ (1<<Character.OTHER_LETTER)));
+ case "M": return category(((1<<Character.NON_SPACING_MARK) |
+ (1<<Character.ENCLOSING_MARK) |
+ (1<<Character.COMBINING_SPACING_MARK)));
+ case "N": return category(((1<<Character.DECIMAL_DIGIT_NUMBER) |
+ (1<<Character.LETTER_NUMBER) |
+ (1<<Character.OTHER_NUMBER)));
+ case "Z": return category(((1<<Character.SPACE_SEPARATOR) |
+ (1<<Character.LINE_SEPARATOR) |
+ (1<<Character.PARAGRAPH_SEPARATOR)));
+ case "C": return category(((1<<Character.CONTROL) |
+ (1<<Character.FORMAT) |
+ (1<<Character.PRIVATE_USE) |
+ (1<<Character.SURROGATE) |
+ (1<<Character.UNASSIGNED))); // Other
+ case "P": return category(((1<<Character.DASH_PUNCTUATION) |
+ (1<<Character.START_PUNCTUATION) |
+ (1<<Character.END_PUNCTUATION) |
+ (1<<Character.CONNECTOR_PUNCTUATION) |
+ (1<<Character.OTHER_PUNCTUATION) |
+ (1<<Character.INITIAL_QUOTE_PUNCTUATION) |
+ (1<<Character.FINAL_QUOTE_PUNCTUATION)));
+ case "S": return category(((1<<Character.MATH_SYMBOL) |
+ (1<<Character.CURRENCY_SYMBOL) |
+ (1<<Character.MODIFIER_SYMBOL) |
+ (1<<Character.OTHER_SYMBOL)));
+ case "LC": return category(((1<<Character.UPPERCASE_LETTER) |
+ (1<<Character.LOWERCASE_LETTER) |
+ (1<<Character.TITLECASE_LETTER)));
+ case "LD": return category(((1<<Character.UPPERCASE_LETTER) |
+ (1<<Character.LOWERCASE_LETTER) |
+ (1<<Character.TITLECASE_LETTER) |
+ (1<<Character.MODIFIER_LETTER) |
+ (1<<Character.OTHER_LETTER) |
+ (1<<Character.DECIMAL_DIGIT_NUMBER)));
+ case "L1": return range(0x00, 0xFF); // Latin-1
+ case "all": return Pattern.ALL();
+ // Posix regular expression character classes, defined in
+ // http://www.unix.org/onlinepubs/009695399/basedefs/xbd_chap09.html
+ case "ASCII": return range(0x00, 0x7F); // ASCII
+ case "Alnum": return ctype(ASCII.ALNUM); // Alphanumeric characters
+ case "Alpha": return ctype(ASCII.ALPHA); // Alphabetic characters
+ case "Blank": return ctype(ASCII.BLANK); // Space and tab characters
+ case "Cntrl": return ctype(ASCII.CNTRL); // Control characters
+ case "Digit": return range('0', '9'); // Numeric characters
+ case "Graph": return ctype(ASCII.GRAPH); // printable and visible
+ case "Lower": return range('a', 'z'); // Lower-case alphabetic
+ case "Print": return range(0x20, 0x7E); // Printable characters
+ case "Punct": return ctype(ASCII.PUNCT); // Punctuation characters
+ case "Space": return ctype(ASCII.SPACE); // Space characters
+ case "Upper": return range('A', 'Z'); // Upper-case alphabetic
+ case "XDigit": return ctype(ASCII.XDIGIT); // hexadecimal digits
- // Posix regular expression character classes, defined in
- // http://www.unix.org/onlinepubs/009695399/basedefs/xbd_chap09.html
- defRange("ASCII", 0x00, 0x7F); // ASCII
- defCtype("Alnum", ASCII.ALNUM); // Alphanumeric characters
- defCtype("Alpha", ASCII.ALPHA); // Alphabetic characters
- defCtype("Blank", ASCII.BLANK); // Space and tab characters
- defCtype("Cntrl", ASCII.CNTRL); // Control characters
- defRange("Digit", '0', '9'); // Numeric characters
- defCtype("Graph", ASCII.GRAPH); // printable and visible
- defRange("Lower", 'a', 'z'); // Lower-case alphabetic
- defRange("Print", 0x20, 0x7E); // Printable characters
- defCtype("Punct", ASCII.PUNCT); // Punctuation characters
- defCtype("Space", ASCII.SPACE); // Space characters
- defRange("Upper", 'A', 'Z'); // Upper-case alphabetic
- defCtype("XDigit",ASCII.XDIGIT); // hexadecimal digits
+ // Java character properties, defined by methods in Character.java
+ case "javaLowerCase": return java.lang.Character::isLowerCase;
+ case "javaUpperCase": return Character::isUpperCase;
+ case "javaAlphabetic": return java.lang.Character::isAlphabetic;
+ case "javaIdeographic": return java.lang.Character::isIdeographic;
+ case "javaTitleCase": return java.lang.Character::isTitleCase;
+ case "javaDigit": return java.lang.Character::isDigit;
+ case "javaDefined": return java.lang.Character::isDefined;
+ case "javaLetter": return java.lang.Character::isLetter;
+ case "javaLetterOrDigit": return java.lang.Character::isLetterOrDigit;
+ case "javaJavaIdentifierStart": return java.lang.Character::isJavaIdentifierStart;
+ case "javaJavaIdentifierPart": return java.lang.Character::isJavaIdentifierPart;
+ case "javaUnicodeIdentifierStart": return java.lang.Character::isUnicodeIdentifierStart;
+ case "javaUnicodeIdentifierPart": return java.lang.Character::isUnicodeIdentifierPart;
+ case "javaIdentifierIgnorable": return java.lang.Character::isIdentifierIgnorable;
+ case "javaSpaceChar": return java.lang.Character::isSpaceChar;
+ case "javaWhitespace": return java.lang.Character::isWhitespace;
+ case "javaISOControl": return java.lang.Character::isISOControl;
+ case "javaMirrored": return java.lang.Character::isMirrored;
+ default: return null;
+ }
+ }
- // Java character properties, defined by methods in Character.java
- defProp("javaLowerCase", java.lang.Character::isLowerCase);
- defProp("javaUpperCase", Character::isUpperCase);
- defProp("javaAlphabetic", java.lang.Character::isAlphabetic);
- defProp("javaIdeographic", java.lang.Character::isIdeographic);
- defProp("javaTitleCase", java.lang.Character::isTitleCase);
- defProp("javaDigit", java.lang.Character::isDigit);
- defProp("javaDefined", java.lang.Character::isDefined);
- defProp("javaLetter", java.lang.Character::isLetter);
- defProp("javaLetterOrDigit", java.lang.Character::isLetterOrDigit);
- defProp("javaJavaIdentifierStart", java.lang.Character::isJavaIdentifierStart);
- defProp("javaJavaIdentifierPart", java.lang.Character::isJavaIdentifierPart);
- defProp("javaUnicodeIdentifierStart", java.lang.Character::isUnicodeIdentifierStart);
- defProp("javaUnicodeIdentifierPart", java.lang.Character::isUnicodeIdentifierPart);
- defProp("javaIdentifierIgnorable", java.lang.Character::isIdentifierIgnorable);
- defProp("javaSpaceChar", java.lang.Character::isSpaceChar);
- defProp("javaWhitespace", java.lang.Character::isWhitespace);
- defProp("javaISOControl", java.lang.Character::isISOControl);
- defProp("javaMirrored", java.lang.Character::isMirrored);
+ private static CharPredicate category(final int typeMask) {
+ return ch -> (typeMask & (1 << Character.getType(ch))) != 0;
+ }
+
+ private static CharPredicate range(final int lower, final int upper) {
+ return (BmpCharPredicate)ch -> lower <= ch && ch <= upper;
+ }
+
+ private static CharPredicate ctype(final int ctype) {
+ return (BmpCharPredicate)ch -> ch < 128 && ASCII.isType(ch, ctype);
}
/////////////////////////////////////////////////////////////////////////////
@@ -369,8 +385,14 @@
/**
* Posix ASCII variants, not in the lookup map
*/
- static final BmpCharPredicate ASCII_DIGIT = ch -> ch < 128 && ASCII.isDigit(ch);
- static final BmpCharPredicate ASCII_WORD = ch -> ch < 128 && ASCII.isWord(ch);
- static final BmpCharPredicate ASCII_SPACE = ch -> ch < 128 && ASCII.isSpace(ch);
+ static final BmpCharPredicate ASCII_DIGIT() {
+ return ch -> ch < 128 && ASCII.isDigit(ch);
+ }
+ static final BmpCharPredicate ASCII_WORD() {
+ return ch -> ch < 128 && ASCII.isWord(ch);
+ }
+ static final BmpCharPredicate ASCII_SPACE() {
+ return ch -> ch < 128 && ASCII.isSpace(ch);
+ }
}
--- a/jdk/src/java.base/share/classes/java/util/regex/Pattern.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/regex/Pattern.java Thu Feb 09 23:15:52 2017 +0100
@@ -1495,7 +1495,7 @@
altns.add(seq);
produceEquivalentAlternation(nfd, altns);
dst.append("(?:");
- altns.forEach( s -> dst.append(s + "|"));
+ altns.forEach( s -> dst.append(s).append('|'));
dst.delete(dst.length() - 1, dst.length());
dst.append(")");
continue;
@@ -2142,12 +2142,12 @@
case '.':
next();
if (has(DOTALL)) {
- node = new CharProperty(ALL);
+ node = new CharProperty(ALL());
} else {
if (has(UNIX_LINES)) {
- node = new CharProperty(UNIXDOT);
+ node = new CharProperty(UNIXDOT());
} else {
- node = new CharProperty(DOT);
+ node = new CharProperty(DOT());
}
}
break;
@@ -2376,7 +2376,7 @@
case 'D':
if (create) {
predicate = has(UNICODE_CHARACTER_CLASS) ?
- CharPredicates.DIGIT : CharPredicates.ASCII_DIGIT;
+ CharPredicates.DIGIT() : CharPredicates.ASCII_DIGIT();
predicate = predicate.negate();
if (!inclass)
root = newCharProperty(predicate);
@@ -2391,7 +2391,7 @@
return -1;
case 'H':
if (create) {
- predicate = HorizWS.negate();
+ predicate = HorizWS().negate();
if (!inclass)
root = newCharProperty(predicate);
}
@@ -2415,7 +2415,7 @@
case 'S':
if (create) {
predicate = has(UNICODE_CHARACTER_CLASS) ?
- CharPredicates.WHITE_SPACE : CharPredicates.ASCII_SPACE;
+ CharPredicates.WHITE_SPACE() : CharPredicates.ASCII_SPACE();
predicate = predicate.negate();
if (!inclass)
root = newCharProperty(predicate);
@@ -2426,7 +2426,7 @@
break;
case 'V':
if (create) {
- predicate = VertWS.negate();
+ predicate = VertWS().negate();
if (!inclass)
root = newCharProperty(predicate);
}
@@ -2434,7 +2434,7 @@
case 'W':
if (create) {
predicate = has(UNICODE_CHARACTER_CLASS) ?
- CharPredicates.WORD : CharPredicates.ASCII_WORD;
+ CharPredicates.WORD() : CharPredicates.ASCII_WORD();
predicate = predicate.negate();
if (!inclass)
root = newCharProperty(predicate);
@@ -2480,7 +2480,7 @@
case 'd':
if (create) {
predicate = has(UNICODE_CHARACTER_CLASS) ?
- CharPredicates.DIGIT : CharPredicates.ASCII_DIGIT;
+ CharPredicates.DIGIT() : CharPredicates.ASCII_DIGIT();
if (!inclass)
root = newCharProperty(predicate);
}
@@ -2493,7 +2493,7 @@
break;
case 'h':
if (create) {
- predicate = HorizWS;
+ predicate = HorizWS();
if (!inclass)
root = newCharProperty(predicate);
}
@@ -2531,7 +2531,7 @@
case 's':
if (create) {
predicate = has(UNICODE_CHARACTER_CLASS) ?
- CharPredicates.WHITE_SPACE : CharPredicates.ASCII_SPACE;
+ CharPredicates.WHITE_SPACE() : CharPredicates.ASCII_SPACE();
if (!inclass)
root = newCharProperty(predicate);
}
@@ -2552,7 +2552,7 @@
if (isrange)
return '\013';
if (create) {
- predicate = VertWS;
+ predicate = VertWS();
if (!inclass)
root = newCharProperty(predicate);
}
@@ -2560,7 +2560,7 @@
case 'w':
if (create) {
predicate = has(UNICODE_CHARACTER_CLASS) ?
- CharPredicates.WORD : CharPredicates.ASCII_WORD;
+ CharPredicates.WORD() : CharPredicates.ASCII_WORD();
if (!inclass)
root = newCharProperty(predicate);
}
@@ -2704,7 +2704,6 @@
(6)AngstromSign u+212b
toLowerCase(u+212b) ==> u+00e5
*/
- int d;
if (ch < 256 &&
!(has(CASE_INSENSITIVE) && has(UNICODE_CASE) &&
(ch == 0xff || ch == 0xb5 ||
@@ -5384,7 +5383,7 @@
}
boolean isWord(int ch) {
- return useUWORD ? CharPredicates.WORD.is(ch)
+ return useUWORD ? CharPredicates.WORD().is(ch)
: (ch == '_' || Character.isLetterOrDigit(ch));
}
@@ -5680,33 +5679,45 @@
/**
* matches a Perl vertical whitespace
*/
- static BmpCharPredicate VertWS = cp ->
- (cp >= 0x0A && cp <= 0x0D) || cp == 0x85 || cp == 0x2028 || cp == 0x2029;
+ static BmpCharPredicate VertWS() {
+ return cp -> (cp >= 0x0A && cp <= 0x0D) ||
+ cp == 0x85 || cp == 0x2028 || cp == 0x2029;
+ }
/**
* matches a Perl horizontal whitespace
*/
- static BmpCharPredicate HorizWS = cp ->
- cp == 0x09 || cp == 0x20 || cp == 0xa0 || cp == 0x1680 ||
- cp == 0x180e || cp >= 0x2000 && cp <= 0x200a || cp == 0x202f ||
- cp == 0x205f || cp == 0x3000;
+ static BmpCharPredicate HorizWS() {
+ return cp ->
+ cp == 0x09 || cp == 0x20 || cp == 0xa0 || cp == 0x1680 ||
+ cp == 0x180e || cp >= 0x2000 && cp <= 0x200a || cp == 0x202f ||
+ cp == 0x205f || cp == 0x3000;
+ }
/**
* for the Unicode category ALL and the dot metacharacter when
* in dotall mode.
*/
- static CharPredicate ALL = ch -> true;
+ static CharPredicate ALL() {
+ return ch -> true;
+ }
/**
* for the dot metacharacter when dotall is not enabled.
*/
- static CharPredicate DOT = ch -> (ch != '\n' && ch != '\r'
- && (ch|1) != '\u2029'
- && ch != '\u0085');
+ static CharPredicate DOT() {
+ return ch ->
+ (ch != '\n' && ch != '\r'
+ && (ch|1) != '\u2029'
+ && ch != '\u0085');
+ }
+
/**
* the dot metacharacter when dotall is not enabled but UNIX_LINES is enabled.
*/
- static CharPredicate UNIXDOT = ch -> ch != '\n';
+ static CharPredicate UNIXDOT() {
+ return ch -> ch != '\n';
+ }
/**
* Indicate that matches a Supplementary Unicode character
--- a/jdk/src/java.base/share/classes/java/util/regex/PrintPattern.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/regex/PrintPattern.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,6 @@
import java.util.HashMap;
import java.util.regex.Pattern.CharPredicate;
-import java.util.regex.CharPredicates;
import static java.util.regex.ASCII.*;
/**
@@ -106,15 +105,15 @@
static HashMap<CharPredicate, String> pmap;
static {
pmap = new HashMap<>();
- pmap.put(Pattern.ALL, "All");
- pmap.put(Pattern.DOT, "Dot");
- pmap.put(Pattern.UNIXDOT, "UnixDot");
- pmap.put(Pattern.VertWS, "VertWS");
- pmap.put(Pattern.HorizWS, "HorizWS");
+ pmap.put(Pattern.ALL(), "All");
+ pmap.put(Pattern.DOT(), "Dot");
+ pmap.put(Pattern.UNIXDOT(), "UnixDot");
+ pmap.put(Pattern.VertWS(), "VertWS");
+ pmap.put(Pattern.HorizWS(), "HorizWS");
- pmap.put(CharPredicates.ASCII_DIGIT, "ASCII.DIGIT");
- pmap.put(CharPredicates.ASCII_WORD, "ASCII.WORD");
- pmap.put(CharPredicates.ASCII_SPACE, "ASCII.SPACE");
+ pmap.put(CharPredicates.ASCII_DIGIT(), "ASCII.DIGIT");
+ pmap.put(CharPredicates.ASCII_WORD(), "ASCII.WORD");
+ pmap.put(CharPredicates.ASCII_SPACE(), "ASCII.SPACE");
}
static void walk(Pattern.Node node, int depth) {
--- a/jdk/src/java.base/share/classes/java/util/spi/ResourceBundleControlProvider.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/java/util/spi/ResourceBundleControlProvider.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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,19 +35,19 @@
* no {@link java.util.ResourceBundle.Control} instance can be modified with {@code
* ResourceBundleControlProvider} implementations.
*
+ * <p>Provider implementations are loaded from the application's class path
+ * using {@link java.util.ServiceLoader} at the first invocation of the
+ * {@code ResourceBundle.getBundle} factory method that takes no
+ * {@link java.util.ResourceBundle.Control} instance.
+ *
+ * <p>All {@code ResourceBundleControlProvider}s are ignored in named modules.
+ *
* @author Masayoshi Okutsu
* @since 1.8
* @see ResourceBundle#getBundle(String, java.util.Locale, ClassLoader, ResourceBundle.Control)
* ResourceBundle.getBundle
- * @see java.util.ServiceLoader#loadInstalled(Class)
- * @deprecated There is no longer any mechanism to install a custom
- * {@code ResourceBundleControlProvider} implementation defined
- * by the platform class loader or its ancestor. The recommended
- * way to use a custom {@code Control} implementation to load resource bundle
- * is to use {@link java.util.ResourceBundle#getBundle(String, Control)}
- * or other factory methods that take custom {@link java.util.ResourceBundle.Control}.
+ * @see java.util.ServiceLoader#load(Class)
*/
-@Deprecated(since="9", forRemoval=true)
public interface ResourceBundleControlProvider {
/**
* Returns a {@code ResourceBundle.Control} instance that is used
--- a/jdk/src/java.base/share/classes/javax/net/ssl/HandshakeCompletedEvent.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/HandshakeCompletedEvent.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -159,11 +159,10 @@
* @exception SSLPeerUnverifiedException if the peer is not verified.
* @see #getPeerPrincipal()
* @deprecated The {@link #getPeerCertificates()} method that returns an
- * array of {@code java.security.cert.Certificate} should
- * be used instead. This method is subject to removal in
- * a future version of Java SE.
+ * array of {@code java.security.cert.Certificate} should
+ * be used instead.
*/
- @Deprecated(since="9", forRemoval=true)
+ @Deprecated(since="9")
public javax.security.cert.X509Certificate [] getPeerCertificateChain()
throws SSLPeerUnverifiedException
{
--- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLSession.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLSession.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -279,11 +279,10 @@
* has not been verified
* @see #getPeerPrincipal()
* @deprecated The {@link #getPeerCertificates()} method that returns an
- * array of {@code java.security.cert.Certificate} should
- * be used instead. This method is subject to removal in
- * a future version of Java SE.
+ * array of {@code java.security.cert.Certificate} should
+ * be used instead.
*/
- @Deprecated(since="9", forRemoval=true)
+ @Deprecated(since="9")
public javax.security.cert.X509Certificate [] getPeerCertificateChain()
throws SSLPeerUnverifiedException;
--- a/jdk/src/java.base/share/classes/javax/security/auth/Policy.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/javax/security/auth/Policy.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, 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
@@ -152,11 +152,10 @@
*
* These two APIs provide callers the means to query the
* Policy for Principal-based Permission entries.
- * This class is subject to removal in a future version of Java SE.
*
* @see java.security.Security security properties
*/
-@Deprecated(since="1.4", forRemoval=true)
+@Deprecated(since="1.4")
public abstract class Policy {
private static Policy policy;
--- a/jdk/src/java.base/share/classes/javax/security/cert/Certificate.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/javax/security/cert/Certificate.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -58,11 +58,10 @@
* @since 1.4
* @see X509Certificate
* @deprecated Use the classes in {@code java.security.cert} instead.
- * This class is subject to removal in a future version of Java SE.
*
* @author Hemma Prafullchandra
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public abstract class Certificate {
/**
--- a/jdk/src/java.base/share/classes/javax/security/cert/CertificateEncodingException.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/javax/security/cert/CertificateEncodingException.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -39,9 +39,8 @@
* @since 1.4
* @author Hemma Prafullchandra
* @deprecated Use the classes in {@code java.security.cert} instead.
- * This class is subject to removal in a future version of Java SE.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public class CertificateEncodingException extends CertificateException {
private static final long serialVersionUID = -8187642723048403470L;
--- a/jdk/src/java.base/share/classes/javax/security/cert/CertificateException.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/javax/security/cert/CertificateException.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, 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
@@ -39,9 +39,8 @@
* @since 1.4
* @see Certificate
* @deprecated Use the classes in {@code java.security.cert} instead.
- * This class is subject to removal in a future version of Java SE.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public class CertificateException extends Exception {
private static final long serialVersionUID = -5757213374030785290L;
--- a/jdk/src/java.base/share/classes/javax/security/cert/CertificateExpiredException.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/javax/security/cert/CertificateExpiredException.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -41,9 +41,8 @@
* @since 1.4
* @author Hemma Prafullchandra
* @deprecated Use the classes in {@code java.security.cert} instead.
- * This class is subject to removal in a future version of Java SE.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public class CertificateExpiredException extends CertificateException {
private static final long serialVersionUID = 5091601212177261883L;
--- a/jdk/src/java.base/share/classes/javax/security/cert/CertificateNotYetValidException.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/javax/security/cert/CertificateNotYetValidException.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -41,9 +41,8 @@
* @since 1.4
* @author Hemma Prafullchandra
* @deprecated Use the classes in {@code java.security.cert} instead.
- * This class is subject to removal in a future version of Java SE.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public class CertificateNotYetValidException extends CertificateException {
private static final long serialVersionUID = -8976172474266822818L;
--- a/jdk/src/java.base/share/classes/javax/security/cert/CertificateParsingException.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/javax/security/cert/CertificateParsingException.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -40,9 +40,8 @@
* @since 1.4
* @author Hemma Prafullchandra
* @deprecated Use the classes in {@code java.security.cert} instead.
- * This class is subject to removal in a future version of Java SE.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public class CertificateParsingException extends CertificateException {
private static final long serialVersionUID = -8449352422951136229L;
--- a/jdk/src/java.base/share/classes/javax/security/cert/X509Certificate.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/javax/security/cert/X509Certificate.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -125,9 +125,8 @@
* @see java.security.cert.X509Extension
* @see java.security.Security security properties
* @deprecated Use the classes in {@code java.security.cert} instead.
- * This class is subject to removal in a future version of Java SE.
*/
-@Deprecated(since="9", forRemoval=true)
+@Deprecated(since="9")
public abstract class X509Certificate extends Certificate {
/*
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java Thu Feb 09 23:15:52 2017 +0100
@@ -53,21 +53,21 @@
// the input stream to read the original module-info.class
private final InputStream in;
- // the packages in the Packages attribute
+ // the packages in the ModulePackages attribute
private Set<String> packages;
- // the value of the Version attribute
+ // the value of the module_version in Module attribute
private Version version;
- // the value of the MainClass attribute
+ // the value of the ModuleMainClass attribute
private String mainClass;
- // the values for the TargetPlatform attribute
+ // the values for the ModuleTarget attribute
private String osName;
private String osArch;
private String osVersion;
- // the hashes for the Hashes attribute
+ // the hashes for the ModuleHashes attribute
private ModuleHashes hashes;
// the value of the ModuleResolution attribute
@@ -78,7 +78,7 @@
}
/**
- * Sets the set of packages for the Packages attribute
+ * Sets the set of packages for the ModulePackages attribute
*/
public ModuleInfoExtender packages(Set<String> packages) {
this.packages = Collections.unmodifiableSet(packages);
@@ -86,7 +86,7 @@
}
/**
- * Sets the value of the Version attribute.
+ * Sets the value of the module_version in Module attribute.
*/
public ModuleInfoExtender version(Version version) {
this.version = version;
@@ -94,7 +94,7 @@
}
/**
- * Sets the value of the MainClass attribute.
+ * Sets the value of the ModuleMainClass attribute.
*/
public ModuleInfoExtender mainClass(String mainClass) {
this.mainClass = mainClass;
@@ -102,7 +102,7 @@
}
/**
- * Sets the values for the TargetPlatform attribute.
+ * Sets the values for the ModuleTarget attribute.
*/
public ModuleInfoExtender targetPlatform(String osName,
String osArch,
@@ -114,7 +114,7 @@
}
/**
- * The Hashes attribute will be emitted to the module-info with
+ * The ModuleHashes attribute will be emitted to the module-info with
* the hashes encapsulated in the given {@code ModuleHashes}
* object.
*/
--- a/jdk/src/java.base/share/classes/module-info.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/module-info.java Thu Feb 09 23:15:52 2017 +0100
@@ -150,7 +150,7 @@
java.desktop;
exports jdk.internal.module to
java.instrument,
- java.management,
+ java.management.rmi,
jdk.jartool,
jdk.jlink;
exports jdk.internal.misc to
@@ -177,6 +177,7 @@
exports jdk.internal.perf to
java.desktop,
java.management,
+ jdk.management.agent,
jdk.internal.jvmstat;
exports jdk.internal.ref to
java.desktop,
@@ -196,7 +197,7 @@
jdk.jdeps,
jdk.jlink;
exports jdk.internal.vm to
- java.management,
+ jdk.management.agent,
jdk.internal.jvmstat;
exports sun.net to
jdk.incubator.httpclient;
@@ -233,6 +234,7 @@
java.desktop,
java.datatransfer,
java.management,
+ java.management.rmi,
java.rmi,
java.sql.rowset,
java.xml,
--- a/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java Thu Feb 09 23:15:52 2017 +0100
@@ -581,12 +581,18 @@
}
// load the class from the module
- Class<?> c = Class.forName(m, mainClass);
- if (c == null && System.getProperty("os.name", "").contains("OS X")
- && Normalizer.isNormalized(mainClass, Normalizer.Form.NFD)) {
+ Class<?> c = null;
+ try {
+ c = Class.forName(m, mainClass);
+ if (c == null && System.getProperty("os.name", "").contains("OS X")
+ && Normalizer.isNormalized(mainClass, Normalizer.Form.NFD)) {
- String cn = Normalizer.normalize(mainClass, Normalizer.Form.NFC);
- c = Class.forName(m, cn);
+ String cn = Normalizer.normalize(mainClass, Normalizer.Form.NFC);
+ c = Class.forName(m, cn);
+ }
+ } catch (LinkageError le) {
+ abort(null, "java.launcher.module.error3", mainClass, m.getName(),
+ le.getClass().getName() + ": " + le.getLocalizedMessage());
}
if (c == null) {
abort(null, "java.launcher.module.error2", mainClass, mainModule);
@@ -619,23 +625,28 @@
Class<?> mainClass = null;
ClassLoader scl = ClassLoader.getSystemClassLoader();
try {
- mainClass = Class.forName(cn, false, scl);
- } catch (NoClassDefFoundError | ClassNotFoundException cnfe) {
- if (System.getProperty("os.name", "").contains("OS X")
- && Normalizer.isNormalized(cn, Normalizer.Form.NFD)) {
- try {
- // On Mac OS X since all names with diacritical marks are
- // given as decomposed it is possible that main class name
- // comes incorrectly from the command line and we have
- // to re-compose it
- String ncn = Normalizer.normalize(cn, Normalizer.Form.NFC);
- mainClass = Class.forName(ncn, false, scl);
- } catch (NoClassDefFoundError | ClassNotFoundException cnfe1) {
+ try {
+ mainClass = Class.forName(cn, false, scl);
+ } catch (NoClassDefFoundError | ClassNotFoundException cnfe) {
+ if (System.getProperty("os.name", "").contains("OS X")
+ && Normalizer.isNormalized(cn, Normalizer.Form.NFD)) {
+ try {
+ // On Mac OS X since all names with diacritical marks are
+ // given as decomposed it is possible that main class name
+ // comes incorrectly from the command line and we have
+ // to re-compose it
+ String ncn = Normalizer.normalize(cn, Normalizer.Form.NFC);
+ mainClass = Class.forName(ncn, false, scl);
+ } catch (NoClassDefFoundError | ClassNotFoundException cnfe1) {
+ abort(cnfe1, "java.launcher.cls.error1", cn);
+ }
+ } else {
abort(cnfe, "java.launcher.cls.error1", cn);
}
- } else {
- abort(cnfe, "java.launcher.cls.error1", cn);
}
+ } catch (LinkageError le) {
+ abort(le, "java.launcher.cls.error6", cn,
+ le.getClass().getName() + ": " + le.getLocalizedMessage());
}
return mainClass;
}
--- a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties Thu Feb 09 23:15:52 2017 +0100
@@ -189,6 +189,9 @@
or a JavaFX application class must extend {1}
java.launcher.cls.error5=\
Error: JavaFX runtime components are missing, and are required to run this application
+java.launcher.cls.error6=\
+ Error: LinkageError occurred while loading main class {0}\n\
+ \t{1}
java.launcher.jar.error1=\
Error: An unexpected error occurred while trying to open file {0}
java.launcher.jar.error2=manifest not found in {0}
@@ -201,3 +204,7 @@
module {0} does not have a MainClass attribute, use -m <module>/<main-class>
java.launcher.module.error2=\
Error: Could not find or load main class {0} in module {1}
+java.launcher.module.error3=\
+ Error: Unable to load main class {0} from module {1}\n\
+ \t{2}
+
--- a/jdk/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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,16 +30,19 @@
import java.net.ProxySelector;
import java.net.SocketAddress;
import java.net.URI;
-import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.io.IOException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.StringJoiner;
import java.util.regex.Pattern;
+import java.util.stream.Stream;
import sun.net.NetProperties;
import sun.net.SocksProxy;
import static java.util.regex.Pattern.quote;
+import static java.util.stream.Collectors.collectingAndThen;
+import static java.util.stream.Collectors.toList;
/**
* Supports proxy settings using system properties This proxy selector
@@ -87,6 +90,8 @@
private static boolean hasSystemProxies = false;
+ private static final List<Proxy> NO_PROXY_LIST = List.of(Proxy.NO_PROXY);
+
static {
final String key = "java.net.useSystemProxies";
Boolean b = AccessController.doPrivileged(
@@ -149,8 +154,9 @@
* select() method. Where all the hard work is done.
* Build a list of proxies depending on URI.
* Since we're only providing compatibility with the system properties
- * from previous releases (see list above), that list will always
- * contain 1 single proxy, default being NO_PROXY.
+ * from previous releases (see list above), that list will typically
+ * contain one single proxy, default being NO_PROXY.
+ * If we can get a system proxy it might contain more entries.
*/
public java.util.List<Proxy> select(URI uri) {
if (uri == null) {
@@ -185,7 +191,6 @@
if (protocol == null || host == null) {
throw new IllegalArgumentException("protocol = "+protocol+" host = "+host);
}
- List<Proxy> proxyl = new ArrayList<Proxy>(1);
NonProxyInfo pinfo = null;
@@ -214,9 +219,9 @@
* System properties it does help having only 1 call to doPrivileged.
* Be mindful what you do in here though!
*/
- Proxy p = AccessController.doPrivileged(
- new PrivilegedAction<Proxy>() {
- public Proxy run() {
+ Proxy[] proxyArray = AccessController.doPrivileged(
+ new PrivilegedAction<Proxy[]>() {
+ public Proxy[] run() {
int i, j;
String phost = null;
int pport = 0;
@@ -239,8 +244,8 @@
/**
* No system property defined for that
* protocol. Let's check System Proxy
- * settings (Gnome & Windows) if we were
- * instructed to.
+ * settings (Gnome, MacOsX & Windows) if
+ * we were instructed to.
*/
if (hasSystemProxies) {
String sproto;
@@ -248,12 +253,9 @@
sproto = "socks";
else
sproto = proto;
- Proxy sproxy = getSystemProxy(sproto, urlhost);
- if (sproxy != null) {
- return sproxy;
- }
+ return getSystemProxies(sproto, urlhost);
}
- return Proxy.NO_PROXY;
+ return null;
}
// If a Proxy Host is defined for that protocol
// Let's get the NonProxyHosts property
@@ -281,7 +283,7 @@
}
}
if (shouldNotUseProxyFor(nprop.pattern, urlhost)) {
- return Proxy.NO_PROXY;
+ return null;
}
}
}
@@ -311,22 +313,24 @@
saddr = InetSocketAddress.createUnresolved(phost, pport);
// Socks is *always* the last on the list.
if (j == (props[i].length - 1)) {
- return SocksProxy.create(saddr, socksProxyVersion());
- } else {
- return new Proxy(Proxy.Type.HTTP, saddr);
+ return new Proxy[] {SocksProxy.create(saddr, socksProxyVersion())};
}
+ return new Proxy[] {new Proxy(Proxy.Type.HTTP, saddr)};
}
}
- return Proxy.NO_PROXY;
+ return null;
}});
- proxyl.add(p);
- /*
- * If no specific property was set for that URI, we should be
- * returning an iterator to an empty List.
- */
- return proxyl;
+ if (proxyArray != null) {
+ // Remove duplicate entries, while preserving order.
+ return Stream.of(proxyArray).distinct().collect(
+ collectingAndThen(toList(), Collections::unmodifiableList));
+ }
+
+ // If no specific proxy was found, return a standard list containing
+ // only one NO_PROXY entry.
+ return NO_PROXY_LIST;
}
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
@@ -354,7 +358,7 @@
}
private static native boolean init();
- private synchronized native Proxy getSystemProxy(String protocol, String host);
+ private synchronized native Proxy[] getSystemProxies(String protocol, String host);
/**
* @return {@code true} if given this pattern for non-proxy hosts and this
--- a/jdk/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/pkcs12/PKCS12KeyStore.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, 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
@@ -982,7 +982,7 @@
new CertEntry((X509Certificate) cert, null, alias, AnyUsage,
attributes);
certificateCount++;
- entries.put(alias, certEntry);
+ entries.put(alias.toLowerCase(Locale.ENGLISH), certEntry);
if (debug != null) {
debug.println("Setting a trusted certificate at alias '" + alias +
--- a/jdk/src/java.base/share/classes/sun/security/ssl/EllipticCurvesExtension.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/EllipticCurvesExtension.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2017, 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
@@ -43,6 +43,9 @@
final class EllipticCurvesExtension extends HelloExtension {
+ /* Class and subclass dynamic debugging support */
+ private static final Debug debug = Debug.getInstance("ssl");
+
private static final int ARBITRARY_PRIME = 0xff01;
private static final int ARBITRARY_CHAR2 = 0xff02;
@@ -159,6 +162,11 @@
} // ignore unknown curves
}
}
+ if (idList.isEmpty() && JsseJce.isEcAvailable()) {
+ throw new IllegalArgumentException(
+ "System property jdk.tls.namedGroups(" + property + ") " +
+ "contains no supported elliptic curves");
+ }
} else { // default curves
int[] ids;
if (requireFips) {
@@ -183,16 +191,17 @@
}
}
- if (idList.isEmpty()) {
- throw new IllegalArgumentException(
- "System property jdk.tls.namedGroups(" + property + ") " +
- "contains no supported elliptic curves");
- } else {
- supportedCurveIds = new int[idList.size()];
- int i = 0;
- for (Integer id : idList) {
- supportedCurveIds[i++] = id;
- }
+ if (debug != null && idList.isEmpty()) {
+ Debug.log(
+ "Initialized [jdk.tls.namedGroups|default] list contains " +
+ "no available elliptic curves. " +
+ (property != null ? "(" + property + ")" : "[Default]"));
+ }
+
+ supportedCurveIds = new int[idList.size()];
+ int i = 0;
+ for (Integer id : idList) {
+ supportedCurveIds[i++] = id;
}
}
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/CalendarNameProviderImpl.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/CalendarNameProviderImpl.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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,8 @@
import java.util.Set;
import java.util.TreeMap;
import java.util.spi.CalendarNameProvider;
+import sun.util.calendar.CalendarSystem;
+import sun.util.calendar.Era;
/**
* Concrete implementation of the {@link java.util.spi.CalendarDataProvider
@@ -75,7 +77,21 @@
if (field == DAY_OF_WEEK || field == YEAR) {
--value;
}
- if (value < 0 || value >= strings.length) {
+ if (value < 0 || value > strings.length) {
+ return null;
+ } else if (value == strings.length) {
+ if (field == ERA && "japanese".equals(calendarType)) {
+ // get the supplemental era, if any, specified through
+ // the property "jdk.calendar.japanese.supplemental.era"
+ // which is always the last element.
+ Era[] jeras = CalendarSystem.forName("japanese").getEras();
+ if (jeras.length == value) {
+ Era supEra = jeras[value - 1]; // 0-based index
+ return style == LONG ?
+ supEra.getName() :
+ supEra.getAbbreviation();
+ }
+ }
return null;
}
name = strings[value];
--- a/jdk/src/java.base/share/conf/security/java.security Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/conf/security/java.security Thu Feb 09 23:15:52 2017 +0100
@@ -116,6 +116,13 @@
# Example:
# jdk.security.provider.preferred=AES/GCM/NoPadding:SunJCE, \
# MessageDigest.SHA-256:SUN, Group.HmacSHA2:SunJCE
+#
+#ifdef solaris-sparc
+# Optional Solaris-SPARC configuration for non-FIPS 140 configurations.
+# jdk.security.provider.preferred=AES:SunJCE, SHA1:SUN, Group.SHA2:SUN, \
+# HmacSHA1:SunJCE, Group.HmacSHA2:SunJCE
+#
+#endif
#jdk.security.provider.preferred=
@@ -240,6 +247,7 @@
#
# The default value is an empty string, which is equivalent to
# securerandom.drbg.config=Hash_DRBG,SHA-256,128,none
+#
securerandom.drbg.config=
#
@@ -262,23 +270,27 @@
# The default is to have a single system-wide policy file,
# and a policy file in the user's home directory.
+#
policy.url.1=file:${java.home}/conf/security/java.policy
policy.url.2=file:${user.home}/.java.policy
# whether or not we expand properties in the policy file
# if this is set to false, properties (${...}) will not be expanded in policy
# files.
+#
policy.expandProperties=true
# whether or not we allow an extra policy to be passed on the command line
# with -Djava.security.policy=somefile. Comment out this line to disable
# this feature.
+#
policy.allowSystemProperty=true
# whether or not we look into the IdentityScope for trusted Identities
# when encountering a 1.1 signed JAR file. If the identity is found
# and is trusted, we grant it AllPermission. Note: the default policy
# provider (sun.security.provider.PolicyFile) does not support this property.
+#
policy.ignoreIdentityScope=false
#
@@ -360,7 +372,6 @@
# For this reason the default caching policy is to maintain these
# results for 10 seconds.
#
-#
networkaddress.cache.negative.ttl=10
#
@@ -460,8 +471,10 @@
# Example,
# krb5.kdc.bad.policy = tryLast
# krb5.kdc.bad.policy = tryLess:2,2000
+#
krb5.kdc.bad.policy = tryLast
+#
# Algorithm restrictions for certification path (CertPath) processing
#
# In some environments, certain algorithms or key lengths may be undesirable
@@ -572,35 +585,6 @@
RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224
#
-# RMI Registry Serial Filter
-#
-# The filter pattern uses the same format as jdk.serialFilter.
-# This filter can override the builtin filter if additional types need to be
-# allowed or rejected from the RMI Registry.
-#
-# Note: This property is currently used by the JDK Reference implementation.
-# It is not guaranteed to be examined and used by other implementations.
-#
-#sun.rmi.registry.registryFilter=pattern;pattern
-#
-# RMI Distributed Garbage Collector (DGC) Serial Filter
-#
-# The filter pattern uses the same format as jdk.serialFilter.
-# This filter can override the builtin filter if additional types need to be
-# allowed or rejected from the RMI DGC.
-#
-# Note: This property is currently used by the JDK Reference implementation.
-# It is not guaranteed to be examined and used by other implementations.
-#
-# The builtin DGC filter can approximately be represented as the filter pattern:
-#
-#sun.rmi.transport.dgcFilter=\
-# java.rmi.server.ObjID;\
-# java.rmi.server.UID;\
-# java.rmi.dgc.VMID;\
-# java.rmi.dgc.Lease;\
-# maxdepth=5;maxarray=10000
-
# Algorithm restrictions for signed JAR files
#
# In some environments, certain algorithms or key lengths may be undesirable
@@ -639,6 +623,7 @@
jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
DSA keySize < 1024
+#
# Algorithm restrictions for Secure Socket Layer/Transport Layer Security
# (SSL/TLS/DTLS) processing
#
@@ -939,3 +924,32 @@
#
#jdk.serialFilter=pattern;pattern
+#
+# RMI Registry Serial Filter
+#
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI Registry.
+#
+# Note: This property is currently used by the JDK Reference implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+#sun.rmi.registry.registryFilter=pattern;pattern
+#
+# RMI Distributed Garbage Collector (DGC) Serial Filter
+#
+# The filter pattern uses the same format as jdk.serialFilter.
+# This filter can override the builtin filter if additional types need to be
+# allowed or rejected from the RMI DGC.
+#
+# Note: This property is currently used by the JDK Reference implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+# The builtin DGC filter can approximately be represented as the filter pattern:
+#
+#sun.rmi.transport.dgcFilter=\
+# java.rmi.server.ObjID;\
+# java.rmi.server.UID;\
+# java.rmi.dgc.VMID;\
+# java.rmi.dgc.Lease;\
+# maxdepth=5;maxarray=10000
--- a/jdk/src/java.base/share/lib/security/default.policy Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/lib/security/default.policy Thu Feb 09 23:15:52 2017 +0100
@@ -102,6 +102,8 @@
};
grant codeBase "jrt:/java.xml.ws" {
+ permission java.net.NetPermission
+ "getProxySelector";
permission java.lang.RuntimePermission
"accessClassInPackage.com.sun.org.apache.xml.internal.resolver";
permission java.lang.RuntimePermission
--- a/jdk/src/java.base/share/native/launcher/main.c Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/native/launcher/main.c Thu Feb 09 23:15:52 2017 +0100
@@ -130,10 +130,10 @@
// Add first arg, which is the app name
JLI_List_add(args, JLI_StringDup(argv[0]));
- // Append JAVA_OPTIONS
- if (JLI_AddArgsFromEnvVar(args, JAVA_OPTIONS)) {
+ // Append JDK_JAVA_OPTIONS
+ if (JLI_AddArgsFromEnvVar(args, JDK_JAVA_OPTIONS)) {
// JLI_SetTraceLauncher is not called yet
- // Show _JAVA_OPTIONS content along with JAVA_OPTIONS to aid diagnosis
+ // Show _JAVA_OPTIONS content along with JDK_JAVA_OPTIONS to aid diagnosis
if (getenv(JLDEBUG_ENV_ENTRY)) {
char *tmp = getenv("_JAVA_OPTIONS");
if (NULL != tmp) {
--- a/jdk/src/java.base/share/native/libjli/args.c Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/native/libjli/args.c Thu Feb 09 23:15:52 2017 +0100
@@ -34,7 +34,7 @@
#define NO_JNI
#endif
#define JLI_ReportMessage(...) printf(__VA_ARGS__)
- #define JAVA_OPTIONS "JAVA_OPTIONS"
+ #define JDK_JAVA_OPTIONS "JDK_JAVA_OPTIONS"
int IsWhiteSpaceOption(const char* name) { return 1; }
#else
#include "java.h"
--- a/jdk/src/java.base/share/native/libjli/java.c Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/native/libjli/java.c Thu Feb 09 23:15:52 2017 +0100
@@ -1587,7 +1587,7 @@
p = JLI_MemAlloc(optLen + valueLen + 1);
memcpy(p, arg, optLen);
memcpy(p + optLen, value, valueLen);
- p[optLen + valueLen + 1] = '\0';
+ p[optLen + valueLen] = '\0';
return p;
}
--- a/jdk/src/java.base/share/native/libjli/java.h Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/share/native/libjli/java.h Thu Feb 09 23:15:52 2017 +0100
@@ -71,7 +71,7 @@
#define SPLASH_FILE_ENV_ENTRY "_JAVA_SPLASH_FILE"
#define SPLASH_JAR_ENV_ENTRY "_JAVA_SPLASH_JAR"
-#define JAVA_OPTIONS "JAVA_OPTIONS"
+#define JDK_JAVA_OPTIONS "JDK_JAVA_OPTIONS"
/*
* Pointers to the needed JNI invocation API, initialized by LoadJavaVM.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/native/libnet/proxy_util.c Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2017, 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 "jni.h"
+#include "jni_util.h"
+
+#include "proxy_util.h"
+
+jclass proxy_class;
+jclass isaddr_class;
+jclass ptype_class;
+jmethodID isaddr_createUnresolvedID;
+jmethodID proxy_ctrID;
+jfieldID pr_no_proxyID;
+jfieldID ptype_httpID;
+jfieldID ptype_socksID;
+
+int initJavaClass(JNIEnv *env) {
+ jclass proxy_cls = NULL;
+ jclass ptype_cls = NULL;
+ jclass isaddr_cls = NULL;
+
+ // Proxy initialization
+ proxy_cls = (*env)->FindClass(env,"java/net/Proxy");
+ CHECK_NULL_RETURN(proxy_cls, 0);
+ proxy_class = (*env)->NewGlobalRef(env, proxy_cls);
+ CHECK_NULL_RETURN(proxy_class, 0);
+ proxy_ctrID = (*env)->GetMethodID(env, proxy_class, "<init>",
+ "(Ljava/net/Proxy$Type;Ljava/net/SocketAddress;)V");
+ CHECK_NULL_RETURN(proxy_ctrID, 0);
+
+ // Proxy$Type initialization
+ ptype_cls = (*env)->FindClass(env,"java/net/Proxy$Type");
+ CHECK_NULL_RETURN(ptype_cls, 0);
+ ptype_class = (*env)->NewGlobalRef(env, ptype_cls);
+ CHECK_NULL_RETURN(ptype_class, 0);
+ ptype_httpID = (*env)->GetStaticFieldID(env, ptype_class, "HTTP",
+ "Ljava/net/Proxy$Type;");
+ CHECK_NULL_RETURN(ptype_httpID, 0);
+ ptype_socksID = (*env)->GetStaticFieldID(env, ptype_class, "SOCKS",
+ "Ljava/net/Proxy$Type;");
+ CHECK_NULL_RETURN(ptype_socksID, 0);
+
+ // NO_PROXY
+ pr_no_proxyID = (*env)->GetStaticFieldID(env, proxy_class, "NO_PROXY",
+ "Ljava/net/Proxy;");
+ CHECK_NULL_RETURN(pr_no_proxyID, 0);
+
+ // InetSocketAddress initialization
+ isaddr_cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
+ CHECK_NULL_RETURN(isaddr_cls, 0);
+ isaddr_class = (*env)->NewGlobalRef(env, isaddr_cls);
+ CHECK_NULL_RETURN(isaddr_class, 0);
+ isaddr_createUnresolvedID = (*env)->GetStaticMethodID(env, isaddr_class,
+ "createUnresolved",
+ "(Ljava/lang/String;I)Ljava/net/InetSocketAddress;");
+
+ return isaddr_createUnresolvedID != NULL ? 1 : 0;
+}
+
+jobject createProxy(JNIEnv *env, jfieldID ptype_ID, const char* phost, unsigned short pport) {
+ jobject jProxy = NULL;
+ jobject type_proxy = NULL;
+ type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_ID);
+ if (type_proxy) {
+ jstring jhost = NULL;
+ jhost = (*env)->NewStringUTF(env, phost);
+ if (jhost) {
+ jobject isa = NULL;
+ isa = (*env)->CallStaticObjectMethod(env, isaddr_class,
+ isaddr_createUnresolvedID, jhost, pport);
+ if (isa) {
+ jProxy = (*env)->NewObject(env, proxy_class, proxy_ctrID,
+ type_proxy, isa);
+ }
+ }
+ }
+ return jProxy;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/native/libnet/proxy_util.h Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+extern jclass proxy_class;
+extern jclass isaddr_class;
+extern jclass ptype_class;
+extern jmethodID isaddr_createUnresolvedID;
+extern jmethodID proxy_ctrID;
+extern jfieldID pr_no_proxyID;
+extern jfieldID ptype_httpID;
+extern jfieldID ptype_socksID;
+
+int initJavaClass(JNIEnv *env);
+
+jobject createProxy(JNIEnv *env, jfieldID ptype_ID, const char* phost, unsigned short pport);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.fs;
+
+import java.nio.file.spi.FileSystemProvider;
+
+/**
+ * Creates this platform's default FileSystemProvider.
+ */
+
+public class DefaultFileSystemProvider {
+ private DefaultFileSystemProvider() { }
+
+ /**
+ * Returns the default FileSystemProvider.
+ */
+ public static FileSystemProvider create() {
+ return new SolarisFileSystemProvider();
+ }
+}
--- a/jdk/src/java.base/unix/classes/sun/nio/fs/DefaultFileSystemProvider.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2008, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.nio.fs;
-
-import java.nio.file.spi.FileSystemProvider;
-import sun.security.action.GetPropertyAction;
-
-/**
- * Creates this platform's default FileSystemProvider.
- */
-
-public class DefaultFileSystemProvider {
- private DefaultFileSystemProvider() { }
-
- @SuppressWarnings("unchecked")
- private static FileSystemProvider createProvider(String cn) {
- Class<FileSystemProvider> c;
- try {
- c = (Class<FileSystemProvider>)Class.forName(cn);
- } catch (ClassNotFoundException x) {
- throw new AssertionError(x);
- }
- try {
- @SuppressWarnings("deprecation")
- FileSystemProvider result = c.newInstance();
- return result;
- } catch (IllegalAccessException | InstantiationException x) {
- throw new AssertionError(x);
- }
- }
-
- /**
- * Returns the default FileSystemProvider.
- */
- public static FileSystemProvider create() {
- String osname = GetPropertyAction.privilegedGetProperty("os.name");
- if (osname.equals("SunOS"))
- return createProvider("sun.nio.fs.SolarisFileSystemProvider");
- if (osname.equals("Linux"))
- return createProvider("sun.nio.fs.LinuxFileSystemProvider");
- if (osname.contains("OS X"))
- return createProvider("sun.nio.fs.MacOSXFileSystemProvider");
- if (osname.equals("AIX"))
- return createProvider("sun.nio.fs.AixFileSystemProvider");
- throw new AssertionError("Platform not recognized");
- }
-}
--- a/jdk/src/java.base/unix/native/libnet/DefaultProxySelector.c Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/unix/native/libnet/DefaultProxySelector.c Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, 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,24 +23,20 @@
* questions.
*/
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "jvm_md.h"
-#include "jlong.h"
+
+#include "proxy_util.h"
+
#include "sun_net_spi_DefaultProxySelector.h"
-#include <dlfcn.h>
-#include <stdio.h>
-#include <stdlib.h>
-#if defined(__linux__) || defined(_ALLBSD_SOURCE)
-#include <string.h>
-#else
-#include <strings.h>
-#endif
-#ifndef CHECK_NULL_RETURN
-#define CHECK_NULL_RETURN(x, y) if ((x) == NULL) return y;
-#endif
/**
* These functions are used by the sun.net.spi.DefaultProxySelector class
@@ -112,43 +108,11 @@
static g_network_address_get_port_func* g_network_address_get_port = NULL;
static g_strfreev_func* g_strfreev = NULL;
-
-static jclass proxy_class;
-static jclass isaddr_class;
-static jclass ptype_class;
-static jmethodID isaddr_createUnresolvedID;
-static jmethodID proxy_ctrID;
-static jfieldID ptype_httpID;
-static jfieldID ptype_socksID;
-
-
static void* gconf_client = NULL;
static int use_gproxyResolver = 0;
static int use_gconf = 0;
-static jobject createProxy(JNIEnv *env, jfieldID ptype_ID,
- const char* phost, unsigned short pport)
-{
- jobject jProxy = NULL;
- jobject type_proxy = NULL;
- type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_ID);
- if (type_proxy) {
- jstring jhost = NULL;
- jhost = (*env)->NewStringUTF(env, phost);
- if (jhost) {
- jobject isa = NULL;
- isa = (*env)->CallStaticObjectMethod(env, isaddr_class,
- isaddr_createUnresolvedID, jhost, pport);
- if (isa) {
- jProxy = (*env)->NewObject(env, proxy_class, proxy_ctrID,
- type_proxy, isa);
- }
- }
- }
- return jProxy;
-}
-
static int initGConf() {
/**
* Let's try to load GConf-2 library
@@ -196,18 +160,18 @@
return 0;
}
-static jobject getProxyByGConf(JNIEnv *env, const char* cproto,
- const char* chost)
+static jobjectArray getProxyByGConf(JNIEnv *env, const char* cproto,
+ const char* chost)
{
char *phost = NULL;
char *mode = NULL;
int pport = 0;
int use_proxy = 0;
int use_same_proxy = 0;
- jobject proxy = NULL;
+ jobjectArray proxy_array = NULL;
jfieldID ptype_ID = ptype_httpID;
- // We only check manual proxy configurations
+ /* We only check manual proxy configurations */
mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL);
if (mode && !strcasecmp(mode, "manual")) {
/*
@@ -293,7 +257,7 @@
char *s;
/**
- * check for the exclude list (aka "No Proxy For" list).
+ * Check for the exclude list (aka "No Proxy For" list).
* It's a list of comma separated suffixes (e.g. domain name).
*/
noproxyfor = (*my_get_string_func)(gconf_client, "/system/proxy/no_proxy_for", NULL);
@@ -313,11 +277,25 @@
s = strtok_r(NULL, ", ", tmpbuf);
}
}
- if (use_proxy)
+ if (use_proxy) {
+ jobject proxy = NULL;
+ /* create a proxy array with one element. */
+ proxy_array = (*env)->NewObjectArray(env, 1, proxy_class, NULL);
+ if (proxy_array == NULL || (*env)->ExceptionCheck(env)) {
+ return NULL;
+ }
proxy = createProxy(env, ptype_ID, phost, pport);
+ if (proxy == NULL || (*env)->ExceptionCheck(env)) {
+ return NULL;
+ }
+ (*env)->SetObjectArrayElement(env, proxy_array, 0, proxy);
+ if ((*env)->ExceptionCheck(env)) {
+ return NULL;
+ }
+ }
}
- return proxy;
+ return proxy_array;
}
static int initGProxyResolver() {
@@ -371,8 +349,8 @@
return 1;
}
-static jobject getProxyByGProxyResolver(JNIEnv *env, const char* cproto,
- const char* chost)
+static jobjectArray getProxyByGProxyResolver(JNIEnv *env, const char *cproto,
+ const char *chost)
{
GProxyResolver* resolver = NULL;
char** proxies = NULL;
@@ -382,19 +360,19 @@
size_t hostLen = 0;
char* uri = NULL;
- jobject jProxy = NULL;
+ jobjectArray proxy_array = NULL;
resolver = (*g_proxy_resolver_get_default)();
if (resolver == NULL) {
return NULL;
}
- // Construct the uri, cproto + "://" + chost
+ /* Construct the uri, cproto + "://" + chost */
protoLen = strlen(cproto);
hostLen = strlen(chost);
uri = malloc(protoLen + hostLen + 4);
if (!uri) {
- // Out of memory
+ /* Out of memory */
return NULL;
}
memcpy(uri, cproto, protoLen);
@@ -414,22 +392,56 @@
if (proxies) {
if (!error) {
int i;
- for(i = 0; proxies[i] && !jProxy; i++) {
- if (strcmp(proxies[i], "direct://")) {
- GSocketConnectable* conn =
- (*g_network_address_parse_uri)(proxies[i], 0,
- &error);
- if (conn && !error) {
- const char* phost = NULL;
- unsigned short pport = 0;
- phost = (*g_network_address_get_hostname)(conn);
- pport = (*g_network_address_get_port)(conn);
- if (phost && pport > 0) {
- jfieldID ptype_ID = ptype_httpID;
- if (!strncmp(proxies[i], "socks", 5))
- ptype_ID = ptype_socksID;
+ int nr_proxies = 0;
+ char** p = proxies;
+ /* count the elements in the null terminated string vector. */
+ while (*p) {
+ nr_proxies++;
+ p++;
+ }
+ /* create a proxy array that has to be filled. */
+ proxy_array = (*env)->NewObjectArray(env, nr_proxies, proxy_class, NULL);
+ if (proxy_array != NULL && !(*env)->ExceptionCheck(env)) {
+ for (i = 0; proxies[i]; i++) {
+ if (strncmp(proxies[i], "direct://", 9)) {
+ GSocketConnectable* conn =
+ (*g_network_address_parse_uri)(proxies[i], 0,
+ &error);
+ if (conn && !error) {
+ const char *phost = NULL;
+ unsigned short pport = 0;
+ phost = (*g_network_address_get_hostname)(conn);
+ pport = (*g_network_address_get_port)(conn);
+ if (phost && pport > 0) {
+ jobject proxy = NULL;
+ jfieldID ptype_ID = ptype_httpID;
+ if (!strncmp(proxies[i], "socks", 5))
+ ptype_ID = ptype_socksID;
- jProxy = createProxy(env, ptype_ID, phost, pport);
+ proxy = createProxy(env, ptype_ID, phost, pport);
+ if (proxy == NULL || (*env)->ExceptionCheck(env)) {
+ proxy_array = NULL;
+ break;
+ }
+ (*env)->SetObjectArrayElement(env, proxy_array, i, proxy);
+ if ((*env)->ExceptionCheck(env)) {
+ proxy_array = NULL;
+ break;
+ }
+ }
+ }
+ } else {
+ /* direct connection - no proxy */
+ jobject proxy = (*env)->GetStaticObjectField(env, proxy_class,
+ pr_no_proxyID);
+ if (proxy == NULL || (*env)->ExceptionCheck(env)) {
+ proxy_array = NULL;
+ break;
+ }
+ (*env)->SetObjectArrayElement(env, proxy_array, i, proxy);
+ if ((*env)->ExceptionCheck(env)) {
+ proxy_array = NULL;
+ break;
}
}
}
@@ -438,48 +450,9 @@
(*g_strfreev)(proxies);
}
- return jProxy;
+ return proxy_array;
}
-static int initJavaClass(JNIEnv *env) {
- jclass proxy_cls = NULL;
- jclass ptype_cls = NULL;
- jclass isaddr_cls = NULL;
-
- // Proxy initialization
- proxy_cls = (*env)->FindClass(env,"java/net/Proxy");
- CHECK_NULL_RETURN(proxy_cls, 0);
- proxy_class = (*env)->NewGlobalRef(env, proxy_cls);
- CHECK_NULL_RETURN(proxy_class, 0);
- proxy_ctrID = (*env)->GetMethodID(env, proxy_class, "<init>",
- "(Ljava/net/Proxy$Type;Ljava/net/SocketAddress;)V");
- CHECK_NULL_RETURN(proxy_ctrID, 0);
-
- // Proxy$Type initialization
- ptype_cls = (*env)->FindClass(env,"java/net/Proxy$Type");
- CHECK_NULL_RETURN(ptype_cls, 0);
- ptype_class = (*env)->NewGlobalRef(env, ptype_cls);
- CHECK_NULL_RETURN(ptype_class, 0);
- ptype_httpID = (*env)->GetStaticFieldID(env, ptype_class, "HTTP",
- "Ljava/net/Proxy$Type;");
- CHECK_NULL_RETURN(ptype_httpID, 0);
- ptype_socksID = (*env)->GetStaticFieldID(env, ptype_class, "SOCKS",
- "Ljava/net/Proxy$Type;");
- CHECK_NULL_RETURN(ptype_socksID, 0);
-
- // InetSocketAddress initialization
- isaddr_cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
- CHECK_NULL_RETURN(isaddr_cls, 0);
- isaddr_class = (*env)->NewGlobalRef(env, isaddr_cls);
- CHECK_NULL_RETURN(isaddr_class, 0);
- isaddr_createUnresolvedID = (*env)->GetStaticMethodID(env, isaddr_class,
- "createUnresolved",
- "(Ljava/lang/String;I)Ljava/net/InetSocketAddress;");
-
- return isaddr_createUnresolvedID != NULL ? 1 : 0;
-}
-
-
/*
* Class: sun_net_spi_DefaultProxySelector
* Method: init
@@ -500,14 +473,14 @@
/*
* Class: sun_net_spi_DefaultProxySelector
- * Method: getSystemProxy
- * Signature: ([Ljava/lang/String;Ljava/lang/String;)Ljava/net/Proxy;
+ * Method: getSystemProxies
+ * Signature: ([Ljava/lang/String;Ljava/lang/String;)[Ljava/net/Proxy;
*/
-JNIEXPORT jobject JNICALL
-Java_sun_net_spi_DefaultProxySelector_getSystemProxy(JNIEnv *env,
- jobject this,
- jstring proto,
- jstring host)
+JNIEXPORT jobjectArray JNICALL
+Java_sun_net_spi_DefaultProxySelector_getSystemProxies(JNIEnv *env,
+ jobject this,
+ jstring proto,
+ jstring host)
{
const char* cproto;
const char* chost;
@@ -515,7 +488,7 @@
jboolean isProtoCopy;
jboolean isHostCopy;
- jobject proxy = NULL;
+ jobjectArray proxyArray = NULL;
cproto = (*env)->GetStringUTFChars(env, proto, &isProtoCopy);
@@ -523,16 +496,15 @@
chost = (*env)->GetStringUTFChars(env, host, &isHostCopy);
if (chost != NULL) {
if (use_gproxyResolver)
- proxy = getProxyByGProxyResolver(env, cproto, chost);
+ proxyArray = getProxyByGProxyResolver(env, cproto, chost);
else if (use_gconf)
- proxy = getProxyByGConf(env, cproto, chost);
-
+ proxyArray = getProxyByGConf(env, cproto, chost);
if (isHostCopy == JNI_TRUE)
(*env)->ReleaseStringUTFChars(env, host, chost);
}
if (isProtoCopy == JNI_TRUE)
(*env)->ReleaseStringUTFChars(env, proto, cproto);
}
- return proxy;
+ return proxyArray;
}
--- a/jdk/src/java.base/windows/native/libjli/cmdtoargs.c Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/windows/native/libjli/cmdtoargs.c Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -200,14 +200,14 @@
int nargs = 0;
StdArg* argv = NULL;
jboolean wildcard = JNI_FALSE;
- char* src = cmdline;
+ char* src = cmdline, *arg = NULL;
JLI_List argsInFile;
size_t i, cnt;
JLI_List envArgs = JLI_List_new(1);
- if (JLI_AddArgsFromEnvVar(envArgs, JAVA_OPTIONS)) {
+ if (JLI_AddArgsFromEnvVar(envArgs, JDK_JAVA_OPTIONS)) {
// JLI_SetTraceLauncher is not called yet
- // Show _JAVA_OPTIONS content along with JAVA_OPTIONS to aid diagnosis
+ // Show _JAVA_OPTIONS content along with JDK_JAVA_OPTIONS to aid diagnosis
if (getenv(JLDEBUG_ENV_ENTRY)) {
char *tmp = getenv("_JAVA_OPTIONS");
if (NULL != tmp) {
@@ -219,7 +219,7 @@
argv = JLI_MemAlloc(cnt * sizeof(StdArg));
// allocate arg buffer with sufficient space to receive the largest arg
- char* arg = JLI_StringDup(cmdline);
+ arg = JLI_StringDup(cmdline);
src = next_arg(src, arg, &wildcard);
// first argument is the app name, do not preprocess and make sure remains first
--- a/jdk/src/java.base/windows/native/libnet/DefaultProxySelector.c Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.base/windows/native/libnet/DefaultProxySelector.c Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, 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
@@ -24,26 +24,24 @@
*/
#include <windows.h>
+#include <Winhttp.h>
+
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
-#include "jlong.h"
+
+#include "proxy_util.h"
+
#include "sun_net_spi_DefaultProxySelector.h"
-/**
+/*
* These functions are used by the sun.net.spi.DefaultProxySelector class
* to access some platform specific settings.
- * This is the Windows code using the registry settings.
+ * On Windows use WinHTTP functions to get the system settings.
*/
-static jclass proxy_class;
-static jclass isaddr_class;
-static jclass ptype_class;
-static jmethodID isaddr_createUnresolvedID;
-static jmethodID proxy_ctrID;
-static jfieldID pr_no_proxyID;
-static jfieldID ptype_httpID;
-static jfieldID ptype_socksID;
+/* Keep one static session for all requests. */
+static HINTERNET session = NULL;
/*
* Class: sun_net_spi_DefaultProxySelector
@@ -52,233 +50,327 @@
*/
JNIEXPORT jboolean JNICALL
Java_sun_net_spi_DefaultProxySelector_init(JNIEnv *env, jclass clazz) {
- HKEY hKey;
- LONG ret;
- jclass cls;
+
+ /*
+ * Get one WinHTTP session handle to initialize the WinHTTP internal data
+ * structures. Keep and use only this one for the whole life time.
+ */
+ session = WinHttpOpen(L"Only used internal", /* we need no real agent string here */
+ WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
+ WINHTTP_NO_PROXY_NAME,
+ WINHTTP_NO_PROXY_BYPASS,
+ 0);
+ if (session == NULL) {
+ return JNI_FALSE;
+ }
+
+ if (!initJavaClass(env)) {
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
- /**
- * Get all the method & field IDs for later use.
- */
- cls = (*env)->FindClass(env,"java/net/Proxy");
- CHECK_NULL_RETURN(cls, JNI_FALSE);
- proxy_class = (*env)->NewGlobalRef(env, cls);
- CHECK_NULL_RETURN(proxy_class, JNI_FALSE);
- cls = (*env)->FindClass(env,"java/net/Proxy$Type");
- CHECK_NULL_RETURN(cls, JNI_FALSE);
- ptype_class = (*env)->NewGlobalRef(env, cls);
- CHECK_NULL_RETURN(ptype_class, JNI_FALSE);
- cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
- CHECK_NULL_RETURN(cls, JNI_FALSE);
- isaddr_class = (*env)->NewGlobalRef(env, cls);
- CHECK_NULL_RETURN(isaddr_class, JNI_FALSE);
- proxy_ctrID = (*env)->GetMethodID(env, proxy_class, "<init>",
- "(Ljava/net/Proxy$Type;Ljava/net/SocketAddress;)V");
- CHECK_NULL_RETURN(proxy_ctrID, JNI_FALSE);
- pr_no_proxyID = (*env)->GetStaticFieldID(env, proxy_class, "NO_PROXY", "Ljava/net/Proxy;");
- CHECK_NULL_RETURN(pr_no_proxyID, JNI_FALSE);
- ptype_httpID = (*env)->GetStaticFieldID(env, ptype_class, "HTTP", "Ljava/net/Proxy$Type;");
- CHECK_NULL_RETURN(ptype_httpID, JNI_FALSE);
- ptype_socksID = (*env)->GetStaticFieldID(env, ptype_class, "SOCKS", "Ljava/net/Proxy$Type;");
- CHECK_NULL_RETURN(ptype_socksID, JNI_FALSE);
- isaddr_createUnresolvedID = (*env)->GetStaticMethodID(env, isaddr_class, "createUnresolved",
- "(Ljava/lang/String;I)Ljava/net/InetSocketAddress;");
- CHECK_NULL_RETURN(isaddr_createUnresolvedID, JNI_FALSE);
+
+#define MAX_STR_LEN 1024
+
+/* A linked list element for a proxy */
+typedef struct list_item {
+ wchar_t *host;
+ int port;
+ struct list_item *next;
+} list_item;
- /**
- * Let's see if we can find the proper Registry entry.
- */
- ret = RegOpenKeyEx(HKEY_CURRENT_USER,
- "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
- 0, KEY_READ, (PHKEY)&hKey);
- if (ret == ERROR_SUCCESS) {
- RegCloseKey(hKey);
- /**
- * It worked, we can probably rely on it then.
- */
- return JNI_TRUE;
- }
-
- return JNI_FALSE;
+/* Free the linked list */
+static void freeList(list_item *head) {
+ list_item *next = NULL;
+ list_item *current = head;
+ while (current != NULL) {
+ next = current->next;
+ free(current->host);
+ free(current);
+ current = next;
+ }
}
-#define MAX_STR_LEN 1024
+
+/*
+ * Creates a linked list of list_item elements that has to be freed later on.
+ * Returns the size of the array as int.
+ */
+static int createProxyList(LPWSTR win_proxy, const WCHAR *pproto, list_item **head) {
+ static const wchar_t separators[] = L"\t\r\n ;";
+ list_item *current = NULL;
+ int nr_elems = 0;
+ wchar_t *context = NULL;
+ wchar_t *current_proxy = NULL;
+ BOOL error = FALSE;
+
+ /*
+ * The proxy server list contains one or more of the following strings
+ * separated by semicolons or whitespace:
+ * ([<scheme>=][<scheme>"://"]<server>[":"<port>])
+ */
+ current_proxy = wcstok_s(win_proxy, separators, &context);
+ while (current_proxy != NULL) {
+ LPWSTR pport;
+ LPWSTR phost;
+ int portVal = 0;
+ wchar_t *next_proxy = NULL;
+ list_item *proxy = NULL;
+ wchar_t* pos = NULL;
+
+ /* Filter based on the scheme, if there is one */
+ pos = wcschr(current_proxy, L'=');
+ if (pos) {
+ *pos = L'\0';
+ if (wcscmp(current_proxy, pproto) != 0) {
+ current_proxy = wcstok_s(NULL, separators, &context);
+ continue;
+ }
+ current_proxy = pos + 1;
+ }
+
+ /* Let's check for a scheme and ignore it. */
+ if ((phost = wcsstr(current_proxy, L"://")) != NULL) {
+ phost += 3;
+ } else {
+ phost = current_proxy;
+ }
+
+ /* Get the port */
+ pport = wcschr(phost, L':');
+ if (pport != NULL) {
+ *pport = 0;
+ pport++;
+ swscanf(pport, L"%d", &portVal);
+ }
+
+ proxy = (list_item *)malloc(sizeof(list_item));
+ if (proxy != NULL) {
+ proxy->next = NULL;
+ proxy->port = portVal;
+ proxy->host = _wcsdup(phost);
+
+ if (proxy->host != NULL) {
+ if (*head == NULL) {
+ *head = proxy; /* first elem */
+ }
+ if (current != NULL) {
+ current->next = proxy;
+ }
+ current = proxy;
+ nr_elems++;
+ } else {
+ free(proxy); /* cleanup */
+ }
+ }
+ /* goto next proxy if available... */
+ current_proxy = wcstok_s(NULL, separators, &context);
+ }
+ return nr_elems;
+}
+
+
/*
* Class: sun_net_spi_DefaultProxySelector
- * Method: getSystemProxy
- * Signature: ([Ljava/lang/String;Ljava/lang/String;)Ljava/net/Proxy;
+ * Method: getSystemProxies
+ * Signature: ([Ljava/lang/String;Ljava/lang/String;)[Ljava/net/Proxy;
*/
-JNIEXPORT jobject JNICALL
-Java_sun_net_spi_DefaultProxySelector_getSystemProxy(JNIEnv *env,
- jobject this,
- jstring proto,
- jstring host)
+JNIEXPORT jobjectArray JNICALL
+Java_sun_net_spi_DefaultProxySelector_getSystemProxies(JNIEnv *env,
+ jobject this,
+ jstring proto,
+ jstring host)
{
- jobject isa = NULL;
- jobject proxy = NULL;
- jobject type_proxy = NULL;
- jobject no_proxy = NULL;
- jboolean isCopy;
- HKEY hKey;
- LONG ret;
- const char* cproto;
- const char* urlhost;
- char pproto[MAX_STR_LEN];
- char regserver[MAX_STR_LEN];
- char override[MAX_STR_LEN];
- char *s, *s2;
- char *ctx = NULL;
- int pport = 0;
- int defport = 0;
- char *phost;
+ jobjectArray proxy_array = NULL;
+ jobject type_proxy = NULL;
+ LPCWSTR lpProto;
+ LPCWSTR lpHost;
+ list_item *head = NULL;
+
+ BOOL use_auto_proxy = FALSE;
+ WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ie_proxy_config;
+ WINHTTP_AUTOPROXY_OPTIONS auto_proxy_options;
+ WINHTTP_PROXY_INFO proxy_info;
+ LPWSTR win_proxy = NULL;
+ LPWSTR win_bypass_proxy = NULL;
+
+ memset(&ie_proxy_config, 0, sizeof(WINHTTP_CURRENT_USER_IE_PROXY_CONFIG));
+ memset(&auto_proxy_options, 0, sizeof(WINHTTP_AUTOPROXY_OPTIONS));
+ memset(&proxy_info, 0, sizeof(WINHTTP_PROXY_INFO));
+
+ lpHost = (*env)->GetStringChars(env, host, NULL);
+ if (lpHost == NULL) {
+ if (!(*env)->ExceptionCheck(env))
+ JNU_ThrowOutOfMemoryError(env, NULL);
+ return NULL;
+ }
- /**
- * Let's open the Registry entry. We'll check a few values in it:
- *
- * - ProxyEnable: 0 means no proxy, 1 means use the proxy
- * - ProxyServer: a string that can take 2 forms:
- * "server[:port]"
- * or
- * "protocol1=server[:port][;protocol2=server[:port]]..."
- * - ProxyOverride: a string containing a list of prefixes for hostnames.
- * e.g.: hoth;localhost;<local>
- */
- ret = RegOpenKeyEx(HKEY_CURRENT_USER,
- "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
- 0, KEY_READ, (PHKEY)&hKey);
- if (ret == ERROR_SUCCESS) {
- DWORD dwLen;
- DWORD dwProxyEnabled;
- ULONG ulType;
- dwLen = sizeof(dwProxyEnabled);
+ lpProto = (*env)->GetStringChars(env, proto, NULL);
+ if (lpProto == NULL) {
+ (*env)->ReleaseStringChars(env, host, lpHost);
+ if (!(*env)->ExceptionCheck(env))
+ JNU_ThrowOutOfMemoryError(env, NULL);
+ return NULL;
+ }
+
+ if (WinHttpGetIEProxyConfigForCurrentUser(&ie_proxy_config) == FALSE) {
+ /* cleanup and exit */
+ (*env)->ReleaseStringChars(env, host, lpHost);
+ (*env)->ReleaseStringChars(env, proto, lpProto);
+ return NULL;
+ }
+
+ if (ie_proxy_config.fAutoDetect) {
+ /* Windows uses WPAD */
+ auto_proxy_options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP |
+ WINHTTP_AUTO_DETECT_TYPE_DNS_A;
+ auto_proxy_options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
+ auto_proxy_options.fAutoLogonIfChallenged = TRUE;
+ use_auto_proxy = TRUE;
+ } else if (ie_proxy_config.lpszAutoConfigUrl != NULL) {
+ /* Windows uses PAC file */
+ auto_proxy_options.lpszAutoConfigUrl = ie_proxy_config.lpszAutoConfigUrl;
+ auto_proxy_options.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
+ use_auto_proxy = TRUE;
+ } else if (ie_proxy_config.lpszProxy != NULL) {
+ /* Windows uses manually entered proxy. */
+ use_auto_proxy = FALSE;
+ win_bypass_proxy = ie_proxy_config.lpszProxyBypass;
+ win_proxy = ie_proxy_config.lpszProxy;
+ }
- /**
- * Let's see if the proxy settings are to be used.
- */
- ret = RegQueryValueEx(hKey, "ProxyEnable", NULL, &ulType,
- (LPBYTE)&dwProxyEnabled, &dwLen);
- if ((ret == ERROR_SUCCESS) && (dwProxyEnabled > 0)) {
- /*
- * Yes, ProxyEnable == 1
- */
- dwLen = sizeof(override);
- override[0] = 0;
- ret = RegQueryValueEx(hKey, "ProxyOverride", NULL, &ulType,
- (LPBYTE)&override, &dwLen);
- dwLen = sizeof(regserver);
- regserver[0] = 0;
- ret = RegQueryValueEx(hKey, "ProxyServer", NULL, &ulType,
- (LPBYTE)®server, &dwLen);
- RegCloseKey(hKey);
- if (ret == ERROR_SUCCESS) {
- if (strlen(override) > 0) {
- /**
- * we did get ProxyServer and may have an override.
- * So let's check the override list first, by walking down the list
- * The semicolons (;) separated entries have to be matched with the
- * the beginning of the hostname.
- */
- s = strtok_s(override, "; ", &ctx);
- urlhost = (*env)->GetStringUTFChars(env, host, &isCopy);
- if (urlhost == NULL) {
- if (!(*env)->ExceptionCheck(env))
- JNU_ThrowOutOfMemoryError(env, NULL);
- return NULL;
- }
- while (s != NULL) {
- if (strncmp(s, urlhost, strlen(s)) == 0) {
- /**
- * the URL host name matches with one of the prefixes,
- * therefore we have to use a direct connection.
- */
- if (isCopy == JNI_TRUE)
- (*env)->ReleaseStringUTFChars(env, host, urlhost);
- goto noproxy;
+ if (use_auto_proxy) {
+ WCHAR url[MAX_STR_LEN];
+ /* Create url for WinHttpGetProxyForUrl */
+ _snwprintf(url, sizeof(url) - 1, L"%s://%s", lpProto, lpHost);
+ /* Get proxy for URL from Windows */
+ use_auto_proxy = WinHttpGetProxyForUrl(session, &url[0], &auto_proxy_options, &proxy_info);
+ if (use_auto_proxy) {
+ win_proxy = proxy_info.lpszProxy;
+ win_bypass_proxy = proxy_info.lpszProxyBypass;
+ }
+ }
+
+ /* Check the bypass entry. */
+ if (NULL != win_bypass_proxy) {
+ /*
+ * From MSDN:
+ * The proxy bypass list contains one or more server names separated by
+ * semicolons or whitespace. The proxy bypass list can also contain the
+ * string "<local>" to indicate that all local intranet sites are
+ * bypassed. Local intranet sites are considered to be all servers that
+ * do not contain a period in their name.
+ */
+ wchar_t *context = NULL;
+ LPWSTR s = wcstok_s(win_bypass_proxy, L"; ", &context);
+
+ while (s != NULL) {
+ size_t maxlen = wcslen(s);
+ if (wcsncmp(s, lpHost, maxlen) == 0) {
+ /*
+ * The URL host name matches with one of the prefixes, use a
+ * direct connection.
+ */
+ goto noproxy;
}
- s = strtok_s(NULL, "; ", &ctx);
- }
- if (isCopy == JNI_TRUE)
- (*env)->ReleaseStringUTFChars(env, host, urlhost);
+ if (wcsncmp(s, L"<local>", maxlen) == 0) {
+ /*
+ * All local intranet sites are bypassed - Microsoft consider all
+ * servers that do not contain a period in their name to be local.
+ */
+ if (wcschr(lpHost, '.') == NULL) {
+ goto noproxy;
+ }
+ }
+ s = wcstok_s(NULL, L"; ", &context);
+ }
+ }
+
+ if (win_proxy != NULL) {
+ wchar_t *context = NULL;
+ int defport = 0;
+ int nr_elems = 0;
+
+ /* Set the default port value & proxy type from protocol. */
+ if ((wcscmp(lpProto, L"http") == 0) ||
+ (wcscmp(lpProto, L"ftp") == 0) ||
+ (wcscmp(lpProto, L"gopher") == 0))
+ defport = 80;
+ if (wcscmp(lpProto, L"https") == 0)
+ defport = 443;
+ if (wcscmp(lpProto, L"socks") == 0) {
+ defport = 1080;
+ type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_socksID);
+ } else {
+ type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
+ }
+ if (type_proxy == NULL || (*env)->ExceptionCheck(env)) {
+ goto noproxy;
}
- cproto = (*env)->GetStringUTFChars(env, proto, &isCopy);
- if (cproto == NULL) {
- if (!(*env)->ExceptionCheck(env))
- JNU_ThrowOutOfMemoryError(env, NULL);
- return NULL;
- }
-
- /*
- * Set default port value & proxy type from protocol.
- */
- if ((strcmp(cproto, "http") == 0) ||
- (strcmp(cproto, "ftp") == 0) ||
- (strcmp(cproto, "gopher") == 0))
- defport = 80;
- if (strcmp(cproto, "https") == 0)
- defport = 443;
- if (strcmp(cproto, "socks") == 0) {
- defport = 1080;
- type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_socksID);
- } else {
- type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
- }
+ nr_elems = createProxyList(win_proxy, lpProto, &head);
+ if (nr_elems != 0 && head != NULL) {
+ int index = 0;
+ proxy_array = (*env)->NewObjectArray(env, nr_elems, proxy_class, NULL);
+ if (proxy_array == NULL || (*env)->ExceptionCheck(env)) {
+ goto noproxy;
+ }
+ while (head != NULL && index < nr_elems) {
+ jstring jhost;
+ jobject isa;
+ jobject proxy;
- sprintf(pproto,"%s=", cproto);
- if (isCopy == JNI_TRUE)
- (*env)->ReleaseStringUTFChars(env, proto, cproto);
- /**
- * Let's check the protocol specific form first.
- */
- if ((s = strstr(regserver, pproto)) != NULL) {
- s += strlen(pproto);
- } else {
- /**
- * If we couldn't find *this* protocol but the string is in the
- * protocol specific format, then don't use proxy
- */
- if (strchr(regserver, '=') != NULL)
- goto noproxy;
- s = regserver;
+ if (head->host != NULL && proxy_array != NULL) {
+ /* Let's create the appropriate Proxy object then. */
+ if (head->port == 0) {
+ head->port = defport;
+ }
+ jhost = (*env)->NewString(env, head->host, (jsize)wcslen(head->host));
+ if (jhost == NULL || (*env)->ExceptionCheck(env)) {
+ proxy_array = NULL;
+ }
+ isa = (*env)->CallStaticObjectMethod(env, isaddr_class,
+ isaddr_createUnresolvedID, jhost,
+ head->port);
+ if (isa == NULL || (*env)->ExceptionCheck(env)) {
+ proxy_array = NULL;
+ }
+ proxy = (*env)->NewObject(env, proxy_class, proxy_ctrID, type_proxy, isa);
+ if (proxy == NULL || (*env)->ExceptionCheck(env)) {
+ proxy_array = NULL;
+ }
+ (*env)->SetObjectArrayElement(env, proxy_array, index, proxy);
+ if ((*env)->ExceptionCheck(env)) {
+ proxy_array = NULL;
+ }
+ index++;
+ }
+ head = head->next;
+ }
}
- s2 = strchr(s, ';');
- if (s2 != NULL)
- *s2 = 0;
-
- /**
- * Is there a port specified?
- */
- s2 = strchr(s, ':');
- if (s2 != NULL) {
- *s2 = 0;
- s2++;
- sscanf(s2, "%d", &pport);
- }
- phost = s;
-
- if (phost != NULL) {
- /**
- * Let's create the appropriate Proxy object then.
- */
- jstring jhost;
- if (pport == 0)
- pport = defport;
- jhost = (*env)->NewStringUTF(env, phost);
- CHECK_NULL_RETURN(jhost, NULL);
- isa = (*env)->CallStaticObjectMethod(env, isaddr_class, isaddr_createUnresolvedID, jhost, pport);
- CHECK_NULL_RETURN(isa, NULL);
- proxy = (*env)->NewObject(env, proxy_class, proxy_ctrID, type_proxy, isa);
- return proxy;
- }
- }
- } else {
- /* ProxyEnable == 0 or Query failed */
- /* close the handle to the registry key */
- RegCloseKey(hKey);
}
- }
noproxy:
- no_proxy = (*env)->GetStaticObjectField(env, proxy_class, pr_no_proxyID);
- return no_proxy;
+ if (head != NULL) {
+ freeList(head);
+ }
+ if (proxy_info.lpszProxy != NULL)
+ GlobalFree(proxy_info.lpszProxy);
+ if (proxy_info.lpszProxyBypass != NULL)
+ GlobalFree(proxy_info.lpszProxyBypass);
+ if (ie_proxy_config.lpszAutoConfigUrl != NULL)
+ GlobalFree(ie_proxy_config.lpszAutoConfigUrl);
+ if (ie_proxy_config.lpszProxy != NULL)
+ GlobalFree(ie_proxy_config.lpszProxy);
+ if (ie_proxy_config.lpszProxyBypass != NULL)
+ GlobalFree(ie_proxy_config.lpszProxyBypass);
+ if (lpHost != NULL)
+ (*env)->ReleaseStringChars(env, host, lpHost);
+ if (lpProto != NULL)
+ (*env)->ReleaseStringChars(env, proto, lpProto);
+
+ return proxy_array;
}
--- a/jdk/src/java.desktop/macosx/classes/sun/java2d/OSXOffScreenSurfaceData.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.desktop/macosx/classes/sun/java2d/OSXOffScreenSurfaceData.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, 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
@@ -608,6 +608,13 @@
fImageInfoInt.put(kNeedToSyncFromJavaPixelsIndex, 1); // the pixels will change
}
+ private void syncFromCustom() {
+
+ }
+
+ private void syncToCustom() {
+
+ }
// /**
// * Invoked when the raster's contents will be taken (via the Raster.getDataBuffer() method)
// */
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/ImageSurfaceData.m Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/ImageSurfaceData.m Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, 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,9 +34,6 @@
#import <JavaNativeFoundation/JavaNativeFoundation.h>
#import "BufImgSurfaceData.h"
-#import "ThreadUtilities.h"
-
-
//#define DEBUG 1
#if defined DEBUG
@@ -195,10 +192,9 @@
PRINT(" customPixelsFromJava")
SurfaceDataOps *sdo = (SurfaceDataOps*)isdo;
- JNFCallVoidMethod([ThreadUtilities getJNIEnv], sdo->sdObject, jm_syncFromCustom); // AWT_THREADING Safe (known object)
+ JNFCallVoidMethod(env, sdo->sdObject, jm_syncFromCustom); // AWT_THREADING Safe (known object)
}
-
IMAGE_SURFACE_INLINE void copyBits(jint w, jint h, jint javaPixelsBytesPerRow, Pixel8bit *pixelsSrc, jint dstPixelsBytesPerRow, Pixel8bit *pixelsDst)
{
PRINT(" copyBits")
@@ -427,7 +423,7 @@
PRINT(" customPixelsToJava")
SurfaceDataOps *sdo = (SurfaceDataOps*)isdo;
- JNFCallVoidMethod([ThreadUtilities getJNIEnv], sdo->sdObject, jm_syncToCustom); // AWT_THREADING Safe (known object)
+ JNFCallVoidMethod(env, sdo->sdObject, jm_syncToCustom); // AWT_THREADING Safe (known object)
}
IMAGE_SURFACE_INLINE void removeAlphaPre_32bit(jint w, jint h, jint javaPixelsBytesPerRow, jint javaPixelBytes, Pixel32bit *pixelsSrc)
@@ -995,9 +991,9 @@
{
PRINT("imageDataProvider_UnholdJavaPixels")
- ImageSDOps* isdo = (ImageSDOps*)info;
- unholdJavaPixels([ThreadUtilities getJNIEnv], isdo);
+ // Currently do nothing
}
+
static void imageDataProvider_FreeTempPixels(void *info, const void *data, size_t size)
{
PRINT("imageDataProvider_FreeTempPixels")
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -1559,6 +1559,59 @@
decodeRLE4(imSize, padding, values, bdata);
}
+ private boolean copyRLE4ScanlineToDst(int lineNo,
+ byte[] val,
+ byte[] bdata) throws IOException {
+ // Return value
+ boolean isSuccess = false;
+
+ // Reusing the code to copy 1 row of pixels or scanline to required
+ // destination buffer.
+ if (lineNo >= sourceRegion.y &&
+ lineNo < sourceRegion.y + sourceRegion.height) {
+ if (noTransform) {
+ int pos = lineNo * (width + 1 >> 1);
+ for(int i = 0, j = 0; i < width >> 1; i++)
+ bdata[pos++] =
+ (byte)((val[j++] << 4) | val[j++]);
+ if ((width & 1) == 1)
+ bdata[pos] |= val[width - 1] << 4;
+
+ processImageUpdate(bi, 0, lineNo,
+ destinationRegion.width, 1, 1, 1,
+ new int[]{0});
+ isSuccess = true;
+ } else if ((lineNo - sourceRegion.y) % scaleY == 0) {
+ int lineStride =
+ ((MultiPixelPackedSampleModel)sampleModel).getScanlineStride();
+ int currentLine = (lineNo - sourceRegion.y) / scaleY +
+ destinationRegion.y;
+ int pos = currentLine * lineStride;
+ pos += destinationRegion.x >> 1;
+ int shift = (1 - (destinationRegion.x & 1)) << 2;
+ for (int i = sourceRegion.x;
+ i < sourceRegion.x + sourceRegion.width;
+ i += scaleX) {
+ bdata[pos] |= val[i] << shift;
+ shift += 4;
+ if (shift == 4) {
+ pos++;
+ }
+ shift &= 7;
+ }
+ processImageUpdate(bi, 0, currentLine,
+ destinationRegion.width, 1, 1, 1,
+ new int[]{0});
+ isSuccess = true;
+ }
+ // Ensure to reset the scanline buffer once the copy is complete.
+ for(int scIndex = 0; scIndex < width; scIndex++) {
+ val[scIndex] = 0;
+ }
+ }
+ return isSuccess;
+ }
+
private void decodeRLE4(int imSize,
int padding,
byte[] values,
@@ -1568,57 +1621,22 @@
int value;
boolean flag = false;
int lineNo = isBottomUp ? height - 1 : 0;
- int lineStride =
- ((MultiPixelPackedSampleModel)sampleModel).getScanlineStride();
int finished = 0;
- while (count != imSize) {
+ // Ensure the image has sufficient data before proceeding to decode
+ while ((count + 1) < imSize) {
value = values[count++] & 0xFF;
if (value == 0) {
-
// Absolute mode
switch(values[count++] & 0xFF) {
case 0:
// End-of-scanline marker
- // End-of-scanline marker
- if (lineNo >= sourceRegion.y &&
- lineNo < sourceRegion.y + sourceRegion.height) {
- if (noTransform) {
- int pos = lineNo * (width + 1 >> 1);
- for(int i = 0, j = 0; i < width >> 1; i++)
- bdata[pos++] =
- (byte)((val[j++] << 4) | val[j++]);
- if ((width & 1) == 1)
- bdata[pos] |= val[width - 1] << 4;
-
- processImageUpdate(bi, 0, lineNo,
- destinationRegion.width, 1, 1, 1,
- new int[]{0});
- finished++;
- } else if ((lineNo - sourceRegion.y) % scaleY == 0) {
- int currentLine = (lineNo - sourceRegion.y) / scaleY +
- destinationRegion.y;
- int pos = currentLine * lineStride;
- pos += destinationRegion.x >> 1;
- int shift = (1 - (destinationRegion.x & 1)) << 2;
- for (int i = sourceRegion.x;
- i < sourceRegion.x + sourceRegion.width;
- i += scaleX) {
- bdata[pos] |= val[i] << shift;
- shift += 4;
- if (shift == 4) {
- pos++;
- }
- shift &= 7;
- }
- processImageUpdate(bi, 0, currentLine,
- destinationRegion.width, 1, 1, 1,
- new int[]{0});
- finished++;
- }
+ // Copy the decoded scanline to destination
+ if (copyRLE4ScanlineToDst(lineNo, val, bdata)) {
+ finished++;
}
processImageProgress(100.0F * finished / destinationRegion.height);
lineNo += isBottomUp ? -1 : 1;
@@ -1633,21 +1651,61 @@
case 1:
// End-of-RLE marker
flag = true;
+
+ // Check if the last decoded scanline was copied to
+ // destination bitmap
+ if (l != 0) {
+ // Copy the decoded scanline to destination
+ if (copyRLE4ScanlineToDst(lineNo, val, bdata)) {
+ finished++;
+ }
+ processImageProgress(100.0F * finished / destinationRegion.height);
+ lineNo += isBottomUp ? -1 : 1;
+ l = 0;
+ }
break;
case 2:
// delta or vector marker
- int xoff = values[count++] & 0xFF;
- int yoff = values[count] & 0xFF;
- // Move to the position xoff, yoff down
- l += xoff + yoff*width;
+ if ((count + 1) < imSize) {
+ int xoff = values[count++] & 0xFF;
+ int yoff = values[count++] & 0xFF;
+
+ // Check if the yOffset shifts the decoding to another
+ // row. In such cases, the decoded pixels in scanline
+ // buffer-val must be copied to the destination image.
+ if (yoff != 0) {
+ // Copy the decoded scanline to destination
+ if (copyRLE4ScanlineToDst(lineNo, val, bdata)) {
+ finished++;
+ }
+ processImageProgress(100.0F * finished
+ / destinationRegion.height);
+ lineNo += isBottomUp ? -yoff : yoff;
+ }
+
+ // Move to the position (xoff, yoff). Since l-is used
+ // to index into the scanline buffer, the accumulated
+ // offset is limited to the width of the scanline
+ l += xoff + yoff*width;
+ l %= width;
+ }
break;
default:
int end = values[count-1] & 0xFF;
- for (int i=0; i<end; i++) {
- val[l++] = (byte)(((i & 1) == 0) ? (values[count] & 0xf0) >> 4
- : (values[count++] & 0x0f));
+ byte readByte = 0;
+ // Ensure to check if the source index-count, does not
+ // exceed the source image size
+ for (int i = 0; (i < end) && (count < imSize); i++) {
+ readByte = (byte)(((i & 1) == 0) ?
+ (values[count] & 0xf0) >> 4 :
+ (values[count++] & 0x0f));
+ // Ensure to check if scanline index-l, does not
+ // exceed the scanline buffer size (width of image)
+ if (l < width) {
+ val[l++] = readByte;
+ }
}
// When end is odd, the above for loop does not
@@ -1665,10 +1723,14 @@
}
} else {
// Encoded mode
- int alternate[] = { (values[count] & 0xf0) >> 4,
- values[count] & 0x0f };
- for (int i=0; (i < value) && (l < width); i++) {
- val[l++] = (byte)alternate[i & 1];
+ // Ensure to check if the source index-count, does not
+ // exceed the source image size
+ if (count < imSize) {
+ int alternate[] = { (values[count] & 0xf0) >> 4,
+ values[count] & 0x0f };
+ for (int i=0; (i < value) && (l < width); i++) {
+ val[l++] = (byte)alternate[i & 1];
+ }
}
count++;
--- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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
@@ -567,7 +567,7 @@
("Type is TIFF_RATIONAL or TIFF_SRATIONAL and count < 1");
} else if (type == TIFFTag.TIFF_IFD_POINTER && count != 1) {
throw new IllegalArgumentException
- ("Type is TIFF_IFD_POINTER count != 1");
+ ("Type is TIFF_IFD_POINTER and count != 1");
} else if(data == null) {
throw new NullPointerException("data == null!");
}
@@ -698,6 +698,11 @@
* data type for the supplied {@code TIFFTag}.
* @throws IllegalArgumentException if {@code count < 0}.
* @see #TIFFField(TIFFTag,int,int,Object)
+ * @throws IllegalArgumentException if {@code count < 1}
+ * and {@code type} is {@code TIFF_RATIONAL} or
+ * {@code TIFF_SRATIONAL}.
+ * @throws IllegalArgumentException if {@code count != 1}
+ * and {@code type} is {@code TIFF_IFD_POINTER}.
*/
public TIFFField(TIFFTag tag, int type, int count) {
this(tag, type, count, createArrayForType(type, count));
@@ -885,11 +890,26 @@
* @throws IllegalArgumentException if {@code dataType} is not
* one of the {@code TIFFTag.TIFF_*} data type constants.
* @throws IllegalArgumentException if {@code count < 0}.
+ * @throws IllegalArgumentException if {@code count < 1}
+ * and {@code type} is {@code TIFF_RATIONAL} or
+ * {@code TIFF_SRATIONAL}.
+ * @throws IllegalArgumentException if {@code count != 1}
+ * and {@code type} is {@code TIFF_IFD_POINTER}.
*/
public static Object createArrayForType(int dataType, int count) {
+
if(count < 0) {
throw new IllegalArgumentException("count < 0!");
+ } else if ((dataType == TIFFTag.TIFF_RATIONAL
+ || dataType == TIFFTag.TIFF_SRATIONAL)
+ && count < 1) {
+ throw new IllegalArgumentException
+ ("Type is TIFF_RATIONAL or TIFF_SRATIONAL and count < 1");
+ } else if (dataType == TIFFTag.TIFF_IFD_POINTER && count != 1) {
+ throw new IllegalArgumentException
+ ("Type is TIFF_IFD_POINTER and count != 1");
}
+
switch (dataType) {
case TIFFTag.TIFF_BYTE:
case TIFFTag.TIFF_SBYTE:
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2017, 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
@@ -48,13 +48,13 @@
* Keys to use for forward focus traversal when the JComponent is
* managing focus.
*/
- private static Set<KeyStroke> managingFocusForwardTraversalKeys;
+ private Set<KeyStroke> managingFocusForwardTraversalKeys;
/**
* Keys to use for backward focus traversal when the JComponent is
* managing focus.
*/
- private static Set<KeyStroke> managingFocusBackwardTraversalKeys;
+ private Set<KeyStroke> managingFocusBackwardTraversalKeys;
/**
* Style for the JSplitPane.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/com/sun/jmx/remote/internal/rmi/ProxyRef.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2003, 2008, 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 com.sun.jmx.remote.internal.rmi;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.lang.reflect.Method;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.server.RemoteObject;
+import java.rmi.server.RemoteRef;
+
+
+@SuppressWarnings("deprecation")
+public class ProxyRef implements RemoteRef {
+ private static final long serialVersionUID = -6503061366316814723L;
+
+ public ProxyRef(RemoteRef ref) {
+ this.ref = ref;
+ }
+
+ public void readExternal(ObjectInput in)
+ throws IOException, ClassNotFoundException {
+ ref.readExternal(in);
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ ref.writeExternal(out);
+ }
+
+ /**
+ * @deprecated
+ */
+ @Deprecated
+ public void invoke(java.rmi.server.RemoteCall call) throws Exception {
+ ref.invoke(call);
+ }
+
+ public Object invoke(Remote obj, Method method, Object[] params,
+ long opnum) throws Exception {
+ return ref.invoke(obj, method, params, opnum);
+ }
+
+ /**
+ * @deprecated
+ */
+ @Deprecated
+ public void done(java.rmi.server.RemoteCall call) throws RemoteException {
+ ref.done(call);
+ }
+
+ public String getRefClass(ObjectOutput out) {
+ return ref.getRefClass(out);
+ }
+
+ /**
+ * @deprecated
+ */
+ @Deprecated
+ public java.rmi.server.RemoteCall newCall(RemoteObject obj,
+ java.rmi.server.Operation[] op, int opnum,
+ long hash) throws RemoteException {
+ return ref.newCall(obj, op, opnum, hash);
+ }
+
+ public boolean remoteEquals(RemoteRef obj) {
+ return ref.remoteEquals(obj);
+ }
+
+ public int remoteHashCode() {
+ return ref.remoteHashCode();
+ }
+
+ public String remoteToString() {
+ return ref.remoteToString();
+ }
+
+ protected RemoteRef ref;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/com/sun/jmx/remote/internal/rmi/RMIExporter.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2003, 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 com.sun.jmx.remote.internal.rmi;
+
+import java.rmi.NoSuchObjectException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.rmi.server.UnicastRemoteObject;
+
+/**
+ * <p>Unpublished interface controlling how the RMI Connector Server
+ * exports objects. The RMIServerImpl object and each
+ * RMIConnectionImpl object are exported using the exporter. The
+ * default exporter calls {@link
+ * UnicastRemoteObject#exportObject(Remote, int,
+ * RMIClientSocketFactory, RMIServerSocketFactory)} to export objects
+ * and {@link UnicastRemoteObject#unexportObject(Remote, boolean)} to
+ * unexport them. A replacement exporter can be specified via the
+ * {@link #EXPORTER_ATTRIBUTE} property in the environment Map passed
+ * to the RMI connector server.</p>
+ */
+public interface RMIExporter {
+ public static final String EXPORTER_ATTRIBUTE =
+ "com.sun.jmx.remote.rmi.exporter";
+
+ public Remote exportObject(Remote obj,
+ int port,
+ RMIClientSocketFactory csf,
+ RMIServerSocketFactory ssf)
+ throws RemoteException;
+
+ public boolean unexportObject(Remote obj, boolean force)
+ throws NoSuchObjectException;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/com/sun/jmx/remote/protocol/rmi/ClientProvider.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2002, 2004, 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 com.sun.jmx.remote.protocol.rmi;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Map;
+
+import javax.management.remote.JMXConnectorProvider;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.rmi.RMIConnector;
+
+public class ClientProvider implements JMXConnectorProvider {
+
+ public JMXConnector newJMXConnector(JMXServiceURL serviceURL,
+ Map<String,?> environment)
+ throws IOException {
+ if (!serviceURL.getProtocol().equals("rmi")) {
+ throw new MalformedURLException("Protocol not rmi: " +
+ serviceURL.getProtocol());
+ }
+ return new RMIConnector(serviceURL, environment);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/com/sun/jmx/remote/protocol/rmi/ServerProvider.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2003, 2004, 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 com.sun.jmx.remote.protocol.rmi;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Map;
+
+import javax.management.MBeanServer;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerProvider;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.rmi.RMIConnectorServer;
+
+public class ServerProvider implements JMXConnectorServerProvider {
+
+ public JMXConnectorServer newJMXConnectorServer(JMXServiceURL serviceURL,
+ Map<String,?> environment,
+ MBeanServer mbeanServer)
+ throws IOException {
+ if (!serviceURL.getProtocol().equals("rmi")) {
+ throw new MalformedURLException("Protocol not rmi: " +
+ serviceURL.getProtocol());
+ }
+ return new RMIConnectorServer(serviceURL, environment, mbeanServer);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/NoCallStackClassLoader.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2003, 2015, 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 javax.management.remote.rmi;
+
+import java.security.ProtectionDomain;
+
+/**
+ <p>A class loader that only knows how to define a limited number
+ of classes, and load a limited number of other classes through
+ delegation to another loader. It is used to get around a problem
+ with Serialization, in particular as used by RMI. The JMX Remote API
+ defines exactly what class loader must be used to deserialize arguments on
+ the server, and return values on the client. We communicate this class
+ loader to RMI by setting it as the context class loader. RMI uses the
+ context class loader to load classes as it deserializes, which is what we
+ want. However, before consulting the context class loader, it
+ looks up the call stack for a class with a non-null class loader,
+ and uses that if it finds one. So, in the standalone version of
+ javax.management.remote, if the class you're looking for is known
+ to the loader of jmxremote.jar (typically the system class loader)
+ then that loader will load it. This contradicts the class-loading
+ semantics required.
+
+ <p>We get around the problem by ensuring that the search up the
+ call stack will find a non-null class loader that doesn't load any
+ classes of interest, namely this one. So even though this loader
+ is indeed consulted during deserialization, it never finds the
+ class being deserialized. RMI then proceeds to use the context
+ class loader, as we require.
+
+ <p>This loader is constructed with the name and byte-code of one
+ or more classes that it defines, and a class-loader to which it
+ will delegate certain other classes required by that byte-code.
+ We construct the byte-code somewhat painstakingly, by compiling
+ the Java code directly, converting into a string, copying that
+ string into the class that needs this loader, and using the
+ stringToBytes method to convert it into the byte array. We
+ compile with -g:none because there's not much point in having
+ line-number information and the like in these directly-encoded
+ classes.
+
+ <p>The referencedClassNames should contain the names of all
+ classes that are referenced by the classes defined by this loader.
+ It is not necessary to include standard J2SE classes, however.
+ Here, a class is referenced if it is the superclass or a
+ superinterface of a defined class, or if it is the type of a
+ field, parameter, or return value. A class is not referenced if
+ it only appears in the throws clause of a method or constructor.
+ Of course, referencedClassNames should not contain any classes
+ that the user might want to deserialize, because the whole point
+ of this loader is that it does not find such classes.
+*/
+
+class NoCallStackClassLoader extends ClassLoader {
+ /** Simplified constructor when this loader only defines one class. */
+ public NoCallStackClassLoader(String className,
+ byte[] byteCode,
+ String[] referencedClassNames,
+ ClassLoader referencedClassLoader,
+ ProtectionDomain protectionDomain) {
+ this(new String[] {className}, new byte[][] {byteCode},
+ referencedClassNames, referencedClassLoader, protectionDomain);
+ }
+
+ public NoCallStackClassLoader(String[] classNames,
+ byte[][] byteCodes,
+ String[] referencedClassNames,
+ ClassLoader referencedClassLoader,
+ ProtectionDomain protectionDomain) {
+ super(null);
+
+ /* Validation. */
+ if (classNames == null || classNames.length == 0
+ || byteCodes == null || classNames.length != byteCodes.length
+ || referencedClassNames == null || protectionDomain == null)
+ throw new IllegalArgumentException();
+ for (int i = 0; i < classNames.length; i++) {
+ if (classNames[i] == null || byteCodes[i] == null)
+ throw new IllegalArgumentException();
+ }
+ for (int i = 0; i < referencedClassNames.length; i++) {
+ if (referencedClassNames[i] == null)
+ throw new IllegalArgumentException();
+ }
+
+ this.classNames = classNames;
+ this.byteCodes = byteCodes;
+ this.referencedClassNames = referencedClassNames;
+ this.referencedClassLoader = referencedClassLoader;
+ this.protectionDomain = protectionDomain;
+ }
+
+ /* This method is called at most once per name. Define the name
+ * if it is one of the classes whose byte code we have, or
+ * delegate the load if it is one of the referenced classes.
+ */
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ // Note: classNames is guaranteed by the constructor to be non-null.
+ for (int i = 0; i < classNames.length; i++) {
+ if (name.equals(classNames[i])) {
+ return defineClass(classNames[i], byteCodes[i], 0,
+ byteCodes[i].length, protectionDomain);
+ }
+ }
+
+ /* If the referencedClassLoader is null, it is the bootstrap
+ * class loader, and there's no point in delegating to it
+ * because it's already our parent class loader.
+ */
+ if (referencedClassLoader != null) {
+ for (int i = 0; i < referencedClassNames.length; i++) {
+ if (name.equals(referencedClassNames[i]))
+ return referencedClassLoader.loadClass(name);
+ }
+ }
+
+ throw new ClassNotFoundException(name);
+ }
+
+ private final String[] classNames;
+ private final byte[][] byteCodes;
+ private final String[] referencedClassNames;
+ private final ClassLoader referencedClassLoader;
+ private final ProtectionDomain protectionDomain;
+
+ /**
+ * <p>Construct a <code>byte[]</code> using the characters of the
+ * given <code>String</code>. Only the low-order byte of each
+ * character is used. This method is useful to reduce the
+ * footprint of classes that include big byte arrays (e.g. the
+ * byte code of other classes), because a string takes up much
+ * less space in a class file than the byte code to initialize a
+ * <code>byte[]</code> with the same number of bytes.</p>
+ *
+ * <p>We use just one byte per character even though characters
+ * contain two bytes. The resultant output length is much the
+ * same: using one byte per character is shorter because it has
+ * more characters in the optimal 1-127 range but longer because
+ * it has more zero bytes (which are frequent, and are encoded as
+ * two bytes in classfile UTF-8). But one byte per character has
+ * two key advantages: (1) you can see the string constants, which
+ * is reassuring, (2) you don't need to know whether the class
+ * file length is odd.</p>
+ *
+ * <p>This method differs from {@link String#getBytes()} in that
+ * it does not use any encoding. So it is guaranteed that each
+ * byte of the result is numerically identical (mod 256) to the
+ * corresponding character of the input.
+ */
+ public static byte[] stringToBytes(String s) {
+ final int slen = s.length();
+ byte[] bytes = new byte[slen];
+ for (int i = 0; i < slen; i++)
+ bytes[i] = (byte) s.charAt(i);
+ return bytes;
+ }
+}
+
+/*
+
+You can use the following Emacs function to convert class files into
+strings to be used by the stringToBytes method above. Select the
+whole (defun...) with the mouse and type M-x eval-region, or save it
+to a file and do M-x load-file. Then visit the *.class file and do
+M-x class-string.
+
+;; class-string.el
+;; visit the *.class file with emacs, then invoke this function
+
+(defun class-string ()
+ "Construct a Java string whose bytes are the same as the current
+buffer. The resultant string is put in a buffer called *string*,
+possibly with a numeric suffix like <2>. From there it can be
+insert-buffer'd into a Java program."
+ (interactive)
+ (let* ((s (buffer-string))
+ (slen (length s))
+ (i 0)
+ (buf (generate-new-buffer "*string*")))
+ (set-buffer buf)
+ (insert "\"")
+ (while (< i slen)
+ (if (> (current-column) 61)
+ (insert "\"+\n\""))
+ (let ((c (aref s i)))
+ (insert (cond
+ ((> c 126) (format "\\%o" c))
+ ((= c ?\") "\\\"")
+ ((= c ?\\) "\\\\")
+ ((< c 33)
+ (let ((nextc (if (< (1+ i) slen)
+ (aref s (1+ i))
+ ?\0)))
+ (cond
+ ((and (<= nextc ?7) (>= nextc ?0))
+ (format "\\%03o" c))
+ (t
+ (format "\\%o" c)))))
+ (t c))))
+ (setq i (1+ i)))
+ (insert "\"")
+ (switch-to-buffer buf)))
+
+Alternatively, the following class reads a class file and outputs a string
+that can be used by the stringToBytes method above.
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+public class BytesToString {
+
+ public static void main(String[] args) throws IOException {
+ File f = new File(args[0]);
+ int len = (int)f.length();
+ byte[] classBytes = new byte[len];
+
+ FileInputStream in = new FileInputStream(args[0]);
+ try {
+ int pos = 0;
+ for (;;) {
+ int n = in.read(classBytes, pos, (len-pos));
+ if (n < 0)
+ throw new RuntimeException("class file changed??");
+ pos += n;
+ if (pos >= n)
+ break;
+ }
+ } finally {
+ in.close();
+ }
+
+ int pos = 0;
+ boolean lastWasOctal = false;
+ for (int i=0; i<len; i++) {
+ int value = classBytes[i];
+ if (value < 0)
+ value += 256;
+ String s = null;
+ if (value == '\\')
+ s = "\\\\";
+ else if (value == '\"')
+ s = "\\\"";
+ else {
+ if ((value >= 32 && value < 127) && ((!lastWasOctal ||
+ (value < '0' || value > '7')))) {
+ s = Character.toString((char)value);
+ }
+ }
+ if (s == null) {
+ s = "\\" + Integer.toString(value, 8);
+ lastWasOctal = true;
+ } else {
+ lastWasOctal = false;
+ }
+ if (pos > 61) {
+ System.out.print("\"");
+ if (i<len)
+ System.out.print("+");
+ System.out.println();
+ pos = 0;
+ }
+ if (pos == 0)
+ System.out.print(" \"");
+ System.out.print(s);
+ pos += s.length();
+ }
+ System.out.println("\"");
+ }
+}
+
+*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnection.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,1092 @@
+/*
+ * Copyright (c) 2002, 2008, 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 javax.management.remote.rmi;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.rmi.MarshalledObject;
+import java.rmi.Remote;
+import java.util.Set;
+
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.IntrospectionException;
+import javax.management.InvalidAttributeValueException;
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServerConnection;
+import javax.management.NotCompliantMBeanException;
+
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+import javax.management.RuntimeMBeanException;
+import javax.management.RuntimeOperationsException;
+import javax.management.remote.NotificationResult;
+import javax.security.auth.Subject;
+
+/**
+ * <p>RMI object used to forward an MBeanServer request from a client
+ * to its MBeanServer implementation on the server side. There is one
+ * Remote object implementing this interface for each remote client
+ * connected to an RMI connector.</p>
+ *
+ * <p>User code does not usually refer to this interface. It is
+ * specified as part of the public API so that different
+ * implementations of that API will interoperate.</p>
+ *
+ * <p>To ensure that client parameters will be deserialized at the
+ * server side with the correct classloader, client parameters such as
+ * parameters used to invoke a method are wrapped in a {@link
+ * MarshalledObject}. An implementation of this interface must first
+ * get the appropriate class loader for the operation and its target,
+ * then deserialize the marshalled parameters with this classloader.
+ * Except as noted, a parameter that is a
+ * <code>MarshalledObject</code> or <code>MarshalledObject[]</code>
+ * must not be null; the behavior is unspecified if it is.</p>
+ *
+ * <p>Class loading aspects are detailed in the
+ * <a href="{@docRoot}/../technotes/guides/jmx/JMX_1_4_specification.pdf">
+ * JMX Specification, version 1.4</a> PDF document.</p>
+ *
+ * <p>Most methods in this interface parallel methods in the {@link
+ * MBeanServerConnection} interface. Where an aspect of the behavior
+ * of a method is not specified here, it is the same as in the
+ * corresponding <code>MBeanServerConnection</code> method.
+ *
+ * @since 1.5
+ */
+/*
+ * Notice that we omit the type parameter from MarshalledObject everywhere,
+ * even though it would add useful information to the documentation. The
+ * reason is that it was only added in Mustang (Java SE 6), whereas versions
+ * 1.4 and 2.0 of the JMX API must be implementable on Tiger per our
+ * commitments for JSR 255. This is also why we suppress rawtypes warnings.
+ */
+@SuppressWarnings("rawtypes")
+public interface RMIConnection extends Closeable, Remote {
+ /**
+ * <p>Returns the connection ID. This string is different for
+ * every open connection to a given RMI connector server.</p>
+ *
+ * @return the connection ID
+ *
+ * @see RMIConnector#connect RMIConnector.connect
+ *
+ * @throws IOException if a general communication exception occurred.
+ */
+ public String getConnectionId() throws IOException;
+
+ /**
+ * <p>Closes this connection. On return from this method, the RMI
+ * object implementing this interface is unexported, so further
+ * remote calls to it will fail.</p>
+ *
+ * @throws IOException if the connection could not be closed,
+ * or the Remote object could not be unexported, or there was a
+ * communication failure when transmitting the remote close
+ * request.
+ */
+ public void close() throws IOException;
+
+ /**
+ * Handles the method {@link
+ * javax.management.MBeanServerConnection#createMBean(String,
+ * ObjectName)}.
+ *
+ * @param className The class name of the MBean to be instantiated.
+ * @param name The object name of the MBean. May be null.
+ * @param delegationSubject The <code>Subject</code> containing the
+ * delegation principals or <code>null</code> if the authentication
+ * principal is used instead.
+ *
+ * @return An <code>ObjectInstance</code>, containing the
+ * <code>ObjectName</code> and the Java class name of the newly
+ * instantiated MBean. If the contained <code>ObjectName</code>
+ * is <code>n</code>, the contained Java class name is
+ * <code>{@link #getMBeanInfo getMBeanInfo(n)}.getClassName()</code>.
+ *
+ * @throws ReflectionException Wraps a
+ * <code>java.lang.ClassNotFoundException</code> or a
+ * <code>java.lang.Exception</code> that occurred
+ * when trying to invoke the MBean's constructor.
+ * @throws InstanceAlreadyExistsException The MBean is already
+ * under the control of the MBean server.
+ * @throws MBeanRegistrationException The
+ * <code>preRegister</code> (<code>MBeanRegistration</code>
+ * interface) method of the MBean has thrown an exception. The
+ * MBean will not be registered.
+ * @throws MBeanException The constructor of the MBean has
+ * thrown an exception.
+ * @throws NotCompliantMBeanException This class is not a JMX
+ * compliant MBean.
+ * @throws RuntimeOperationsException Wraps a
+ * <code>java.lang.IllegalArgumentException</code>: The className
+ * passed in parameter is null, the <code>ObjectName</code> passed
+ * in parameter contains a pattern or no <code>ObjectName</code>
+ * is specified for the MBean.
+ * @throws SecurityException if the client, or the delegated Subject
+ * if any, does not have permission to perform this operation.
+ * @throws IOException if a general communication exception occurred.
+ */
+ public ObjectInstance createMBean(String className,
+ ObjectName name,
+ Subject delegationSubject)
+ throws
+ ReflectionException,
+ InstanceAlreadyExistsException,
+ MBeanRegistrationException,
+ MBeanException,
+ NotCompliantMBeanException,
+ IOException;
+
+ /**
+ * Handles the method {@link
+ * javax.management.MBeanServerConnection#createMBean(String,
+ * ObjectName, ObjectName)}.
+ *
+ * @param className The class name of the MBean to be instantiated.
+ * @param name The object name of the MBean. May be null.
+ * @param loaderName The object name of the class loader to be used.
+ * @param delegationSubject The <code>Subject</code> containing the
+ * delegation principals or <code>null</code> if the authentication
+ * principal is used instead.
+ *
+ * @return An <code>ObjectInstance</code>, containing the
+ * <code>ObjectName</code> and the Java class name of the newly
+ * instantiated MBean. If the contained <code>ObjectName</code>
+ * is <code>n</code>, the contained Java class name is
+ * <code>{@link #getMBeanInfo getMBeanInfo(n)}.getClassName()</code>.
+ *
+ * @throws ReflectionException Wraps a
+ * <code>java.lang.ClassNotFoundException</code> or a
+ * <code>java.lang.Exception</code> that occurred when trying to
+ * invoke the MBean's constructor.
+ * @throws InstanceAlreadyExistsException The MBean is already
+ * under the control of the MBean server.
+ * @throws MBeanRegistrationException The
+ * <code>preRegister</code> (<code>MBeanRegistration</code>
+ * interface) method of the MBean has thrown an exception. The
+ * MBean will not be registered.
+ * @throws MBeanException The constructor of the MBean has
+ * thrown an exception.
+ * @throws NotCompliantMBeanException This class is not a JMX
+ * compliant MBean.
+ * @throws InstanceNotFoundException The specified class loader
+ * is not registered in the MBean server.
+ * @throws RuntimeOperationsException Wraps a
+ * <code>java.lang.IllegalArgumentException</code>: The className
+ * passed in parameter is null, the <code>ObjectName</code> passed
+ * in parameter contains a pattern or no <code>ObjectName</code>
+ * is specified for the MBean.
+ * @throws SecurityException if the client, or the delegated Subject
+ * if any, does not have permission to perform this operation.
+ * @throws IOException if a general communication exception occurred.
+ */
+ public ObjectInstance createMBean(String className,
+ ObjectName name,
+ ObjectName loaderName,
+ Subject delegationSubject)
+ throws
+ ReflectionException,
+ InstanceAlreadyExistsException,
+ MBeanRegistrationException,
+ MBeanException,
+ NotCompliantMBeanException,
+ InstanceNotFoundException,
+ IOException;
+
+ /**
+ * Handles the method {@link
+ * javax.management.MBeanServerConnection#createMBean(String,
+ * ObjectName, Object[], String[])}. The <code>Object[]</code>
+ * parameter is wrapped in a <code>MarshalledObject</code>.
+ *
+ * @param className The class name of the MBean to be instantiated.
+ * @param name The object name of the MBean. May be null.
+ * @param params An array containing the parameters of the
+ * constructor to be invoked, encapsulated into a
+ * <code>MarshalledObject</code>. The encapsulated array can be
+ * null, equivalent to an empty array.
+ * @param signature An array containing the signature of the
+ * constructor to be invoked. Can be null, equivalent to an empty
+ * array.
+ * @param delegationSubject The <code>Subject</code> containing the
+ * delegation principals or <code>null</code> if the authentication
+ * principal is used instead.
+ *
+ * @return An <code>ObjectInstance</code>, containing the
+ * <code>ObjectName</code> and the Java class name of the newly
+ * instantiated MBean. If the contained <code>ObjectName</code>
+ * is <code>n</code>, the contained Java class name is
+ * <code>{@link #getMBeanInfo getMBeanInfo(n)}.getClassName()</code>.
+ *
+ * @throws ReflectionException Wraps a
+ * <code>java.lang.ClassNotFoundException</code> or a
+ * <code>java.lang.Exception</code> that occurred when trying to
+ * invoke the MBean's constructor.
+ * @throws InstanceAlreadyExistsException The MBean is already
+ * under the control of the MBean server.
+ * @throws MBeanRegistrationException The
+ * <code>preRegister</code> (<code>MBeanRegistration</code>
+ * interface) method of the MBean has thrown an exception. The
+ * MBean will not be registered.
+ * @throws MBeanException The constructor of the MBean has
+ * thrown an exception.
+ * @throws NotCompliantMBeanException This class is not a JMX
+ * compliant MBean.
+ * @throws RuntimeOperationsException Wraps a
+ * <code>java.lang.IllegalArgumentException</code>: The className
+ * passed in parameter is null, the <code>ObjectName</code> passed
+ * in parameter contains a pattern, or no <code>ObjectName</code>
+ * is specified for the MBean.
+ * @throws SecurityException if the client, or the delegated Subject
+ * if any, does not have permission to perform this operation.
+ * @throws IOException if a general communication exception occurred.
+ */
+ public ObjectInstance createMBean(String className,
+ ObjectName name,
+ MarshalledObject params,
+ String signature[],
+ Subject delegationSubject)
+ throws
+ ReflectionException,
+ InstanceAlreadyExistsException,
+ MBeanRegistrationException,
+ MBeanException,
+ NotCompliantMBeanException,
+ IOException;
+
+ /**
+ * Handles the method {@link
+ * javax.management.MBeanServerConnection#createMBean(String,
+ * ObjectName, ObjectName, Object[], String[])}. The
+ * <code>Object[]</code> parameter is wrapped in a
+ * <code>MarshalledObject</code>.
+ *
+ * @param className The class name of the MBean to be instantiated.
+ * @param name The object name of the MBean. May be null.
+ * @param loaderName The object name of the class loader to be used.
+ * @param params An array containing the parameters of the
+ * constructor to be invoked, encapsulated into a
+ * <code>MarshalledObject</code>. The encapsulated array can be
+ * null, equivalent to an empty array.
+ * @param signature An array containing the signature of the
+ * constructor to be invoked. Can be null, equivalent to an empty
+ * array.
+ * @param delegationSubject The <code>Subject</code> containing the
+ * delegation principals or <code>null</code> if the authentication
+ * principal is used instead.
+ *
+ * @return An <code>ObjectInstance</code>, containing the
+ * <code>ObjectName</code> and the Java class name of the newly
+ * instantiated MBean. If the contained <code>ObjectName</code>
+ * is <code>n</code>, the contained Java class name is
+ * <code>{@link #getMBeanInfo getMBeanInfo(n)}.getClassName()</code>.
+ *
+ * @throws ReflectionException Wraps a
+ * <code>java.lang.ClassNotFoundException</code> or a
+ * <code>java.lang.Exception</code> that occurred when trying to
+ * invoke the MBean's constructor.
+ * @throws InstanceAlreadyExistsException The MBean is already
+ * under the control of the MBean server.
+ * @throws MBeanRegistrationException The
+ * <code>preRegister</code> (<code>MBeanRegistration</code>
+ * interface) method of the MBean has thrown an exception. The
+ * MBean will not be registered.
+ * @throws MBeanException The constructor of the MBean has
+ * thrown an exception.
+ * @throws NotCompliantMBeanException This class is not a JMX
+ * compliant MBean.
+ * @throws InstanceNotFoundException The specified class loader
+ * is not registered in the MBean server.
+ * @throws RuntimeOperationsException Wraps a
+ * <code>java.lang.IllegalArgumentException</code>: The className
+ * passed in parameter is null, the <code>ObjectName</code> passed
+ * in parameter contains a pattern, or no <code>ObjectName</code>
+ * is specified for the MBean.
+ * @throws SecurityException if the client, or the delegated Subject
+ * if any, does not have permission to perform this operation.
+ * @throws IOException if a general communication exception occurred.
+ */
+ public ObjectInstance createMBean(String className,
+ ObjectName name,
+ ObjectName loaderName,
+ MarshalledObject params,
+ String signature[],
+ Subject delegationSubject)
+ throws
+ ReflectionException,
+ InstanceAlreadyExistsException,
+ MBeanRegistrationException,
+ MBeanException,
+ NotCompliantMBeanException,
+ InstanceNotFoundException,
+ IOException;
+
+ /**
+ * Handles the method
+ * {@link javax.management.MBeanServerConnection#unregisterMBean(ObjectName)}.
+ *
+ * @param name The object name of the MBean to be unregistered.
+ * @param delegationSubject The <code>Subject</code> containing the
+ * delegation principals or <code>null</code> if the authentication
+ * principal is used instead.
+ *
+ * @throws InstanceNotFoundException The MBean specified is not
+ * registered in the MBean server.
+ * @throws MBeanRegistrationException The preDeregister
+ * ((<code>MBeanRegistration</code> interface) method of the MBean
+ * has thrown an exception.
+ * @throws RuntimeOperationsException Wraps a
+ * <code>java.lang.IllegalArgumentException</code>: The object
+ * name in parameter is null or the MBean you are when trying to
+ * unregister is the {@link javax.management.MBeanServerDelegate
+ * MBeanServerDelegate} MBean.
+ * @throws SecurityException if the client, or the delegated Subject
+ * if any, does not have permission to perform this operation.
+ * @throws IOException if a general communication exception occurred.
+ */
+ public void unregisterMBean(ObjectName name, Subject delegationSubject)
+ throws
+ InstanceNotFoundException,
+ MBeanRegistrationException,
+ IOException;
+
+ /**
+ * Handles the method
+ * {@link javax.management.MBeanServerConnection#getObjectInstance(ObjectName)}.
+ *
+ * @param name The object name of the MBean.
+ * @param delegationSubject The <code>Subject</code> containing the
+ * delegation principals or <code>null</code> if the authentication
+ * principal is used instead.
+ *
+ * @return The <code>ObjectInstance</code> associated with the MBean
+ * specified by <var>name</var>. The contained <code>ObjectName</code>
+ * is <code>name</code> and the contained class name is
+ * <code>{@link #getMBeanInfo getMBeanInfo(name)}.getClassName()</code>.
+ *
+ * @throws InstanceNotFoundException The MBean specified is not
+ * registered in the MBean server.
+ * @throws RuntimeOperationsException Wraps a
+ * <code>java.lang.IllegalArgumentException</code>: The object
+ * name in parameter is null.
+ * @throws SecurityException if the client, or the delegated Subject
+ * if any, does not have permission to perform this operation.
+ * @throws IOException if a general communication exception occurred.
+ */
+ public ObjectInstance getObjectInstance(ObjectName name,
+ Subject delegationSubject)
+ throws InstanceNotFoundException, IOException;
+
+ /**
+ * Handles the method {@link
+ * javax.management.MBeanServerConnection#queryMBeans(ObjectName,
+ * QueryExp)}. The <code>QueryExp</code> is wrapped in a
+ * <code>MarshalledObject</code>.
+ *
+ * @param name The object name pattern identifying the MBeans to
+ * be retrieved. If null or no domain and key properties are
+ * specified, all the MBeans registered will be retrieved.
+ * @param query The query expression to be applied for selecting
+ * MBeans, encapsulated into a <code>MarshalledObject</code>. If
+ * the <code>MarshalledObject</code> encapsulates a null value no
+ * query expression will be applied for selecting MBeans.
+ * @param delegationSubject The <code>Subject</code> containing the
+ * delegation principals or <code>null</code> if the authentication
+ * principal is used instead.
+ *
+ * @return A set containing the <code>ObjectInstance</code>
+ * objects for the selected MBeans. If no MBean satisfies the
+ * query an empty list is returned.
+ *
+ * @throws SecurityException if the client, or the delegated Subject
+ * if any, does not have permission to perform this operation.
+ * @throws IOException if a general communication exception occurred.
+ */
+ public Set<ObjectInstance>
+ queryMBeans(ObjectName name,
+ MarshalledObject query,
+ Subject delegationSubject)
+ throws IOException;
+
+ /**
+ * Handles the method {@link
+ * javax.management.MBeanServerConnection#queryNames(ObjectName,
+ * QueryExp)}. The <code>QueryExp</code> is wrapped in a
+ * <code>MarshalledObject</code>.
+ *
+ * @param name The object name pattern identifying the MBean names
+ * to be retrieved. If null or no domain and key properties are
+ * specified, the name of all registered MBeans will be retrieved.
+ * @param query The query expression to be applied for selecting
+ * MBeans, encapsulated into a <code>MarshalledObject</code>. If
+ * the <code>MarshalledObject</code> encapsulates a null value no
+ * query expression will be applied for selecting MBeans.
+ * @param delegationSubject The <code>Subject</code> containing the
+ * delegation principals or <code>null</code> if the authentication
+ * principal is used instead.
+ *
+ * @return A set containing the ObjectNames for the MBeans
+ * selected. If no MBean satisfies the query, an empty list is
+ * returned.
+ *
+ * @throws SecurityException if the client, or the delegated Subject
+ * if any, does not have permission to perform this operation.
+ * @throws IOException if a general communication exception occurred.
+ */
+ public Set<ObjectName>
+ queryNames(ObjectName name,
+ MarshalledObject query,
+ Subject delegationSubject)
+ throws IOException;
+
+ /**
+ * Handles the method
+ * {@link javax.management.MBeanServerConnection#isRegistered(ObjectName)}.
+ *
+ * @param name The object name of the MBean to be checked.
+ * @param delegationSubject The <code>Subject</code> containing the
+ * delegation principals or <code>null</code> if the authentication
+ * principal is used instead.
+ *
+ * @return True if the MBean is already registered in the MBean
+ * server, false otherwise.
+ *
+ * @throws RuntimeOperationsException Wraps a
+ * <code>java.lang.IllegalArgumentException</code>: The object
+ * name in parameter is null.
+ * @throws SecurityException if the client, or the delegated Subject
+ * if any, does not have permission to perform this operation.
+ * @throws IOException if a general communication exception occurred.
+ */
+ public boolean isRegistered(ObjectName name, Subject delegationSubject)
+ throws IOException;
+
+ /**
+ * Handles the method
+ * {@link javax.management.MBeanServerConnection#getMBeanCount()}.
+ *
+ * @param delegationSubject The <code>Subject</code> containing the
+ * delegation principals or <code>null</code> if the authentication
+ * principal is used instead.
+ *
+ * @return the number of MBeans registered.
+ *
+ * @throws SecurityException if the client, or the delegated Subject
+ * if any, does not have permission to perform this operation.
+ * @throws IOException if a general communication exception occurred.
+ */
+ public Integer getMBeanCount(Subject delegationSubject)
+ throws IOException;
+
+ /**
+ * Handles the method {@link
+ * javax.management.MBeanServerConnection#getAttribute(ObjectName,
+ * String)}.
+ *
+ * @param name The object name of the MBean from which the
+ * attribute is to be retrieved.
+ * @param attribute A String specifying the name of the attribute
+ * to be retrieved.
+ * @param delegationSubject The <code>Subject</code> containing the
+ * delegation principals or <code>null</code> if the authentication
+ * principal is used instead.
+ *
+ * @return The value of the retrieved attribute.
+ *
+ * @throws AttributeNotFoundException The attribute specified
+ * is not accessible in the MBean.
+ * @throws MBeanException Wraps an exception thrown by the
+ * MBean's getter.
+ * @throws InstanceNotFoundException The MBean specified is not
+ * registered in the MBean server.
+ * @throws ReflectionException Wraps a
+ * <code>java.lang.Exception</code> thrown when trying to invoke
+ * the getter.
+ * @throws RuntimeOperationsException Wraps a
+ * <code>java.lang.IllegalArgumentException</code>: The object
+ * name in parameter is null or the attribute in parameter is
+ * null.
+ * @throws RuntimeMBeanException Wraps a runtime exception thrown
+ * by the MBean's getter.
+ * @throws SecurityException if the client, or the delegated Subject
+ * if any, does not have permission to perform this operation.
+ * @throws IOException if a general communication exception occurred.
+ *
+ * @see #setAttribute
+ */
+ public Object getAttribute(ObjectName name,
+ String attribute,
+ Subject delegationSubject)
+ throws
+ MBeanException,
+ AttributeNotFoundException,
+ InstanceNotFoundException,
+ ReflectionException,
+ IOException;
+
+ /**
+ * Handles the method {@link
+ * javax.management.MBeanServerConnection#getAttributes(ObjectName,
+ * String[])}.
+ *
+ * @param name The object name of the MBean from which the
+ * attributes are retrieved.
+ * @param attributes A list of the attributes to be retrieved.
+ * @param delegationSubject The <code>Subject</code> containing the
+ * delegation principals or <code>null</code> if the authentication
+ * principal is used instead.
+ *
+ * @return The list of the retrieved attributes.
+ *
+ * @throws InstanceNotFoundException The MBean specified is not
+ * registered in the MBean server.
+ * @throws ReflectionException An exception occurred when
+ * trying to invoke the getAttributes method of a Dynamic MBean.
+ * @throws RuntimeOperationsException Wrap a
+ * <code>java.lang.IllegalArgumentException</code>: The object
+ * name in parameter is null or attributes in parameter is null.
+ * @throws SecurityException if the client, or the delegated Subject
+ * if any, does not have permission to perform this operation.
+ * @throws IOException if a general communication exception occurred.
+ *
+ * @see #setAttributes
+ */
+ public AttributeList getAttributes(ObjectName name,
+ String[] attributes,
+ Subject delegationSubject)
+ throws
+ InstanceNotFoundException,
+ ReflectionException,
+ IOException;
+
+ /**
+ * Handles the method {@link
+ * javax.management.MBeanServerConnection#setAttribute(ObjectName,
+ * Attribute)}. The <code>Attribute</code> parameter is wrapped
+ * in a <code>MarshalledObject</code>.
+ *
+ * @param name The name of the MBean within which the attribute is
+ * to be set.
+ * @param attribute The identification of the attribute to be set
+ * and the value it is to be set to, encapsulated into a
+ * <code>MarshalledObject</code>.
+ * @param delegationSubject The <code>Subject</code> containing the
+ * delegation principals or <code>null</code> if the authentication
+ * principal is used instead.
+ *
+ * @throws InstanceNotFoundException The MBean specified is not
+ * registered in the MBean server.
+ * @throws AttributeNotFoundException The attribute specified
+ * is not accessible in the MBean.
+ * @throws InvalidAttributeValueException The value specified
+ * for the attribute is not valid.
+ * @throws MBeanException Wraps an exception thrown by the
+ * MBean's setter.
+ * @throws ReflectionException Wraps a
+ * <code>java.lang.Exception</code> thrown when trying to invoke
+ * the setter.
+ * @throws RuntimeOperationsException Wraps a
+ * <code>java.lang.IllegalArgumentException</code>: The object
+ * name in parameter is null or the attribute in parameter is
+ * null.
+ * @throws SecurityException if the client, or the delegated Subject
+ * if any, does not have permission to perform this operation.
+ * @throws IOException if a general communication exception occurred.
+ *
+ * @see #getAttribute
+ */
+ public void setAttribute(ObjectName name,
+ MarshalledObject attribute,
+ Subject delegationSubject)
+ throws
+ InstanceNotFoundException,
+ AttributeNotFoundException,
+ InvalidAttributeValueException,
+ MBeanException,
+ ReflectionException,
+ IOException;
+
+ /**
+ * Handles the method {@link
+ * javax.management.MBeanServerConnection#setAttributes(ObjectName,
+ * AttributeList)}. The <code>AttributeList</code> parameter is
+ * wrapped in a <code>MarshalledObject</code>.
+ *
+ * @param name The object name of the MBean within which the
+ * attributes are to be set.
+ * @param attributes A list of attributes: The identification of
+ * the attributes to be set and the values they are to be set to,
+ * encapsulated into a <code>MarshalledObject</code>.
+ * @param delegationSubject The <code>Subject</code> containing the
+ * delegation principals or <code>null</code> if the authentication
+ * principal is used instead.
+ *
+ * @return The list of attributes that were set, with their new
+ * values.
+ *
+ * @throws InstanceNotFoundException The MBean specified is not
+ * registered in the MBean server.
+ * @throws ReflectionException An exception occurred when
+ * trying to invoke the getAttributes method of a Dynamic MBean.
+ * @throws RuntimeOperationsException Wraps a
+ * <code>java.lang.IllegalArgumentException</code>: The object
+ * name in parameter is null or attributes in parameter is null.
+ * @throws SecurityException if the client, or the delegated Subject
+ * if any, does not have permission to perform this operation.
+ * @throws IOException if a general communication exception occurred.
+ *
+ * @see #getAttributes
+ */
+ public AttributeList setAttributes(ObjectName name,
+ MarshalledObject attributes,
+ Subject delegationSubject)
+ throws
+ InstanceNotFoundException,
+ ReflectionException,
+ IOException;
+
+ /**
+ * Handles the method {@link
+ * javax.management.MBeanServerConnection#invoke(ObjectName,
+ * String, Object[], String[])}. The <code>Object[]</code>
+ * parameter is wrapped in a <code>MarshalledObject</code>.
+ *
+ * @param name The object name of the MBean on which the method is
+ * to be invoked.
+ * @param operationName The name of the operation to be invoked.
+ * @param params An array containing the parameters to be set when
+ * the operation is invoked, encapsulated into a
+ * <code>MarshalledObject</code>. The encapsulated array can be
+ * null, equivalent to an empty array.
+ * @param signature An array containing the signature of the
+ * operation. The class objects will be loaded using the same
+ * class loader as the one used for loading the MBean on which the
+ * operation was invoked. Can be null, equivalent to an empty
+ * array.
+ * @param delegationSubject The <code>Subject</code> containing the
+ * delegation principals or <code>null</code> if the authentication
+ * principal is used instead.
+ *
+ * @return The object returned by the operation, which represents
+ * the result of invoking the operation on the MBean specified.
+ *
+ * @throws InstanceNotFoundException The MBean specified is not
+ * registered in the MBean server.
+ * @throws MBeanException Wraps an exception thrown by the
+ * MBean's invoked method.
+ * @throws ReflectionException Wraps a
+ * <code>java.lang.Exception</code> thrown while trying to invoke
+ * the method.
+ * @throws SecurityException if the client, or the delegated Subject
+ * if any, does not have permission to perform this operation.
+ * @throws IOException if a general communication exception occurred.
+ * @throws RuntimeOperationsException Wraps an {@link
+ * IllegalArgumentException} when <code>name</code> or
+ * <code>operationName</code> is null.
+ */
+ public Object invoke(ObjectName name,
+ String operationName,
+ MarshalledObject params,
+ String signature[],
+ Subject delegationSubject)
+ throws
+ InstanceNotFoundException,
+ MBeanException,
+ ReflectionException,
+ IOException;
+
+ /**
+ * Handles the method
+ * {@link javax.management.MBeanServerConnection#getDefaultDomain()}.
+ *
+ * @param delegationSubject The <code>Subject</code> containing the
+ * delegation principals or <code>null</code> if the authentication
+ * principal is used instead.
+ *
+ * @return the default domain.
+ *
+ * @throws SecurityException if the client, or the delegated Subject
+ * if any, does not have permission to perform this operation.
+ * @throws IOException if a general communication exception occurred.
+ */
+ public String getDefaultDomain(Subject delegationSubject)
+ throws IOException;
+
+ /**
+ * Handles the method
+ * {@link javax.management.MBeanServerConnection#getDomains()}.
+ *
+ * @param delegationSubject The <code>Subject</code> containing the
+ * delegation principals or <code>null</code> if the authentication
+ * principal is used instead.
+ *
+ * @return the list of domains.
+ *
+ * @throws SecurityException if the client, or the delegated Subject
+ * if any, does not have permission to perform this operation.
+ * @throws IOException if a general communication exception occurred.
+ */
+ public String[] getDomains(Subject delegationSubject)
+ throws IOException;
+
+ /**
+ * Handles the method
+ * {@link javax.management.MBeanServerConnection#getMBeanInfo(ObjectName)}.
+ *
+ * @param name The name of the MBean to analyze
+ * @param delegationSubject The <code>Subject</code> containing the
+ * delegation principals or <code>null</code> if the authentication
+ * principal is used instead.
+ *
+ * @return An instance of <code>MBeanInfo</code> allowing the
+ * retrieval of all attributes and operations of this MBean.
+ *
+ * @throws IntrospectionException An exception occurred during
+ * introspection.
+ * @throws InstanceNotFoundException The MBean specified was
+ * not found.
+ * @throws ReflectionException An exception occurred when
+ * trying to invoke the getMBeanInfo of a Dynamic MBean.
+ * @throws SecurityException if the client, or the delegated Subject
+ * if any, does not have permission to perform this operation.
+ * @throws IOException if a general communication exception occurred.
+ * @throws RuntimeOperationsException Wraps a
+ * <code>java.lang.IllegalArgumentException</code>: The object
+ * name in parameter is null.
+ */
+ public MBeanInfo getMBeanInfo(ObjectName name, Subject delegationSubject)
+ throws
+ InstanceNotFoundException,
+ IntrospectionException,
+ ReflectionException,
+ IOException;
+
+ /**
+ * Handles the method {@link
+ * javax.management.MBeanServerConnection#isInstanceOf(ObjectName,
+ * String)}.
+ *
+ * @param name The <code>ObjectName</code> of the MBean.
+ * @param className The name of the class.
+ * @param delegationSubject The <code>Subject</code> containing the
+ * delegation principals or <code>null</code> if the authentication
+ * principal is used instead.
+ *
+ * @return true if the MBean specified is an instance of the
+ * specified class according to the rules above, false otherwise.
+ *
+ * @throws InstanceNotFoundException The MBean specified is not
+ * registered in the MBean server.
+ * @throws SecurityException if the client, or the delegated Subject
+ * if any, does not have permission to perform this operation.
+ * @throws IOException if a general communication exception occurred.
+ * @throws RuntimeOperationsException Wraps a
+ * <code>java.lang.IllegalArgumentException</code>: The object
+ * name in parameter is null.
+ */
+ public boolean isInstanceOf(ObjectName name,
+ String className,
+ Subject delegationSubject)
+ throws InstanceNotFoundException, IOException;
+
+ /**
+ * Handles the method {@link
+ * javax.management.MBeanServerConnection#addNotificationListener(ObjectName,
+ * ObjectName, NotificationFilter, Object)}. The
+ * <code>NotificationFilter</code> parameter is wrapped in a
+ * <code>MarshalledObject</code>. The <code>Object</code>
+ * (handback) parameter is also wrapped in a
+ * <code>MarshalledObject</code>.
+ *
+ * @param name The name of the MBean on which the listener should
+ * be added.
+ * @param listener The object name of the listener which will
+ * handle the notifications emitted by the registered MBean.
+ * @param filter The filter object, encapsulated into a
+ * <code>MarshalledObject</code>. If filter encapsulated in the
+ * <code>MarshalledObject</code> has a null value, no filtering
+ * will be performed before handling notifications.
+ * @param handback The context to be sent to the listener when a
+ * notification is emitted, encapsulated into a
+ * <code>MarshalledObject</code>.
+ * @param delegationSubject The <code>Subject</code> containing the
+ * delegation principals or <code>null</code> if the authentication
+ * principal is used instead.
+ *
+ * @throws InstanceNotFoundException The MBean name of the
+ * notification listener or of the notification broadcaster does
+ * not match any of the registered MBeans.
+ * @throws RuntimeOperationsException Wraps an {@link
+ * IllegalArgumentException}. The MBean named by
+ * <code>listener</code> exists but does not implement the
+ * {@link javax.management.NotificationListener} interface,
+ * or <code>name</code> or <code>listener</code> is null.
+ * @throws SecurityException if the client, or the delegated Subject
+ * if any, does not have permission to perform this operation.
+ * @throws IOException if a general communication exception occurred.
+ *
+ * @see #removeNotificationListener(ObjectName, ObjectName, Subject)
+ * @see #removeNotificationListener(ObjectName, ObjectName,
+ * MarshalledObject, MarshalledObject, Subject)
+ */
+ public void addNotificationListener(ObjectName name,
+ ObjectName listener,
+ MarshalledObject filter,
+ MarshalledObject handback,
+ Subject delegationSubject)
+ throws InstanceNotFoundException, IOException;
+
+ /**
+ * Handles the method {@link
+ * javax.management.MBeanServerConnection#removeNotificationListener(ObjectName,
+ * ObjectName)}.
+ *
+ * @param name The name of the MBean on which the listener should
+ * be removed.
+ * @param listener The object name of the listener to be removed.
+ * @param delegationSubject The <code>Subject</code> containing the
+ * delegation principals or <code>null</code> if the authentication
+ * principal is used instead.
+ *
+ * @throws InstanceNotFoundException The MBean name provided
+ * does not match any of the registered MBeans.
+ * @throws ListenerNotFoundException The listener is not
+ * registered in the MBean.
+ * @throws SecurityException if the client, or the delegated Subject
+ * if any, does not have permission to perform this operation.
+ * @throws IOException if a general communication exception occurred.
+ * @throws RuntimeOperationsException Wraps an {@link
+ * IllegalArgumentException} when <code>name</code> or
+ * <code>listener</code> is null.
+ *
+ * @see #addNotificationListener
+ */
+ public void removeNotificationListener(ObjectName name,
+ ObjectName listener,
+ Subject delegationSubject)
+ throws
+ InstanceNotFoundException,
+ ListenerNotFoundException,
+ IOException;
+
+ /**
+ * Handles the method {@link
+ * javax.management.MBeanServerConnection#removeNotificationListener(ObjectName,
+ * ObjectName, NotificationFilter, Object)}. The
+ * <code>NotificationFilter</code> parameter is wrapped in a
+ * <code>MarshalledObject</code>. The <code>Object</code>
+ * parameter is also wrapped in a <code>MarshalledObject</code>.
+ *
+ * @param name The name of the MBean on which the listener should
+ * be removed.
+ * @param listener A listener that was previously added to this
+ * MBean.
+ * @param filter The filter that was specified when the listener
+ * was added, encapsulated into a <code>MarshalledObject</code>.
+ * @param handback The handback that was specified when the
+ * listener was added, encapsulated into a <code>MarshalledObject</code>.
+ * @param delegationSubject The <code>Subject</code> containing the
+ * delegation principals or <code>null</code> if the authentication
+ * principal is used instead.
+ *
+ * @throws InstanceNotFoundException The MBean name provided
+ * does not match any of the registered MBeans.
+ * @throws ListenerNotFoundException The listener is not
+ * registered in the MBean, or it is not registered with the given
+ * filter and handback.
+ * @throws SecurityException if the client, or the delegated Subject
+ * if any, does not have permission to perform this operation.
+ * @throws IOException if a general communication exception occurred.
+ * @throws RuntimeOperationsException Wraps an {@link
+ * IllegalArgumentException} when <code>name</code> or
+ * <code>listener</code> is null.
+ *
+ * @see #addNotificationListener
+ */
+ public void removeNotificationListener(ObjectName name,
+ ObjectName listener,
+ MarshalledObject filter,
+ MarshalledObject handback,
+ Subject delegationSubject)
+ throws
+ InstanceNotFoundException,
+ ListenerNotFoundException,
+ IOException;
+
+ // Special Handling of Notifications -------------------------------------
+
+ /**
+ * <p>Handles the method {@link
+ * javax.management.MBeanServerConnection#addNotificationListener(ObjectName,
+ * NotificationListener, NotificationFilter, Object)}.</p>
+ *
+ * <p>Register for notifications from the given MBeans that match
+ * the given filters. The remote client can subsequently retrieve
+ * the notifications using the {@link #fetchNotifications
+ * fetchNotifications} method.</p>
+ *
+ * <p>For each listener, the original
+ * <code>NotificationListener</code> and <code>handback</code> are
+ * kept on the client side; in order for the client to be able to
+ * identify them, the server generates and returns a unique
+ * <code>listenerID</code>. This <code>listenerID</code> is
+ * forwarded with the <code>Notifications</code> to the remote
+ * client.</p>
+ *
+ * <p>If any one of the given (name, filter) pairs cannot be
+ * registered, then the operation fails with an exception, and no
+ * names or filters are registered.</p>
+ *
+ * @param names the <code>ObjectNames</code> identifying the
+ * MBeans emitting the Notifications.
+ * @param filters an array of marshalled representations of the
+ * <code>NotificationFilters</code>. Elements of this array can
+ * be null.
+ * @param delegationSubjects the <code>Subjects</code> on behalf
+ * of which the listeners are being added. Elements of this array
+ * can be null. Also, the <code>delegationSubjects</code>
+ * parameter itself can be null, which is equivalent to an array
+ * of null values with the same size as the <code>names</code> and
+ * <code>filters</code> arrays.
+ *
+ * @return an array of <code>listenerIDs</code> identifying the
+ * local listeners. This array has the same number of elements as
+ * the parameters.
+ *
+ * @throws IllegalArgumentException if <code>names</code> or
+ * <code>filters</code> is null, or if <code>names</code> contains
+ * a null element, or if the three arrays do not all have the same
+ * size.
+ * @throws ClassCastException if one of the elements of
+ * <code>filters</code> unmarshalls as a non-null object that is
+ * not a <code>NotificationFilter</code>.
+ * @throws InstanceNotFoundException if one of the
+ * <code>names</code> does not correspond to any registered MBean.
+ * @throws SecurityException if, for one of the MBeans, the
+ * client, or the delegated Subject if any, does not have
+ * permission to add a listener.
+ * @throws IOException if a general communication exception occurred.
+ */
+ public Integer[] addNotificationListeners(ObjectName[] names,
+ MarshalledObject[] filters,
+ Subject[] delegationSubjects)
+ throws InstanceNotFoundException, IOException;
+
+ /**
+ * <p>Handles the
+ * {@link javax.management.MBeanServerConnection#removeNotificationListener(ObjectName,NotificationListener)
+ * removeNotificationListener(ObjectName, NotificationListener)} and
+ * {@link javax.management.MBeanServerConnection#removeNotificationListener(ObjectName,NotificationListener,NotificationFilter,Object)
+ * removeNotificationListener(ObjectName, NotificationListener, NotificationFilter, Object)} methods.</p>
+ *
+ * <p>This method removes one or more
+ * <code>NotificationListener</code>s from a given MBean in the
+ * MBean server.</p>
+ *
+ * <p>The <code>NotificationListeners</code> are identified by the
+ * IDs which were returned by the {@link
+ * #addNotificationListeners(ObjectName[], MarshalledObject[],
+ * Subject[])} method.</p>
+ *
+ * @param name the <code>ObjectName</code> identifying the MBean
+ * emitting the Notifications.
+ * @param listenerIDs the list of the IDs corresponding to the
+ * listeners to remove.
+ * @param delegationSubject The <code>Subject</code> containing the
+ * delegation principals or <code>null</code> if the authentication
+ * principal is used instead.
+ *
+ * @throws InstanceNotFoundException if the given
+ * <code>name</code> does not correspond to any registered MBean.
+ * @throws ListenerNotFoundException if one of the listeners was
+ * not found on the server side. This exception can happen if the
+ * MBean discarded a listener for some reason other than a call to
+ * <code>MBeanServer.removeNotificationListener</code>.
+ * @throws SecurityException if the client, or the delegated Subject
+ * if any, does not have permission to remove the listeners.
+ * @throws IOException if a general communication exception occurred.
+ * @throws IllegalArgumentException if <code>ObjectName</code> or
+ * <code>listenerIds</code> is null or if <code>listenerIds</code>
+ * contains a null element.
+ */
+ public void removeNotificationListeners(ObjectName name,
+ Integer[] listenerIDs,
+ Subject delegationSubject)
+ throws
+ InstanceNotFoundException,
+ ListenerNotFoundException,
+ IOException;
+
+ /**
+ * <p>Retrieves notifications from the connector server. This
+ * method can block until there is at least one notification or
+ * until the specified timeout is reached. The method can also
+ * return at any time with zero notifications.</p>
+ *
+ * <p>A notification can be included in the result if its sequence
+ * number is no less than <code>clientSequenceNumber</code> and
+ * this client has registered at least one listener for the MBean
+ * generating the notification, with a filter that accepts the
+ * notification. Each listener that is interested in the
+ * notification is identified by an Integer ID that was returned
+ * by {@link #addNotificationListeners(ObjectName[],
+ * MarshalledObject[], Subject[])}.</p>
+ *
+ * @param clientSequenceNumber the first sequence number that the
+ * client is interested in. If negative, it is interpreted as
+ * meaning the sequence number that the next notification will
+ * have.
+ *
+ * @param maxNotifications the maximum number of different
+ * notifications to return. The <code>TargetedNotification</code>
+ * array in the returned <code>NotificationResult</code> can have
+ * more elements than this if the same notification appears more
+ * than once. The behavior is unspecified if this parameter is
+ * negative.
+ *
+ * @param timeout the maximum time in milliseconds to wait for a
+ * notification to arrive. This can be 0 to indicate that the
+ * method should not wait if there are no notifications, but
+ * should return at once. It can be <code>Long.MAX_VALUE</code>
+ * to indicate that there is no timeout. The behavior is
+ * unspecified if this parameter is negative.
+ *
+ * @return A <code>NotificationResult</code>.
+ *
+ * @throws IOException if a general communication exception occurred.
+ */
+ public NotificationResult fetchNotifications(long clientSequenceNumber,
+ int maxNotifications,
+ long timeout)
+ throws IOException;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,1834 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 javax.management.remote.rmi;
+
+import java.io.IOException;
+import java.rmi.MarshalledObject;
+import java.rmi.UnmarshalException;
+import java.rmi.server.Unreferenced;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.Permission;
+import java.security.Permissions;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.*;
+import javax.management.remote.JMXServerErrorException;
+import javax.management.remote.NotificationResult;
+import javax.security.auth.Subject;
+import sun.reflect.misc.ReflectUtil;
+
+import static javax.management.remote.rmi.RMIConnector.Util.cast;
+import com.sun.jmx.remote.internal.ServerCommunicatorAdmin;
+import com.sun.jmx.remote.internal.ServerNotifForwarder;
+import com.sun.jmx.remote.security.JMXSubjectDomainCombiner;
+import com.sun.jmx.remote.security.SubjectDelegator;
+import com.sun.jmx.remote.util.ClassLoaderWithRepository;
+import com.sun.jmx.remote.util.ClassLogger;
+import com.sun.jmx.remote.util.EnvHelp;
+import com.sun.jmx.remote.util.OrderClassLoaders;
+import javax.management.loading.ClassLoaderRepository;
+
+/**
+ * <p>Implementation of the {@link RMIConnection} interface. User
+ * code will not usually reference this class.</p>
+ *
+ * @since 1.5
+ */
+/*
+ * Notice that we omit the type parameter from MarshalledObject everywhere,
+ * even though it would add useful information to the documentation. The
+ * reason is that it was only added in Mustang (Java SE 6), whereas versions
+ * 1.4 and 2.0 of the JMX API must be implementable on Tiger per our
+ * commitments for JSR 255.
+ */
+public class RMIConnectionImpl implements RMIConnection, Unreferenced {
+
+ /**
+ * Constructs a new {@link RMIConnection}. This connection can be
+ * used with the JRMP transport. This object does
+ * not export itself: it is the responsibility of the caller to
+ * export it appropriately (see {@link
+ * RMIJRMPServerImpl#makeClient(String,Subject)}).
+ *
+ * @param rmiServer The RMIServerImpl object for which this
+ * connection is created. The behavior is unspecified if this
+ * parameter is null.
+ * @param connectionId The ID for this connection. The behavior
+ * is unspecified if this parameter is null.
+ * @param defaultClassLoader The default ClassLoader to be used
+ * when deserializing marshalled objects. Can be null, to signify
+ * the bootstrap class loader.
+ * @param subject the authenticated subject to be used for
+ * authorization. Can be null, to signify that no subject has
+ * been authenticated.
+ * @param env the environment containing attributes for the new
+ * <code>RMIServerImpl</code>. Can be null, equivalent to an
+ * empty map.
+ */
+ public RMIConnectionImpl(RMIServerImpl rmiServer,
+ String connectionId,
+ ClassLoader defaultClassLoader,
+ Subject subject,
+ Map<String,?> env) {
+ if (rmiServer == null || connectionId == null)
+ throw new NullPointerException("Illegal null argument");
+ if (env == null)
+ env = Collections.emptyMap();
+ this.rmiServer = rmiServer;
+ this.connectionId = connectionId;
+ this.defaultClassLoader = defaultClassLoader;
+
+ this.subjectDelegator = new SubjectDelegator();
+ this.subject = subject;
+ if (subject == null) {
+ this.acc = null;
+ this.removeCallerContext = false;
+ } else {
+ this.removeCallerContext =
+ SubjectDelegator.checkRemoveCallerContext(subject);
+ if (this.removeCallerContext) {
+ this.acc =
+ JMXSubjectDomainCombiner.getDomainCombinerContext(subject);
+ } else {
+ this.acc =
+ JMXSubjectDomainCombiner.getContext(subject);
+ }
+ }
+ this.mbeanServer = rmiServer.getMBeanServer();
+
+ final ClassLoader dcl = defaultClassLoader;
+
+ ClassLoaderRepository repository = AccessController.doPrivileged(
+ new PrivilegedAction<ClassLoaderRepository>() {
+ public ClassLoaderRepository run() {
+ return mbeanServer.getClassLoaderRepository();
+ }
+ },
+ withPermissions(new MBeanPermission("*", "getClassLoaderRepository"))
+ );
+ this.classLoaderWithRepository = AccessController.doPrivileged(
+ new PrivilegedAction<ClassLoaderWithRepository>() {
+ public ClassLoaderWithRepository run() {
+ return new ClassLoaderWithRepository(
+ repository,
+ dcl);
+ }
+ },
+ withPermissions(new RuntimePermission("createClassLoader"))
+ );
+
+ this.defaultContextClassLoader =
+ AccessController.doPrivileged(
+ new PrivilegedAction<ClassLoader>() {
+ @Override
+ public ClassLoader run() {
+ return new CombinedClassLoader(Thread.currentThread().getContextClassLoader(),
+ dcl);
+ }
+ });
+
+ serverCommunicatorAdmin = new
+ RMIServerCommunicatorAdmin(EnvHelp.getServerConnectionTimeout(env));
+
+ this.env = env;
+ }
+
+ private static AccessControlContext withPermissions(Permission ... perms){
+ Permissions col = new Permissions();
+
+ for (Permission thePerm : perms ) {
+ col.add(thePerm);
+ }
+
+ final ProtectionDomain pd = new ProtectionDomain(null, col);
+ return new AccessControlContext( new ProtectionDomain[] { pd });
+ }
+
+ private synchronized ServerNotifForwarder getServerNotifFwd() {
+ // Lazily created when first use. Mainly when
+ // addNotificationListener is first called.
+ if (serverNotifForwarder == null)
+ serverNotifForwarder =
+ new ServerNotifForwarder(mbeanServer,
+ env,
+ rmiServer.getNotifBuffer(),
+ connectionId);
+ return serverNotifForwarder;
+ }
+
+ public String getConnectionId() throws IOException {
+ // We should call reqIncomming() here... shouldn't we?
+ return connectionId;
+ }
+
+ public void close() throws IOException {
+ final boolean debug = logger.debugOn();
+ final String idstr = (debug?"["+this.toString()+"]":null);
+
+ synchronized (this) {
+ if (terminated) {
+ if (debug) logger.debug("close",idstr + " already terminated.");
+ return;
+ }
+
+ if (debug) logger.debug("close",idstr + " closing.");
+
+ terminated = true;
+
+ if (serverCommunicatorAdmin != null) {
+ serverCommunicatorAdmin.terminate();
+ }
+
+ if (serverNotifForwarder != null) {
+ serverNotifForwarder.terminate();
+ }
+ }
+
+ rmiServer.clientClosed(this);
+
+ if (debug) logger.debug("close",idstr + " closed.");
+ }
+
+ public void unreferenced() {
+ logger.debug("unreferenced", "called");
+ try {
+ close();
+ logger.debug("unreferenced", "done");
+ } catch (IOException e) {
+ logger.fine("unreferenced", e);
+ }
+ }
+
+ //-------------------------------------------------------------------------
+ // MBeanServerConnection Wrapper
+ //-------------------------------------------------------------------------
+
+ public ObjectInstance createMBean(String className,
+ ObjectName name,
+ Subject delegationSubject)
+ throws
+ ReflectionException,
+ InstanceAlreadyExistsException,
+ MBeanRegistrationException,
+ MBeanException,
+ NotCompliantMBeanException,
+ IOException {
+ try {
+ final Object params[] =
+ new Object[] { className, name };
+
+ if (logger.debugOn())
+ logger.debug("createMBean(String,ObjectName)",
+ "connectionId=" + connectionId +", className=" +
+ className+", name=" + name);
+
+ return (ObjectInstance)
+ doPrivilegedOperation(
+ CREATE_MBEAN,
+ params,
+ delegationSubject);
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof ReflectionException)
+ throw (ReflectionException) e;
+ if (e instanceof InstanceAlreadyExistsException)
+ throw (InstanceAlreadyExistsException) e;
+ if (e instanceof MBeanRegistrationException)
+ throw (MBeanRegistrationException) e;
+ if (e instanceof MBeanException)
+ throw (MBeanException) e;
+ if (e instanceof NotCompliantMBeanException)
+ throw (NotCompliantMBeanException) e;
+ if (e instanceof IOException)
+ throw (IOException) e;
+ throw newIOException("Got unexpected server exception: " + e, e);
+ }
+ }
+
+ public ObjectInstance createMBean(String className,
+ ObjectName name,
+ ObjectName loaderName,
+ Subject delegationSubject)
+ throws
+ ReflectionException,
+ InstanceAlreadyExistsException,
+ MBeanRegistrationException,
+ MBeanException,
+ NotCompliantMBeanException,
+ InstanceNotFoundException,
+ IOException {
+ try {
+ final Object params[] =
+ new Object[] { className, name, loaderName };
+
+ if (logger.debugOn())
+ logger.debug("createMBean(String,ObjectName,ObjectName)",
+ "connectionId=" + connectionId
+ +", className=" + className
+ +", name=" + name
+ +", loaderName=" + loaderName);
+
+ return (ObjectInstance)
+ doPrivilegedOperation(
+ CREATE_MBEAN_LOADER,
+ params,
+ delegationSubject);
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof ReflectionException)
+ throw (ReflectionException) e;
+ if (e instanceof InstanceAlreadyExistsException)
+ throw (InstanceAlreadyExistsException) e;
+ if (e instanceof MBeanRegistrationException)
+ throw (MBeanRegistrationException) e;
+ if (e instanceof MBeanException)
+ throw (MBeanException) e;
+ if (e instanceof NotCompliantMBeanException)
+ throw (NotCompliantMBeanException) e;
+ if (e instanceof InstanceNotFoundException)
+ throw (InstanceNotFoundException) e;
+ if (e instanceof IOException)
+ throw (IOException) e;
+ throw newIOException("Got unexpected server exception: " + e, e);
+ }
+ }
+
+ @SuppressWarnings("rawtypes") // MarshalledObject
+ public ObjectInstance createMBean(String className,
+ ObjectName name,
+ MarshalledObject params,
+ String signature[],
+ Subject delegationSubject)
+ throws
+ ReflectionException,
+ InstanceAlreadyExistsException,
+ MBeanRegistrationException,
+ MBeanException,
+ NotCompliantMBeanException,
+ IOException {
+
+ final Object[] values;
+ final boolean debug = logger.debugOn();
+
+ if (debug) logger.debug(
+ "createMBean(String,ObjectName,Object[],String[])",
+ "connectionId=" + connectionId
+ +", unwrapping parameters using classLoaderWithRepository.");
+
+ values =
+ nullIsEmpty(unwrap(params, classLoaderWithRepository, Object[].class,delegationSubject));
+
+ try {
+ final Object params2[] =
+ new Object[] { className, name, values,
+ nullIsEmpty(signature) };
+
+ if (debug)
+ logger.debug("createMBean(String,ObjectName,Object[],String[])",
+ "connectionId=" + connectionId
+ +", className=" + className
+ +", name=" + name
+ +", signature=" + strings(signature));
+
+ return (ObjectInstance)
+ doPrivilegedOperation(
+ CREATE_MBEAN_PARAMS,
+ params2,
+ delegationSubject);
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof ReflectionException)
+ throw (ReflectionException) e;
+ if (e instanceof InstanceAlreadyExistsException)
+ throw (InstanceAlreadyExistsException) e;
+ if (e instanceof MBeanRegistrationException)
+ throw (MBeanRegistrationException) e;
+ if (e instanceof MBeanException)
+ throw (MBeanException) e;
+ if (e instanceof NotCompliantMBeanException)
+ throw (NotCompliantMBeanException) e;
+ if (e instanceof IOException)
+ throw (IOException) e;
+ throw newIOException("Got unexpected server exception: " + e, e);
+ }
+ }
+
+ @SuppressWarnings("rawtypes") // MarshalledObject
+ public ObjectInstance createMBean(String className,
+ ObjectName name,
+ ObjectName loaderName,
+ MarshalledObject params,
+ String signature[],
+ Subject delegationSubject)
+ throws
+ ReflectionException,
+ InstanceAlreadyExistsException,
+ MBeanRegistrationException,
+ MBeanException,
+ NotCompliantMBeanException,
+ InstanceNotFoundException,
+ IOException {
+
+ final Object[] values;
+ final boolean debug = logger.debugOn();
+
+ if (debug) logger.debug(
+ "createMBean(String,ObjectName,ObjectName,Object[],String[])",
+ "connectionId=" + connectionId
+ +", unwrapping params with MBean extended ClassLoader.");
+
+ values = nullIsEmpty(unwrap(params,
+ getClassLoader(loaderName),
+ defaultClassLoader,
+ Object[].class,delegationSubject));
+
+ try {
+ final Object params2[] =
+ new Object[] { className, name, loaderName, values,
+ nullIsEmpty(signature) };
+
+ if (debug) logger.debug(
+ "createMBean(String,ObjectName,ObjectName,Object[],String[])",
+ "connectionId=" + connectionId
+ +", className=" + className
+ +", name=" + name
+ +", loaderName=" + loaderName
+ +", signature=" + strings(signature));
+
+ return (ObjectInstance)
+ doPrivilegedOperation(
+ CREATE_MBEAN_LOADER_PARAMS,
+ params2,
+ delegationSubject);
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof ReflectionException)
+ throw (ReflectionException) e;
+ if (e instanceof InstanceAlreadyExistsException)
+ throw (InstanceAlreadyExistsException) e;
+ if (e instanceof MBeanRegistrationException)
+ throw (MBeanRegistrationException) e;
+ if (e instanceof MBeanException)
+ throw (MBeanException) e;
+ if (e instanceof NotCompliantMBeanException)
+ throw (NotCompliantMBeanException) e;
+ if (e instanceof InstanceNotFoundException)
+ throw (InstanceNotFoundException) e;
+ if (e instanceof IOException)
+ throw (IOException) e;
+ throw newIOException("Got unexpected server exception: " + e, e);
+ }
+ }
+
+ public void unregisterMBean(ObjectName name, Subject delegationSubject)
+ throws
+ InstanceNotFoundException,
+ MBeanRegistrationException,
+ IOException {
+ try {
+ final Object params[] = new Object[] { name };
+
+ if (logger.debugOn()) logger.debug("unregisterMBean",
+ "connectionId=" + connectionId
+ +", name="+name);
+
+ doPrivilegedOperation(
+ UNREGISTER_MBEAN,
+ params,
+ delegationSubject);
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof InstanceNotFoundException)
+ throw (InstanceNotFoundException) e;
+ if (e instanceof MBeanRegistrationException)
+ throw (MBeanRegistrationException) e;
+ if (e instanceof IOException)
+ throw (IOException) e;
+ throw newIOException("Got unexpected server exception: " + e, e);
+ }
+ }
+
+ public ObjectInstance getObjectInstance(ObjectName name,
+ Subject delegationSubject)
+ throws
+ InstanceNotFoundException,
+ IOException {
+
+ checkNonNull("ObjectName", name);
+
+ try {
+ final Object params[] = new Object[] { name };
+
+ if (logger.debugOn()) logger.debug("getObjectInstance",
+ "connectionId=" + connectionId
+ +", name="+name);
+
+ return (ObjectInstance)
+ doPrivilegedOperation(
+ GET_OBJECT_INSTANCE,
+ params,
+ delegationSubject);
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof InstanceNotFoundException)
+ throw (InstanceNotFoundException) e;
+ if (e instanceof IOException)
+ throw (IOException) e;
+ throw newIOException("Got unexpected server exception: " + e, e);
+ }
+ }
+
+ @SuppressWarnings("rawtypes") // MarshalledObject
+ public Set<ObjectInstance>
+ queryMBeans(ObjectName name,
+ MarshalledObject query,
+ Subject delegationSubject)
+ throws IOException {
+ final QueryExp queryValue;
+ final boolean debug=logger.debugOn();
+
+ if (debug) logger.debug("queryMBeans",
+ "connectionId=" + connectionId
+ +" unwrapping query with defaultClassLoader.");
+
+ queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class, delegationSubject);
+
+ try {
+ final Object params[] = new Object[] { name, queryValue };
+
+ if (debug) logger.debug("queryMBeans",
+ "connectionId=" + connectionId
+ +", name="+name +", query="+query);
+
+ return cast(
+ doPrivilegedOperation(
+ QUERY_MBEANS,
+ params,
+ delegationSubject));
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof IOException)
+ throw (IOException) e;
+ throw newIOException("Got unexpected server exception: " + e, e);
+ }
+ }
+
+ @SuppressWarnings("rawtypes") // MarshalledObject
+ public Set<ObjectName>
+ queryNames(ObjectName name,
+ MarshalledObject query,
+ Subject delegationSubject)
+ throws IOException {
+ final QueryExp queryValue;
+ final boolean debug=logger.debugOn();
+
+ if (debug) logger.debug("queryNames",
+ "connectionId=" + connectionId
+ +" unwrapping query with defaultClassLoader.");
+
+ queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class, delegationSubject);
+
+ try {
+ final Object params[] = new Object[] { name, queryValue };
+
+ if (debug) logger.debug("queryNames",
+ "connectionId=" + connectionId
+ +", name="+name +", query="+query);
+
+ return cast(
+ doPrivilegedOperation(
+ QUERY_NAMES,
+ params,
+ delegationSubject));
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof IOException)
+ throw (IOException) e;
+ throw newIOException("Got unexpected server exception: " + e, e);
+ }
+ }
+
+ public boolean isRegistered(ObjectName name,
+ Subject delegationSubject) throws IOException {
+ try {
+ final Object params[] = new Object[] { name };
+ return ((Boolean)
+ doPrivilegedOperation(
+ IS_REGISTERED,
+ params,
+ delegationSubject)).booleanValue();
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof IOException)
+ throw (IOException) e;
+ throw newIOException("Got unexpected server exception: " + e, e);
+ }
+ }
+
+ public Integer getMBeanCount(Subject delegationSubject)
+ throws IOException {
+ try {
+ final Object params[] = new Object[] { };
+
+ if (logger.debugOn()) logger.debug("getMBeanCount",
+ "connectionId=" + connectionId);
+
+ return (Integer)
+ doPrivilegedOperation(
+ GET_MBEAN_COUNT,
+ params,
+ delegationSubject);
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof IOException)
+ throw (IOException) e;
+ throw newIOException("Got unexpected server exception: " + e, e);
+ }
+ }
+
+ public Object getAttribute(ObjectName name,
+ String attribute,
+ Subject delegationSubject)
+ throws
+ MBeanException,
+ AttributeNotFoundException,
+ InstanceNotFoundException,
+ ReflectionException,
+ IOException {
+ try {
+ final Object params[] = new Object[] { name, attribute };
+ if (logger.debugOn()) logger.debug("getAttribute",
+ "connectionId=" + connectionId
+ +", name=" + name
+ +", attribute="+ attribute);
+
+ return
+ doPrivilegedOperation(
+ GET_ATTRIBUTE,
+ params,
+ delegationSubject);
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof MBeanException)
+ throw (MBeanException) e;
+ if (e instanceof AttributeNotFoundException)
+ throw (AttributeNotFoundException) e;
+ if (e instanceof InstanceNotFoundException)
+ throw (InstanceNotFoundException) e;
+ if (e instanceof ReflectionException)
+ throw (ReflectionException) e;
+ if (e instanceof IOException)
+ throw (IOException) e;
+ throw newIOException("Got unexpected server exception: " + e, e);
+ }
+ }
+
+ public AttributeList getAttributes(ObjectName name,
+ String[] attributes,
+ Subject delegationSubject)
+ throws
+ InstanceNotFoundException,
+ ReflectionException,
+ IOException {
+ try {
+ final Object params[] = new Object[] { name, attributes };
+
+ if (logger.debugOn()) logger.debug("getAttributes",
+ "connectionId=" + connectionId
+ +", name=" + name
+ +", attributes="+ strings(attributes));
+
+ return (AttributeList)
+ doPrivilegedOperation(
+ GET_ATTRIBUTES,
+ params,
+ delegationSubject);
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof InstanceNotFoundException)
+ throw (InstanceNotFoundException) e;
+ if (e instanceof ReflectionException)
+ throw (ReflectionException) e;
+ if (e instanceof IOException)
+ throw (IOException) e;
+ throw newIOException("Got unexpected server exception: " + e, e);
+ }
+ }
+
+ @SuppressWarnings("rawtypes") // MarshalledObject
+ public void setAttribute(ObjectName name,
+ MarshalledObject attribute,
+ Subject delegationSubject)
+ throws
+ InstanceNotFoundException,
+ AttributeNotFoundException,
+ InvalidAttributeValueException,
+ MBeanException,
+ ReflectionException,
+ IOException {
+ final Attribute attr;
+ final boolean debug=logger.debugOn();
+
+ if (debug) logger.debug("setAttribute",
+ "connectionId=" + connectionId
+ +" unwrapping attribute with MBean extended ClassLoader.");
+
+ attr = unwrap(attribute,
+ getClassLoaderFor(name),
+ defaultClassLoader,
+ Attribute.class, delegationSubject);
+
+ try {
+ final Object params[] = new Object[] { name, attr };
+
+ if (debug) logger.debug("setAttribute",
+ "connectionId=" + connectionId
+ +", name="+name
+ +", attribute name="+attr.getName());
+
+ doPrivilegedOperation(
+ SET_ATTRIBUTE,
+ params,
+ delegationSubject);
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof InstanceNotFoundException)
+ throw (InstanceNotFoundException) e;
+ if (e instanceof AttributeNotFoundException)
+ throw (AttributeNotFoundException) e;
+ if (e instanceof InvalidAttributeValueException)
+ throw (InvalidAttributeValueException) e;
+ if (e instanceof MBeanException)
+ throw (MBeanException) e;
+ if (e instanceof ReflectionException)
+ throw (ReflectionException) e;
+ if (e instanceof IOException)
+ throw (IOException) e;
+ throw newIOException("Got unexpected server exception: " + e, e);
+ }
+ }
+
+ @SuppressWarnings("rawtypes") // MarshalledObject
+ public AttributeList setAttributes(ObjectName name,
+ MarshalledObject attributes,
+ Subject delegationSubject)
+ throws
+ InstanceNotFoundException,
+ ReflectionException,
+ IOException {
+ final AttributeList attrlist;
+ final boolean debug=logger.debugOn();
+
+ if (debug) logger.debug("setAttributes",
+ "connectionId=" + connectionId
+ +" unwrapping attributes with MBean extended ClassLoader.");
+
+ attrlist =
+ unwrap(attributes,
+ getClassLoaderFor(name),
+ defaultClassLoader,
+ AttributeList.class, delegationSubject);
+
+ try {
+ final Object params[] = new Object[] { name, attrlist };
+
+ if (debug) logger.debug("setAttributes",
+ "connectionId=" + connectionId
+ +", name="+name
+ +", attribute names="+RMIConnector.getAttributesNames(attrlist));
+
+ return (AttributeList)
+ doPrivilegedOperation(
+ SET_ATTRIBUTES,
+ params,
+ delegationSubject);
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof InstanceNotFoundException)
+ throw (InstanceNotFoundException) e;
+ if (e instanceof ReflectionException)
+ throw (ReflectionException) e;
+ if (e instanceof IOException)
+ throw (IOException) e;
+ throw newIOException("Got unexpected server exception: " + e, e);
+ }
+ }
+
+ @SuppressWarnings("rawtypes") // MarshalledObject
+ public Object invoke(ObjectName name,
+ String operationName,
+ MarshalledObject params,
+ String signature[],
+ Subject delegationSubject)
+ throws
+ InstanceNotFoundException,
+ MBeanException,
+ ReflectionException,
+ IOException {
+
+ checkNonNull("ObjectName", name);
+ checkNonNull("Operation name", operationName);
+
+ final Object[] values;
+ final boolean debug=logger.debugOn();
+
+ if (debug) logger.debug("invoke",
+ "connectionId=" + connectionId
+ +" unwrapping params with MBean extended ClassLoader.");
+
+ values = nullIsEmpty(unwrap(params,
+ getClassLoaderFor(name),
+ defaultClassLoader,
+ Object[].class, delegationSubject));
+
+ try {
+ final Object params2[] =
+ new Object[] { name, operationName, values,
+ nullIsEmpty(signature) };
+
+ if (debug) logger.debug("invoke",
+ "connectionId=" + connectionId
+ +", name="+name
+ +", operationName="+operationName
+ +", signature="+strings(signature));
+
+ return
+ doPrivilegedOperation(
+ INVOKE,
+ params2,
+ delegationSubject);
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof InstanceNotFoundException)
+ throw (InstanceNotFoundException) e;
+ if (e instanceof MBeanException)
+ throw (MBeanException) e;
+ if (e instanceof ReflectionException)
+ throw (ReflectionException) e;
+ if (e instanceof IOException)
+ throw (IOException) e;
+ throw newIOException("Got unexpected server exception: " + e, e);
+ }
+ }
+
+ public String getDefaultDomain(Subject delegationSubject)
+ throws IOException {
+ try {
+ final Object params[] = new Object[] { };
+
+ if (logger.debugOn()) logger.debug("getDefaultDomain",
+ "connectionId=" + connectionId);
+
+ return (String)
+ doPrivilegedOperation(
+ GET_DEFAULT_DOMAIN,
+ params,
+ delegationSubject);
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof IOException)
+ throw (IOException) e;
+ throw newIOException("Got unexpected server exception: " + e, e);
+ }
+ }
+
+ public String[] getDomains(Subject delegationSubject) throws IOException {
+ try {
+ final Object params[] = new Object[] { };
+
+ if (logger.debugOn()) logger.debug("getDomains",
+ "connectionId=" + connectionId);
+
+ return (String[])
+ doPrivilegedOperation(
+ GET_DOMAINS,
+ params,
+ delegationSubject);
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof IOException)
+ throw (IOException) e;
+ throw newIOException("Got unexpected server exception: " + e, e);
+ }
+ }
+
+ public MBeanInfo getMBeanInfo(ObjectName name, Subject delegationSubject)
+ throws
+ InstanceNotFoundException,
+ IntrospectionException,
+ ReflectionException,
+ IOException {
+
+ checkNonNull("ObjectName", name);
+
+ try {
+ final Object params[] = new Object[] { name };
+
+ if (logger.debugOn()) logger.debug("getMBeanInfo",
+ "connectionId=" + connectionId
+ +", name="+name);
+
+ return (MBeanInfo)
+ doPrivilegedOperation(
+ GET_MBEAN_INFO,
+ params,
+ delegationSubject);
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof InstanceNotFoundException)
+ throw (InstanceNotFoundException) e;
+ if (e instanceof IntrospectionException)
+ throw (IntrospectionException) e;
+ if (e instanceof ReflectionException)
+ throw (ReflectionException) e;
+ if (e instanceof IOException)
+ throw (IOException) e;
+ throw newIOException("Got unexpected server exception: " + e, e);
+ }
+ }
+
+ public boolean isInstanceOf(ObjectName name,
+ String className,
+ Subject delegationSubject)
+ throws InstanceNotFoundException, IOException {
+
+ checkNonNull("ObjectName", name);
+
+ try {
+ final Object params[] = new Object[] { name, className };
+
+ if (logger.debugOn()) logger.debug("isInstanceOf",
+ "connectionId=" + connectionId
+ +", name="+name
+ +", className="+className);
+
+ return ((Boolean)
+ doPrivilegedOperation(
+ IS_INSTANCE_OF,
+ params,
+ delegationSubject)).booleanValue();
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof InstanceNotFoundException)
+ throw (InstanceNotFoundException) e;
+ if (e instanceof IOException)
+ throw (IOException) e;
+ throw newIOException("Got unexpected server exception: " + e, e);
+ }
+ }
+
+ @SuppressWarnings("rawtypes") // MarshalledObject
+ public Integer[] addNotificationListeners(ObjectName[] names,
+ MarshalledObject[] filters,
+ Subject[] delegationSubjects)
+ throws InstanceNotFoundException, IOException {
+
+ if (names == null || filters == null) {
+ throw new IllegalArgumentException("Got null arguments.");
+ }
+
+ Subject[] sbjs = (delegationSubjects != null) ? delegationSubjects :
+ new Subject[names.length];
+ if (names.length != filters.length || filters.length != sbjs.length) {
+ final String msg =
+ "The value lengths of 3 parameters are not same.";
+ throw new IllegalArgumentException(msg);
+ }
+
+ for (int i=0; i<names.length; i++) {
+ if (names[i] == null) {
+ throw new IllegalArgumentException("Null Object name.");
+ }
+ }
+
+ int i=0;
+ ClassLoader targetCl;
+ NotificationFilter[] filterValues =
+ new NotificationFilter[names.length];
+ Integer[] ids = new Integer[names.length];
+ final boolean debug=logger.debugOn();
+
+ try {
+ for (; i<names.length; i++) {
+ targetCl = getClassLoaderFor(names[i]);
+
+ if (debug) logger.debug("addNotificationListener"+
+ "(ObjectName,NotificationFilter)",
+ "connectionId=" + connectionId +
+ " unwrapping filter with target extended ClassLoader.");
+
+ filterValues[i] =
+ unwrap(filters[i], targetCl, defaultClassLoader,
+ NotificationFilter.class, sbjs[i]);
+
+ if (debug) logger.debug("addNotificationListener"+
+ "(ObjectName,NotificationFilter)",
+ "connectionId=" + connectionId
+ +", name=" + names[i]
+ +", filter=" + filterValues[i]);
+
+ ids[i] = (Integer)
+ doPrivilegedOperation(ADD_NOTIFICATION_LISTENERS,
+ new Object[] { names[i],
+ filterValues[i] },
+ sbjs[i]);
+ }
+
+ return ids;
+ } catch (Exception e) {
+ // remove all registered listeners
+ for (int j=0; j<i; j++) {
+ try {
+ getServerNotifFwd().removeNotificationListener(names[j],
+ ids[j]);
+ } catch (Exception eee) {
+ // strange
+ }
+ }
+
+ if (e instanceof PrivilegedActionException) {
+ e = extractException(e);
+ }
+
+ if (e instanceof ClassCastException) {
+ throw (ClassCastException) e;
+ } else if (e instanceof IOException) {
+ throw (IOException)e;
+ } else if (e instanceof InstanceNotFoundException) {
+ throw (InstanceNotFoundException) e;
+ } else if (e instanceof RuntimeException) {
+ throw (RuntimeException) e;
+ } else {
+ throw newIOException("Got unexpected server exception: "+e,e);
+ }
+ }
+ }
+
+ @SuppressWarnings("rawtypes") // MarshalledObject
+ public void addNotificationListener(ObjectName name,
+ ObjectName listener,
+ MarshalledObject filter,
+ MarshalledObject handback,
+ Subject delegationSubject)
+ throws InstanceNotFoundException, IOException {
+
+ checkNonNull("Target MBean name", name);
+ checkNonNull("Listener MBean name", listener);
+
+ final NotificationFilter filterValue;
+ final Object handbackValue;
+ final boolean debug=logger.debugOn();
+
+ final ClassLoader targetCl = getClassLoaderFor(name);
+
+ if (debug) logger.debug("addNotificationListener"+
+ "(ObjectName,ObjectName,NotificationFilter,Object)",
+ "connectionId=" + connectionId
+ +" unwrapping filter with target extended ClassLoader.");
+
+ filterValue =
+ unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class, delegationSubject);
+
+ if (debug) logger.debug("addNotificationListener"+
+ "(ObjectName,ObjectName,NotificationFilter,Object)",
+ "connectionId=" + connectionId
+ +" unwrapping handback with target extended ClassLoader.");
+
+ handbackValue =
+ unwrap(handback, targetCl, defaultClassLoader, Object.class, delegationSubject);
+
+ try {
+ final Object params[] =
+ new Object[] { name, listener, filterValue, handbackValue };
+
+ if (debug) logger.debug("addNotificationListener"+
+ "(ObjectName,ObjectName,NotificationFilter,Object)",
+ "connectionId=" + connectionId
+ +", name=" + name
+ +", listenerName=" + listener
+ +", filter=" + filterValue
+ +", handback=" + handbackValue);
+
+ doPrivilegedOperation(
+ ADD_NOTIFICATION_LISTENER_OBJECTNAME,
+ params,
+ delegationSubject);
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof InstanceNotFoundException)
+ throw (InstanceNotFoundException) e;
+ if (e instanceof IOException)
+ throw (IOException) e;
+ throw newIOException("Got unexpected server exception: " + e, e);
+ }
+ }
+
+ public void removeNotificationListeners(ObjectName name,
+ Integer[] listenerIDs,
+ Subject delegationSubject)
+ throws
+ InstanceNotFoundException,
+ ListenerNotFoundException,
+ IOException {
+
+ if (name == null || listenerIDs == null)
+ throw new IllegalArgumentException("Illegal null parameter");
+
+ for (int i = 0; i < listenerIDs.length; i++) {
+ if (listenerIDs[i] == null)
+ throw new IllegalArgumentException("Null listener ID");
+ }
+
+ try {
+ final Object params[] = new Object[] { name, listenerIDs };
+
+ if (logger.debugOn()) logger.debug("removeNotificationListener"+
+ "(ObjectName,Integer[])",
+ "connectionId=" + connectionId
+ +", name=" + name
+ +", listenerIDs=" + objects(listenerIDs));
+
+ doPrivilegedOperation(
+ REMOVE_NOTIFICATION_LISTENER,
+ params,
+ delegationSubject);
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof InstanceNotFoundException)
+ throw (InstanceNotFoundException) e;
+ if (e instanceof ListenerNotFoundException)
+ throw (ListenerNotFoundException) e;
+ if (e instanceof IOException)
+ throw (IOException) e;
+ throw newIOException("Got unexpected server exception: " + e, e);
+ }
+ }
+
+ public void removeNotificationListener(ObjectName name,
+ ObjectName listener,
+ Subject delegationSubject)
+ throws
+ InstanceNotFoundException,
+ ListenerNotFoundException,
+ IOException {
+
+ checkNonNull("Target MBean name", name);
+ checkNonNull("Listener MBean name", listener);
+
+ try {
+ final Object params[] = new Object[] { name, listener };
+
+ if (logger.debugOn()) logger.debug("removeNotificationListener"+
+ "(ObjectName,ObjectName)",
+ "connectionId=" + connectionId
+ +", name=" + name
+ +", listenerName=" + listener);
+
+ doPrivilegedOperation(
+ REMOVE_NOTIFICATION_LISTENER_OBJECTNAME,
+ params,
+ delegationSubject);
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof InstanceNotFoundException)
+ throw (InstanceNotFoundException) e;
+ if (e instanceof ListenerNotFoundException)
+ throw (ListenerNotFoundException) e;
+ if (e instanceof IOException)
+ throw (IOException) e;
+ throw newIOException("Got unexpected server exception: " + e, e);
+ }
+ }
+
+ @SuppressWarnings("rawtypes") // MarshalledObject
+ public void removeNotificationListener(ObjectName name,
+ ObjectName listener,
+ MarshalledObject filter,
+ MarshalledObject handback,
+ Subject delegationSubject)
+ throws
+ InstanceNotFoundException,
+ ListenerNotFoundException,
+ IOException {
+
+ checkNonNull("Target MBean name", name);
+ checkNonNull("Listener MBean name", listener);
+
+ final NotificationFilter filterValue;
+ final Object handbackValue;
+ final boolean debug=logger.debugOn();
+
+ final ClassLoader targetCl = getClassLoaderFor(name);
+
+ if (debug) logger.debug("removeNotificationListener"+
+ "(ObjectName,ObjectName,NotificationFilter,Object)",
+ "connectionId=" + connectionId
+ +" unwrapping filter with target extended ClassLoader.");
+
+ filterValue =
+ unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class, delegationSubject);
+
+ if (debug) logger.debug("removeNotificationListener"+
+ "(ObjectName,ObjectName,NotificationFilter,Object)",
+ "connectionId=" + connectionId
+ +" unwrapping handback with target extended ClassLoader.");
+
+ handbackValue =
+ unwrap(handback, targetCl, defaultClassLoader, Object.class, delegationSubject);
+
+ try {
+ final Object params[] =
+ new Object[] { name, listener, filterValue, handbackValue };
+
+ if (debug) logger.debug("removeNotificationListener"+
+ "(ObjectName,ObjectName,NotificationFilter,Object)",
+ "connectionId=" + connectionId
+ +", name=" + name
+ +", listenerName=" + listener
+ +", filter=" + filterValue
+ +", handback=" + handbackValue);
+
+ doPrivilegedOperation(
+ REMOVE_NOTIFICATION_LISTENER_OBJECTNAME_FILTER_HANDBACK,
+ params,
+ delegationSubject);
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof InstanceNotFoundException)
+ throw (InstanceNotFoundException) e;
+ if (e instanceof ListenerNotFoundException)
+ throw (ListenerNotFoundException) e;
+ if (e instanceof IOException)
+ throw (IOException) e;
+ throw newIOException("Got unexpected server exception: " + e, e);
+ }
+ }
+
+ public NotificationResult fetchNotifications(long clientSequenceNumber,
+ int maxNotifications,
+ long timeout)
+ throws IOException {
+
+ if (logger.debugOn()) logger.debug("fetchNotifications",
+ "connectionId=" + connectionId
+ +", timeout=" + timeout);
+
+ if (maxNotifications < 0 || timeout < 0)
+ throw new IllegalArgumentException("Illegal negative argument");
+
+ final boolean serverTerminated =
+ serverCommunicatorAdmin.reqIncoming();
+ try {
+ if (serverTerminated) {
+ // we must not call fetchNotifs() if the server is
+ // terminated (timeout elapsed).
+ // returns null to force the client to stop fetching
+ if (logger.debugOn()) logger.debug("fetchNotifications",
+ "The notification server has been closed, "
+ + "returns null to force the client to stop fetching");
+ return null;
+ }
+ final long csn = clientSequenceNumber;
+ final int mn = maxNotifications;
+ final long t = timeout;
+ PrivilegedAction<NotificationResult> action =
+ new PrivilegedAction<NotificationResult>() {
+ public NotificationResult run() {
+ return getServerNotifFwd().fetchNotifs(csn, t, mn);
+ }
+ };
+ if (acc == null)
+ return action.run();
+ else
+ return AccessController.doPrivileged(action, acc);
+ } finally {
+ serverCommunicatorAdmin.rspOutgoing();
+ }
+ }
+
+ /**
+ * <p>Returns a string representation of this object. In general,
+ * the <code>toString</code> method returns a string that
+ * "textually represents" this object. The result should be a
+ * concise but informative representation that is easy for a
+ * person to read.</p>
+ *
+ * @return a String representation of this object.
+ **/
+ @Override
+ public String toString() {
+ return super.toString() + ": connectionId=" + connectionId;
+ }
+
+ //------------------------------------------------------------------------
+ // private classes
+ //------------------------------------------------------------------------
+
+ private class PrivilegedOperation
+ implements PrivilegedExceptionAction<Object> {
+
+ public PrivilegedOperation(int operation, Object[] params) {
+ this.operation = operation;
+ this.params = params;
+ }
+
+ public Object run() throws Exception {
+ return doOperation(operation, params);
+ }
+
+ private int operation;
+ private Object[] params;
+ }
+
+ //------------------------------------------------------------------------
+ // private classes
+ //------------------------------------------------------------------------
+ private class RMIServerCommunicatorAdmin extends ServerCommunicatorAdmin {
+ public RMIServerCommunicatorAdmin(long timeout) {
+ super(timeout);
+ }
+
+ protected void doStop() {
+ try {
+ close();
+ } catch (IOException ie) {
+ logger.warning("RMIServerCommunicatorAdmin-doStop",
+ "Failed to close: " + ie);
+ logger.debug("RMIServerCommunicatorAdmin-doStop",ie);
+ }
+ }
+
+ }
+
+
+ //------------------------------------------------------------------------
+ // private methods
+ //------------------------------------------------------------------------
+
+ private ClassLoader getClassLoader(final ObjectName name)
+ throws InstanceNotFoundException {
+ try {
+ return
+ AccessController.doPrivileged(
+ new PrivilegedExceptionAction<ClassLoader>() {
+ public ClassLoader run() throws InstanceNotFoundException {
+ return mbeanServer.getClassLoader(name);
+ }
+ },
+ withPermissions(new MBeanPermission("*", "getClassLoader"))
+ );
+ } catch (PrivilegedActionException pe) {
+ throw (InstanceNotFoundException) extractException(pe);
+ }
+ }
+
+ private ClassLoader getClassLoaderFor(final ObjectName name)
+ throws InstanceNotFoundException {
+ try {
+ return (ClassLoader)
+ AccessController.doPrivileged(
+ new PrivilegedExceptionAction<Object>() {
+ public Object run() throws InstanceNotFoundException {
+ return mbeanServer.getClassLoaderFor(name);
+ }
+ },
+ withPermissions(new MBeanPermission("*", "getClassLoaderFor"))
+ );
+ } catch (PrivilegedActionException pe) {
+ throw (InstanceNotFoundException) extractException(pe);
+ }
+ }
+
+ private Object doPrivilegedOperation(final int operation,
+ final Object[] params,
+ final Subject delegationSubject)
+ throws PrivilegedActionException, IOException {
+
+ serverCommunicatorAdmin.reqIncoming();
+ try {
+
+ final AccessControlContext reqACC;
+ if (delegationSubject == null)
+ reqACC = acc;
+ else {
+ if (subject == null) {
+ final String msg =
+ "Subject delegation cannot be enabled unless " +
+ "an authenticated subject is put in place";
+ throw new SecurityException(msg);
+ }
+ reqACC = subjectDelegator.delegatedContext(
+ acc, delegationSubject, removeCallerContext);
+ }
+
+ PrivilegedOperation op =
+ new PrivilegedOperation(operation, params);
+ if (reqACC == null) {
+ try {
+ return op.run();
+ } catch (Exception e) {
+ if (e instanceof RuntimeException)
+ throw (RuntimeException) e;
+ throw new PrivilegedActionException(e);
+ }
+ } else {
+ return AccessController.doPrivileged(op, reqACC);
+ }
+ } catch (Error e) {
+ throw new JMXServerErrorException(e.toString(),e);
+ } finally {
+ serverCommunicatorAdmin.rspOutgoing();
+ }
+ }
+
+ private Object doOperation(int operation, Object[] params)
+ throws Exception {
+
+ switch (operation) {
+
+ case CREATE_MBEAN:
+ return mbeanServer.createMBean((String)params[0],
+ (ObjectName)params[1]);
+
+ case CREATE_MBEAN_LOADER:
+ return mbeanServer.createMBean((String)params[0],
+ (ObjectName)params[1],
+ (ObjectName)params[2]);
+
+ case CREATE_MBEAN_PARAMS:
+ return mbeanServer.createMBean((String)params[0],
+ (ObjectName)params[1],
+ (Object[])params[2],
+ (String[])params[3]);
+
+ case CREATE_MBEAN_LOADER_PARAMS:
+ return mbeanServer.createMBean((String)params[0],
+ (ObjectName)params[1],
+ (ObjectName)params[2],
+ (Object[])params[3],
+ (String[])params[4]);
+
+ case GET_ATTRIBUTE:
+ return mbeanServer.getAttribute((ObjectName)params[0],
+ (String)params[1]);
+
+ case GET_ATTRIBUTES:
+ return mbeanServer.getAttributes((ObjectName)params[0],
+ (String[])params[1]);
+
+ case GET_DEFAULT_DOMAIN:
+ return mbeanServer.getDefaultDomain();
+
+ case GET_DOMAINS:
+ return mbeanServer.getDomains();
+
+ case GET_MBEAN_COUNT:
+ return mbeanServer.getMBeanCount();
+
+ case GET_MBEAN_INFO:
+ return mbeanServer.getMBeanInfo((ObjectName)params[0]);
+
+ case GET_OBJECT_INSTANCE:
+ return mbeanServer.getObjectInstance((ObjectName)params[0]);
+
+ case INVOKE:
+ return mbeanServer.invoke((ObjectName)params[0],
+ (String)params[1],
+ (Object[])params[2],
+ (String[])params[3]);
+
+ case IS_INSTANCE_OF:
+ return mbeanServer.isInstanceOf((ObjectName)params[0],
+ (String)params[1])
+ ? Boolean.TRUE : Boolean.FALSE;
+
+ case IS_REGISTERED:
+ return mbeanServer.isRegistered((ObjectName)params[0])
+ ? Boolean.TRUE : Boolean.FALSE;
+
+ case QUERY_MBEANS:
+ return mbeanServer.queryMBeans((ObjectName)params[0],
+ (QueryExp)params[1]);
+
+ case QUERY_NAMES:
+ return mbeanServer.queryNames((ObjectName)params[0],
+ (QueryExp)params[1]);
+
+ case SET_ATTRIBUTE:
+ mbeanServer.setAttribute((ObjectName)params[0],
+ (Attribute)params[1]);
+ return null;
+
+ case SET_ATTRIBUTES:
+ return mbeanServer.setAttributes((ObjectName)params[0],
+ (AttributeList)params[1]);
+
+ case UNREGISTER_MBEAN:
+ mbeanServer.unregisterMBean((ObjectName)params[0]);
+ return null;
+
+ case ADD_NOTIFICATION_LISTENERS:
+ return getServerNotifFwd().addNotificationListener(
+ (ObjectName)params[0],
+ (NotificationFilter)params[1]);
+
+ case ADD_NOTIFICATION_LISTENER_OBJECTNAME:
+ mbeanServer.addNotificationListener((ObjectName)params[0],
+ (ObjectName)params[1],
+ (NotificationFilter)params[2],
+ params[3]);
+ return null;
+
+ case REMOVE_NOTIFICATION_LISTENER:
+ getServerNotifFwd().removeNotificationListener(
+ (ObjectName)params[0],
+ (Integer[])params[1]);
+ return null;
+
+ case REMOVE_NOTIFICATION_LISTENER_OBJECTNAME:
+ mbeanServer.removeNotificationListener((ObjectName)params[0],
+ (ObjectName)params[1]);
+ return null;
+
+ case REMOVE_NOTIFICATION_LISTENER_OBJECTNAME_FILTER_HANDBACK:
+ mbeanServer.removeNotificationListener(
+ (ObjectName)params[0],
+ (ObjectName)params[1],
+ (NotificationFilter)params[2],
+ params[3]);
+ return null;
+
+ default:
+ throw new IllegalArgumentException("Invalid operation");
+ }
+ }
+
+ private static class SetCcl implements PrivilegedExceptionAction<ClassLoader> {
+ private final ClassLoader classLoader;
+
+ SetCcl(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+
+ public ClassLoader run() {
+ Thread currentThread = Thread.currentThread();
+ ClassLoader old = currentThread.getContextClassLoader();
+ currentThread.setContextClassLoader(classLoader);
+ return old;
+ }
+ }
+
+ private <T> T unwrap(final MarshalledObject<?> mo,
+ final ClassLoader cl,
+ final Class<T> wrappedClass,
+ Subject delegationSubject)
+ throws IOException {
+ if (mo == null) {
+ return null;
+ }
+ try {
+ final ClassLoader old = AccessController.doPrivileged(new SetCcl(cl));
+ try{
+ final AccessControlContext reqACC;
+ if (delegationSubject == null)
+ reqACC = acc;
+ else {
+ if (subject == null) {
+ final String msg =
+ "Subject delegation cannot be enabled unless " +
+ "an authenticated subject is put in place";
+ throw new SecurityException(msg);
+ }
+ reqACC = subjectDelegator.delegatedContext(
+ acc, delegationSubject, removeCallerContext);
+ }
+ if(reqACC != null){
+ return AccessController.doPrivileged(
+ (PrivilegedExceptionAction<T>) () ->
+ wrappedClass.cast(mo.get()), reqACC);
+ }else{
+ return wrappedClass.cast(mo.get());
+ }
+ }finally{
+ AccessController.doPrivileged(new SetCcl(old));
+ }
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof IOException) {
+ throw (IOException) e;
+ }
+ if (e instanceof ClassNotFoundException) {
+ throw new UnmarshalException(e.toString(), e);
+ }
+ logger.warning("unwrap", "Failed to unmarshall object: " + e);
+ logger.debug("unwrap", e);
+ }catch (ClassNotFoundException ex) {
+ logger.warning("unwrap", "Failed to unmarshall object: " + ex);
+ logger.debug("unwrap", ex);
+ throw new UnmarshalException(ex.toString(), ex);
+ }
+ return null;
+ }
+
+ private <T> T unwrap(final MarshalledObject<?> mo,
+ final ClassLoader cl1,
+ final ClassLoader cl2,
+ final Class<T> wrappedClass,
+ Subject delegationSubject)
+ throws IOException {
+ if (mo == null) {
+ return null;
+ }
+ try {
+ ClassLoader orderCL = AccessController.doPrivileged(
+ new PrivilegedExceptionAction<ClassLoader>() {
+ public ClassLoader run() throws Exception {
+ return new CombinedClassLoader(Thread.currentThread().getContextClassLoader(),
+ new OrderClassLoaders(cl1, cl2));
+ }
+ }
+ );
+ return unwrap(mo, orderCL, wrappedClass,delegationSubject);
+ } catch (PrivilegedActionException pe) {
+ Exception e = extractException(pe);
+ if (e instanceof IOException) {
+ throw (IOException) e;
+ }
+ if (e instanceof ClassNotFoundException) {
+ throw new UnmarshalException(e.toString(), e);
+ }
+ logger.warning("unwrap", "Failed to unmarshall object: " + e);
+ logger.debug("unwrap", e);
+ }
+ return null;
+ }
+
+ /**
+ * Construct a new IOException with a nested exception.
+ * The nested exception is set only if JDK {@literal >= 1.4}
+ */
+ private static IOException newIOException(String message,
+ Throwable cause) {
+ final IOException x = new IOException(message);
+ return EnvHelp.initCause(x,cause);
+ }
+
+ /**
+ * Iterate until we extract the real exception
+ * from a stack of PrivilegedActionExceptions.
+ */
+ private static Exception extractException(Exception e) {
+ while (e instanceof PrivilegedActionException) {
+ e = ((PrivilegedActionException)e).getException();
+ }
+ return e;
+ }
+
+ private static final Object[] NO_OBJECTS = new Object[0];
+ private static final String[] NO_STRINGS = new String[0];
+
+ /*
+ * The JMX spec doesn't explicitly say that a null Object[] or
+ * String[] in e.g. MBeanServer.invoke is equivalent to an empty
+ * array, but the RI behaves that way. In the interests of
+ * maximal interoperability, we make it so even when we're
+ * connected to some other JMX implementation that might not do
+ * that. This should be clarified in the next version of JMX.
+ */
+ private static Object[] nullIsEmpty(Object[] array) {
+ return (array == null) ? NO_OBJECTS : array;
+ }
+
+ private static String[] nullIsEmpty(String[] array) {
+ return (array == null) ? NO_STRINGS : array;
+ }
+
+ /*
+ * Similarly, the JMX spec says for some but not all methods in
+ * MBeanServer that take an ObjectName target, that if it's null
+ * you get this exception. We specify it for all of them, and
+ * make it so for the ones where it's not specified in JMX even if
+ * the JMX implementation doesn't do so.
+ */
+ private static void checkNonNull(String what, Object x) {
+ if (x == null) {
+ RuntimeException wrapped =
+ new IllegalArgumentException(what + " must not be null");
+ throw new RuntimeOperationsException(wrapped);
+ }
+ }
+
+ //------------------------------------------------------------------------
+ // private variables
+ //------------------------------------------------------------------------
+
+ private final Subject subject;
+
+ private final SubjectDelegator subjectDelegator;
+
+ private final boolean removeCallerContext;
+
+ private final AccessControlContext acc;
+
+ private final RMIServerImpl rmiServer;
+
+ private final MBeanServer mbeanServer;
+
+ private final ClassLoader defaultClassLoader;
+
+ private final ClassLoader defaultContextClassLoader;
+
+ private final ClassLoaderWithRepository classLoaderWithRepository;
+
+ private boolean terminated = false;
+
+ private final String connectionId;
+
+ private final ServerCommunicatorAdmin serverCommunicatorAdmin;
+
+ // Method IDs for doOperation
+ //---------------------------
+
+ private final static int
+ ADD_NOTIFICATION_LISTENERS = 1;
+ private final static int
+ ADD_NOTIFICATION_LISTENER_OBJECTNAME = 2;
+ private final static int
+ CREATE_MBEAN = 3;
+ private final static int
+ CREATE_MBEAN_PARAMS = 4;
+ private final static int
+ CREATE_MBEAN_LOADER = 5;
+ private final static int
+ CREATE_MBEAN_LOADER_PARAMS = 6;
+ private final static int
+ GET_ATTRIBUTE = 7;
+ private final static int
+ GET_ATTRIBUTES = 8;
+ private final static int
+ GET_DEFAULT_DOMAIN = 9;
+ private final static int
+ GET_DOMAINS = 10;
+ private final static int
+ GET_MBEAN_COUNT = 11;
+ private final static int
+ GET_MBEAN_INFO = 12;
+ private final static int
+ GET_OBJECT_INSTANCE = 13;
+ private final static int
+ INVOKE = 14;
+ private final static int
+ IS_INSTANCE_OF = 15;
+ private final static int
+ IS_REGISTERED = 16;
+ private final static int
+ QUERY_MBEANS = 17;
+ private final static int
+ QUERY_NAMES = 18;
+ private final static int
+ REMOVE_NOTIFICATION_LISTENER = 19;
+ private final static int
+ REMOVE_NOTIFICATION_LISTENER_OBJECTNAME = 20;
+ private final static int
+ REMOVE_NOTIFICATION_LISTENER_OBJECTNAME_FILTER_HANDBACK = 21;
+ private final static int
+ SET_ATTRIBUTE = 22;
+ private final static int
+ SET_ATTRIBUTES = 23;
+ private final static int
+ UNREGISTER_MBEAN = 24;
+
+ // SERVER NOTIFICATION
+ //--------------------
+
+ private ServerNotifForwarder serverNotifForwarder;
+ private Map<String, ?> env;
+
+ // TRACES & DEBUG
+ //---------------
+
+ private static String objects(final Object[] objs) {
+ if (objs == null)
+ return "null";
+ else
+ return Arrays.asList(objs).toString();
+ }
+
+ private static String strings(final String[] strs) {
+ return objects(strs);
+ }
+
+ private static final ClassLogger logger =
+ new ClassLogger("javax.management.remote.rmi", "RMIConnectionImpl");
+
+ private static final class CombinedClassLoader extends ClassLoader {
+
+ private final static class ClassLoaderWrapper extends ClassLoader {
+ ClassLoaderWrapper(ClassLoader cl) {
+ super(cl);
+ }
+
+ @Override
+ protected Class<?> loadClass(String name, boolean resolve)
+ throws ClassNotFoundException {
+ return super.loadClass(name, resolve);
+ }
+ };
+
+ final ClassLoaderWrapper defaultCL;
+
+ private CombinedClassLoader(ClassLoader parent, ClassLoader defaultCL) {
+ super(parent);
+ this.defaultCL = new ClassLoaderWrapper(defaultCL);
+ }
+
+ @Override
+ protected Class<?> loadClass(String name, boolean resolve)
+ throws ClassNotFoundException {
+ ReflectUtil.checkPackageAccess(name);
+ try {
+ super.loadClass(name, resolve);
+ } catch(Exception e) {
+ for(Throwable t = e; t != null; t = t.getCause()) {
+ if(t instanceof SecurityException) {
+ throw t==e?(SecurityException)t:new SecurityException(t.getMessage(), e);
+ }
+ }
+ }
+ final Class<?> cl = defaultCL.loadClass(name, resolve);
+ return cl;
+ }
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnector.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,2309 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 javax.management.remote.rmi;
+
+import com.sun.jmx.remote.internal.ClientCommunicatorAdmin;
+import com.sun.jmx.remote.internal.ClientListenerInfo;
+import com.sun.jmx.remote.internal.ClientNotifForwarder;
+import com.sun.jmx.remote.internal.rmi.ProxyRef;
+import com.sun.jmx.remote.util.ClassLogger;
+import com.sun.jmx.remote.util.EnvHelp;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamClass;
+import java.io.Serializable;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Module;
+import java.lang.reflect.Proxy;
+import java.net.MalformedURLException;
+import java.rmi.MarshalledObject;
+import java.rmi.NoSuchObjectException;
+import java.rmi.Remote;
+import java.rmi.ServerException;
+import java.rmi.UnmarshalException;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RemoteObject;
+import java.rmi.server.RemoteObjectInvocationHandler;
+import java.rmi.server.RemoteRef;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.stream.Collectors;
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.IntrospectionException;
+import javax.management.InvalidAttributeValueException;
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerDelegate;
+import javax.management.MBeanServerNotification;
+import javax.management.NotCompliantMBeanException;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.NotificationFilter;
+import javax.management.NotificationFilterSupport;
+import javax.management.NotificationListener;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+import javax.management.QueryExp;
+import javax.management.ReflectionException;
+import javax.management.remote.JMXConnectionNotification;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.NotificationResult;
+import javax.management.remote.JMXAddressable;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.rmi.ssl.SslRMIClientSocketFactory;
+import javax.security.auth.Subject;
+import jdk.internal.module.Modules;
+import sun.reflect.misc.ReflectUtil;
+import sun.rmi.server.UnicastRef2;
+import sun.rmi.transport.LiveRef;
+import java.io.NotSerializableException;
+
+/**
+ * <p>A connection to a remote RMI connector. Usually, such
+ * connections are made using {@link
+ * javax.management.remote.JMXConnectorFactory JMXConnectorFactory}.
+ * However, specialized applications can use this class directly, for
+ * example with an {@link RMIServer} stub obtained without going
+ * through JNDI.</p>
+ *
+ * @since 1.5
+ */
+public class RMIConnector implements JMXConnector, Serializable, JMXAddressable {
+
+ private static final ClassLogger logger =
+ new ClassLogger("javax.management.remote.rmi", "RMIConnector");
+
+ private static final long serialVersionUID = 817323035842634473L;
+
+ static final class Util {
+ private Util() {}
+
+ /* This method can be used by code that is deliberately violating the
+ * allowed checked casts. Rather than marking the whole method containing
+ * the code with @SuppressWarnings, you can use a call to this method for
+ * the exact place where you need to escape the constraints. Typically
+ * you will "import static" this method and then write either
+ * X x = cast(y);
+ * or, if that doesn't work (e.g. X is a type variable)
+ * Util.<X>cast(y);
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T cast(Object x) {
+ return (T) x;
+ }
+ }
+
+ private RMIConnector(RMIServer rmiServer, JMXServiceURL address,
+ Map<String, ?> environment) {
+ if (rmiServer == null && address == null) throw new
+ IllegalArgumentException("rmiServer and jmxServiceURL both null");
+ initTransients();
+
+ this.rmiServer = rmiServer;
+ this.jmxServiceURL = address;
+ if (environment == null) {
+ this.env = Collections.emptyMap();
+ } else {
+ EnvHelp.checkAttributes(environment);
+ this.env = Collections.unmodifiableMap(environment);
+ }
+ }
+
+ /**
+ * <p>Constructs an {@code RMIConnector} that will connect
+ * the RMI connector server with the given address.</p>
+ *
+ * <p>The address can refer directly to the connector server,
+ * using the following syntax:</p>
+ *
+ * <pre>
+ * service:jmx:rmi://<em>[host[:port]]</em>/stub/<em>encoded-stub</em>
+ * </pre>
+ *
+ * <p>(Here, the square brackets {@code []} are not part of the
+ * address but indicate that the host and port are optional.)</p>
+ *
+ * <p>The address can instead indicate where to find an RMI stub
+ * through JNDI, using the following syntax:</p>
+ *
+ * <pre>
+ * service:jmx:rmi://<em>[host[:port]]</em>/jndi/<em>jndi-name</em>
+ * </pre>
+ *
+ * <p>An implementation may also recognize additional address
+ * syntaxes, for example:</p>
+ *
+ * <pre>
+ * service:jmx:iiop://<em>[host[:port]]</em>/stub/<em>encoded-stub</em>
+ * </pre>
+ *
+ * @param url the address of the RMI connector server.
+ *
+ * @param environment additional attributes specifying how to make
+ * the connection. For JNDI-based addresses, these attributes can
+ * usefully include JNDI attributes recognized by {@link
+ * InitialContext#InitialContext(Hashtable) InitialContext}. This
+ * parameter can be null, which is equivalent to an empty Map.
+ *
+ * @exception IllegalArgumentException if {@code url}
+ * is null.
+ */
+ public RMIConnector(JMXServiceURL url, Map<String,?> environment) {
+ this(null, url, environment);
+ }
+
+ /**
+ * <p>Constructs an {@code RMIConnector} using the given RMI stub.
+ *
+ * @param rmiServer an RMI stub representing the RMI connector server.
+ * @param environment additional attributes specifying how to make
+ * the connection. This parameter can be null, which is
+ * equivalent to an empty Map.
+ *
+ * @exception IllegalArgumentException if {@code rmiServer}
+ * is null.
+ */
+ public RMIConnector(RMIServer rmiServer, Map<String,?> environment) {
+ this(rmiServer, null, environment);
+ }
+
+ /**
+ * <p>Returns a string representation of this object. In general,
+ * the {@code toString} method returns a string that
+ * "textually represents" this object. The result should be a
+ * concise but informative representation that is easy for a
+ * person to read.</p>
+ *
+ * @return a String representation of this object.
+ **/
+ @Override
+ public String toString() {
+ final StringBuilder b = new StringBuilder(this.getClass().getName());
+ b.append(":");
+ if (rmiServer != null) {
+ b.append(" rmiServer=").append(rmiServer.toString());
+ }
+ if (jmxServiceURL != null) {
+ if (rmiServer!=null) b.append(",");
+ b.append(" jmxServiceURL=").append(jmxServiceURL.toString());
+ }
+ return b.toString();
+ }
+
+ /**
+ * <p>The address of this connector.</p>
+ *
+ * @return the address of this connector, or null if it
+ * does not have one.
+ *
+ * @since 1.6
+ */
+ public JMXServiceURL getAddress() {
+ return jmxServiceURL;
+ }
+
+ //--------------------------------------------------------------------
+ // implements JMXConnector interface
+ //--------------------------------------------------------------------
+
+ /**
+ * @throws IOException if the connection could not be made because of a
+ * communication problem
+ */
+ public void connect() throws IOException {
+ connect(null);
+ }
+
+ /**
+ * @throws IOException if the connection could not be made because of a
+ * communication problem
+ */
+ public synchronized void connect(Map<String,?> environment)
+ throws IOException {
+ final boolean tracing = logger.traceOn();
+ String idstr = (tracing?"["+this.toString()+"]":null);
+
+ if (terminated) {
+ logger.trace("connect",idstr + " already closed.");
+ throw new IOException("Connector closed");
+ }
+ if (connected) {
+ logger.trace("connect",idstr + " already connected.");
+ return;
+ }
+
+ try {
+ if (tracing) logger.trace("connect",idstr + " connecting...");
+
+ final Map<String, Object> usemap =
+ new HashMap<String, Object>((this.env==null) ?
+ Collections.<String, Object>emptyMap() : this.env);
+
+
+ if (environment != null) {
+ EnvHelp.checkAttributes(environment);
+ usemap.putAll(environment);
+ }
+
+ // Get RMIServer stub from directory or URL encoding if needed.
+ if (tracing) logger.trace("connect",idstr + " finding stub...");
+ RMIServer stub = (rmiServer!=null)?rmiServer:
+ findRMIServer(jmxServiceURL, usemap);
+
+ // Check for secure RMIServer stub if the corresponding
+ // client-side environment property is set to "true".
+ //
+ String stringBoolean = (String) usemap.get("jmx.remote.x.check.stub");
+ boolean checkStub = EnvHelp.computeBooleanFromString(stringBoolean);
+
+ if (checkStub) checkStub(stub, rmiServerImplStubClass);
+
+ if (tracing) logger.trace("connect",idstr + " connecting stub...");
+ idstr = (tracing?"["+this.toString()+"]":null);
+
+ // Calling newClient on the RMIServer stub.
+ if (tracing)
+ logger.trace("connect",idstr + " getting connection...");
+ Object credentials = usemap.get(CREDENTIALS);
+
+ try {
+ connection = getConnection(stub, credentials, checkStub);
+ } catch (java.rmi.RemoteException re) {
+ throw re;
+ }
+
+ // Always use one of:
+ // ClassLoader provided in Map at connect time,
+ // or contextClassLoader at connect time.
+ if (tracing)
+ logger.trace("connect",idstr + " getting class loader...");
+ defaultClassLoader = EnvHelp.resolveClientClassLoader(usemap);
+
+ usemap.put(JMXConnectorFactory.DEFAULT_CLASS_LOADER,
+ defaultClassLoader);
+
+ rmiNotifClient = new RMINotifClient(defaultClassLoader, usemap);
+
+ env = usemap;
+ final long checkPeriod = EnvHelp.getConnectionCheckPeriod(usemap);
+ communicatorAdmin = new RMIClientCommunicatorAdmin(checkPeriod);
+
+ connected = true;
+
+ // The connectionId variable is used in doStart(), when
+ // reconnecting, to identify the "old" connection.
+ //
+ connectionId = getConnectionId();
+
+ Notification connectedNotif =
+ new JMXConnectionNotification(JMXConnectionNotification.OPENED,
+ this,
+ connectionId,
+ clientNotifSeqNo++,
+ "Successful connection",
+ null);
+ sendNotification(connectedNotif);
+
+ if (tracing) logger.trace("connect",idstr + " done...");
+ } catch (IOException e) {
+ if (tracing)
+ logger.trace("connect",idstr + " failed to connect: " + e);
+ throw e;
+ } catch (RuntimeException e) {
+ if (tracing)
+ logger.trace("connect",idstr + " failed to connect: " + e);
+ throw e;
+ } catch (NamingException e) {
+ final String msg = "Failed to retrieve RMIServer stub: " + e;
+ if (tracing) logger.trace("connect",idstr + " " + msg);
+ throw EnvHelp.initCause(new IOException(msg),e);
+ }
+ }
+
+ public synchronized String getConnectionId() throws IOException {
+ if (terminated || !connected) {
+ if (logger.traceOn())
+ logger.trace("getConnectionId","["+this.toString()+
+ "] not connected.");
+
+ throw new IOException("Not connected");
+ }
+
+ // we do a remote call to have an IOException if the connection is broken.
+ // see the bug 4939578
+ return connection.getConnectionId();
+ }
+
+ public synchronized MBeanServerConnection getMBeanServerConnection()
+ throws IOException {
+ return getMBeanServerConnection(null);
+ }
+
+ public synchronized MBeanServerConnection
+ getMBeanServerConnection(Subject delegationSubject)
+ throws IOException {
+
+ if (terminated) {
+ if (logger.traceOn())
+ logger.trace("getMBeanServerConnection","[" + this.toString() +
+ "] already closed.");
+ throw new IOException("Connection closed");
+ } else if (!connected) {
+ if (logger.traceOn())
+ logger.trace("getMBeanServerConnection","[" + this.toString() +
+ "] is not connected.");
+ throw new IOException("Not connected");
+ }
+
+ return getConnectionWithSubject(delegationSubject);
+ }
+
+ public void
+ addConnectionNotificationListener(NotificationListener listener,
+ NotificationFilter filter,
+ Object handback) {
+ if (listener == null)
+ throw new NullPointerException("listener");
+ connectionBroadcaster.addNotificationListener(listener, filter,
+ handback);
+ }
+
+ public void
+ removeConnectionNotificationListener(NotificationListener listener)
+ throws ListenerNotFoundException {
+ if (listener == null)
+ throw new NullPointerException("listener");
+ connectionBroadcaster.removeNotificationListener(listener);
+ }
+
+ public void
+ removeConnectionNotificationListener(NotificationListener listener,
+ NotificationFilter filter,
+ Object handback)
+ throws ListenerNotFoundException {
+ if (listener == null)
+ throw new NullPointerException("listener");
+ connectionBroadcaster.removeNotificationListener(listener, filter,
+ handback);
+ }
+
+ private void sendNotification(Notification n) {
+ connectionBroadcaster.sendNotification(n);
+ }
+
+ public synchronized void close() throws IOException {
+ close(false);
+ }
+
+ // allows to do close after setting the flag "terminated" to true.
+ // It is necessary to avoid a deadlock, see 6296324
+ private synchronized void close(boolean intern) throws IOException {
+ final boolean tracing = logger.traceOn();
+ final boolean debug = logger.debugOn();
+ final String idstr = (tracing?"["+this.toString()+"]":null);
+
+ if (!intern) {
+ // Return if already cleanly closed.
+ //
+ if (terminated) {
+ if (closeException == null) {
+ if (tracing) logger.trace("close",idstr + " already closed.");
+ return;
+ }
+ } else {
+ terminated = true;
+ }
+ }
+
+ if (closeException != null && tracing) {
+ // Already closed, but not cleanly. Attempt again.
+ //
+ if (tracing) {
+ logger.trace("close",idstr + " had failed: " + closeException);
+ logger.trace("close",idstr + " attempting to close again.");
+ }
+ }
+
+ String savedConnectionId = null;
+ if (connected) {
+ savedConnectionId = connectionId;
+ }
+
+ closeException = null;
+
+ if (tracing) logger.trace("close",idstr + " closing.");
+
+ if (communicatorAdmin != null) {
+ communicatorAdmin.terminate();
+ }
+
+ if (rmiNotifClient != null) {
+ try {
+ rmiNotifClient.terminate();
+ if (tracing) logger.trace("close",idstr +
+ " RMI Notification client terminated.");
+ } catch (RuntimeException x) {
+ closeException = x;
+ if (tracing) logger.trace("close",idstr +
+ " Failed to terminate RMI Notification client: " + x);
+ if (debug) logger.debug("close",x);
+ }
+ }
+
+ if (connection != null) {
+ try {
+ connection.close();
+ if (tracing) logger.trace("close",idstr + " closed.");
+ } catch (NoSuchObjectException nse) {
+ // OK, the server maybe closed itself.
+ } catch (IOException e) {
+ closeException = e;
+ if (tracing) logger.trace("close",idstr +
+ " Failed to close RMIServer: " + e);
+ if (debug) logger.debug("close",e);
+ }
+ }
+
+ // Clean up MBeanServerConnection table
+ //
+ rmbscMap.clear();
+
+ /* Send notification of closure. We don't do this if the user
+ * never called connect() on the connector, because there's no
+ * connection id in that case. */
+
+ if (savedConnectionId != null) {
+ Notification closedNotif =
+ new JMXConnectionNotification(JMXConnectionNotification.CLOSED,
+ this,
+ savedConnectionId,
+ clientNotifSeqNo++,
+ "Client has been closed",
+ null);
+ sendNotification(closedNotif);
+ }
+
+ // throw exception if needed
+ //
+ if (closeException != null) {
+ if (tracing) logger.trace("close",idstr + " failed to close: " +
+ closeException);
+ if (closeException instanceof IOException)
+ throw (IOException) closeException;
+ if (closeException instanceof RuntimeException)
+ throw (RuntimeException) closeException;
+ final IOException x =
+ new IOException("Failed to close: " + closeException);
+ throw EnvHelp.initCause(x,closeException);
+ }
+ }
+
+ // added for re-connection
+ private Integer addListenerWithSubject(ObjectName name,
+ MarshalledObject<NotificationFilter> filter,
+ Subject delegationSubject,
+ boolean reconnect)
+ throws InstanceNotFoundException, IOException {
+
+ final boolean debug = logger.debugOn();
+ if (debug)
+ logger.debug("addListenerWithSubject",
+ "(ObjectName,MarshalledObject,Subject)");
+
+ final ObjectName[] names = new ObjectName[] {name};
+ final MarshalledObject<NotificationFilter>[] filters =
+ Util.cast(new MarshalledObject<?>[] {filter});
+ final Subject[] delegationSubjects = new Subject[] {
+ delegationSubject
+ };
+
+ final Integer[] listenerIDs =
+ addListenersWithSubjects(names,filters,delegationSubjects,
+ reconnect);
+
+ if (debug) logger.debug("addListenerWithSubject","listenerID="
+ + listenerIDs[0]);
+ return listenerIDs[0];
+ }
+
+ // added for re-connection
+ private Integer[] addListenersWithSubjects(ObjectName[] names,
+ MarshalledObject<NotificationFilter>[] filters,
+ Subject[] delegationSubjects,
+ boolean reconnect)
+ throws InstanceNotFoundException, IOException {
+
+ final boolean debug = logger.debugOn();
+ if (debug)
+ logger.debug("addListenersWithSubjects",
+ "(ObjectName[],MarshalledObject[],Subject[])");
+
+ final ClassLoader old = pushDefaultClassLoader();
+ Integer[] listenerIDs = null;
+
+ try {
+ listenerIDs = connection.addNotificationListeners(names,
+ filters,
+ delegationSubjects);
+ } catch (NoSuchObjectException noe) {
+ // maybe reconnect
+ if (reconnect) {
+ communicatorAdmin.gotIOException(noe);
+
+ listenerIDs = connection.addNotificationListeners(names,
+ filters,
+ delegationSubjects);
+ } else {
+ throw noe;
+ }
+ } catch (IOException ioe) {
+ // send a failed notif if necessary
+ communicatorAdmin.gotIOException(ioe);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+
+ if (debug) logger.debug("addListenersWithSubjects","registered "
+ + ((listenerIDs==null)?0:listenerIDs.length)
+ + " listener(s)");
+ return listenerIDs;
+ }
+
+ //--------------------------------------------------------------------
+ // Implementation of MBeanServerConnection
+ //--------------------------------------------------------------------
+ private class RemoteMBeanServerConnection implements MBeanServerConnection {
+ private Subject delegationSubject;
+
+ public RemoteMBeanServerConnection() {
+ this(null);
+ }
+
+ public RemoteMBeanServerConnection(Subject delegationSubject) {
+ this.delegationSubject = delegationSubject;
+ }
+
+ public ObjectInstance createMBean(String className,
+ ObjectName name)
+ throws ReflectionException,
+ InstanceAlreadyExistsException,
+ MBeanRegistrationException,
+ MBeanException,
+ NotCompliantMBeanException,
+ IOException {
+ if (logger.debugOn())
+ logger.debug("createMBean(String,ObjectName)",
+ "className=" + className + ", name=" +
+ name);
+
+ final ClassLoader old = pushDefaultClassLoader();
+ try {
+ return connection.createMBean(className,
+ name,
+ delegationSubject);
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ return connection.createMBean(className,
+ name,
+ delegationSubject);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+ }
+
+ public ObjectInstance createMBean(String className,
+ ObjectName name,
+ ObjectName loaderName)
+ throws ReflectionException,
+ InstanceAlreadyExistsException,
+ MBeanRegistrationException,
+ MBeanException,
+ NotCompliantMBeanException,
+ InstanceNotFoundException,
+ IOException {
+
+ if (logger.debugOn())
+ logger.debug("createMBean(String,ObjectName,ObjectName)",
+ "className=" + className + ", name="
+ + name + ", loaderName="
+ + loaderName + ")");
+
+ final ClassLoader old = pushDefaultClassLoader();
+ try {
+ return connection.createMBean(className,
+ name,
+ loaderName,
+ delegationSubject);
+
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ return connection.createMBean(className,
+ name,
+ loaderName,
+ delegationSubject);
+
+ } finally {
+ popDefaultClassLoader(old);
+ }
+ }
+
+ public ObjectInstance createMBean(String className,
+ ObjectName name,
+ Object params[],
+ String signature[])
+ throws ReflectionException,
+ InstanceAlreadyExistsException,
+ MBeanRegistrationException,
+ MBeanException,
+ NotCompliantMBeanException,
+ IOException {
+ if (logger.debugOn())
+ logger.debug("createMBean(String,ObjectName,Object[],String[])",
+ "className=" + className + ", name="
+ + name + ", signature=" + strings(signature));
+
+ final MarshalledObject<Object[]> sParams =
+ new MarshalledObject<Object[]>(params);
+ final ClassLoader old = pushDefaultClassLoader();
+ try {
+ return connection.createMBean(className,
+ name,
+ sParams,
+ signature,
+ delegationSubject);
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ return connection.createMBean(className,
+ name,
+ sParams,
+ signature,
+ delegationSubject);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+ }
+
+ public ObjectInstance createMBean(String className,
+ ObjectName name,
+ ObjectName loaderName,
+ Object params[],
+ String signature[])
+ throws ReflectionException,
+ InstanceAlreadyExistsException,
+ MBeanRegistrationException,
+ MBeanException,
+ NotCompliantMBeanException,
+ InstanceNotFoundException,
+ IOException {
+ if (logger.debugOn()) logger.debug(
+ "createMBean(String,ObjectName,ObjectName,Object[],String[])",
+ "className=" + className + ", name=" + name + ", loaderName="
+ + loaderName + ", signature=" + strings(signature));
+
+ final MarshalledObject<Object[]> sParams =
+ new MarshalledObject<Object[]>(params);
+ final ClassLoader old = pushDefaultClassLoader();
+ try {
+ return connection.createMBean(className,
+ name,
+ loaderName,
+ sParams,
+ signature,
+ delegationSubject);
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ return connection.createMBean(className,
+ name,
+ loaderName,
+ sParams,
+ signature,
+ delegationSubject);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+ }
+
+ public void unregisterMBean(ObjectName name)
+ throws InstanceNotFoundException,
+ MBeanRegistrationException,
+ IOException {
+ if (logger.debugOn())
+ logger.debug("unregisterMBean", "name=" + name);
+
+ final ClassLoader old = pushDefaultClassLoader();
+ try {
+ connection.unregisterMBean(name, delegationSubject);
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ connection.unregisterMBean(name, delegationSubject);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+ }
+
+ public ObjectInstance getObjectInstance(ObjectName name)
+ throws InstanceNotFoundException,
+ IOException {
+ if (logger.debugOn())
+ logger.debug("getObjectInstance", "name=" + name);
+
+ final ClassLoader old = pushDefaultClassLoader();
+ try {
+ return connection.getObjectInstance(name, delegationSubject);
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ return connection.getObjectInstance(name, delegationSubject);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+ }
+
+ public Set<ObjectInstance> queryMBeans(ObjectName name,
+ QueryExp query)
+ throws IOException {
+ if (logger.debugOn()) logger.debug("queryMBeans",
+ "name=" + name + ", query=" + query);
+
+ final MarshalledObject<QueryExp> sQuery =
+ new MarshalledObject<QueryExp>(query);
+ final ClassLoader old = pushDefaultClassLoader();
+ try {
+ return connection.queryMBeans(name, sQuery, delegationSubject);
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ return connection.queryMBeans(name, sQuery, delegationSubject);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+ }
+
+ public Set<ObjectName> queryNames(ObjectName name,
+ QueryExp query)
+ throws IOException {
+ if (logger.debugOn()) logger.debug("queryNames",
+ "name=" + name + ", query=" + query);
+
+ final MarshalledObject<QueryExp> sQuery =
+ new MarshalledObject<QueryExp>(query);
+ final ClassLoader old = pushDefaultClassLoader();
+ try {
+ return connection.queryNames(name, sQuery, delegationSubject);
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ return connection.queryNames(name, sQuery, delegationSubject);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+ }
+
+ public boolean isRegistered(ObjectName name)
+ throws IOException {
+ if (logger.debugOn())
+ logger.debug("isRegistered", "name=" + name);
+
+ final ClassLoader old = pushDefaultClassLoader();
+ try {
+ return connection.isRegistered(name, delegationSubject);
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ return connection.isRegistered(name, delegationSubject);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+ }
+
+ public Integer getMBeanCount()
+ throws IOException {
+ if (logger.debugOn()) logger.debug("getMBeanCount", "");
+
+ final ClassLoader old = pushDefaultClassLoader();
+ try {
+ return connection.getMBeanCount(delegationSubject);
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ return connection.getMBeanCount(delegationSubject);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+ }
+
+ public Object getAttribute(ObjectName name,
+ String attribute)
+ throws MBeanException,
+ AttributeNotFoundException,
+ InstanceNotFoundException,
+ ReflectionException,
+ IOException {
+ if (logger.debugOn()) logger.debug("getAttribute",
+ "name=" + name + ", attribute="
+ + attribute);
+
+ final ClassLoader old = pushDefaultClassLoader();
+ try {
+ return connection.getAttribute(name,
+ attribute,
+ delegationSubject);
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ return connection.getAttribute(name,
+ attribute,
+ delegationSubject);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+ }
+
+ public AttributeList getAttributes(ObjectName name,
+ String[] attributes)
+ throws InstanceNotFoundException,
+ ReflectionException,
+ IOException {
+ if (logger.debugOn()) logger.debug("getAttributes",
+ "name=" + name + ", attributes="
+ + strings(attributes));
+
+ final ClassLoader old = pushDefaultClassLoader();
+ try {
+ return connection.getAttributes(name,
+ attributes,
+ delegationSubject);
+
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ return connection.getAttributes(name,
+ attributes,
+ delegationSubject);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+ }
+
+
+ public void setAttribute(ObjectName name,
+ Attribute attribute)
+ throws InstanceNotFoundException,
+ AttributeNotFoundException,
+ InvalidAttributeValueException,
+ MBeanException,
+ ReflectionException,
+ IOException {
+
+ if (logger.debugOn()) logger.debug("setAttribute",
+ "name=" + name + ", attribute name="
+ + attribute.getName());
+
+ final MarshalledObject<Attribute> sAttribute =
+ new MarshalledObject<Attribute>(attribute);
+ final ClassLoader old = pushDefaultClassLoader();
+ try {
+ connection.setAttribute(name, sAttribute, delegationSubject);
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ connection.setAttribute(name, sAttribute, delegationSubject);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+ }
+
+ public AttributeList setAttributes(ObjectName name,
+ AttributeList attributes)
+ throws InstanceNotFoundException,
+ ReflectionException,
+ IOException {
+
+ if (logger.debugOn()) {
+ logger.debug("setAttributes",
+ "name=" + name + ", attribute names="
+ + getAttributesNames(attributes));
+ }
+
+ final MarshalledObject<AttributeList> sAttributes =
+ new MarshalledObject<AttributeList>(attributes);
+ final ClassLoader old = pushDefaultClassLoader();
+ try {
+ return connection.setAttributes(name,
+ sAttributes,
+ delegationSubject);
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ return connection.setAttributes(name,
+ sAttributes,
+ delegationSubject);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+ }
+
+
+ public Object invoke(ObjectName name,
+ String operationName,
+ Object params[],
+ String signature[])
+ throws InstanceNotFoundException,
+ MBeanException,
+ ReflectionException,
+ IOException {
+
+ if (logger.debugOn()) logger.debug("invoke",
+ "name=" + name
+ + ", operationName=" + operationName
+ + ", signature=" + strings(signature));
+
+ final MarshalledObject<Object[]> sParams =
+ new MarshalledObject<Object[]>(params);
+ final ClassLoader old = pushDefaultClassLoader();
+ try {
+ return connection.invoke(name,
+ operationName,
+ sParams,
+ signature,
+ delegationSubject);
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ return connection.invoke(name,
+ operationName,
+ sParams,
+ signature,
+ delegationSubject);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+ }
+
+
+ public String getDefaultDomain()
+ throws IOException {
+ if (logger.debugOn()) logger.debug("getDefaultDomain", "");
+
+ final ClassLoader old = pushDefaultClassLoader();
+ try {
+ return connection.getDefaultDomain(delegationSubject);
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ return connection.getDefaultDomain(delegationSubject);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+ }
+
+ public String[] getDomains() throws IOException {
+ if (logger.debugOn()) logger.debug("getDomains", "");
+
+ final ClassLoader old = pushDefaultClassLoader();
+ try {
+ return connection.getDomains(delegationSubject);
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ return connection.getDomains(delegationSubject);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+ }
+
+ public MBeanInfo getMBeanInfo(ObjectName name)
+ throws InstanceNotFoundException,
+ IntrospectionException,
+ ReflectionException,
+ IOException {
+
+ if (logger.debugOn()) logger.debug("getMBeanInfo", "name=" + name);
+ final ClassLoader old = pushDefaultClassLoader();
+ try {
+ return connection.getMBeanInfo(name, delegationSubject);
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ return connection.getMBeanInfo(name, delegationSubject);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+ }
+
+
+ public boolean isInstanceOf(ObjectName name,
+ String className)
+ throws InstanceNotFoundException,
+ IOException {
+ if (logger.debugOn())
+ logger.debug("isInstanceOf", "name=" + name +
+ ", className=" + className);
+
+ final ClassLoader old = pushDefaultClassLoader();
+ try {
+ return connection.isInstanceOf(name,
+ className,
+ delegationSubject);
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ return connection.isInstanceOf(name,
+ className,
+ delegationSubject);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+ }
+
+ public void addNotificationListener(ObjectName name,
+ ObjectName listener,
+ NotificationFilter filter,
+ Object handback)
+ throws InstanceNotFoundException,
+ IOException {
+
+ if (logger.debugOn())
+ logger.debug("addNotificationListener" +
+ "(ObjectName,ObjectName,NotificationFilter,Object)",
+ "name=" + name + ", listener=" + listener
+ + ", filter=" + filter + ", handback=" + handback);
+
+ final MarshalledObject<NotificationFilter> sFilter =
+ new MarshalledObject<NotificationFilter>(filter);
+ final MarshalledObject<Object> sHandback =
+ new MarshalledObject<Object>(handback);
+ final ClassLoader old = pushDefaultClassLoader();
+ try {
+ connection.addNotificationListener(name,
+ listener,
+ sFilter,
+ sHandback,
+ delegationSubject);
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ connection.addNotificationListener(name,
+ listener,
+ sFilter,
+ sHandback,
+ delegationSubject);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+ }
+
+ public void removeNotificationListener(ObjectName name,
+ ObjectName listener)
+ throws InstanceNotFoundException,
+ ListenerNotFoundException,
+ IOException {
+
+ if (logger.debugOn()) logger.debug("removeNotificationListener" +
+ "(ObjectName,ObjectName)",
+ "name=" + name
+ + ", listener=" + listener);
+
+ final ClassLoader old = pushDefaultClassLoader();
+ try {
+ connection.removeNotificationListener(name,
+ listener,
+ delegationSubject);
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ connection.removeNotificationListener(name,
+ listener,
+ delegationSubject);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+ }
+
+ public void removeNotificationListener(ObjectName name,
+ ObjectName listener,
+ NotificationFilter filter,
+ Object handback)
+ throws InstanceNotFoundException,
+ ListenerNotFoundException,
+ IOException {
+ if (logger.debugOn())
+ logger.debug("removeNotificationListener" +
+ "(ObjectName,ObjectName,NotificationFilter,Object)",
+ "name=" + name
+ + ", listener=" + listener
+ + ", filter=" + filter
+ + ", handback=" + handback);
+
+ final MarshalledObject<NotificationFilter> sFilter =
+ new MarshalledObject<NotificationFilter>(filter);
+ final MarshalledObject<Object> sHandback =
+ new MarshalledObject<Object>(handback);
+ final ClassLoader old = pushDefaultClassLoader();
+ try {
+ connection.removeNotificationListener(name,
+ listener,
+ sFilter,
+ sHandback,
+ delegationSubject);
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ connection.removeNotificationListener(name,
+ listener,
+ sFilter,
+ sHandback,
+ delegationSubject);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+ }
+
+ // Specific Notification Handle ----------------------------------
+
+ public void addNotificationListener(ObjectName name,
+ NotificationListener listener,
+ NotificationFilter filter,
+ Object handback)
+ throws InstanceNotFoundException,
+ IOException {
+
+ final boolean debug = logger.debugOn();
+
+ if (debug)
+ logger.debug("addNotificationListener" +
+ "(ObjectName,NotificationListener,"+
+ "NotificationFilter,Object)",
+ "name=" + name
+ + ", listener=" + listener
+ + ", filter=" + filter
+ + ", handback=" + handback);
+
+ final Integer listenerID =
+ addListenerWithSubject(name,
+ new MarshalledObject<NotificationFilter>(filter),
+ delegationSubject,true);
+ rmiNotifClient.addNotificationListener(listenerID, name, listener,
+ filter, handback,
+ delegationSubject);
+ }
+
+ public void removeNotificationListener(ObjectName name,
+ NotificationListener listener)
+ throws InstanceNotFoundException,
+ ListenerNotFoundException,
+ IOException {
+
+ final boolean debug = logger.debugOn();
+
+ if (debug) logger.debug("removeNotificationListener"+
+ "(ObjectName,NotificationListener)",
+ "name=" + name
+ + ", listener=" + listener);
+
+ final Integer[] ret =
+ rmiNotifClient.removeNotificationListener(name, listener);
+
+ if (debug) logger.debug("removeNotificationListener",
+ "listenerIDs=" + objects(ret));
+
+ final ClassLoader old = pushDefaultClassLoader();
+
+ try {
+ connection.removeNotificationListeners(name,
+ ret,
+ delegationSubject);
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ connection.removeNotificationListeners(name,
+ ret,
+ delegationSubject);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+
+ }
+
+ public void removeNotificationListener(ObjectName name,
+ NotificationListener listener,
+ NotificationFilter filter,
+ Object handback)
+ throws InstanceNotFoundException,
+ ListenerNotFoundException,
+ IOException {
+ final boolean debug = logger.debugOn();
+
+ if (debug)
+ logger.debug("removeNotificationListener"+
+ "(ObjectName,NotificationListener,"+
+ "NotificationFilter,Object)",
+ "name=" + name
+ + ", listener=" + listener
+ + ", filter=" + filter
+ + ", handback=" + handback);
+
+ final Integer ret =
+ rmiNotifClient.removeNotificationListener(name, listener,
+ filter, handback);
+
+ if (debug) logger.debug("removeNotificationListener",
+ "listenerID=" + ret);
+
+ final ClassLoader old = pushDefaultClassLoader();
+ try {
+ connection.removeNotificationListeners(name,
+ new Integer[] {ret},
+ delegationSubject);
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ connection.removeNotificationListeners(name,
+ new Integer[] {ret},
+ delegationSubject);
+ } finally {
+ popDefaultClassLoader(old);
+ }
+
+ }
+ }
+
+ //--------------------------------------------------------------------
+ private class RMINotifClient extends ClientNotifForwarder {
+ public RMINotifClient(ClassLoader cl, Map<String, ?> env) {
+ super(cl, env);
+ }
+
+ protected NotificationResult fetchNotifs(long clientSequenceNumber,
+ int maxNotifications,
+ long timeout)
+ throws IOException, ClassNotFoundException {
+
+ boolean retried = false;
+ while (true) { // used for a successful re-connection
+ // or a transient network problem
+ try {
+ return connection.fetchNotifications(clientSequenceNumber,
+ maxNotifications,
+ timeout); // return normally
+ } catch (IOException ioe) {
+ // Examine the chain of exceptions to determine whether this
+ // is a deserialization issue. If so - we propagate the
+ // appropriate exception to the caller, who will then
+ // proceed with fetching notifications one by one
+ rethrowDeserializationException(ioe);
+
+ try {
+ communicatorAdmin.gotIOException(ioe);
+ // reconnection OK, back to "while" to do again
+ } catch (IOException ee) {
+ boolean toClose = false;
+
+ synchronized (this) {
+ if (terminated) {
+ // the connection is closed.
+ throw ioe;
+ } else if (retried) {
+ toClose = true;
+ }
+ }
+
+ if (toClose) {
+ // JDK-8049303
+ // We received an IOException - but the communicatorAdmin
+ // did not close the connection - possibly because
+ // the original exception was raised by a transient network
+ // problem?
+ // We already know that this exception is not due to a deserialization
+ // issue as we already took care of that before involving the
+ // communicatorAdmin. Moreover - we already made one retry attempt
+ // at fetching the same batch of notifications - and the
+ // problem persisted.
+ // Since trying again doesn't seem to solve the issue, we will now
+ // close the connection. Doing otherwise might cause the
+ // NotifFetcher thread to die silently.
+ final Notification failedNotif =
+ new JMXConnectionNotification(
+ JMXConnectionNotification.FAILED,
+ this,
+ connectionId,
+ clientNotifSeqNo++,
+ "Failed to communicate with the server: " + ioe.toString(),
+ ioe);
+
+ sendNotification(failedNotif);
+
+ try {
+ close(true);
+ } catch (Exception e) {
+ // OK.
+ // We are closing
+ }
+ throw ioe; // the connection is closed here.
+ } else {
+ // JDK-8049303 possible transient network problem,
+ // let's try one more time
+ retried = true;
+ }
+ }
+ }
+ }
+ }
+
+ private void rethrowDeserializationException(IOException ioe)
+ throws ClassNotFoundException, IOException {
+ // specially treating for an UnmarshalException
+ if (ioe instanceof UnmarshalException) {
+ NotSerializableException nse = new NotSerializableException();
+ nse.initCause(ioe);
+ throw nse; // the fix of 6937053 made ClientNotifForwarder.fetchNotifs
+ // fetch one by one with UnmarshalException
+ }
+
+ // Not serialization problem, return.
+ }
+
+ protected Integer addListenerForMBeanRemovedNotif()
+ throws IOException, InstanceNotFoundException {
+ NotificationFilterSupport clientFilter =
+ new NotificationFilterSupport();
+ clientFilter.enableType(
+ MBeanServerNotification.UNREGISTRATION_NOTIFICATION);
+ MarshalledObject<NotificationFilter> sFilter =
+ new MarshalledObject<NotificationFilter>(clientFilter);
+
+ Integer[] listenerIDs;
+ final ObjectName[] names =
+ new ObjectName[] {MBeanServerDelegate.DELEGATE_NAME};
+ final MarshalledObject<NotificationFilter>[] filters =
+ Util.cast(new MarshalledObject<?>[] {sFilter});
+ final Subject[] subjects = new Subject[] {null};
+ try {
+ listenerIDs =
+ connection.addNotificationListeners(names,
+ filters,
+ subjects);
+
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ listenerIDs =
+ connection.addNotificationListeners(names,
+ filters,
+ subjects);
+ }
+ return listenerIDs[0];
+ }
+
+ protected void removeListenerForMBeanRemovedNotif(Integer id)
+ throws IOException, InstanceNotFoundException,
+ ListenerNotFoundException {
+ try {
+ connection.removeNotificationListeners(
+ MBeanServerDelegate.DELEGATE_NAME,
+ new Integer[] {id},
+ null);
+ } catch (IOException ioe) {
+ communicatorAdmin.gotIOException(ioe);
+
+ connection.removeNotificationListeners(
+ MBeanServerDelegate.DELEGATE_NAME,
+ new Integer[] {id},
+ null);
+ }
+
+ }
+
+ protected void lostNotifs(String message, long number) {
+ final String notifType = JMXConnectionNotification.NOTIFS_LOST;
+
+ final JMXConnectionNotification n =
+ new JMXConnectionNotification(notifType,
+ RMIConnector.this,
+ connectionId,
+ clientNotifCounter++,
+ message,
+ Long.valueOf(number));
+ sendNotification(n);
+ }
+ }
+
+ private class RMIClientCommunicatorAdmin extends ClientCommunicatorAdmin {
+ public RMIClientCommunicatorAdmin(long period) {
+ super(period);
+ }
+
+ @Override
+ public void gotIOException(IOException ioe) throws IOException {
+ if (ioe instanceof NoSuchObjectException) {
+ // need to restart
+ super.gotIOException(ioe);
+
+ return;
+ }
+
+ // check if the connection is broken
+ try {
+ connection.getDefaultDomain(null);
+ } catch (IOException ioexc) {
+ boolean toClose = false;
+
+ synchronized(this) {
+ if (!terminated) {
+ terminated = true;
+
+ toClose = true;
+ }
+ }
+
+ if (toClose) {
+ // we should close the connection,
+ // but send a failed notif at first
+ final Notification failedNotif =
+ new JMXConnectionNotification(
+ JMXConnectionNotification.FAILED,
+ this,
+ connectionId,
+ clientNotifSeqNo++,
+ "Failed to communicate with the server: "+ioe.toString(),
+ ioe);
+
+ sendNotification(failedNotif);
+
+ try {
+ close(true);
+ } catch (Exception e) {
+ // OK.
+ // We are closing
+ }
+ }
+ }
+
+ // forward the exception
+ if (ioe instanceof ServerException) {
+ /* Need to unwrap the exception.
+ Some user-thrown exception at server side will be wrapped by
+ rmi into a ServerException.
+ For example, a RMIConnnectorServer will wrap a
+ ClassNotFoundException into a UnmarshalException, and rmi
+ will throw a ServerException at client side which wraps this
+ UnmarshalException.
+ No failed notif here.
+ */
+ Throwable tt = ((ServerException)ioe).detail;
+
+ if (tt instanceof IOException) {
+ throw (IOException)tt;
+ } else if (tt instanceof RuntimeException) {
+ throw (RuntimeException)tt;
+ }
+ }
+
+ throw ioe;
+ }
+
+ public void reconnectNotificationListeners(ClientListenerInfo[] old) throws IOException {
+ final int len = old.length;
+ int i;
+
+ ClientListenerInfo[] clis = new ClientListenerInfo[len];
+
+ final Subject[] subjects = new Subject[len];
+ final ObjectName[] names = new ObjectName[len];
+ final NotificationListener[] listeners = new NotificationListener[len];
+ final NotificationFilter[] filters = new NotificationFilter[len];
+ final MarshalledObject<NotificationFilter>[] mFilters =
+ Util.cast(new MarshalledObject<?>[len]);
+ final Object[] handbacks = new Object[len];
+
+ for (i=0;i<len;i++) {
+ subjects[i] = old[i].getDelegationSubject();
+ names[i] = old[i].getObjectName();
+ listeners[i] = old[i].getListener();
+ filters[i] = old[i].getNotificationFilter();
+ mFilters[i] = new MarshalledObject<NotificationFilter>(filters[i]);
+ handbacks[i] = old[i].getHandback();
+ }
+
+ try {
+ Integer[] ids = addListenersWithSubjects(names,mFilters,subjects,false);
+
+ for (i=0;i<len;i++) {
+ clis[i] = new ClientListenerInfo(ids[i],
+ names[i],
+ listeners[i],
+ filters[i],
+ handbacks[i],
+ subjects[i]);
+ }
+
+ rmiNotifClient.postReconnection(clis);
+
+ return;
+ } catch (InstanceNotFoundException infe) {
+ // OK, we will do one by one
+ }
+
+ int j = 0;
+ for (i=0;i<len;i++) {
+ try {
+ Integer id = addListenerWithSubject(names[i],
+ new MarshalledObject<NotificationFilter>(filters[i]),
+ subjects[i],
+ false);
+
+ clis[j++] = new ClientListenerInfo(id,
+ names[i],
+ listeners[i],
+ filters[i],
+ handbacks[i],
+ subjects[i]);
+ } catch (InstanceNotFoundException infe) {
+ logger.warning("reconnectNotificationListeners",
+ "Can't reconnect listener for " +
+ names[i]);
+ }
+ }
+
+ if (j != len) {
+ ClientListenerInfo[] tmp = clis;
+ clis = new ClientListenerInfo[j];
+ System.arraycopy(tmp, 0, clis, 0, j);
+ }
+
+ rmiNotifClient.postReconnection(clis);
+ }
+
+ protected void checkConnection() throws IOException {
+ if (logger.debugOn())
+ logger.debug("RMIClientCommunicatorAdmin-checkConnection",
+ "Calling the method getDefaultDomain.");
+
+ connection.getDefaultDomain(null);
+ }
+
+ protected void doStart() throws IOException {
+ // Get RMIServer stub from directory or URL encoding if needed.
+ RMIServer stub;
+ try {
+ stub = (rmiServer!=null)?rmiServer:
+ findRMIServer(jmxServiceURL, env);
+ } catch (NamingException ne) {
+ throw new IOException("Failed to get a RMI stub: "+ne);
+ }
+
+ // Calling newClient on the RMIServer stub.
+ Object credentials = env.get(CREDENTIALS);
+ connection = stub.newClient(credentials);
+
+ // notif issues
+ final ClientListenerInfo[] old = rmiNotifClient.preReconnection();
+
+ reconnectNotificationListeners(old);
+
+ connectionId = getConnectionId();
+
+ Notification reconnectedNotif =
+ new JMXConnectionNotification(JMXConnectionNotification.OPENED,
+ this,
+ connectionId,
+ clientNotifSeqNo++,
+ "Reconnected to server",
+ null);
+ sendNotification(reconnectedNotif);
+
+ }
+
+ protected void doStop() {
+ try {
+ close();
+ } catch (IOException ioe) {
+ logger.warning("RMIClientCommunicatorAdmin-doStop",
+ "Failed to call the method close():" + ioe);
+ logger.debug("RMIClientCommunicatorAdmin-doStop",ioe);
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+ // Private stuff - Serialization
+ //--------------------------------------------------------------------
+ /**
+ * Read RMIConnector fields from an {@link java.io.ObjectInputStream
+ * ObjectInputStream}.
+ * Calls {@code s.defaultReadObject()} and then initializes
+ * all transient variables that need initializing.
+ * @param s The ObjectInputStream to read from.
+ * @exception InvalidObjectException if none of <var>rmiServer</var> stub
+ * or <var>jmxServiceURL</var> are set.
+ * @see #RMIConnector(JMXServiceURL,Map)
+ * @see #RMIConnector(RMIServer,Map)
+ **/
+ private void readObject(java.io.ObjectInputStream s)
+ throws IOException, ClassNotFoundException {
+ s.defaultReadObject();
+
+ if (rmiServer == null && jmxServiceURL == null) throw new
+ InvalidObjectException("rmiServer and jmxServiceURL both null");
+
+ initTransients();
+ }
+
+ /**
+ * Writes the RMIConnector fields to an {@link java.io.ObjectOutputStream
+ * ObjectOutputStream}.
+ * <p>Connects the underlying RMIServer stub to an ORB, if needed,
+ * before serializing it. This is done using the environment
+ * map that was provided to the constructor, if any, and as documented
+ * in {@link javax.management.remote.rmi}.</p>
+ * <p>This method then calls {@code s.defaultWriteObject()}.
+ * Usually, <var>rmiServer</var> is null if this object
+ * was constructed with a JMXServiceURL, and <var>jmxServiceURL</var>
+ * is null if this object is constructed with a RMIServer stub.
+ * <p>Note that the environment Map is not serialized, since the objects
+ * it contains are assumed to be contextual and relevant only
+ * with respect to the local environment (class loader, ORB, etc...).</p>
+ * <p>After an RMIConnector is deserialized, it is assumed that the
+ * user will call {@link #connect(Map)}, providing a new Map that
+ * can contain values which are contextually relevant to the new
+ * local environment.</p>
+ * <p>Since connection to the ORB is needed prior to serializing, and
+ * since the ORB to connect to is one of those contextual parameters,
+ * it is not recommended to re-serialize a just de-serialized object -
+ * as the de-serialized object has no map. Thus, when an RMIConnector
+ * object is needed for serialization or transmission to a remote
+ * application, it is recommended to obtain a new RMIConnector stub
+ * by calling {@link RMIConnectorServer#toJMXConnector(Map)}.</p>
+ * @param s The ObjectOutputStream to write to.
+ * @exception InvalidObjectException if none of <var>rmiServer</var> stub
+ * or <var>jmxServiceURL</var> are set.
+ * @see #RMIConnector(JMXServiceURL,Map)
+ * @see #RMIConnector(RMIServer,Map)
+ **/
+ private void writeObject(java.io.ObjectOutputStream s)
+ throws IOException {
+ if (rmiServer == null && jmxServiceURL == null) throw new
+ InvalidObjectException("rmiServer and jmxServiceURL both null.");
+ s.defaultWriteObject();
+ }
+
+ // Initialization of transient variables.
+ private void initTransients() {
+ rmbscMap = new WeakHashMap<Subject, WeakReference<MBeanServerConnection>>();
+ connected = false;
+ terminated = false;
+
+ connectionBroadcaster = new NotificationBroadcasterSupport();
+ }
+
+ //--------------------------------------------------------------------
+ // Private stuff - Check if stub can be trusted.
+ //--------------------------------------------------------------------
+
+ private static void checkStub(Remote stub,
+ Class<?> stubClass) {
+
+ // Check remote stub is from the expected class.
+ //
+ if (stub.getClass() != stubClass) {
+ if (!Proxy.isProxyClass(stub.getClass())) {
+ throw new SecurityException(
+ "Expecting a " + stubClass.getName() + " stub!");
+ } else {
+ InvocationHandler handler = Proxy.getInvocationHandler(stub);
+ if (handler.getClass() != RemoteObjectInvocationHandler.class)
+ throw new SecurityException(
+ "Expecting a dynamic proxy instance with a " +
+ RemoteObjectInvocationHandler.class.getName() +
+ " invocation handler!");
+ else
+ stub = (Remote) handler;
+ }
+ }
+
+ // Check RemoteRef in stub is from the expected class
+ // "sun.rmi.server.UnicastRef2".
+ //
+ RemoteRef ref = ((RemoteObject)stub).getRef();
+ if (ref.getClass() != UnicastRef2.class)
+ throw new SecurityException(
+ "Expecting a " + UnicastRef2.class.getName() +
+ " remote reference in stub!");
+
+ // Check RMIClientSocketFactory in stub is from the expected class
+ // "javax.rmi.ssl.SslRMIClientSocketFactory".
+ //
+ LiveRef liveRef = ((UnicastRef2)ref).getLiveRef();
+ RMIClientSocketFactory csf = liveRef.getClientSocketFactory();
+ if (csf == null || csf.getClass() != SslRMIClientSocketFactory.class)
+ throw new SecurityException(
+ "Expecting a " + SslRMIClientSocketFactory.class.getName() +
+ " RMI client socket factory in stub!");
+ }
+
+ //--------------------------------------------------------------------
+ // Private stuff - RMIServer creation
+ //--------------------------------------------------------------------
+
+ private RMIServer findRMIServer(JMXServiceURL directoryURL,
+ Map<String, Object> environment)
+ throws NamingException, IOException {
+
+ String path = directoryURL.getURLPath();
+ int end = path.indexOf(';');
+ if (end < 0) end = path.length();
+ if (path.startsWith("/jndi/"))
+ return findRMIServerJNDI(path.substring(6,end), environment);
+ else if (path.startsWith("/stub/"))
+ return findRMIServerJRMP(path.substring(6,end), environment);
+ else {
+ final String msg = "URL path must begin with /jndi/ or /stub/ " +
+ "or /ior/: " + path;
+ throw new MalformedURLException(msg);
+ }
+ }
+
+ /**
+ * Lookup the RMIServer stub in a directory.
+ * @param jndiURL A JNDI URL indicating the location of the Stub
+ * (see {@link javax.management.remote.rmi}), e.g.:
+ * <ul><li>{@code rmi://registry-host:port/rmi-stub-name}</li>
+ * <li>or {@code ldap://ldap-host:port/java-container-dn}</li>
+ * </ul>
+ * @param env the environment Map passed to the connector.
+ * @return The retrieved RMIServer stub.
+ * @exception NamingException if the stub couldn't be found.
+ **/
+ private RMIServer findRMIServerJNDI(String jndiURL, Map<String, ?> env)
+ throws NamingException {
+
+ InitialContext ctx = new InitialContext(EnvHelp.mapToHashtable(env));
+
+ Object objref = ctx.lookup(jndiURL);
+ ctx.close();
+
+ return narrowJRMPServer(objref);
+ }
+
+ private static RMIServer narrowJRMPServer(Object objref) {
+
+ return (RMIServer) objref;
+ }
+
+ private RMIServer findRMIServerJRMP(String base64, Map<String, ?> env)
+ throws IOException {
+ final byte[] serialized;
+ try {
+ serialized = base64ToByteArray(base64);
+ } catch (IllegalArgumentException e) {
+ throw new MalformedURLException("Bad BASE64 encoding: " +
+ e.getMessage());
+ }
+ final ByteArrayInputStream bin = new ByteArrayInputStream(serialized);
+
+ final ClassLoader loader = EnvHelp.resolveClientClassLoader(env);
+ final ObjectInputStream oin =
+ (loader == null) ?
+ new ObjectInputStream(bin) :
+ new ObjectInputStreamWithLoader(bin, loader);
+ final Object stub;
+ try {
+ stub = oin.readObject();
+ } catch (ClassNotFoundException e) {
+ throw new MalformedURLException("Class not found: " + e);
+ }
+ return (RMIServer)stub;
+ }
+
+ private static final class ObjectInputStreamWithLoader
+ extends ObjectInputStream {
+ ObjectInputStreamWithLoader(InputStream in, ClassLoader cl)
+ throws IOException, IllegalArgumentException {
+ super(in);
+ if (cl == null ) {
+ throw new IllegalArgumentException("class loader is null");
+ }
+ this.loader = cl;
+ }
+
+ @Override
+ protected Class<?> resolveClass(ObjectStreamClass classDesc)
+ throws IOException, ClassNotFoundException {
+ String name = classDesc.getName();
+ ReflectUtil.checkPackageAccess(name);
+ return Class.forName(name, false, Objects.requireNonNull(loader));
+ }
+
+ private final ClassLoader loader;
+ }
+
+ private MBeanServerConnection getConnectionWithSubject(Subject delegationSubject) {
+ MBeanServerConnection conn = null;
+
+ if (delegationSubject == null) {
+ if (nullSubjectConnRef == null
+ || (conn = nullSubjectConnRef.get()) == null) {
+ conn = new RemoteMBeanServerConnection(null);
+ nullSubjectConnRef = new WeakReference<MBeanServerConnection>(conn);
+ }
+ } else {
+ WeakReference<MBeanServerConnection> wr = rmbscMap.get(delegationSubject);
+ if (wr == null || (conn = wr.get()) == null) {
+ conn = new RemoteMBeanServerConnection(delegationSubject);
+ rmbscMap.put(delegationSubject, new WeakReference<MBeanServerConnection>(conn));
+ }
+ }
+ return conn;
+ }
+
+ /*
+ The following section of code avoids a class loading problem
+ with RMI. The problem is that an RMI stub, when deserializing
+ a remote method return value or exception, will first of all
+ consult the first non-bootstrap class loader it finds in the
+ call stack. This can lead to behavior that is not portable
+ between implementations of the JMX Remote API. Notably, an
+ implementation on J2SE 1.4 will find the RMI stub's loader on
+ the stack. But in J2SE 5, this stub is loaded by the
+ bootstrap loader, so RMI will find the loader of the user code
+ that called an MBeanServerConnection method.
+
+ To avoid this problem, we take advantage of what the RMI stub
+ is doing internally. Each remote call will end up calling
+ ref.invoke(...), where ref is the RemoteRef parameter given to
+ the RMI stub's constructor. It is within this call that the
+ deserialization will happen. So we fabricate our own RemoteRef
+ that delegates everything to the "real" one but that is loaded
+ by a class loader that knows no other classes. The class
+ loader NoCallStackClassLoader does this: the RemoteRef is an
+ instance of the class named by proxyRefClassName, which is
+ fabricated by the class loader using byte code that is defined
+ by the string below.
+
+ The call stack when the deserialization happens is thus this:
+ MBeanServerConnection.getAttribute (or whatever)
+ -> RMIConnectionImpl_Stub.getAttribute
+ -> ProxyRef.invoke(...getAttribute...)
+ -> UnicastRef.invoke(...getAttribute...)
+ -> internal RMI stuff
+
+ Here UnicastRef is the RemoteRef created when the stub was
+ deserialized (which is of some RMI internal class). It and the
+ "internal RMI stuff" are loaded by the bootstrap loader, so are
+ transparent to the stack search. The first non-bootstrap
+ loader found is our ProxyRefLoader, as required.
+
+ In a future version of this code as integrated into J2SE 5,
+ this workaround could be replaced by direct access to the
+ internals of RMI. For now, we use the same code base for J2SE
+ and for the standalone Reference Implementation.
+
+ The byte code below encodes the following class, compiled using
+ J2SE 1.4.2 with the -g:none option.
+
+ package jdk.jmx.remote.internal.rmi;
+
+ import java.lang.reflect.Method;
+ import java.rmi.Remote;
+ import java.rmi.server.RemoteRef;
+ import com.sun.jmx.remote.internal.rmi.ProxyRef;
+
+ public class PRef extends ProxyRef {
+ public PRef(RemoteRef ref) {
+ super(ref);
+ }
+
+ public Object invoke(Remote obj, Method method,
+ Object[] params, long opnum)
+ throws Exception {
+ return ref.invoke(obj, method, params, opnum);
+ }
+ }
+ */
+
+ private static final String rmiServerImplStubClassName =
+ RMIServer.class.getName() + "Impl_Stub";
+ private static final Class<?> rmiServerImplStubClass;
+ private static final String rmiConnectionImplStubClassName =
+ RMIConnection.class.getName() + "Impl_Stub";
+ private static final Class<?> rmiConnectionImplStubClass;
+ private static final String pRefClassName =
+ "jdk.jmx.remote.internal.rmi.PRef";
+ private static final Constructor<?> proxyRefConstructor;
+ static {
+ final String pRefByteCodeString =
+ "\312\376\272\276\0\0\0\65\0\27\12\0\5\0\15\11\0\4\0\16\13\0\17"+
+ "\0\20\7\0\21\7\0\22\1\0\6<init>\1\0\36(Ljava/rmi/server/Remote"+
+ "Ref;)V\1\0\4Code\1\0\6invoke\1\0S(Ljava/rmi/Remote;Ljava/lang/"+
+ "reflect/Method;[Ljava/lang/Object;J)Ljava/lang/Object;\1\0\12E"+
+ "xceptions\7\0\23\14\0\6\0\7\14\0\24\0\25\7\0\26\14\0\11\0\12\1"+
+ "\0 jdk/jmx/remote/internal/rmi/PRef\1\0(com/sun/jmx/remote/int"+
+ "ernal/rmi/ProxyRef\1\0\23java/lang/Exception\1\0\3ref\1\0\33Lj"+
+ "ava/rmi/server/RemoteRef;\1\0\31java/rmi/server/RemoteRef\0!\0"+
+ "\4\0\5\0\0\0\0\0\2\0\1\0\6\0\7\0\1\0\10\0\0\0\22\0\2\0\2\0\0\0"+
+ "\6*+\267\0\1\261\0\0\0\0\0\1\0\11\0\12\0\2\0\10\0\0\0\33\0\6\0"+
+ "\6\0\0\0\17*\264\0\2+,-\26\4\271\0\3\6\0\260\0\0\0\0\0\13\0\0\0"+
+ "\4\0\1\0\14\0\0";
+ final byte[] pRefByteCode =
+ NoCallStackClassLoader.stringToBytes(pRefByteCodeString);
+ PrivilegedExceptionAction<Constructor<?>> action =
+ new PrivilegedExceptionAction<Constructor<?>>() {
+ public Constructor<?> run() throws Exception {
+ Class<RMIConnector> thisClass = RMIConnector.class;
+ ClassLoader thisLoader = thisClass.getClassLoader();
+ ProtectionDomain thisProtectionDomain =
+ thisClass.getProtectionDomain();
+
+ String proxyRefCName = ProxyRef.class.getName();
+ ClassLoader cl =
+ new NoCallStackClassLoader(pRefClassName,
+ pRefByteCode,
+ new String[] { proxyRefCName },
+ thisLoader,
+ thisProtectionDomain);
+
+ Module jmxModule = ProxyRef.class.getModule();
+ Module rmiModule = RemoteRef.class.getModule();
+
+ String pkg = packageOf(pRefClassName);
+ assert pkg != null && pkg.length() > 0 && !pkg.equals(packageOf(proxyRefCName));
+ Module m = Modules.defineModule(cl, "jdk.remoteref", Collections.singleton(pkg));
+
+ // jdk.remoteref needs to read to java.base and jmxModule
+ Modules.addReads(m, Object.class.getModule());
+ Modules.addReads(m, jmxModule);
+ Modules.addReads(m, rmiModule);
+
+ // jdk.remoteref needs access to ProxyRef class
+ Modules.addExports(jmxModule, packageOf(proxyRefCName), m);
+
+ // java.management needs to instantiate the fabricated RemoteRef class
+ Modules.addReads(jmxModule, m);
+ Modules.addExports(m, pkg, jmxModule);
+
+ Class<?> c = cl.loadClass(pRefClassName);
+ return c.getConstructor(RemoteRef.class);
+ }
+ };
+
+ Class<?> serverStubClass;
+ try {
+ serverStubClass = Class.forName(rmiServerImplStubClassName);
+ } catch (Exception e) {
+ logger.error("<clinit>",
+ "Failed to instantiate " +
+ rmiServerImplStubClassName + ": " + e);
+ logger.debug("<clinit>",e);
+ serverStubClass = null;
+ }
+ rmiServerImplStubClass = serverStubClass;
+
+ Class<?> stubClass;
+ Constructor<?> constr;
+ try {
+ stubClass = Class.forName(rmiConnectionImplStubClassName);
+ constr = (Constructor<?>) AccessController.doPrivileged(action);
+ } catch (Exception e) {
+ logger.error("<clinit>",
+ "Failed to initialize proxy reference constructor "+
+ "for " + rmiConnectionImplStubClassName + ": " + e);
+ logger.debug("<clinit>",e);
+ stubClass = null;
+ constr = null;
+ }
+ rmiConnectionImplStubClass = stubClass;
+ proxyRefConstructor = constr;
+ }
+
+ private static String packageOf(String cn) {
+ int i = cn.lastIndexOf('.');
+ return i > 0 ? cn.substring(0, i) : "";
+ }
+
+ private static RMIConnection shadowJrmpStub(RemoteObject stub)
+ throws InstantiationException, IllegalAccessException,
+ InvocationTargetException, ClassNotFoundException,
+ NoSuchMethodException {
+ RemoteRef ref = stub.getRef();
+ RemoteRef proxyRef = (RemoteRef)
+ proxyRefConstructor.newInstance(new Object[] {ref});
+ final Constructor<?> rmiConnectionImplStubConstructor =
+ rmiConnectionImplStubClass.getConstructor(RemoteRef.class);
+ Object[] args = {proxyRef};
+ RMIConnection proxyStub = (RMIConnection)
+ rmiConnectionImplStubConstructor.newInstance(args);
+ return proxyStub;
+ }
+
+ private static RMIConnection getConnection(RMIServer server,
+ Object credentials,
+ boolean checkStub)
+ throws IOException {
+ RMIConnection c = server.newClient(credentials);
+ if (checkStub) checkStub(c, rmiConnectionImplStubClass);
+ try {
+ if (c.getClass() == rmiConnectionImplStubClass)
+ return shadowJrmpStub((RemoteObject) c);
+ logger.trace("getConnection",
+ "Did not wrap " + c.getClass() + " to foil " +
+ "stack search for classes: class loading semantics " +
+ "may be incorrect");
+ } catch (Exception e) {
+ logger.error("getConnection",
+ "Could not wrap " + c.getClass() + " to foil " +
+ "stack search for classes: class loading semantics " +
+ "may be incorrect: " + e);
+ logger.debug("getConnection",e);
+ // so just return the original stub, which will work for all
+ // but the most exotic class loading situations
+ }
+ return c;
+ }
+
+ private static byte[] base64ToByteArray(String s) {
+ int sLen = s.length();
+ int numGroups = sLen/4;
+ if (4*numGroups != sLen)
+ throw new IllegalArgumentException(
+ "String length must be a multiple of four.");
+ int missingBytesInLastGroup = 0;
+ int numFullGroups = numGroups;
+ if (sLen != 0) {
+ if (s.charAt(sLen-1) == '=') {
+ missingBytesInLastGroup++;
+ numFullGroups--;
+ }
+ if (s.charAt(sLen-2) == '=')
+ missingBytesInLastGroup++;
+ }
+ byte[] result = new byte[3*numGroups - missingBytesInLastGroup];
+
+ // Translate all full groups from base64 to byte array elements
+ int inCursor = 0, outCursor = 0;
+ for (int i=0; i<numFullGroups; i++) {
+ int ch0 = base64toInt(s.charAt(inCursor++));
+ int ch1 = base64toInt(s.charAt(inCursor++));
+ int ch2 = base64toInt(s.charAt(inCursor++));
+ int ch3 = base64toInt(s.charAt(inCursor++));
+ result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
+ result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
+ result[outCursor++] = (byte) ((ch2 << 6) | ch3);
+ }
+
+ // Translate partial group, if present
+ if (missingBytesInLastGroup != 0) {
+ int ch0 = base64toInt(s.charAt(inCursor++));
+ int ch1 = base64toInt(s.charAt(inCursor++));
+ result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
+
+ if (missingBytesInLastGroup == 1) {
+ int ch2 = base64toInt(s.charAt(inCursor++));
+ result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
+ }
+ }
+ // assert inCursor == s.length()-missingBytesInLastGroup;
+ // assert outCursor == result.length;
+ return result;
+ }
+
+ /**
+ * Translates the specified character, which is assumed to be in the
+ * "Base 64 Alphabet" into its equivalent 6-bit positive integer.
+ *
+ * @throws IllegalArgumentException if
+ * c is not in the Base64 Alphabet.
+ */
+ private static int base64toInt(char c) {
+ int result;
+
+ if (c >= base64ToInt.length)
+ result = -1;
+ else
+ result = base64ToInt[c];
+
+ if (result < 0)
+ throw new IllegalArgumentException("Illegal character " + c);
+ return result;
+ }
+
+ /**
+ * This array is a lookup table that translates unicode characters
+ * drawn from the "Base64 Alphabet" (as specified in Table 1 of RFC 2045)
+ * into their 6-bit positive integer equivalents. Characters that
+ * are not in the Base64 alphabet but fall within the bounds of the
+ * array are translated to -1.
+ */
+ private static final byte base64ToInt[] = {
+ -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, 62, -1, -1, -1, 63, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
+ };
+
+ //--------------------------------------------------------------------
+ // Private stuff - Find / Set default class loader
+ //--------------------------------------------------------------------
+ private ClassLoader pushDefaultClassLoader() {
+ final Thread t = Thread.currentThread();
+ final ClassLoader old = t.getContextClassLoader();
+ if (defaultClassLoader != null)
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
+ t.setContextClassLoader(defaultClassLoader);
+ return null;
+ }
+ });
+ return old;
+ }
+
+ private void popDefaultClassLoader(final ClassLoader old) {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
+ Thread.currentThread().setContextClassLoader(old);
+ return null;
+ }
+ });
+ }
+
+ //--------------------------------------------------------------------
+ // Private variables
+ //--------------------------------------------------------------------
+ /**
+ * @serial The RMIServer stub of the RMI JMX Connector server to
+ * which this client connector is (or will be) connected. This
+ * field can be null when <var>jmxServiceURL</var> is not
+ * null. This includes the case where <var>jmxServiceURL</var>
+ * contains a serialized RMIServer stub. If both
+ * <var>rmiServer</var> and <var>jmxServiceURL</var> are null then
+ * serialization will fail.
+ *
+ * @see #RMIConnector(RMIServer,Map)
+ **/
+ private final RMIServer rmiServer;
+
+ /**
+ * @serial The JMXServiceURL of the RMI JMX Connector server to
+ * which this client connector will be connected. This field can
+ * be null when <var>rmiServer</var> is not null. If both
+ * <var>rmiServer</var> and <var>jmxServiceURL</var> are null then
+ * serialization will fail.
+ *
+ * @see #RMIConnector(JMXServiceURL,Map)
+ **/
+ private final JMXServiceURL jmxServiceURL;
+
+ // ---------------------------------------------------------
+ // WARNING - WARNING - WARNING - WARNING - WARNING - WARNING
+ // ---------------------------------------------------------
+ // Any transient variable which needs to be initialized should
+ // be initialized in the method initTransient()
+ private transient Map<String, Object> env;
+ private transient ClassLoader defaultClassLoader;
+ private transient RMIConnection connection;
+ private transient String connectionId;
+
+ private transient long clientNotifSeqNo = 0;
+
+ private transient WeakHashMap<Subject, WeakReference<MBeanServerConnection>> rmbscMap;
+ private transient WeakReference<MBeanServerConnection> nullSubjectConnRef = null;
+
+ private transient RMINotifClient rmiNotifClient;
+ // = new RMINotifClient(new Integer(0));
+
+ private transient long clientNotifCounter = 0;
+
+ private transient boolean connected;
+ // = false;
+ private transient boolean terminated;
+ // = false;
+
+ private transient Exception closeException;
+
+ private transient NotificationBroadcasterSupport connectionBroadcaster;
+
+ private transient ClientCommunicatorAdmin communicatorAdmin;
+
+ /**
+ * A static WeakReference to an {@link org.omg.CORBA.ORB ORB} to
+ * connect unconnected stubs.
+ **/
+ private static volatile WeakReference<Object> orb = null;
+
+ // TRACES & DEBUG
+ //---------------
+ private static String objects(final Object[] objs) {
+ if (objs == null)
+ return "null";
+ else
+ return Arrays.asList(objs).toString();
+ }
+
+ private static String strings(final String[] strs) {
+ return objects(strs);
+ }
+
+ static String getAttributesNames(AttributeList attributes) {
+ return attributes != null ?
+ attributes.asList().stream()
+ .map(Attribute::getName)
+ .collect(Collectors.joining(", ", "[", "]"))
+ : "[]";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIConnectorServer.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,819 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 javax.management.remote.rmi;
+
+
+import com.sun.jmx.remote.security.MBeanServerFileAccessController;
+import com.sun.jmx.remote.util.ClassLogger;
+import com.sun.jmx.remote.util.EnvHelp;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.net.MalformedURLException;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanServer;
+import javax.management.remote.JMXAuthenticator;
+
+import javax.management.remote.JMXConnectionNotification;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.MBeanServerForwarder;
+
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+/**
+ * <p>A JMX API connector server that creates RMI-based connections
+ * from remote clients. Usually, such connector servers are made
+ * using {@link javax.management.remote.JMXConnectorServerFactory
+ * JMXConnectorServerFactory}. However, specialized applications can
+ * use this class directly, for example with an {@link RMIServerImpl}
+ * object.</p>
+ *
+ * @since 1.5
+ */
+public class RMIConnectorServer extends JMXConnectorServer {
+ /**
+ * <p>Name of the attribute that specifies whether the {@link
+ * RMIServer} stub that represents an RMI connector server should
+ * override an existing stub at the same address. The value
+ * associated with this attribute, if any, should be a string that
+ * is equal, ignoring case, to <code>"true"</code> or
+ * <code>"false"</code>. The default value is false.</p>
+ */
+ public static final String JNDI_REBIND_ATTRIBUTE =
+ "jmx.remote.jndi.rebind";
+
+ /**
+ * <p>Name of the attribute that specifies the {@link
+ * RMIClientSocketFactory} for the RMI objects created in
+ * conjunction with this connector. The value associated with this
+ * attribute must be of type <code>RMIClientSocketFactory</code> and can
+ * only be specified in the <code>Map</code> argument supplied when
+ * creating a connector server.</p>
+ */
+ public static final String RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE =
+ "jmx.remote.rmi.client.socket.factory";
+
+ /**
+ * <p>Name of the attribute that specifies the {@link
+ * RMIServerSocketFactory} for the RMI objects created in
+ * conjunction with this connector. The value associated with this
+ * attribute must be of type <code>RMIServerSocketFactory</code> and can
+ * only be specified in the <code>Map</code> argument supplied when
+ * creating a connector server.</p>
+ */
+ public static final String RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE =
+ "jmx.remote.rmi.server.socket.factory";
+
+ /**
+ * Name of the attribute that specifies a list of class names acceptable
+ * as parameters to the {@link RMIServer#newClient(java.lang.Object) RMIServer.newClient()}
+ * remote method call.
+ * <p>
+ * This list of classes should correspond to the transitive closure of the
+ * credentials class (or classes) used by the installed {@linkplain JMXAuthenticator}
+ * associated with the {@linkplain RMIServer} implementation.
+ * <p>
+ * If the attribute is not set, or is null, then any class is
+ * deemed acceptable.
+ */
+ public static final String CREDENTIAL_TYPES =
+ "jmx.remote.rmi.server.credential.types";
+
+ /**
+ * <p>Makes an <code>RMIConnectorServer</code>.
+ * This is equivalent to calling {@link #RMIConnectorServer(
+ * JMXServiceURL,Map,RMIServerImpl,MBeanServer)
+ * RMIConnectorServer(directoryURL,environment,null,null)}</p>
+ *
+ * @param url the URL defining how to create the connector server.
+ * Cannot be null.
+ *
+ * @param environment attributes governing the creation and
+ * storing of the RMI object. Can be null, which is equivalent to
+ * an empty Map.
+ *
+ * @exception IllegalArgumentException if <code>url</code> is null.
+ *
+ * @exception MalformedURLException if <code>url</code> does not
+ * conform to the syntax for an RMI connector, or if its protocol
+ * is not recognized by this implementation. Only "rmi" is valid when
+ * this constructor is used.
+ *
+ * @exception IOException if the connector server cannot be created
+ * for some reason or if it is inevitable that its {@link #start()
+ * start} method will fail.
+ */
+ public RMIConnectorServer(JMXServiceURL url, Map<String,?> environment)
+ throws IOException {
+ this(url, environment, (MBeanServer) null);
+ }
+
+ /**
+ * <p>Makes an <code>RMIConnectorServer</code> for the given MBean
+ * server.
+ * This is equivalent to calling {@link #RMIConnectorServer(
+ * JMXServiceURL,Map,RMIServerImpl,MBeanServer)
+ * RMIConnectorServer(directoryURL,environment,null,mbeanServer)}</p>
+ *
+ * @param url the URL defining how to create the connector server.
+ * Cannot be null.
+ *
+ * @param environment attributes governing the creation and
+ * storing of the RMI object. Can be null, which is equivalent to
+ * an empty Map.
+ *
+ * @param mbeanServer the MBean server to which the new connector
+ * server is attached, or null if it will be attached by being
+ * registered as an MBean in the MBean server.
+ *
+ * @exception IllegalArgumentException if <code>url</code> is null.
+ *
+ * @exception MalformedURLException if <code>url</code> does not
+ * conform to the syntax for an RMI connector, or if its protocol
+ * is not recognized by this implementation. Only "rmi" is valid
+ * when this constructor is used.
+ *
+ * @exception IOException if the connector server cannot be created
+ * for some reason or if it is inevitable that its {@link #start()
+ * start} method will fail.
+ */
+ public RMIConnectorServer(JMXServiceURL url, Map<String,?> environment,
+ MBeanServer mbeanServer)
+ throws IOException {
+ this(url, environment, (RMIServerImpl) null, mbeanServer);
+ }
+
+ /**
+ * <p>Makes an <code>RMIConnectorServer</code> for the given MBean
+ * server.</p>
+ *
+ * @param url the URL defining how to create the connector server.
+ * Cannot be null.
+ *
+ * @param environment attributes governing the creation and
+ * storing of the RMI object. Can be null, which is equivalent to
+ * an empty Map.
+ *
+ * @param rmiServerImpl An implementation of the RMIServer interface,
+ * consistent with the protocol type specified in <var>url</var>.
+ * If this parameter is non null, the protocol type specified by
+ * <var>url</var> is not constrained, and is assumed to be valid.
+ * Otherwise, only "rmi" will be recognized.
+ *
+ * @param mbeanServer the MBean server to which the new connector
+ * server is attached, or null if it will be attached by being
+ * registered as an MBean in the MBean server.
+ *
+ * @exception IllegalArgumentException if <code>url</code> is null.
+ *
+ * @exception MalformedURLException if <code>url</code> does not
+ * conform to the syntax for an RMI connector, or if its protocol
+ * is not recognized by this implementation. Only "rmi" is recognized
+ * when <var>rmiServerImpl</var> is null.
+ *
+ * @exception IOException if the connector server cannot be created
+ * for some reason or if it is inevitable that its {@link #start()
+ * start} method will fail.
+ *
+ * @see #start
+ */
+ public RMIConnectorServer(JMXServiceURL url, Map<String,?> environment,
+ RMIServerImpl rmiServerImpl,
+ MBeanServer mbeanServer)
+ throws IOException {
+ super(mbeanServer);
+
+ if (url == null) throw new
+ IllegalArgumentException("Null JMXServiceURL");
+ if (rmiServerImpl == null) {
+ final String prt = url.getProtocol();
+ if (prt == null || !(prt.equals("rmi"))) {
+ final String msg = "Invalid protocol type: " + prt;
+ throw new MalformedURLException(msg);
+ }
+ final String urlPath = url.getURLPath();
+ if (!urlPath.equals("")
+ && !urlPath.equals("/")
+ && !urlPath.startsWith("/jndi/")) {
+ final String msg = "URL path must be empty or start with " +
+ "/jndi/";
+ throw new MalformedURLException(msg);
+ }
+ }
+
+ if (environment == null)
+ this.attributes = Collections.emptyMap();
+ else {
+ EnvHelp.checkAttributes(environment);
+ this.attributes = Collections.unmodifiableMap(environment);
+ }
+
+ this.address = url;
+ this.rmiServerImpl = rmiServerImpl;
+ }
+
+ /**
+ * <p>Returns a client stub for this connector server. A client
+ * stub is a serializable object whose {@link
+ * JMXConnector#connect(Map) connect} method can be used to make
+ * one new connection to this connector server.</p>
+ *
+ * @param env client connection parameters of the same sort that
+ * could be provided to {@link JMXConnector#connect(Map)
+ * JMXConnector.connect(Map)}. Can be null, which is equivalent
+ * to an empty map.
+ *
+ * @return a client stub that can be used to make a new connection
+ * to this connector server.
+ *
+ * @exception UnsupportedOperationException if this connector
+ * server does not support the generation of client stubs.
+ *
+ * @exception IllegalStateException if the JMXConnectorServer is
+ * not started (see {@link #isActive()}).
+ *
+ * @exception IOException if a communications problem means that a
+ * stub cannot be created.
+ **/
+ public JMXConnector toJMXConnector(Map<String,?> env) throws IOException {
+ // The serialized for of rmiServerImpl is automatically
+ // a RMI server stub.
+ if (!isActive()) throw new
+ IllegalStateException("Connector is not active");
+
+ // Merge maps
+ Map<String, Object> usemap = new HashMap<String, Object>(
+ (this.attributes==null)?Collections.<String, Object>emptyMap():
+ this.attributes);
+
+ if (env != null) {
+ EnvHelp.checkAttributes(env);
+ usemap.putAll(env);
+ }
+
+ usemap = EnvHelp.filterAttributes(usemap);
+
+ final RMIServer stub=(RMIServer)rmiServerImpl.toStub();
+
+ return new RMIConnector(stub, usemap);
+ }
+
+ /**
+ * <p>Activates the connector server, that is starts listening for
+ * client connections. Calling this method when the connector
+ * server is already active has no effect. Calling this method
+ * when the connector server has been stopped will generate an
+ * <code>IOException</code>.</p>
+ *
+ * <p>The behavior of this method when called for the first time
+ * depends on the parameters that were supplied at construction,
+ * as described below.</p>
+ *
+ * <p>First, an object of a subclass of {@link RMIServerImpl} is
+ * required, to export the connector server through RMI:</p>
+ *
+ * <ul>
+ *
+ * <li>If an <code>RMIServerImpl</code> was supplied to the
+ * constructor, it is used.
+ *
+ * <li>Otherwise, if the <code>JMXServiceURL</code>
+ * was null, or its protocol part was <code>rmi</code>, an object
+ * of type {@link RMIJRMPServerImpl} is created.
+ *
+ * <li>Otherwise, the implementation can create an
+ * implementation-specific {@link RMIServerImpl} or it can throw
+ * {@link MalformedURLException}.
+ *
+ * </ul>
+ *
+ * <p>If the given address includes a JNDI directory URL as
+ * specified in the package documentation for {@link
+ * javax.management.remote.rmi}, then this
+ * <code>RMIConnectorServer</code> will bootstrap by binding the
+ * <code>RMIServerImpl</code> to the given address.</p>
+ *
+ * <p>If the URL path part of the <code>JMXServiceURL</code> was
+ * empty or a single slash (<code>/</code>), then the RMI object
+ * will not be bound to a directory. Instead, a reference to it
+ * will be encoded in the URL path of the RMIConnectorServer
+ * address (returned by {@link #getAddress()}). The encodings for
+ * <code>rmi</code> are described in the package documentation for
+ * {@link javax.management.remote.rmi}.</p>
+ *
+ * <p>The behavior when the URL path is neither empty nor a JNDI
+ * directory URL, or when the protocol is not <code>rmi</code>,
+ * is implementation defined, and may include throwing
+ * {@link MalformedURLException} when the connector server is created
+ * or when it is started.</p>
+ *
+ * @exception IllegalStateException if the connector server has
+ * not been attached to an MBean server.
+ * @exception IOException if the connector server cannot be
+ * started.
+ */
+ public synchronized void start() throws IOException {
+ final boolean tracing = logger.traceOn();
+
+ if (state == STARTED) {
+ if (tracing) logger.trace("start", "already started");
+ return;
+ } else if (state == STOPPED) {
+ if (tracing) logger.trace("start", "already stopped");
+ throw new IOException("The server has been stopped.");
+ }
+
+ if (getMBeanServer() == null)
+ throw new IllegalStateException("This connector server is not " +
+ "attached to an MBean server");
+
+ // Check the internal access file property to see
+ // if an MBeanServerForwarder is to be provided
+ //
+ if (attributes != null) {
+ // Check if access file property is specified
+ //
+ String accessFile =
+ (String) attributes.get("jmx.remote.x.access.file");
+ if (accessFile != null) {
+ // Access file property specified, create an instance
+ // of the MBeanServerFileAccessController class
+ //
+ MBeanServerForwarder mbsf;
+ try {
+ mbsf = new MBeanServerFileAccessController(accessFile);
+ } catch (IOException e) {
+ throw EnvHelp.initCause(
+ new IllegalArgumentException(e.getMessage()), e);
+ }
+ // Set the MBeanServerForwarder
+ //
+ setMBeanServerForwarder(mbsf);
+ }
+ }
+
+ try {
+ if (tracing) logger.trace("start", "setting default class loader");
+ defaultClassLoader = EnvHelp.resolveServerClassLoader(
+ attributes, getMBeanServer());
+ } catch (InstanceNotFoundException infc) {
+ IllegalArgumentException x = new
+ IllegalArgumentException("ClassLoader not found: "+infc);
+ throw EnvHelp.initCause(x,infc);
+ }
+
+ if (tracing) logger.trace("start", "setting RMIServer object");
+ final RMIServerImpl rmiServer;
+
+ if (rmiServerImpl != null)
+ rmiServer = rmiServerImpl;
+ else
+ rmiServer = newServer();
+
+ rmiServer.setMBeanServer(getMBeanServer());
+ rmiServer.setDefaultClassLoader(defaultClassLoader);
+ rmiServer.setRMIConnectorServer(this);
+ rmiServer.export();
+
+ try {
+ if (tracing) logger.trace("start", "getting RMIServer object to export");
+ final RMIServer objref = objectToBind(rmiServer, attributes);
+
+ if (address != null && address.getURLPath().startsWith("/jndi/")) {
+ final String jndiUrl = address.getURLPath().substring(6);
+
+ if (tracing)
+ logger.trace("start", "Using external directory: " + jndiUrl);
+
+ String stringBoolean = (String) attributes.get(JNDI_REBIND_ATTRIBUTE);
+ final boolean rebind = EnvHelp.computeBooleanFromString( stringBoolean );
+
+ if (tracing)
+ logger.trace("start", JNDI_REBIND_ATTRIBUTE + "=" + rebind);
+
+ try {
+ if (tracing) logger.trace("start", "binding to " + jndiUrl);
+
+ final Hashtable<?, ?> usemap = EnvHelp.mapToHashtable(attributes);
+
+ bind(jndiUrl, usemap, objref, rebind);
+
+ boundJndiUrl = jndiUrl;
+ } catch (NamingException e) {
+ // fit e in the nested exception if we are on 1.4
+ throw newIOException("Cannot bind to URL ["+jndiUrl+"]: "
+ + e, e);
+ }
+ } else {
+ // if jndiURL is null, we must encode the stub into the URL.
+ if (tracing) logger.trace("start", "Encoding URL");
+
+ encodeStubInAddress(objref, attributes);
+
+ if (tracing) logger.trace("start", "Encoded URL: " + this.address);
+ }
+ } catch (Exception e) {
+ try {
+ rmiServer.close();
+ } catch (Exception x) {
+ // OK: we are already throwing another exception
+ }
+ if (e instanceof RuntimeException)
+ throw (RuntimeException) e;
+ else if (e instanceof IOException)
+ throw (IOException) e;
+ else
+ throw newIOException("Got unexpected exception while " +
+ "starting the connector server: "
+ + e, e);
+ }
+
+ rmiServerImpl = rmiServer;
+
+ synchronized(openedServers) {
+ openedServers.add(this);
+ }
+
+ state = STARTED;
+
+ if (tracing) {
+ logger.trace("start", "Connector Server Address = " + address);
+ logger.trace("start", "started.");
+ }
+ }
+
+ /**
+ * <p>Deactivates the connector server, that is, stops listening for
+ * client connections. Calling this method will also close all
+ * client connections that were made by this server. After this
+ * method returns, whether normally or with an exception, the
+ * connector server will not create any new client
+ * connections.</p>
+ *
+ * <p>Once a connector server has been stopped, it cannot be started
+ * again.</p>
+ *
+ * <p>Calling this method when the connector server has already
+ * been stopped has no effect. Calling this method when the
+ * connector server has not yet been started will disable the
+ * connector server object permanently.</p>
+ *
+ * <p>If closing a client connection produces an exception, that
+ * exception is not thrown from this method. A {@link
+ * JMXConnectionNotification} is emitted from this MBean with the
+ * connection ID of the connection that could not be closed.</p>
+ *
+ * <p>Closing a connector server is a potentially slow operation.
+ * For example, if a client machine with an open connection has
+ * crashed, the close operation might have to wait for a network
+ * protocol timeout. Callers that do not want to block in a close
+ * operation should do it in a separate thread.</p>
+ *
+ * <p>This method calls the method {@link RMIServerImpl#close()
+ * close} on the connector server's <code>RMIServerImpl</code>
+ * object.</p>
+ *
+ * <p>If the <code>RMIServerImpl</code> was bound to a JNDI
+ * directory by the {@link #start() start} method, it is unbound
+ * from the directory by this method.</p>
+ *
+ * @exception IOException if the server cannot be closed cleanly,
+ * or if the <code>RMIServerImpl</code> cannot be unbound from the
+ * directory. When this exception is thrown, the server has
+ * already attempted to close all client connections, if
+ * appropriate; to call {@link RMIServerImpl#close()}; and to
+ * unbind the <code>RMIServerImpl</code> from its directory, if
+ * appropriate. All client connections are closed except possibly
+ * those that generated exceptions when the server attempted to
+ * close them.
+ */
+ public void stop() throws IOException {
+ final boolean tracing = logger.traceOn();
+
+ synchronized (this) {
+ if (state == STOPPED) {
+ if (tracing) logger.trace("stop","already stopped.");
+ return;
+ } else if (state == CREATED) {
+ if (tracing) logger.trace("stop","not started yet.");
+ }
+
+ if (tracing) logger.trace("stop", "stopping.");
+ state = STOPPED;
+ }
+
+ synchronized(openedServers) {
+ openedServers.remove(this);
+ }
+
+ IOException exception = null;
+
+ // rmiServerImpl can be null if stop() called without start()
+ if (rmiServerImpl != null) {
+ try {
+ if (tracing) logger.trace("stop", "closing RMI server.");
+ rmiServerImpl.close();
+ } catch (IOException e) {
+ if (tracing) logger.trace("stop", "failed to close RMI server: " + e);
+ if (logger.debugOn()) logger.debug("stop",e);
+ exception = e;
+ }
+ }
+
+ if (boundJndiUrl != null) {
+ try {
+ if (tracing)
+ logger.trace("stop",
+ "unbind from external directory: " + boundJndiUrl);
+
+ final Hashtable<?, ?> usemap = EnvHelp.mapToHashtable(attributes);
+
+ InitialContext ctx =
+ new InitialContext(usemap);
+
+ ctx.unbind(boundJndiUrl);
+
+ ctx.close();
+ } catch (NamingException e) {
+ if (tracing) logger.trace("stop", "failed to unbind RMI server: "+e);
+ if (logger.debugOn()) logger.debug("stop",e);
+ // fit e in as the nested exception if we are on 1.4
+ if (exception == null)
+ exception = newIOException("Cannot bind to URL: " + e, e);
+ }
+ }
+
+ if (exception != null) throw exception;
+
+ if (tracing) logger.trace("stop", "stopped");
+ }
+
+ public synchronized boolean isActive() {
+ return (state == STARTED);
+ }
+
+ public JMXServiceURL getAddress() {
+ if (!isActive())
+ return null;
+ return address;
+ }
+
+ public Map<String,?> getAttributes() {
+ Map<String, ?> map = EnvHelp.filterAttributes(attributes);
+ return Collections.unmodifiableMap(map);
+ }
+
+ @Override
+ public synchronized
+ void setMBeanServerForwarder(MBeanServerForwarder mbsf) {
+ super.setMBeanServerForwarder(mbsf);
+ if (rmiServerImpl != null)
+ rmiServerImpl.setMBeanServer(getMBeanServer());
+ }
+
+ /* We repeat the definitions of connection{Opened,Closed,Failed}
+ here so that they are accessible to other classes in this package
+ even though they have protected access. */
+
+ @Override
+ protected void connectionOpened(String connectionId, String message,
+ Object userData) {
+ super.connectionOpened(connectionId, message, userData);
+ }
+
+ @Override
+ protected void connectionClosed(String connectionId, String message,
+ Object userData) {
+ super.connectionClosed(connectionId, message, userData);
+ }
+
+ @Override
+ protected void connectionFailed(String connectionId, String message,
+ Object userData) {
+ super.connectionFailed(connectionId, message, userData);
+ }
+
+ /**
+ * Bind a stub to a registry.
+ * @param jndiUrl URL of the stub in the registry, extracted
+ * from the <code>JMXServiceURL</code>.
+ * @param attributes A Hashtable containing environment parameters,
+ * built from the Map specified at this object creation.
+ * @param rmiServer The object to bind in the registry
+ * @param rebind true if the object must be rebound.
+ **/
+ void bind(String jndiUrl, Hashtable<?, ?> attributes,
+ RMIServer rmiServer, boolean rebind)
+ throws NamingException, MalformedURLException {
+ // if jndiURL is not null, we nust bind the stub to a
+ // directory.
+ InitialContext ctx =
+ new InitialContext(attributes);
+
+ if (rebind)
+ ctx.rebind(jndiUrl, rmiServer);
+ else
+ ctx.bind(jndiUrl, rmiServer);
+ ctx.close();
+ }
+
+ /**
+ * Creates a new RMIServerImpl.
+ **/
+ RMIServerImpl newServer() throws IOException {
+ final int port;
+ if (address == null)
+ port = 0;
+ else
+ port = address.getPort();
+
+ return newJRMPServer(attributes, port);
+ }
+
+ /**
+ * Encode a stub into the JMXServiceURL.
+ * @param rmiServer The stub object to encode in the URL
+ * @param attributes A Map containing environment parameters,
+ * built from the Map specified at this object creation.
+ **/
+ private void encodeStubInAddress(
+ RMIServer rmiServer, Map<String, ?> attributes)
+ throws IOException {
+
+ final String protocol, host;
+ final int port;
+
+ if (address == null) {
+ protocol = "rmi";
+ host = null; // will default to local host name
+ port = 0;
+ } else {
+ protocol = address.getProtocol();
+ host = (address.getHost().equals("")) ? null : address.getHost();
+ port = address.getPort();
+ }
+
+ final String urlPath = encodeStub(rmiServer, attributes);
+
+ address = new JMXServiceURL(protocol, host, port, urlPath);
+ }
+
+ /**
+ * Returns the IOR of the given rmiServer.
+ **/
+ static String encodeStub(
+ RMIServer rmiServer, Map<String, ?> env) throws IOException {
+ return "/stub/" + encodeJRMPStub(rmiServer, env);
+ }
+
+ static String encodeJRMPStub(
+ RMIServer rmiServer, Map<String, ?> env)
+ throws IOException {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ ObjectOutputStream oout = new ObjectOutputStream(bout);
+ oout.writeObject(rmiServer);
+ oout.close();
+ byte[] bytes = bout.toByteArray();
+ return byteArrayToBase64(bytes);
+ }
+
+ /**
+ * Object that we will bind to the registry.
+ * This object is a stub connected to our RMIServerImpl.
+ **/
+ private static RMIServer objectToBind(
+ RMIServerImpl rmiServer, Map<String, ?> env)
+ throws IOException {
+ return (RMIServer)rmiServer.toStub();
+ }
+
+ private static RMIServerImpl newJRMPServer(Map<String, ?> env, int port)
+ throws IOException {
+ RMIClientSocketFactory csf = (RMIClientSocketFactory)
+ env.get(RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE);
+ RMIServerSocketFactory ssf = (RMIServerSocketFactory)
+ env.get(RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE);
+ return new RMIJRMPServerImpl(port, csf, ssf, env);
+ }
+
+ private static String byteArrayToBase64(byte[] a) {
+ int aLen = a.length;
+ int numFullGroups = aLen/3;
+ int numBytesInPartialGroup = aLen - 3*numFullGroups;
+ int resultLen = 4*((aLen + 2)/3);
+ final StringBuilder result = new StringBuilder(resultLen);
+
+ // Translate all full groups from byte array elements to Base64
+ int inCursor = 0;
+ for (int i=0; i<numFullGroups; i++) {
+ int byte0 = a[inCursor++] & 0xff;
+ int byte1 = a[inCursor++] & 0xff;
+ int byte2 = a[inCursor++] & 0xff;
+ result.append(intToAlpha[byte0 >> 2]);
+ result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
+ result.append(intToAlpha[(byte1 << 2)&0x3f | (byte2 >> 6)]);
+ result.append(intToAlpha[byte2 & 0x3f]);
+ }
+
+ // Translate partial group if present
+ if (numBytesInPartialGroup != 0) {
+ int byte0 = a[inCursor++] & 0xff;
+ result.append(intToAlpha[byte0 >> 2]);
+ if (numBytesInPartialGroup == 1) {
+ result.append(intToAlpha[(byte0 << 4) & 0x3f]);
+ result.append("==");
+ } else {
+ // assert numBytesInPartialGroup == 2;
+ int byte1 = a[inCursor++] & 0xff;
+ result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
+ result.append(intToAlpha[(byte1 << 2)&0x3f]);
+ result.append('=');
+ }
+ }
+ // assert inCursor == a.length;
+ // assert result.length() == resultLen;
+ return result.toString();
+ }
+
+ /**
+ * This array is a lookup table that translates 6-bit positive integer
+ * index values into their "Base64 Alphabet" equivalents as specified
+ * in Table 1 of RFC 2045.
+ */
+ private static final char intToAlpha[] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
+ };
+
+ /**
+ * Construct a new IOException with a nested exception.
+ * The nested exception is set only if JDK {@literal >= 1.4}
+ */
+ private static IOException newIOException(String message,
+ Throwable cause) {
+ final IOException x = new IOException(message);
+ return EnvHelp.initCause(x,cause);
+ }
+
+
+ // Private variables
+ // -----------------
+
+ private static ClassLogger logger =
+ new ClassLogger("javax.management.remote.rmi", "RMIConnectorServer");
+
+ private JMXServiceURL address;
+ private RMIServerImpl rmiServerImpl;
+ private final Map<String, ?> attributes;
+ private ClassLoader defaultClassLoader = null;
+
+ private String boundJndiUrl;
+
+ // state
+ private static final int CREATED = 0;
+ private static final int STARTED = 1;
+ private static final int STOPPED = 2;
+
+ private int state = CREATED;
+ private final static Set<RMIConnectorServer> openedServers =
+ new HashSet<RMIConnectorServer>();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIIIOPServerImpl.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2003, 2015, 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 javax.management.remote.rmi;
+
+import java.io.IOException;
+import java.rmi.Remote;
+import java.util.Map;
+import javax.security.auth.Subject;
+
+/**
+ * <p>An {@link RMIServerImpl} that is exported through IIOP and that
+ * creates client connections as RMI objects exported through IIOP.
+ * User code does not usually reference this class directly.</p>
+ *
+ * @see RMIServerImpl
+ *
+ * @since 1.5
+ * @deprecated This transport is no longer supported.
+ */
+@Deprecated
+public class RMIIIOPServerImpl extends RMIServerImpl {
+ /**
+ * Throws {@linkplain UnsupportedOperationException}
+ *
+ * @param env the environment containing attributes for the new
+ * <code>RMIServerImpl</code>. Can be null, which is equivalent
+ * to an empty Map.
+ *
+ * @throws IOException if the RMI object cannot be created.
+ */
+ public RMIIIOPServerImpl(Map<String,?> env)
+ throws IOException {
+ super(env);
+
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected void export() throws IOException {
+ throw new UnsupportedOperationException("Method not supported. JMX RMI-IIOP is deprecated");
+ }
+
+ @Override
+ protected String getProtocol() {
+ return "iiop";
+ }
+
+ @Override
+ public Remote toStub() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected RMIConnection makeClient(String connectionId, Subject subject)
+ throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected void closeClient(RMIConnection client) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected void closeServer() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ RMIConnection doNewClient(final Object credentials) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 javax.management.remote.rmi;
+
+import java.io.IOException;
+import java.rmi.NoSuchObjectException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.rmi.server.UnicastRemoteObject;
+import java.rmi.server.RemoteObject;
+import java.util.Map;
+import java.util.Collections;
+import javax.security.auth.Subject;
+
+import com.sun.jmx.remote.internal.rmi.RMIExporter;
+import com.sun.jmx.remote.util.EnvHelp;
+import java.io.ObjectStreamClass;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import sun.reflect.misc.ReflectUtil;
+import sun.rmi.server.DeserializationChecker;
+import sun.rmi.server.UnicastServerRef;
+import sun.rmi.server.UnicastServerRef2;
+
+/**
+ * <p>An {@link RMIServer} object that is exported through JRMP and that
+ * creates client connections as RMI objects exported through JRMP.
+ * User code does not usually reference this class directly.</p>
+ *
+ * @see RMIServerImpl
+ *
+ * @since 1.5
+ */
+public class RMIJRMPServerImpl extends RMIServerImpl {
+
+ private final ExportedWrapper exportedWrapper;
+
+ /**
+ * <p>Creates a new {@link RMIServer} object that will be exported
+ * on the given port using the given socket factories.</p>
+ *
+ * @param port the port on which this object and the {@link
+ * RMIConnectionImpl} objects it creates will be exported. Can be
+ * zero, to indicate any available port.
+ *
+ * @param csf the client socket factory for the created RMI
+ * objects. Can be null.
+ *
+ * @param ssf the server socket factory for the created RMI
+ * objects. Can be null.
+ *
+ * @param env the environment map. Can be null.
+ *
+ * @exception IOException if the {@link RMIServer} object
+ * cannot be created.
+ *
+ * @exception IllegalArgumentException if <code>port</code> is
+ * negative.
+ */
+ public RMIJRMPServerImpl(int port,
+ RMIClientSocketFactory csf,
+ RMIServerSocketFactory ssf,
+ Map<String,?> env)
+ throws IOException {
+
+ super(env);
+
+ if (port < 0)
+ throw new IllegalArgumentException("Negative port: " + port);
+
+ this.port = port;
+ this.csf = csf;
+ this.ssf = ssf;
+ this.env = (env == null) ? Collections.<String, Object>emptyMap() : env;
+
+ String[] credentialsTypes
+ = (String[]) this.env.get(RMIConnectorServer.CREDENTIAL_TYPES);
+ List<String> types = null;
+ if (credentialsTypes != null) {
+ types = new ArrayList<>();
+ for (String type : credentialsTypes) {
+ if (type == null) {
+ throw new IllegalArgumentException("A credential type is null.");
+ }
+ ReflectUtil.checkPackageAccess(type);
+ types.add(type);
+ }
+ }
+ exportedWrapper = types != null ?
+ new ExportedWrapper(this, types) :
+ null;
+ }
+
+ protected void export() throws IOException {
+ if (exportedWrapper != null) {
+ export(exportedWrapper);
+ } else {
+ export(this);
+ }
+ }
+
+ private void export(Remote obj) throws RemoteException {
+ final RMIExporter exporter =
+ (RMIExporter) env.get(RMIExporter.EXPORTER_ATTRIBUTE);
+ final boolean daemon = EnvHelp.isServerDaemon(env);
+
+ if (daemon && exporter != null) {
+ throw new IllegalArgumentException("If "+EnvHelp.JMX_SERVER_DAEMON+
+ " is specified as true, "+RMIExporter.EXPORTER_ATTRIBUTE+
+ " cannot be used to specify an exporter!");
+ }
+
+ if (daemon) {
+ if (csf == null && ssf == null) {
+ new UnicastServerRef(port).exportObject(obj, null, true);
+ } else {
+ new UnicastServerRef2(port, csf, ssf).exportObject(obj, null, true);
+ }
+ } else if (exporter != null) {
+ exporter.exportObject(obj, port, csf, ssf);
+ } else {
+ UnicastRemoteObject.exportObject(obj, port, csf, ssf);
+ }
+ }
+
+ private void unexport(Remote obj, boolean force)
+ throws NoSuchObjectException {
+ RMIExporter exporter =
+ (RMIExporter) env.get(RMIExporter.EXPORTER_ATTRIBUTE);
+ if (exporter == null)
+ UnicastRemoteObject.unexportObject(obj, force);
+ else
+ exporter.unexportObject(obj, force);
+ }
+
+ protected String getProtocol() {
+ return "rmi";
+ }
+
+ /**
+ * <p>Returns a serializable stub for this {@link RMIServer} object.</p>
+ *
+ * @return a serializable stub.
+ *
+ * @exception IOException if the stub cannot be obtained - e.g the
+ * RMIJRMPServerImpl has not been exported yet.
+ */
+ public Remote toStub() throws IOException {
+ if (exportedWrapper != null) {
+ return RemoteObject.toStub(exportedWrapper);
+ } else {
+ return RemoteObject.toStub(this);
+ }
+ }
+
+ /**
+ * <p>Creates a new client connection as an RMI object exported
+ * through JRMP. The port and socket factories for the new
+ * {@link RMIConnection} object are the ones supplied
+ * to the <code>RMIJRMPServerImpl</code> constructor.</p>
+ *
+ * @param connectionId the ID of the new connection. Every
+ * connection opened by this connector server will have a
+ * different id. The behavior is unspecified if this parameter is
+ * null.
+ *
+ * @param subject the authenticated subject. Can be null.
+ *
+ * @return the newly-created <code>RMIConnection</code>.
+ *
+ * @exception IOException if the new {@link RMIConnection}
+ * object cannot be created or exported.
+ */
+ protected RMIConnection makeClient(String connectionId, Subject subject)
+ throws IOException {
+
+ if (connectionId == null)
+ throw new NullPointerException("Null connectionId");
+
+ RMIConnection client =
+ new RMIConnectionImpl(this, connectionId, getDefaultClassLoader(),
+ subject, env);
+ export(client);
+ return client;
+ }
+
+ protected void closeClient(RMIConnection client) throws IOException {
+ unexport(client, true);
+ }
+
+ /**
+ * <p>Called by {@link #close()} to close the connector server by
+ * unexporting this object. After returning from this method, the
+ * connector server must not accept any new connections.</p>
+ *
+ * @exception IOException if the attempt to close the connector
+ * server failed.
+ */
+ protected void closeServer() throws IOException {
+ if (exportedWrapper != null) {
+ unexport(exportedWrapper, true);
+ } else {
+ unexport(this, true);
+ }
+ }
+
+ private final int port;
+ private final RMIClientSocketFactory csf;
+ private final RMIServerSocketFactory ssf;
+ private final Map<String, ?> env;
+
+ private static class ExportedWrapper implements RMIServer, DeserializationChecker {
+ private final RMIServer impl;
+ private final List<String> allowedTypes;
+
+ private ExportedWrapper(RMIServer impl, List<String> credentialsTypes) {
+ this.impl = impl;
+ allowedTypes = credentialsTypes;
+ }
+
+ @Override
+ public String getVersion() throws RemoteException {
+ return impl.getVersion();
+ }
+
+ @Override
+ public RMIConnection newClient(Object credentials) throws IOException {
+ return impl.newClient(credentials);
+ }
+
+ @Override
+ public void check(Method method, ObjectStreamClass descriptor,
+ int paramIndex, int callID) {
+ String type = descriptor.getName();
+ if (!allowedTypes.contains(type)) {
+ throw new ClassCastException("Unsupported type: " + type);
+ }
+ }
+
+ @Override
+ public void checkProxyClass(Method method, String[] ifaces,
+ int paramIndex, int callID) {
+ if (ifaces != null && ifaces.length > 0) {
+ for (String iface : ifaces) {
+ if (!allowedTypes.contains(iface)) {
+ throw new ClassCastException("Unsupported type: " + iface);
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIServer.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2002, 2007, 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 javax.management.remote.rmi;
+
+import java.io.IOException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+/**
+ * <p>RMI object used to establish connections to an RMI connector.
+ * There is one Remote object implementing this interface for each RMI
+ * connector.</p>
+ *
+ * <p>User code does not usually refer to this interface. It is
+ * specified as part of the public API so that different
+ * implementations of that API will interoperate.</p>
+ *
+ * @since 1.5
+ */
+public interface RMIServer extends Remote {
+ /**
+ * <p>The version of the RMI Connector Protocol understood by this
+ * connector server. This is a string with the following format:</p>
+ *
+ * <pre>
+ * <em>protocol-version</em> <em>implementation-name</em>
+ * </pre>
+ *
+ * <p>The <code><em>protocol-version</em></code> is a series of
+ * two or more non-negative integers separated by periods
+ * (<code>.</code>). An implementation of the version described
+ * by this documentation must use the string <code>1.0</code>
+ * here.</p>
+ *
+ * <p>After the protocol version there must be a space, followed
+ * by the implementation name. The format of the implementation
+ * name is unspecified. It is recommended that it include an
+ * implementation version number. An implementation can use an
+ * empty string as its implementation name, for example for
+ * security reasons.</p>
+ *
+ * @return a string with the format described here.
+ *
+ * @exception RemoteException if there is a communication
+ * exception during the remote method call.
+ */
+ public String getVersion() throws RemoteException;
+
+ /**
+ * <p>Makes a new connection through this RMI connector. Each
+ * remote client calls this method to obtain a new RMI object
+ * representing its connection.</p>
+ *
+ * @param credentials this object specifies the user-defined credentials
+ * to be passed in to the server in order to authenticate the user before
+ * creating the <code>RMIConnection</code>. Can be null.
+ *
+ * @return the newly-created connection object.
+ *
+ * @exception IOException if the new client object cannot be
+ * created or exported, or if there is a communication exception
+ * during the remote method call.
+ *
+ * @exception SecurityException if the given credentials do not
+ * allow the server to authenticate the caller successfully.
+ */
+ public RMIConnection newClient(Object credentials) throws IOException;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/RMIServerImpl.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,550 @@
+/*
+ * Copyright (c) 2002, 2015, 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 javax.management.remote.rmi;
+
+import com.sun.jmx.remote.internal.ArrayNotificationBuffer;
+import com.sun.jmx.remote.internal.NotificationBuffer;
+import com.sun.jmx.remote.security.JMXPluggableAuthenticator;
+import com.sun.jmx.remote.util.ClassLogger;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.lang.ref.WeakReference;
+import java.rmi.Remote;
+import java.rmi.server.RemoteServer;
+import java.rmi.server.ServerNotActiveException;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.MBeanServer;
+import javax.management.remote.JMXAuthenticator;
+import javax.management.remote.JMXConnectorServer;
+import javax.security.auth.Subject;
+
+/**
+ * <p>An RMI object representing a connector server. Remote clients
+ * can make connections using the {@link #newClient(Object)} method. This
+ * method returns an RMI object representing the connection.</p>
+ *
+ * <p>User code does not usually reference this class directly.
+ * RMI connection servers are usually created with the class {@link
+ * RMIConnectorServer}. Remote clients usually create connections
+ * either with {@link javax.management.remote.JMXConnectorFactory}
+ * or by instantiating {@link RMIConnector}.</p>
+ *
+ * <p>This is an abstract class. Concrete subclasses define the
+ * details of the client connection objects.</p>
+ *
+ * @since 1.5
+ */
+public abstract class RMIServerImpl implements Closeable, RMIServer {
+ /**
+ * <p>Constructs a new <code>RMIServerImpl</code>.</p>
+ *
+ * @param env the environment containing attributes for the new
+ * <code>RMIServerImpl</code>. Can be null, which is equivalent
+ * to an empty Map.
+ */
+ public RMIServerImpl(Map<String,?> env) {
+ this.env = (env == null) ? Collections.<String,Object>emptyMap() : env;
+ }
+
+ void setRMIConnectorServer(RMIConnectorServer connServer)
+ throws IOException {
+ this.connServer = connServer;
+ }
+
+ /**
+ * <p>Exports this RMI object.</p>
+ *
+ * @exception IOException if this RMI object cannot be exported.
+ */
+ protected abstract void export() throws IOException;
+
+ /**
+ * Returns a remotable stub for this server object.
+ * @return a remotable stub.
+ * @exception IOException if the stub cannot be obtained - e.g the
+ * RMIServerImpl has not been exported yet.
+ **/
+ public abstract Remote toStub() throws IOException;
+
+ /**
+ * <p>Sets the default <code>ClassLoader</code> for this connector
+ * server. New client connections will use this classloader.
+ * Existing client connections are unaffected.</p>
+ *
+ * @param cl the new <code>ClassLoader</code> to be used by this
+ * connector server.
+ *
+ * @see #getDefaultClassLoader
+ */
+ public synchronized void setDefaultClassLoader(ClassLoader cl) {
+ this.cl = cl;
+ }
+
+ /**
+ * <p>Gets the default <code>ClassLoader</code> used by this connector
+ * server.</p>
+ *
+ * @return the default <code>ClassLoader</code> used by this
+ * connector server.
+ *
+ * @see #setDefaultClassLoader
+ */
+ public synchronized ClassLoader getDefaultClassLoader() {
+ return cl;
+ }
+
+ /**
+ * <p>Sets the <code>MBeanServer</code> to which this connector
+ * server is attached. New client connections will interact
+ * with this <code>MBeanServer</code>. Existing client connections are
+ * unaffected.</p>
+ *
+ * @param mbs the new <code>MBeanServer</code>. Can be null, but
+ * new client connections will be refused as long as it is.
+ *
+ * @see #getMBeanServer
+ */
+ public synchronized void setMBeanServer(MBeanServer mbs) {
+ this.mbeanServer = mbs;
+ }
+
+ /**
+ * <p>The <code>MBeanServer</code> to which this connector server
+ * is attached. This is the last value passed to {@link
+ * #setMBeanServer} on this object, or null if that method has
+ * never been called.</p>
+ *
+ * @return the <code>MBeanServer</code> to which this connector
+ * is attached.
+ *
+ * @see #setMBeanServer
+ */
+ public synchronized MBeanServer getMBeanServer() {
+ return mbeanServer;
+ }
+
+ public String getVersion() {
+ // Expected format is: "protocol-version implementation-name"
+ try {
+ return "1.0 java_runtime_" +
+ System.getProperty("java.runtime.version");
+ } catch (SecurityException e) {
+ return "1.0 ";
+ }
+ }
+
+ /**
+ * <p>Creates a new client connection. This method calls {@link
+ * #makeClient makeClient} and adds the returned client connection
+ * object to an internal list. When this
+ * <code>RMIServerImpl</code> is shut down via its {@link
+ * #close()} method, the {@link RMIConnection#close() close()}
+ * method of each object remaining in the list is called.</p>
+ *
+ * <p>The fact that a client connection object is in this internal
+ * list does not prevent it from being garbage collected.</p>
+ *
+ * @param credentials this object specifies the user-defined
+ * credentials to be passed in to the server in order to
+ * authenticate the caller before creating the
+ * <code>RMIConnection</code>. Can be null.
+ *
+ * @return the newly-created <code>RMIConnection</code>. This is
+ * usually the object created by <code>makeClient</code>, though
+ * an implementation may choose to wrap that object in another
+ * object implementing <code>RMIConnection</code>.
+ *
+ * @exception IOException if the new client object cannot be
+ * created or exported.
+ *
+ * @exception SecurityException if the given credentials do not allow
+ * the server to authenticate the user successfully.
+ *
+ * @exception IllegalStateException if {@link #getMBeanServer()}
+ * is null.
+ */
+ public RMIConnection newClient(Object credentials) throws IOException {
+ return doNewClient(credentials);
+ }
+
+ /**
+ * This method could be overridden by subclasses defined in this package
+ * to perform additional operations specific to the underlying transport
+ * before creating the new client connection.
+ */
+ RMIConnection doNewClient(Object credentials) throws IOException {
+ final boolean tracing = logger.traceOn();
+
+ if (tracing) logger.trace("newClient","making new client");
+
+ if (getMBeanServer() == null)
+ throw new IllegalStateException("Not attached to an MBean server");
+
+ Subject subject = null;
+ JMXAuthenticator authenticator =
+ (JMXAuthenticator) env.get(JMXConnectorServer.AUTHENTICATOR);
+ if (authenticator == null) {
+ /*
+ * Create the JAAS-based authenticator only if authentication
+ * has been enabled
+ */
+ if (env.get("jmx.remote.x.password.file") != null ||
+ env.get("jmx.remote.x.login.config") != null) {
+ authenticator = new JMXPluggableAuthenticator(env);
+ }
+ }
+ if (authenticator != null) {
+ if (tracing) logger.trace("newClient","got authenticator: " +
+ authenticator.getClass().getName());
+ try {
+ subject = authenticator.authenticate(credentials);
+ } catch (SecurityException e) {
+ logger.trace("newClient", "Authentication failed: " + e);
+ throw e;
+ }
+ }
+
+ if (tracing) {
+ if (subject != null)
+ logger.trace("newClient","subject is not null");
+ else logger.trace("newClient","no subject");
+ }
+
+ final String connectionId = makeConnectionId(getProtocol(), subject);
+
+ if (tracing)
+ logger.trace("newClient","making new connection: " + connectionId);
+
+ RMIConnection client = makeClient(connectionId, subject);
+
+ dropDeadReferences();
+ WeakReference<RMIConnection> wr = new WeakReference<RMIConnection>(client);
+ synchronized (clientList) {
+ clientList.add(wr);
+ }
+
+ connServer.connectionOpened(connectionId, "Connection opened", null);
+
+ synchronized (clientList) {
+ if (!clientList.contains(wr)) {
+ // can be removed only by a JMXConnectionNotification listener
+ throw new IOException("The connection is refused.");
+ }
+ }
+
+ if (tracing)
+ logger.trace("newClient","new connection done: " + connectionId );
+
+ return client;
+ }
+
+ /**
+ * <p>Creates a new client connection. This method is called by
+ * the public method {@link #newClient(Object)}.</p>
+ *
+ * @param connectionId the ID of the new connection. Every
+ * connection opened by this connector server will have a
+ * different ID. The behavior is unspecified if this parameter is
+ * null.
+ *
+ * @param subject the authenticated subject. Can be null.
+ *
+ * @return the newly-created <code>RMIConnection</code>.
+ *
+ * @exception IOException if the new client object cannot be
+ * created or exported.
+ */
+ protected abstract RMIConnection makeClient(String connectionId,
+ Subject subject)
+ throws IOException;
+
+ /**
+ * <p>Closes a client connection made by {@link #makeClient makeClient}.
+ *
+ * @param client a connection previously returned by
+ * <code>makeClient</code> on which the <code>closeClient</code>
+ * method has not previously been called. The behavior is
+ * unspecified if these conditions are violated, including the
+ * case where <code>client</code> is null.
+ *
+ * @exception IOException if the client connection cannot be
+ * closed.
+ */
+ protected abstract void closeClient(RMIConnection client)
+ throws IOException;
+
+ /**
+ * <p>Returns the protocol string for this object. The string is
+ * <code>rmi</code> for RMI/JRMP.
+ *
+ * @return the protocol string for this object.
+ */
+ protected abstract String getProtocol();
+
+ /**
+ * <p>Method called when a client connection created by {@link
+ * #makeClient makeClient} is closed. A subclass that defines
+ * <code>makeClient</code> must arrange for this method to be
+ * called when the resultant object's {@link RMIConnection#close()
+ * close} method is called. This enables it to be removed from
+ * the <code>RMIServerImpl</code>'s list of connections. It is
+ * not an error for <code>client</code> not to be in that
+ * list.</p>
+ *
+ * <p>After removing <code>client</code> from the list of
+ * connections, this method calls {@link #closeClient
+ * closeClient(client)}.</p>
+ *
+ * @param client the client connection that has been closed.
+ *
+ * @exception IOException if {@link #closeClient} throws this
+ * exception.
+ *
+ * @exception NullPointerException if <code>client</code> is null.
+ */
+ protected void clientClosed(RMIConnection client) throws IOException {
+ final boolean debug = logger.debugOn();
+
+ if (debug) logger.trace("clientClosed","client="+client);
+
+ if (client == null)
+ throw new NullPointerException("Null client");
+
+ synchronized (clientList) {
+ dropDeadReferences();
+ for (Iterator<WeakReference<RMIConnection>> it = clientList.iterator();
+ it.hasNext(); ) {
+ WeakReference<RMIConnection> wr = it.next();
+ if (wr.get() == client) {
+ it.remove();
+ break;
+ }
+ }
+ /* It is not a bug for this loop not to find the client. In
+ our close() method, we remove a client from the list before
+ calling its close() method. */
+ }
+
+ if (debug) logger.trace("clientClosed", "closing client.");
+ closeClient(client);
+
+ if (debug) logger.trace("clientClosed", "sending notif");
+ connServer.connectionClosed(client.getConnectionId(),
+ "Client connection closed", null);
+
+ if (debug) logger.trace("clientClosed","done");
+ }
+
+ /**
+ * <p>Closes this connection server. This method first calls the
+ * {@link #closeServer()} method so that no new client connections
+ * will be accepted. Then, for each remaining {@link
+ * RMIConnection} object returned by {@link #makeClient
+ * makeClient}, its {@link RMIConnection#close() close} method is
+ * called.</p>
+ *
+ * <p>The behavior when this method is called more than once is
+ * unspecified.</p>
+ *
+ * <p>If {@link #closeServer()} throws an
+ * <code>IOException</code>, the individual connections are
+ * nevertheless closed, and then the <code>IOException</code> is
+ * thrown from this method.</p>
+ *
+ * <p>If {@link #closeServer()} returns normally but one or more
+ * of the individual connections throws an
+ * <code>IOException</code>, then, after closing all the
+ * connections, one of those <code>IOException</code>s is thrown
+ * from this method. If more than one connection throws an
+ * <code>IOException</code>, it is unspecified which one is thrown
+ * from this method.</p>
+ *
+ * @exception IOException if {@link #closeServer()} or one of the
+ * {@link RMIConnection#close()} calls threw
+ * <code>IOException</code>.
+ */
+ public synchronized void close() throws IOException {
+ final boolean tracing = logger.traceOn();
+ final boolean debug = logger.debugOn();
+
+ if (tracing) logger.trace("close","closing");
+
+ IOException ioException = null;
+ try {
+ if (debug) logger.debug("close","closing Server");
+ closeServer();
+ } catch (IOException e) {
+ if (tracing) logger.trace("close","Failed to close server: " + e);
+ if (debug) logger.debug("close",e);
+ ioException = e;
+ }
+
+ if (debug) logger.debug("close","closing Clients");
+ // Loop to close all clients
+ while (true) {
+ synchronized (clientList) {
+ if (debug) logger.debug("close","droping dead references");
+ dropDeadReferences();
+
+ if (debug) logger.debug("close","client count: "+clientList.size());
+ if (clientList.size() == 0)
+ break;
+ /* Loop until we find a non-null client. Because we called
+ dropDeadReferences(), this will usually be the first
+ element of the list, but a garbage collection could have
+ happened in between. */
+ for (Iterator<WeakReference<RMIConnection>> it = clientList.iterator();
+ it.hasNext(); ) {
+ WeakReference<RMIConnection> wr = it.next();
+ RMIConnection client = wr.get();
+ it.remove();
+ if (client != null) {
+ try {
+ client.close();
+ } catch (IOException e) {
+ if (tracing)
+ logger.trace("close","Failed to close client: " + e);
+ if (debug) logger.debug("close",e);
+ if (ioException == null)
+ ioException = e;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ if(notifBuffer != null)
+ notifBuffer.dispose();
+
+ if (ioException != null) {
+ if (tracing) logger.trace("close","close failed.");
+ throw ioException;
+ }
+
+ if (tracing) logger.trace("close","closed.");
+ }
+
+ /**
+ * <p>Called by {@link #close()} to close the connector server.
+ * After returning from this method, the connector server must
+ * not accept any new connections.</p>
+ *
+ * @exception IOException if the attempt to close the connector
+ * server failed.
+ */
+ protected abstract void closeServer() throws IOException;
+
+ private static synchronized String makeConnectionId(String protocol,
+ Subject subject) {
+ connectionIdNumber++;
+
+ String clientHost = "";
+ try {
+ clientHost = RemoteServer.getClientHost();
+ /*
+ * According to the rules specified in the javax.management.remote
+ * package description, a numeric IPv6 address (detected by the
+ * presence of otherwise forbidden ":" character) forming a part
+ * of the connection id must be enclosed in square brackets.
+ */
+ if (clientHost.contains(":")) {
+ clientHost = "[" + clientHost + "]";
+ }
+ } catch (ServerNotActiveException e) {
+ logger.trace("makeConnectionId", "getClientHost", e);
+ }
+
+ final StringBuilder buf = new StringBuilder();
+ buf.append(protocol).append(":");
+ if (clientHost.length() > 0)
+ buf.append("//").append(clientHost);
+ buf.append(" ");
+ if (subject != null) {
+ Set<Principal> principals = subject.getPrincipals();
+ String sep = "";
+ for (Iterator<Principal> it = principals.iterator(); it.hasNext(); ) {
+ Principal p = it.next();
+ String name = p.getName().replace(' ', '_').replace(';', ':');
+ buf.append(sep).append(name);
+ sep = ";";
+ }
+ }
+ buf.append(" ").append(connectionIdNumber);
+ if (logger.traceOn())
+ logger.trace("newConnectionId","connectionId="+buf);
+ return buf.toString();
+ }
+
+ private void dropDeadReferences() {
+ synchronized (clientList) {
+ for (Iterator<WeakReference<RMIConnection>> it = clientList.iterator();
+ it.hasNext(); ) {
+ WeakReference<RMIConnection> wr = it.next();
+ if (wr.get() == null)
+ it.remove();
+ }
+ }
+ }
+
+ synchronized NotificationBuffer getNotifBuffer() {
+ //Notification buffer is lazily created when the first client connects
+ if(notifBuffer == null)
+ notifBuffer =
+ ArrayNotificationBuffer.getNotificationBuffer(mbeanServer,
+ env);
+ return notifBuffer;
+ }
+
+ private static final ClassLogger logger =
+ new ClassLogger("javax.management.remote.rmi", "RMIServerImpl");
+
+ /** List of WeakReference values. Each one references an
+ RMIConnection created by this object, or null if the
+ RMIConnection has been garbage-collected. */
+ private final List<WeakReference<RMIConnection>> clientList =
+ new ArrayList<WeakReference<RMIConnection>>();
+
+ private ClassLoader cl;
+
+ private MBeanServer mbeanServer;
+
+ private final Map<String, ?> env;
+
+ private RMIConnectorServer connServer;
+
+ private static int connectionIdNumber;
+
+ private NotificationBuffer notifBuffer;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/javax/management/remote/rmi/package.html Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,340 @@
+<html>
+<head>
+ <title>RMI connector</title>
+<!--
+Copyright (c) 2002, 2015, 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.
+-->
+</head>
+<body bgcolor="white">
+ <p>The RMI connector is a connector for the JMX Remote API that
+ uses RMI to transmit client requests to a remote MBean server.
+ This package defines the classes that the user of an RMI
+ connector needs to reference directly, for both the client and
+ server sides. It also defines certain classes that the user
+ will not usually reference directly, but that must be defined so
+ that different implementations of the RMI connector can
+ interoperate.</p>
+
+ <p>The RMI connector supports the JRMP transport for RMI.</p>
+
+ <p>Like most connectors in the JMX Remote API, an RMI connector
+ usually has an address, which
+ is a {@link javax.management.remote.JMXServiceURL
+ JMXServiceURL}. The protocol part of this address is
+ <code>rmi</code> for a connector that uses the default RMI
+ transport (JRMP).</p>
+
+ <p>There are two forms for RMI connector addresses:</p>
+
+ <ul>
+ <li>
+ In the <em>JNDI form</em>, the URL indicates <em>where to find
+ an RMI stub for the connector</em>. This RMI stub is a Java
+ object of type {@link javax.management.remote.rmi.RMIServer
+ RMIServer} that gives remote access to the connector server.
+ With this address form, the RMI stub is obtained from an
+ external directory entry included in the URL. An external
+ directory is any directory recognized by {@link javax.naming
+ JNDI}, typically the RMI registry, LDAP, or COS Naming.
+
+ <li>
+ In the <em>encoded form</em>, the URL directly includes the
+ information needed to connect to the connector server. When
+ using RMI/JRMP, the encoded form is the serialized RMI stub
+ for the server object, encoded using BASE64 without embedded
+ newlines.
+ </ul>
+
+ <p>Addresses are covered in more detail below.</p>
+
+
+ <h3>Creating an RMI connector server</h3>
+
+ <p>The usual way to create an RMI connector server is to supply an
+ RMI connector address to the method {@link
+ javax.management.remote.JMXConnectorServerFactory#newJMXConnectorServer
+ JMXConnectorServerFactory.newJMXConnectorServer}. The MBean
+ server to which the connector server is attached can be
+ specified as a parameter to that method. Alternatively, the
+ connector server can be registered as an MBean in that MBean
+ server.</p>
+
+ <p>An RMI connector server can also be created by constructing an
+ instance of {@link
+ javax.management.remote.rmi.RMIConnectorServer
+ RMIConnectorServer}, explicitly or through the MBean server's
+ <code>createMBean</code> method.</p>
+
+ <h4>Choosing the RMI transport</h4>
+
+ <p>You can choose the RMI transport by specifying
+ <code>rmi</code> in the <code><em>protocol</em></code> part of the
+ <code>serviceURL</code> when creating the connector server. You
+ can also create specialized connector servers by instantiating
+ an appropriate subclass of {@link
+ javax.management.remote.rmi.RMIServerImpl RMIServerImpl} and
+ supplying it to the <code>RMIConnectorServer</code>
+ constructor.</p>
+
+
+ <h4><a name="servergen">Connector addresses generated by the
+ server</a></h4>
+
+ <p>If the <code>serviceURL</code> you specify has an empty URL
+ path (after the optional host and port), or if you do not
+ specify a <code>serviceURL</code>, then the connector server
+ will fabricate a new <code>JMXServiceURL</code> that clients can
+ use to connect:</p>
+
+ <ul>
+
+ <li><p>If the <code>serviceURL</code> looks like:</p>
+
+ <pre>
+ <code>service:jmx:rmi://<em>host</em>:<em>port</em></code>
+ </pre>
+
+ <p>then the connector server will generate an {@link
+ javax.management.remote.rmi.RMIJRMPServerImpl
+ RMIJRMPServerImpl} and the returned <code>JMXServiceURL</code>
+ looks like:</p>
+
+ <pre>
+ <code>service:jmx:rmi://<em>host</em>:<em>port</em>/stub/<em>XXXX</em></code>
+ </pre>
+
+ <p>where <code><em>XXXX</em></code> is the serialized form of the
+ stub for the generated object, encoded in BASE64 without
+ newlines.</p>
+
+ <li><p>If there is no <code>serviceURL</code>, there must be a
+ user-provided <code>RMIServerImpl</code>. The connector server
+ will generate a <code>JMXServiceURL</code> using the <code>rmi</code>
+ form.</p>
+
+ </ul>
+
+ <p>The <code><em>host</em></code> in a user-provided
+ <code>serviceURL</code> is optional. If present, it is copied
+ into the generated <code>JMXServiceURL</code> but otherwise
+ ignored. If absent, the generated <code>JXMServiceURL</code>
+ will have the local host name.</p>
+
+ <p>The <code><em>port</em></code> in a user-provided
+ <code>serviceURL</code> is also optional. If present, it is
+ also copied into the generated <code>JMXServiceURL</code>;
+ otherwise, the generated <code>JMXServiceURL</code> has no port.
+ For an <code>serviceURL</code> using the <code>rmi</code>
+ protocol, the <code><em>port</em></code>, if present, indicates
+ what port the generated remote object should be exported on. It
+ has no other effect.</p>
+
+ <p>If the user provides an <code>RMIServerImpl</code> rather than a
+ <code>JMXServiceURL</code>, then the generated
+ <code>JMXServiceURL</code> will have the local host name in its
+ <code><em>host</em></code> part and no
+ <code><em>port</em></code>.</p>
+
+
+ <h4><a name="directory">Connector addresses based on directory
+ entries</a></h4>
+
+ <p>As an alternative to the generated addresses just described,
+ the <code>serviceURL</code> address supplied when creating a
+ connector server can specify a <em>directory address</em> in
+ which to store the provided or generated <code>RMIServer</code>
+ stub. This directory address is then used by both client and
+ server.</p>
+
+ <p>In this case, the <code>serviceURL</code> has the following form:</p>
+
+ <pre>
+ <code>service:jmx:rmi://<em>host</em>:<em>port</em>/jndi/<em>jndi-name</em></code>
+ </pre>
+
+ <p>Here, <code><em>jndi-name</em></code> is a string that can be
+ supplied to {@link javax.naming.InitialContext#bind
+ javax.naming.InitialContext.bind}.</p>
+
+ <p>As usual, the <code><em>host</em></code> and
+ <code>:<em>port</em></code> can be omitted.</p>
+
+ <p>The connector server will generate an
+ <code>RMIServerImpl</code> based on the protocol
+ (<code>rmi</code>) and the <code><em>port</em></code> if any. When
+ the connector server is started, it will derive a stub from this
+ object using its {@link
+ javax.management.remote.rmi.RMIServerImpl#toStub toStub} method
+ and store the object using the given
+ <code><em>jndi-name</em></code>. The properties defined by the
+ JNDI API are consulted as usual.</p>
+
+ <p>For example, if the <code>JMXServiceURL</code> is:
+
+ <pre>
+ <code>service:jmx:rmi://ignoredhost/jndi/rmi://myhost/myname</code>
+ </pre>
+
+ then the connector server will generate an
+ <code>RMIJRMPServerImpl</code> and store its stub using the JNDI
+ name
+
+ <pre>
+ <code>rmi://myhost/myname</code>
+ </pre>
+
+ which means entry <code>myname</code> in the RMI registry
+ running on the default port of host <code>myhost</code>. Note
+ that the RMI registry only allows registration from the local
+ host. So, in this case, <code>myhost</code> must be the name
+ (or a name) of the host that the connector server is running
+ on.
+
+ <p>In this <code>JMXServiceURL</code>, the first <code>rmi:</code>
+ specifies the RMI
+ connector, while the second <code>rmi:</code> specifies the RMI
+ registry.
+
+ <p>As another example, if the <code>JMXServiceURL</code> is:
+
+ <pre>
+ <code>service:jmx:rmi://ignoredhost/jndi/ldap://dirhost:9999/cn=this,ou=that</code>
+ </pre>
+
+ then the connector server will generate an
+ <code>RMIJRMPServerImpl</code> and store its stub using the JNDI
+ name
+
+ <pre>
+ <code>ldap://dirhost:9999/cn=this,ou=that</code>
+ </pre>
+
+ which means entry <code>cn=this,ou=that</code> in the LDAP
+ directory running on port 9999 of host <code>dirhost</code>.
+
+ <p>If the <code>JMXServiceURL</code> is:
+
+ <pre>
+ <code>service:jmx:rmi://ignoredhost/jndi/cn=this,ou=that</code>
+ </pre>
+
+ then the connector server will generate an
+ <code>RMIJRMPServerImpl</code> and store its stub using the JNDI
+ name
+
+ <pre>
+ <code>cn=this,ou=that</code>
+ </pre>
+
+ For this case to work, the JNDI API must have been configured
+ appropriately to supply the information about what directory to
+ use.
+
+ <p>In these examples, the host name <code>ignoredhost</code> is
+ not used by the connector server or its clients. It can be
+ omitted, for example:</p>
+
+ <pre>
+ <code>service:jmx:rmi:///jndi/cn=this,ou=that</code>
+ </pre>
+
+ <p>However, it is good practice to use the name of the host
+ where the connector server is running. This is often different
+ from the name of the directory host.</p>
+
+
+ <h4>Connector server attributes</h4>
+
+ <p>When using the default JRMP transport, RMI socket factories can
+ be specified using the attributes
+ <code>jmx.remote.rmi.client.socket.factory</code> and
+ <code>jmx.remote.rmi.server.socket.factory</code> in the
+ <code>environment</code> given to the
+ <code>RMIConnectorServer</code> constructor. The values of these
+ attributes must be of type {@link
+ java.rmi.server.RMIClientSocketFactory} and {@link
+ java.rmi.server.RMIServerSocketFactory}, respectively. These
+ factories are used when creating the RMI objects associated with
+ the connector.</p>
+
+ <h3>Creating an RMI connector client</h3>
+
+ <p>An RMI connector client is usually constructed using {@link
+ javax.management.remote.JMXConnectorFactory}, with a
+ <code>JMXServiceURL</code> that has <code>rmi</code> as its protocol.</p>
+
+ <p>If the <code>JMXServiceURL</code> was generated by the server,
+ as described above under <a href="#servergen">"connector
+ addresses generated by the server"</a>, then the client will
+ need to obtain it directly or indirectly from the server.
+ Typically, the server makes the <code>JMXServiceURL</code>
+ available by storing it in a file or a lookup service.</p>
+
+ <p>If the <code>JMXServiceURL</code> uses the directory syntax, as
+ described above under <a href="#directory">"connector addresses
+ based on directory entries"</a>, then the client may obtain it
+ as just explained, or client and server may both know the
+ appropriate directory entry to use. For example, if the
+ connector server for the Whatsit agent uses the entry
+ <code>whatsit-agent-connector</code> in the RMI registry on host
+ <code>myhost</code>, then client and server can both know
+ that the appropriate <code>JMXServiceURL</code> is:</p>
+
+ <pre>
+ <code>service:jmx:rmi:///jndi/rmi://myhost/whatsit-agent-connector</code>
+ </pre>
+
+ <p>If you have an RMI stub of type {@link
+ javax.management.remote.rmi.RMIServer RMIServer}, you can
+ construct an RMI connection directly by using the appropriate
+ constructor of {@link javax.management.remote.rmi.RMIConnector
+ RMIConnector}.</p>
+
+ <h3>Dynamic code downloading</h3>
+
+ <p>If an RMI connector client or server receives from its peer an
+ instance of a class that it does not know, and if dynamic code
+ downloading is active for the RMI connection, then the class can
+ be downloaded from a codebase specified by the peer. The
+ article <a
+ href="{@docRoot}/../technotes/guides/rmi/codebase.html"><em>Dynamic
+ code downloading using Java RMI</em></a> explains this in more
+ detail.</p>
+
+
+ @see <a href="{@docRoot}/../technotes/guides/rmi/index.html">
+ Java™ Remote Method
+ Invocation (RMI)</a>
+
+ @see <a href="{@docRoot}/../technotes/guides/jndi/index.html">
+ Java Naming and Directory Interface™ (JNDI)</a>
+
+ @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045,
+ section 6.8, "Base64 Content-Transfer-Encoding"</a>
+
+
+ @since 1.5
+
+ </body>
+</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management.rmi/share/classes/module-info.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/**
+ * Defines the RMI Connector for the Java Management Extensions (JMX) Remote API.
+ * <P>
+ * The {@linkplain javax.management.remote.rmi RMI connector} is a connector
+ * for the JMX Remote API that uses RMI to transmit client requests to a remote
+ * MBean server.
+ *
+ * @provides javax.management.remote.JMXConnectorProvider
+ * A provider of {@code JMXConnector} for the RMI protocol.<br>
+ * Instances of {@code JMXConnector} using the RMI protocol
+ * are usually created by the {@link
+ * javax.management.remote.JMXConnectorFactory} which will locate
+ * and load the appropriate {@code JMXConnectorProvider} service
+ * implementation for the given protocol.
+ *
+ * @provides javax.management.remote.JMXConnectorServerProvider
+ * A provider of {@code JMXConnectorServer} for the RMI protocol.<br>
+ * Instances of {@code JMXConnectorServer} using the RMI protocol
+ * are usually created by the {@link
+ * javax.management.remote.JMXConnectorServerFactory} which will locate
+ * and load the appropriate {@code JMXConnectorServerProvider} service
+ * implementation for the given protocol.
+ *
+ */
+module java.management.rmi {
+
+ requires transitive java.management;
+ requires transitive java.rmi;
+ requires java.naming;
+
+ exports javax.management.remote.rmi;
+
+ // The qualified export below is required to preserve backward
+ // compatibility for the legacy case where an ordered list
+ // of package prefixes can be specified to the factory.
+ exports com.sun.jmx.remote.protocol.rmi to java.management;
+
+ // jdk.management.agent needs to create an RMIExporter instance.
+ exports com.sun.jmx.remote.internal.rmi to jdk.management.agent;
+
+ // The java.management.rmi module provides implementations
+ // of the JMXConnectorProvider and JMXConnectorServerProvider
+ // services supporting the RMI protocol.
+ provides javax.management.remote.JMXConnectorProvider
+ with com.sun.jmx.remote.protocol.rmi.ClientProvider;
+ provides javax.management.remote.JMXConnectorServerProvider
+ with com.sun.jmx.remote.protocol.rmi.ServerProvider;
+
+}
--- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java Thu Feb 09 23:15:52 2017 +0100
@@ -52,7 +52,6 @@
import com.sun.jmx.remote.util.ClassLogger;
import com.sun.jmx.remote.util.EnvHelp;
import java.lang.reflect.UndeclaredThrowableException;
-import java.rmi.UnmarshalException;
import java.util.concurrent.RejectedExecutionException;
@@ -633,7 +632,7 @@
}
return nr;
- } catch (ClassNotFoundException | NotSerializableException | UnmarshalException e) {
+ } catch (ClassNotFoundException | NotSerializableException e) {
logger.trace("NotifFetcher.fetchNotifs", e);
return fetchOneNotif();
} catch (IOException ioe) {
@@ -705,7 +704,7 @@
try {
// 1 notif to skip possible missing class
result = cnf.fetchNotifs(startSequenceNumber, 1, 0L);
- } catch (ClassNotFoundException | NotSerializableException | UnmarshalException e) {
+ } catch (ClassNotFoundException | NotSerializableException e) {
logger.warning("NotifFetcher.fetchOneNotif",
"Failed to deserialize a notification: "+e.toString());
if (logger.traceOn()) {
--- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ProxyRef.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 2003, 2008, 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 com.sun.jmx.remote.internal;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.lang.reflect.Method;
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-import java.rmi.server.RemoteObject;
-import java.rmi.server.RemoteRef;
-
-
-@SuppressWarnings("deprecation")
-public class ProxyRef implements RemoteRef {
- private static final long serialVersionUID = -6503061366316814723L;
-
- public ProxyRef(RemoteRef ref) {
- this.ref = ref;
- }
-
- public void readExternal(ObjectInput in)
- throws IOException, ClassNotFoundException {
- ref.readExternal(in);
- }
-
- public void writeExternal(ObjectOutput out) throws IOException {
- ref.writeExternal(out);
- }
-
- /**
- * @deprecated
- */
- @Deprecated
- public void invoke(java.rmi.server.RemoteCall call) throws Exception {
- ref.invoke(call);
- }
-
- public Object invoke(Remote obj, Method method, Object[] params,
- long opnum) throws Exception {
- return ref.invoke(obj, method, params, opnum);
- }
-
- /**
- * @deprecated
- */
- @Deprecated
- public void done(java.rmi.server.RemoteCall call) throws RemoteException {
- ref.done(call);
- }
-
- public String getRefClass(ObjectOutput out) {
- return ref.getRefClass(out);
- }
-
- /**
- * @deprecated
- */
- @Deprecated
- public java.rmi.server.RemoteCall newCall(RemoteObject obj,
- java.rmi.server.Operation[] op, int opnum,
- long hash) throws RemoteException {
- return ref.newCall(obj, op, opnum, hash);
- }
-
- public boolean remoteEquals(RemoteRef obj) {
- return ref.remoteEquals(obj);
- }
-
- public int remoteHashCode() {
- return ref.remoteHashCode();
- }
-
- public String remoteToString() {
- return ref.remoteToString();
- }
-
- protected RemoteRef ref;
-}
--- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/RMIExporter.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2003, 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 com.sun.jmx.remote.internal;
-
-import java.rmi.NoSuchObjectException;
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-import java.rmi.server.RMIClientSocketFactory;
-import java.rmi.server.RMIServerSocketFactory;
-import java.rmi.server.UnicastRemoteObject;
-
-/**
- * <p>Unpublished interface controlling how the RMI Connector Server
- * exports objects. The RMIServerImpl object and each
- * RMIConnectionImpl object are exported using the exporter. The
- * default exporter calls {@link
- * UnicastRemoteObject#exportObject(Remote, int,
- * RMIClientSocketFactory, RMIServerSocketFactory)} to export objects
- * and {@link UnicastRemoteObject#unexportObject(Remote, boolean)} to
- * unexport them. A replacement exporter can be specified via the
- * {@link #EXPORTER_ATTRIBUTE} property in the environment Map passed
- * to the RMI connector server.</p>
- */
-public interface RMIExporter {
- public static final String EXPORTER_ATTRIBUTE =
- "com.sun.jmx.remote.rmi.exporter";
-
- public Remote exportObject(Remote obj,
- int port,
- RMIClientSocketFactory csf,
- RMIServerSocketFactory ssf)
- throws RemoteException;
-
- public boolean unexportObject(Remote obj, boolean force)
- throws NoSuchObjectException;
-}
--- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/Unmarshal.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2003, 2008, 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 com.sun.jmx.remote.internal;
-
-import java.io.IOException;
-import java.rmi.MarshalledObject;
-
-public interface Unmarshal {
- public Object get(MarshalledObject<?> mo)
- throws IOException, ClassNotFoundException;
-}
--- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/protocol/rmi/ClientProvider.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2002, 2004, 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 com.sun.jmx.remote.protocol.rmi;
-
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.util.Map;
-
-import javax.management.remote.JMXConnectorProvider;
-import javax.management.remote.JMXConnector;
-import javax.management.remote.JMXServiceURL;
-import javax.management.remote.rmi.RMIConnector;
-
-public class ClientProvider implements JMXConnectorProvider {
-
- public JMXConnector newJMXConnector(JMXServiceURL serviceURL,
- Map<String,?> environment)
- throws IOException {
- if (!serviceURL.getProtocol().equals("rmi")) {
- throw new MalformedURLException("Protocol not rmi: " +
- serviceURL.getProtocol());
- }
- return new RMIConnector(serviceURL, environment);
- }
-}
--- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/protocol/rmi/ServerProvider.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2003, 2004, 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 com.sun.jmx.remote.protocol.rmi;
-
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.util.Map;
-
-import javax.management.MBeanServer;
-import javax.management.remote.JMXConnectorServer;
-import javax.management.remote.JMXConnectorServerProvider;
-import javax.management.remote.JMXServiceURL;
-import javax.management.remote.rmi.RMIConnectorServer;
-
-public class ServerProvider implements JMXConnectorServerProvider {
-
- public JMXConnectorServer newJMXConnectorServer(JMXServiceURL serviceURL,
- Map<String,?> environment,
- MBeanServer mbeanServer)
- throws IOException {
- if (!serviceURL.getProtocol().equals("rmi")) {
- throw new MalformedURLException("Protocol not rmi: " +
- serviceURL.getProtocol());
- }
- return new RMIConnectorServer(serviceURL, environment, mbeanServer);
- }
-
-}
--- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/security/FileLoginModule.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.management/share/classes/com/sun/jmx/remote/security/FileLoginModule.java Thu Feb 09 23:15:52 2017 +0100
@@ -47,7 +47,6 @@
import com.sun.jmx.remote.util.ClassLogger;
import com.sun.jmx.remote.util.EnvHelp;
-import sun.management.jmxremote.ConnectorBootstrap;
/**
* This {@link LoginModule} performs file-based authentication.
@@ -110,12 +109,14 @@
*/
public class FileLoginModule implements LoginModule {
+ private static final String PASSWORD_FILE_NAME = "jmxremote.password";
+
// Location of the default password file
private static final String DEFAULT_PASSWORD_FILE_NAME =
AccessController.doPrivileged(new GetPropertyAction("java.home")) +
File.separatorChar + "conf" +
File.separatorChar + "management" + File.separatorChar +
- ConnectorBootstrap.DefaultValues.PASSWORD_FILE_NAME;
+ PASSWORD_FILE_NAME;
// Key to retrieve the stored username
private static final String USERNAME_KEY =
@@ -200,8 +201,7 @@
passwordFileDisplayName = passwordFile;
} catch (SecurityException e) {
hasJavaHomePermission = false;
- passwordFileDisplayName =
- ConnectorBootstrap.DefaultValues.PASSWORD_FILE_NAME;
+ passwordFileDisplayName = PASSWORD_FILE_NAME;
}
}
}
--- a/jdk/src/java.management/share/classes/javax/management/remote/JMXConnectorFactory.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.management/share/classes/javax/management/remote/JMXConnectorFactory.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,13 +27,17 @@
import com.sun.jmx.mbeanserver.Util;
import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.lang.reflect.Module;
import java.net.MalformedURLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
-import java.util.Iterator;
import java.util.ServiceLoader;
+import java.util.ServiceLoader.Provider;
import java.util.StringTokenizer;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
import java.security.AccessController;
import java.security.PrivilegedAction;
@@ -332,25 +336,32 @@
IOException exception = null;
if (provider == null) {
+ Predicate<Provider<?>> systemProvider =
+ JMXConnectorFactory::isSystemProvider;
// Loader is null when context class loader is set to null
// and no loader has been provided in map.
// com.sun.jmx.remote.util.Service class extracted from j2se
// provider search algorithm doesn't handle well null classloader.
+ JMXConnector connection = null;
if (loader != null) {
try {
- JMXConnector connection =
- getConnectorAsService(loader, providerURL, envcopy);
- if (connection != null)
- return connection;
+ connection = getConnectorAsService(loader,
+ providerURL,
+ envcopy,
+ systemProvider.negate());
+ if (connection != null) return connection;
} catch (JMXProviderException e) {
throw e;
} catch (IOException e) {
exception = e;
}
}
- provider = getProvider(protocol, PROTOCOL_PROVIDER_DEFAULT_PACKAGE,
- JMXConnectorFactory.class.getClassLoader(),
- providerClassName, targetInterface);
+ connection = getConnectorAsService(
+ JMXConnectorFactory.class.getClassLoader(),
+ providerURL,
+ Collections.unmodifiableMap(envcopy),
+ systemProvider);
+ if (connection != null) return connection;
}
if (provider == null) {
@@ -437,13 +448,6 @@
return instance;
}
- static <T> Iterator<T> getProviderIterator(final Class<T> providerClass,
- final ClassLoader loader) {
- ServiceLoader<T> serviceLoader =
- ServiceLoader.load(providerClass, loader);
- return serviceLoader.iterator();
- }
-
private static ClassLoader wrap(final ClassLoader parent) {
return parent != null ? AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
@Override
@@ -459,44 +463,265 @@
}) : null;
}
+ /**
+ * Checks whether the given provider is our system provider for
+ * the RMI connector.
+ * If providers for additional protocols are added in the future
+ * then the name of their modules may need to be added here.
+ * System providers will be loaded only if no other provider is found.
+ * @param provider the provider to test.
+ * @return true if this provider is a default system provider.
+ */
+ static boolean isSystemProvider(Provider<?> provider) {
+ Module providerModule = provider.type().getModule();
+ return providerModule.isNamed()
+ && providerModule.getName().equals("java.management.rmi");
+ }
+
+ /**
+ * Creates a JMXConnector from the first JMXConnectorProvider service
+ * supporting the given url that can be loaded from the given loader.
+ * <p>
+ * Parses the list of JMXConnectorProvider services that can be loaded
+ * from the given loader, only retaining those that satisfy the given filter.
+ * Then for each provider, attempts to create a new JMXConnector.
+ * The first JMXConnector successfully created is returned.
+ * <p>
+ * The filter predicate is usually used to either exclude system providers
+ * or only retain system providers (see isSystemProvider(...) above).
+ *
+ * @param loader The ClassLoader to use when looking up an implementation
+ * of the service. If null, then only installed services will be
+ * considered.
+ *
+ * @param url The JMXServiceURL of the connector for which a provider is
+ * requested.
+ *
+ * @param filter A filter used to exclude or return provider
+ * implementations. Typically the filter will either exclude
+ * system services (system default implementations) or only
+ * retain those.
+ * This can allow to first look for custom implementations (e.g.
+ * deployed on the CLASSPATH with META-INF/services) and
+ * then only default to system implementations.
+ *
+ * @throws IOException if no connector could not be instantiated, and
+ * at least one provider threw an exception that wasn't a
+ * {@code MalformedURLException} or a {@code JMProviderException}.
+ *
+ * @throws JMXProviderException if a provider for the protocol in
+ * <code>url</code> was found, but couldn't create the connector
+ * some reason.
+ *
+ * @return an instance of JMXConnector if a provider was found from
+ * which one could be instantiated, {@code null} otherwise.
+ */
private static JMXConnector getConnectorAsService(ClassLoader loader,
JMXServiceURL url,
- Map<String, ?> map)
+ Map<String, ?> map,
+ Predicate<Provider<?>> filter)
throws IOException {
- Iterator<JMXConnectorProvider> providers =
- getProviderIterator(JMXConnectorProvider.class, loader);
- JMXConnector connection;
- IOException exception = null;
- while (providers.hasNext()) {
- JMXConnectorProvider provider = providers.next();
- try {
- connection = provider.newJMXConnector(url, map);
- return connection;
- } catch (JMXProviderException e) {
- throw e;
- } catch (Exception e) {
- if (logger.traceOn())
- logger.trace("getConnectorAsService",
- "URL[" + url +
- "] Service provider exception: " + e);
- if (!(e instanceof MalformedURLException)) {
- if (exception == null) {
- if (e instanceof IOException) {
- exception = (IOException) e;
- } else {
- exception = EnvHelp.initCause(
- new IOException(e.getMessage()), e);
+ final ConnectorFactory<JMXConnectorProvider, JMXConnector> factory =
+ (p) -> p.newJMXConnector(url, map);
+ return getConnectorAsService(JMXConnectorProvider.class, loader, url,
+ filter, factory);
+ }
+
+
+ /**
+ * A factory function that can create a connector from a provider.
+ * The pair (P,C) will be either one of:
+ * a. (JMXConnectorProvider, JMXConnector) or
+ * b. (JMXConnectorServerProvider, JMXConnectorServer)
+ */
+ @FunctionalInterface
+ static interface ConnectorFactory<P,C> {
+ public C apply(P provider) throws Exception;
+ }
+
+ /**
+ * An instance of ProviderFinder is used to traverse a
+ * {@code Stream<Provider<P>>} and find the first implementation of P
+ * that supports creating a connector C from the given JMXServiceURL.
+ * <p>
+ * The pair (P,C) will be either one of: <br>
+ * a. (JMXConnectorProvider, JMXConnector) or <br>
+ * b. (JMXConnectorServerProvider, JMXConnectorServer)
+ * <p>
+ * The first connector successfully created while traversing the stream
+ * is stored in the ProviderFinder instance. After that, the
+ * ProviderFinder::test method, if called, will always return false, skipping
+ * the remaining providers.
+ * <p>
+ * An instance of ProviderFinder is always expected to be used in conjunction
+ * with Stream::findFirst, so that the stream traversal is stopped as soon
+ * as a matching provider is found.
+ * <p>
+ * At the end of the stream traversal, the ProviderFinder::get method can be
+ * used to obtain the connector instance (an instance of C) that was created.
+ * If no connector could be created, and an exception was encountered while
+ * traversing the stream and attempting to create the connector, then that
+ * exception will be thrown by ProviderFinder::get, wrapped, if needed,
+ * inside an IOException.
+ * <p>
+ * If any JMXProviderException is encountered while traversing the stream and
+ * attempting to create the connector, that exception will be wrapped in an
+ * UncheckedIOException and thrown immediately within the stream, thus
+ * interrupting the traversal.
+ * <p>
+ * If no matching provider was found (no provider found or attempting
+ * factory.apply always returned null or threw a MalformedURLException,
+ * indicating the provider didn't support the protocol asked for by
+ * the JMXServiceURL), then ProviderFinder::get will simply return null.
+ */
+ private static final class ProviderFinder<P,C> implements Predicate<Provider<P>> {
+
+ final ConnectorFactory<P,C> factory;
+ final JMXServiceURL url;
+ private IOException exception = null;
+ private C connection = null;
+
+ ProviderFinder(ConnectorFactory<P,C> factory, JMXServiceURL url) {
+ this.factory = factory;
+ this.url = url;
+ }
+
+ /**
+ * Returns {@code true} for the first provider {@code sp} that can
+ * be used to obtain an instance of {@code C} from the given
+ * {@code factory}.
+ *
+ * @param sp a candidate provider for instantiating {@code C}.
+ *
+ * @throws UncheckedIOException if {@code sp} throws a
+ * JMXProviderException. The JMXProviderException is set as the
+ * root cause.
+ *
+ * @return {@code true} for the first provider {@code sp} for which
+ * {@code C} could be instantiated, {@code false} otherwise.
+ */
+ public boolean test(Provider<P> sp) {
+ if (connection == null) {
+ P provider = sp.get();
+ try {
+ connection = factory.apply(provider);
+ return connection != null;
+ } catch (JMXProviderException e) {
+ throw new UncheckedIOException(e);
+ } catch (Exception e) {
+ if (logger.traceOn())
+ logger.trace("getConnectorAsService",
+ "URL[" + url +
+ "] Service provider exception: " + e);
+ if (!(e instanceof MalformedURLException)) {
+ if (exception == null) {
+ if (e instanceof IOException) {
+ exception = (IOException) e;
+ } else {
+ exception = EnvHelp.initCause(
+ new IOException(e.getMessage()), e);
+ }
}
}
}
- continue;
+ }
+ return false;
+ }
+
+ /**
+ * Returns an instance of {@code C} if a provider was found from
+ * which {@code C} could be instantiated.
+ *
+ * @throws IOException if {@code C} could not be instantiated, and
+ * at least one provider threw an exception that wasn't a
+ * {@code MalformedURLException} or a {@code JMProviderException}.
+ *
+ * @return an instance of {@code C} if a provider was found from
+ * which {@code C} could be instantiated, {@code null} otherwise.
+ */
+ C get() throws IOException {
+ if (connection != null) return connection;
+ else if (exception != null) throw exception;
+ else return null;
+ }
+ }
+
+ /**
+ * Creates a connector from a provider loaded from the ServiceLoader.
+ * <p>
+ * The pair (P,C) will be either one of: <br>
+ * a. (JMXConnectorProvider, JMXConnector) or <br>
+ * b. (JMXConnectorServerProvider, JMXConnectorServer)
+ *
+ * @param providerClass The service type for which an implementation
+ * should be looked up from the {@code ServiceLoader}. This will
+ * be either {@code JMXConnectorProvider.class} or
+ * {@code JMXConnectorServerProvider.class}
+ *
+ * @param loader The ClassLoader to use when looking up an implementation
+ * of the service. If null, then only installed services will be
+ * considered.
+ *
+ * @param url The JMXServiceURL of the connector for which a provider is
+ * requested.
+ *
+ * @param filter A filter used to exclude or return provider
+ * implementations. Typically the filter will either exclude
+ * system services (system default implementations) or only
+ * retain those.
+ * This can allow to first look for custom implementations (e.g.
+ * deployed on the CLASSPATH with META-INF/services) and
+ * then only default to system implementations.
+ *
+ * @param factory A functional factory that can attempt to create an
+ * instance of connector {@code C} from a provider {@code P}.
+ * Typically, this is a simple wrapper over {@code
+ * JMXConnectorProvider::newJMXConnector} or {@code
+ * JMXConnectorProviderServer::newJMXConnectorServer}.
+ *
+ * @throws IOException if {@code C} could not be instantiated, and
+ * at least one provider {@code P} threw an exception that wasn't a
+ * {@code MalformedURLException} or a {@code JMProviderException}.
+ *
+ * @throws JMXProviderException if a provider {@code P} for the protocol in
+ * <code>url</code> was found, but couldn't create the connector
+ * {@code C} for some reason.
+ *
+ * @return an instance of {@code C} if a provider {@code P} was found from
+ * which one could be instantiated, {@code null} otherwise.
+ */
+ static <P,C> C getConnectorAsService(Class<P> providerClass,
+ ClassLoader loader,
+ JMXServiceURL url,
+ Predicate<Provider<?>> filter,
+ ConnectorFactory<P,C> factory)
+ throws IOException {
+
+ // sanity check
+ if (JMXConnectorProvider.class != providerClass
+ && JMXConnectorServerProvider.class != providerClass) {
+ // should never happen
+ throw new InternalError("Unsupported service interface: "
+ + providerClass.getName());
+ }
+
+ ServiceLoader<P> serviceLoader = loader == null
+ ? ServiceLoader.loadInstalled(providerClass)
+ : ServiceLoader.load(providerClass, loader);
+ Stream<Provider<P>> stream = serviceLoader.stream().filter(filter);
+ ProviderFinder<P,C> finder = new ProviderFinder<>(factory, url);
+
+ try {
+ stream.filter(finder).findFirst();
+ return finder.get();
+ } catch (UncheckedIOException e) {
+ if (e.getCause() instanceof JMXProviderException) {
+ throw (JMXProviderException) e.getCause();
+ } else {
+ throw e;
}
}
- if (exception == null)
- return null;
- else
- throw exception;
}
static <T> T getProvider(String protocol,
--- a/jdk/src/java.management/share/classes/javax/management/remote/JMXConnectorServerFactory.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.management/share/classes/javax/management/remote/JMXConnectorServerFactory.java Thu Feb 09 23:15:52 2017 +0100
@@ -30,13 +30,16 @@
import com.sun.jmx.remote.util.EnvHelp;
import java.io.IOException;
+import java.io.UncheckedIOException;
import java.net.MalformedURLException;
import java.util.Collections;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.Map;
+import java.util.ServiceLoader.Provider;
+import java.util.function.Predicate;
import javax.management.MBeanServer;
+import javax.management.remote.JMXConnectorFactory.ConnectorFactory;
/**
* <p>Factory to create JMX API connector servers. There
@@ -205,43 +208,15 @@
}
private static JMXConnectorServer
- getConnectorServerAsService(ClassLoader loader,
- JMXServiceURL url,
- Map<String, ?> map,
- MBeanServer mbs)
+ getConnectorServerAsService(ClassLoader loader, JMXServiceURL url,
+ Map<String, ?> map, MBeanServer mbs,
+ Predicate<Provider<?>> filter)
throws IOException {
- Iterator<JMXConnectorServerProvider> providers =
- JMXConnectorFactory.
- getProviderIterator(JMXConnectorServerProvider.class, loader);
-
- IOException exception = null;
- while (providers.hasNext()) {
- try {
- return providers.next().newJMXConnectorServer(url, map, mbs);
- } catch (JMXProviderException e) {
- throw e;
- } catch (Exception e) {
- if (logger.traceOn())
- logger.trace("getConnectorAsService",
- "URL[" + url +
- "] Service provider exception: " + e);
- if (!(e instanceof MalformedURLException)) {
- if (exception == null) {
- if (e instanceof IOException) {
- exception = (IOException) e;
- } else {
- exception = EnvHelp.initCause(
- new IOException(e.getMessage()), e);
- }
- }
- }
- continue;
- }
- }
- if (exception == null)
- return null;
- else
- throw exception;
+ final ConnectorFactory<JMXConnectorServerProvider,JMXConnectorServer>
+ factory = (p) -> p.newJMXConnectorServer(url, map, mbs);
+ return JMXConnectorFactory.getConnectorAsService(
+ JMXConnectorServerProvider.class,
+ loader, url, filter, factory);
}
/**
@@ -309,18 +284,22 @@
loader);
IOException exception = null;
+ JMXConnectorServer connection = null;
if (provider == null) {
+ Predicate<Provider<?>> systemProvider =
+ JMXConnectorFactory::isSystemProvider;
// Loader is null when context class loader is set to null
// and no loader has been provided in map.
// com.sun.jmx.remote.util.Service class extracted from j2se
// provider search algorithm doesn't handle well null classloader.
if (loader != null) {
try {
- JMXConnectorServer connection =
+ connection =
getConnectorServerAsService(loader,
serviceURL,
envcopy,
- mbeanServer);
+ mbeanServer,
+ systemProvider.negate());
if (connection != null)
return connection;
} catch (JMXProviderException e) {
@@ -329,13 +308,13 @@
exception = e;
}
}
- provider =
- JMXConnectorFactory.getProvider(
- protocol,
- PROTOCOL_PROVIDER_DEFAULT_PACKAGE,
- JMXConnectorFactory.class.getClassLoader(),
- providerClassName,
- targetInterface);
+ connection = getConnectorServerAsService(
+ JMXConnectorFactory.class.getClassLoader(),
+ serviceURL,
+ Collections.unmodifiableMap(envcopy),
+ mbeanServer,
+ systemProvider);
+ if (connection != null) return connection;
}
if (provider == null) {
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/NoCallStackClassLoader.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,296 +0,0 @@
-/*
- * Copyright (c) 2003, 2015, 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 javax.management.remote.rmi;
-
-import java.security.ProtectionDomain;
-
-/**
- <p>A class loader that only knows how to define a limited number
- of classes, and load a limited number of other classes through
- delegation to another loader. It is used to get around a problem
- with Serialization, in particular as used by RMI. The JMX Remote API
- defines exactly what class loader must be used to deserialize arguments on
- the server, and return values on the client. We communicate this class
- loader to RMI by setting it as the context class loader. RMI uses the
- context class loader to load classes as it deserializes, which is what we
- want. However, before consulting the context class loader, it
- looks up the call stack for a class with a non-null class loader,
- and uses that if it finds one. So, in the standalone version of
- javax.management.remote, if the class you're looking for is known
- to the loader of jmxremote.jar (typically the system class loader)
- then that loader will load it. This contradicts the class-loading
- semantics required.
-
- <p>We get around the problem by ensuring that the search up the
- call stack will find a non-null class loader that doesn't load any
- classes of interest, namely this one. So even though this loader
- is indeed consulted during deserialization, it never finds the
- class being deserialized. RMI then proceeds to use the context
- class loader, as we require.
-
- <p>This loader is constructed with the name and byte-code of one
- or more classes that it defines, and a class-loader to which it
- will delegate certain other classes required by that byte-code.
- We construct the byte-code somewhat painstakingly, by compiling
- the Java code directly, converting into a string, copying that
- string into the class that needs this loader, and using the
- stringToBytes method to convert it into the byte array. We
- compile with -g:none because there's not much point in having
- line-number information and the like in these directly-encoded
- classes.
-
- <p>The referencedClassNames should contain the names of all
- classes that are referenced by the classes defined by this loader.
- It is not necessary to include standard J2SE classes, however.
- Here, a class is referenced if it is the superclass or a
- superinterface of a defined class, or if it is the type of a
- field, parameter, or return value. A class is not referenced if
- it only appears in the throws clause of a method or constructor.
- Of course, referencedClassNames should not contain any classes
- that the user might want to deserialize, because the whole point
- of this loader is that it does not find such classes.
-*/
-
-class NoCallStackClassLoader extends ClassLoader {
- /** Simplified constructor when this loader only defines one class. */
- public NoCallStackClassLoader(String className,
- byte[] byteCode,
- String[] referencedClassNames,
- ClassLoader referencedClassLoader,
- ProtectionDomain protectionDomain) {
- this(new String[] {className}, new byte[][] {byteCode},
- referencedClassNames, referencedClassLoader, protectionDomain);
- }
-
- public NoCallStackClassLoader(String[] classNames,
- byte[][] byteCodes,
- String[] referencedClassNames,
- ClassLoader referencedClassLoader,
- ProtectionDomain protectionDomain) {
- super(null);
-
- /* Validation. */
- if (classNames == null || classNames.length == 0
- || byteCodes == null || classNames.length != byteCodes.length
- || referencedClassNames == null || protectionDomain == null)
- throw new IllegalArgumentException();
- for (int i = 0; i < classNames.length; i++) {
- if (classNames[i] == null || byteCodes[i] == null)
- throw new IllegalArgumentException();
- }
- for (int i = 0; i < referencedClassNames.length; i++) {
- if (referencedClassNames[i] == null)
- throw new IllegalArgumentException();
- }
-
- this.classNames = classNames;
- this.byteCodes = byteCodes;
- this.referencedClassNames = referencedClassNames;
- this.referencedClassLoader = referencedClassLoader;
- this.protectionDomain = protectionDomain;
- }
-
- /* This method is called at most once per name. Define the name
- * if it is one of the classes whose byte code we have, or
- * delegate the load if it is one of the referenced classes.
- */
- @Override
- protected Class<?> findClass(String name) throws ClassNotFoundException {
- // Note: classNames is guaranteed by the constructor to be non-null.
- for (int i = 0; i < classNames.length; i++) {
- if (name.equals(classNames[i])) {
- return defineClass(classNames[i], byteCodes[i], 0,
- byteCodes[i].length, protectionDomain);
- }
- }
-
- /* If the referencedClassLoader is null, it is the bootstrap
- * class loader, and there's no point in delegating to it
- * because it's already our parent class loader.
- */
- if (referencedClassLoader != null) {
- for (int i = 0; i < referencedClassNames.length; i++) {
- if (name.equals(referencedClassNames[i]))
- return referencedClassLoader.loadClass(name);
- }
- }
-
- throw new ClassNotFoundException(name);
- }
-
- private final String[] classNames;
- private final byte[][] byteCodes;
- private final String[] referencedClassNames;
- private final ClassLoader referencedClassLoader;
- private final ProtectionDomain protectionDomain;
-
- /**
- * <p>Construct a <code>byte[]</code> using the characters of the
- * given <code>String</code>. Only the low-order byte of each
- * character is used. This method is useful to reduce the
- * footprint of classes that include big byte arrays (e.g. the
- * byte code of other classes), because a string takes up much
- * less space in a class file than the byte code to initialize a
- * <code>byte[]</code> with the same number of bytes.</p>
- *
- * <p>We use just one byte per character even though characters
- * contain two bytes. The resultant output length is much the
- * same: using one byte per character is shorter because it has
- * more characters in the optimal 1-127 range but longer because
- * it has more zero bytes (which are frequent, and are encoded as
- * two bytes in classfile UTF-8). But one byte per character has
- * two key advantages: (1) you can see the string constants, which
- * is reassuring, (2) you don't need to know whether the class
- * file length is odd.</p>
- *
- * <p>This method differs from {@link String#getBytes()} in that
- * it does not use any encoding. So it is guaranteed that each
- * byte of the result is numerically identical (mod 256) to the
- * corresponding character of the input.
- */
- public static byte[] stringToBytes(String s) {
- final int slen = s.length();
- byte[] bytes = new byte[slen];
- for (int i = 0; i < slen; i++)
- bytes[i] = (byte) s.charAt(i);
- return bytes;
- }
-}
-
-/*
-
-You can use the following Emacs function to convert class files into
-strings to be used by the stringToBytes method above. Select the
-whole (defun...) with the mouse and type M-x eval-region, or save it
-to a file and do M-x load-file. Then visit the *.class file and do
-M-x class-string.
-
-;; class-string.el
-;; visit the *.class file with emacs, then invoke this function
-
-(defun class-string ()
- "Construct a Java string whose bytes are the same as the current
-buffer. The resultant string is put in a buffer called *string*,
-possibly with a numeric suffix like <2>. From there it can be
-insert-buffer'd into a Java program."
- (interactive)
- (let* ((s (buffer-string))
- (slen (length s))
- (i 0)
- (buf (generate-new-buffer "*string*")))
- (set-buffer buf)
- (insert "\"")
- (while (< i slen)
- (if (> (current-column) 61)
- (insert "\"+\n\""))
- (let ((c (aref s i)))
- (insert (cond
- ((> c 126) (format "\\%o" c))
- ((= c ?\") "\\\"")
- ((= c ?\\) "\\\\")
- ((< c 33)
- (let ((nextc (if (< (1+ i) slen)
- (aref s (1+ i))
- ?\0)))
- (cond
- ((and (<= nextc ?7) (>= nextc ?0))
- (format "\\%03o" c))
- (t
- (format "\\%o" c)))))
- (t c))))
- (setq i (1+ i)))
- (insert "\"")
- (switch-to-buffer buf)))
-
-Alternatively, the following class reads a class file and outputs a string
-that can be used by the stringToBytes method above.
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-
-public class BytesToString {
-
- public static void main(String[] args) throws IOException {
- File f = new File(args[0]);
- int len = (int)f.length();
- byte[] classBytes = new byte[len];
-
- FileInputStream in = new FileInputStream(args[0]);
- try {
- int pos = 0;
- for (;;) {
- int n = in.read(classBytes, pos, (len-pos));
- if (n < 0)
- throw new RuntimeException("class file changed??");
- pos += n;
- if (pos >= n)
- break;
- }
- } finally {
- in.close();
- }
-
- int pos = 0;
- boolean lastWasOctal = false;
- for (int i=0; i<len; i++) {
- int value = classBytes[i];
- if (value < 0)
- value += 256;
- String s = null;
- if (value == '\\')
- s = "\\\\";
- else if (value == '\"')
- s = "\\\"";
- else {
- if ((value >= 32 && value < 127) && ((!lastWasOctal ||
- (value < '0' || value > '7')))) {
- s = Character.toString((char)value);
- }
- }
- if (s == null) {
- s = "\\" + Integer.toString(value, 8);
- lastWasOctal = true;
- } else {
- lastWasOctal = false;
- }
- if (pos > 61) {
- System.out.print("\"");
- if (i<len)
- System.out.print("+");
- System.out.println();
- pos = 0;
- }
- if (pos == 0)
- System.out.print(" \"");
- System.out.print(s);
- pos += s.length();
- }
- System.out.println("\"");
- }
-}
-
-*/
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnection.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1092 +0,0 @@
-/*
- * Copyright (c) 2002, 2008, 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 javax.management.remote.rmi;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.rmi.MarshalledObject;
-import java.rmi.Remote;
-import java.util.Set;
-
-import javax.management.AttributeList;
-import javax.management.AttributeNotFoundException;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.IntrospectionException;
-import javax.management.InvalidAttributeValueException;
-import javax.management.ListenerNotFoundException;
-import javax.management.MBeanException;
-import javax.management.MBeanInfo;
-import javax.management.MBeanRegistrationException;
-import javax.management.MBeanServerConnection;
-import javax.management.NotCompliantMBeanException;
-
-import javax.management.ObjectInstance;
-import javax.management.ObjectName;
-import javax.management.ReflectionException;
-import javax.management.RuntimeMBeanException;
-import javax.management.RuntimeOperationsException;
-import javax.management.remote.NotificationResult;
-import javax.security.auth.Subject;
-
-/**
- * <p>RMI object used to forward an MBeanServer request from a client
- * to its MBeanServer implementation on the server side. There is one
- * Remote object implementing this interface for each remote client
- * connected to an RMI connector.</p>
- *
- * <p>User code does not usually refer to this interface. It is
- * specified as part of the public API so that different
- * implementations of that API will interoperate.</p>
- *
- * <p>To ensure that client parameters will be deserialized at the
- * server side with the correct classloader, client parameters such as
- * parameters used to invoke a method are wrapped in a {@link
- * MarshalledObject}. An implementation of this interface must first
- * get the appropriate class loader for the operation and its target,
- * then deserialize the marshalled parameters with this classloader.
- * Except as noted, a parameter that is a
- * <code>MarshalledObject</code> or <code>MarshalledObject[]</code>
- * must not be null; the behavior is unspecified if it is.</p>
- *
- * <p>Class loading aspects are detailed in the
- * <a href="{@docRoot}/../technotes/guides/jmx/JMX_1_4_specification.pdf">
- * JMX Specification, version 1.4</a> PDF document.</p>
- *
- * <p>Most methods in this interface parallel methods in the {@link
- * MBeanServerConnection} interface. Where an aspect of the behavior
- * of a method is not specified here, it is the same as in the
- * corresponding <code>MBeanServerConnection</code> method.
- *
- * @since 1.5
- */
-/*
- * Notice that we omit the type parameter from MarshalledObject everywhere,
- * even though it would add useful information to the documentation. The
- * reason is that it was only added in Mustang (Java SE 6), whereas versions
- * 1.4 and 2.0 of the JMX API must be implementable on Tiger per our
- * commitments for JSR 255. This is also why we suppress rawtypes warnings.
- */
-@SuppressWarnings("rawtypes")
-public interface RMIConnection extends Closeable, Remote {
- /**
- * <p>Returns the connection ID. This string is different for
- * every open connection to a given RMI connector server.</p>
- *
- * @return the connection ID
- *
- * @see RMIConnector#connect RMIConnector.connect
- *
- * @throws IOException if a general communication exception occurred.
- */
- public String getConnectionId() throws IOException;
-
- /**
- * <p>Closes this connection. On return from this method, the RMI
- * object implementing this interface is unexported, so further
- * remote calls to it will fail.</p>
- *
- * @throws IOException if the connection could not be closed,
- * or the Remote object could not be unexported, or there was a
- * communication failure when transmitting the remote close
- * request.
- */
- public void close() throws IOException;
-
- /**
- * Handles the method {@link
- * javax.management.MBeanServerConnection#createMBean(String,
- * ObjectName)}.
- *
- * @param className The class name of the MBean to be instantiated.
- * @param name The object name of the MBean. May be null.
- * @param delegationSubject The <code>Subject</code> containing the
- * delegation principals or <code>null</code> if the authentication
- * principal is used instead.
- *
- * @return An <code>ObjectInstance</code>, containing the
- * <code>ObjectName</code> and the Java class name of the newly
- * instantiated MBean. If the contained <code>ObjectName</code>
- * is <code>n</code>, the contained Java class name is
- * <code>{@link #getMBeanInfo getMBeanInfo(n)}.getClassName()</code>.
- *
- * @throws ReflectionException Wraps a
- * <code>java.lang.ClassNotFoundException</code> or a
- * <code>java.lang.Exception</code> that occurred
- * when trying to invoke the MBean's constructor.
- * @throws InstanceAlreadyExistsException The MBean is already
- * under the control of the MBean server.
- * @throws MBeanRegistrationException The
- * <code>preRegister</code> (<code>MBeanRegistration</code>
- * interface) method of the MBean has thrown an exception. The
- * MBean will not be registered.
- * @throws MBeanException The constructor of the MBean has
- * thrown an exception.
- * @throws NotCompliantMBeanException This class is not a JMX
- * compliant MBean.
- * @throws RuntimeOperationsException Wraps a
- * <code>java.lang.IllegalArgumentException</code>: The className
- * passed in parameter is null, the <code>ObjectName</code> passed
- * in parameter contains a pattern or no <code>ObjectName</code>
- * is specified for the MBean.
- * @throws SecurityException if the client, or the delegated Subject
- * if any, does not have permission to perform this operation.
- * @throws IOException if a general communication exception occurred.
- */
- public ObjectInstance createMBean(String className,
- ObjectName name,
- Subject delegationSubject)
- throws
- ReflectionException,
- InstanceAlreadyExistsException,
- MBeanRegistrationException,
- MBeanException,
- NotCompliantMBeanException,
- IOException;
-
- /**
- * Handles the method {@link
- * javax.management.MBeanServerConnection#createMBean(String,
- * ObjectName, ObjectName)}.
- *
- * @param className The class name of the MBean to be instantiated.
- * @param name The object name of the MBean. May be null.
- * @param loaderName The object name of the class loader to be used.
- * @param delegationSubject The <code>Subject</code> containing the
- * delegation principals or <code>null</code> if the authentication
- * principal is used instead.
- *
- * @return An <code>ObjectInstance</code>, containing the
- * <code>ObjectName</code> and the Java class name of the newly
- * instantiated MBean. If the contained <code>ObjectName</code>
- * is <code>n</code>, the contained Java class name is
- * <code>{@link #getMBeanInfo getMBeanInfo(n)}.getClassName()</code>.
- *
- * @throws ReflectionException Wraps a
- * <code>java.lang.ClassNotFoundException</code> or a
- * <code>java.lang.Exception</code> that occurred when trying to
- * invoke the MBean's constructor.
- * @throws InstanceAlreadyExistsException The MBean is already
- * under the control of the MBean server.
- * @throws MBeanRegistrationException The
- * <code>preRegister</code> (<code>MBeanRegistration</code>
- * interface) method of the MBean has thrown an exception. The
- * MBean will not be registered.
- * @throws MBeanException The constructor of the MBean has
- * thrown an exception.
- * @throws NotCompliantMBeanException This class is not a JMX
- * compliant MBean.
- * @throws InstanceNotFoundException The specified class loader
- * is not registered in the MBean server.
- * @throws RuntimeOperationsException Wraps a
- * <code>java.lang.IllegalArgumentException</code>: The className
- * passed in parameter is null, the <code>ObjectName</code> passed
- * in parameter contains a pattern or no <code>ObjectName</code>
- * is specified for the MBean.
- * @throws SecurityException if the client, or the delegated Subject
- * if any, does not have permission to perform this operation.
- * @throws IOException if a general communication exception occurred.
- */
- public ObjectInstance createMBean(String className,
- ObjectName name,
- ObjectName loaderName,
- Subject delegationSubject)
- throws
- ReflectionException,
- InstanceAlreadyExistsException,
- MBeanRegistrationException,
- MBeanException,
- NotCompliantMBeanException,
- InstanceNotFoundException,
- IOException;
-
- /**
- * Handles the method {@link
- * javax.management.MBeanServerConnection#createMBean(String,
- * ObjectName, Object[], String[])}. The <code>Object[]</code>
- * parameter is wrapped in a <code>MarshalledObject</code>.
- *
- * @param className The class name of the MBean to be instantiated.
- * @param name The object name of the MBean. May be null.
- * @param params An array containing the parameters of the
- * constructor to be invoked, encapsulated into a
- * <code>MarshalledObject</code>. The encapsulated array can be
- * null, equivalent to an empty array.
- * @param signature An array containing the signature of the
- * constructor to be invoked. Can be null, equivalent to an empty
- * array.
- * @param delegationSubject The <code>Subject</code> containing the
- * delegation principals or <code>null</code> if the authentication
- * principal is used instead.
- *
- * @return An <code>ObjectInstance</code>, containing the
- * <code>ObjectName</code> and the Java class name of the newly
- * instantiated MBean. If the contained <code>ObjectName</code>
- * is <code>n</code>, the contained Java class name is
- * <code>{@link #getMBeanInfo getMBeanInfo(n)}.getClassName()</code>.
- *
- * @throws ReflectionException Wraps a
- * <code>java.lang.ClassNotFoundException</code> or a
- * <code>java.lang.Exception</code> that occurred when trying to
- * invoke the MBean's constructor.
- * @throws InstanceAlreadyExistsException The MBean is already
- * under the control of the MBean server.
- * @throws MBeanRegistrationException The
- * <code>preRegister</code> (<code>MBeanRegistration</code>
- * interface) method of the MBean has thrown an exception. The
- * MBean will not be registered.
- * @throws MBeanException The constructor of the MBean has
- * thrown an exception.
- * @throws NotCompliantMBeanException This class is not a JMX
- * compliant MBean.
- * @throws RuntimeOperationsException Wraps a
- * <code>java.lang.IllegalArgumentException</code>: The className
- * passed in parameter is null, the <code>ObjectName</code> passed
- * in parameter contains a pattern, or no <code>ObjectName</code>
- * is specified for the MBean.
- * @throws SecurityException if the client, or the delegated Subject
- * if any, does not have permission to perform this operation.
- * @throws IOException if a general communication exception occurred.
- */
- public ObjectInstance createMBean(String className,
- ObjectName name,
- MarshalledObject params,
- String signature[],
- Subject delegationSubject)
- throws
- ReflectionException,
- InstanceAlreadyExistsException,
- MBeanRegistrationException,
- MBeanException,
- NotCompliantMBeanException,
- IOException;
-
- /**
- * Handles the method {@link
- * javax.management.MBeanServerConnection#createMBean(String,
- * ObjectName, ObjectName, Object[], String[])}. The
- * <code>Object[]</code> parameter is wrapped in a
- * <code>MarshalledObject</code>.
- *
- * @param className The class name of the MBean to be instantiated.
- * @param name The object name of the MBean. May be null.
- * @param loaderName The object name of the class loader to be used.
- * @param params An array containing the parameters of the
- * constructor to be invoked, encapsulated into a
- * <code>MarshalledObject</code>. The encapsulated array can be
- * null, equivalent to an empty array.
- * @param signature An array containing the signature of the
- * constructor to be invoked. Can be null, equivalent to an empty
- * array.
- * @param delegationSubject The <code>Subject</code> containing the
- * delegation principals or <code>null</code> if the authentication
- * principal is used instead.
- *
- * @return An <code>ObjectInstance</code>, containing the
- * <code>ObjectName</code> and the Java class name of the newly
- * instantiated MBean. If the contained <code>ObjectName</code>
- * is <code>n</code>, the contained Java class name is
- * <code>{@link #getMBeanInfo getMBeanInfo(n)}.getClassName()</code>.
- *
- * @throws ReflectionException Wraps a
- * <code>java.lang.ClassNotFoundException</code> or a
- * <code>java.lang.Exception</code> that occurred when trying to
- * invoke the MBean's constructor.
- * @throws InstanceAlreadyExistsException The MBean is already
- * under the control of the MBean server.
- * @throws MBeanRegistrationException The
- * <code>preRegister</code> (<code>MBeanRegistration</code>
- * interface) method of the MBean has thrown an exception. The
- * MBean will not be registered.
- * @throws MBeanException The constructor of the MBean has
- * thrown an exception.
- * @throws NotCompliantMBeanException This class is not a JMX
- * compliant MBean.
- * @throws InstanceNotFoundException The specified class loader
- * is not registered in the MBean server.
- * @throws RuntimeOperationsException Wraps a
- * <code>java.lang.IllegalArgumentException</code>: The className
- * passed in parameter is null, the <code>ObjectName</code> passed
- * in parameter contains a pattern, or no <code>ObjectName</code>
- * is specified for the MBean.
- * @throws SecurityException if the client, or the delegated Subject
- * if any, does not have permission to perform this operation.
- * @throws IOException if a general communication exception occurred.
- */
- public ObjectInstance createMBean(String className,
- ObjectName name,
- ObjectName loaderName,
- MarshalledObject params,
- String signature[],
- Subject delegationSubject)
- throws
- ReflectionException,
- InstanceAlreadyExistsException,
- MBeanRegistrationException,
- MBeanException,
- NotCompliantMBeanException,
- InstanceNotFoundException,
- IOException;
-
- /**
- * Handles the method
- * {@link javax.management.MBeanServerConnection#unregisterMBean(ObjectName)}.
- *
- * @param name The object name of the MBean to be unregistered.
- * @param delegationSubject The <code>Subject</code> containing the
- * delegation principals or <code>null</code> if the authentication
- * principal is used instead.
- *
- * @throws InstanceNotFoundException The MBean specified is not
- * registered in the MBean server.
- * @throws MBeanRegistrationException The preDeregister
- * ((<code>MBeanRegistration</code> interface) method of the MBean
- * has thrown an exception.
- * @throws RuntimeOperationsException Wraps a
- * <code>java.lang.IllegalArgumentException</code>: The object
- * name in parameter is null or the MBean you are when trying to
- * unregister is the {@link javax.management.MBeanServerDelegate
- * MBeanServerDelegate} MBean.
- * @throws SecurityException if the client, or the delegated Subject
- * if any, does not have permission to perform this operation.
- * @throws IOException if a general communication exception occurred.
- */
- public void unregisterMBean(ObjectName name, Subject delegationSubject)
- throws
- InstanceNotFoundException,
- MBeanRegistrationException,
- IOException;
-
- /**
- * Handles the method
- * {@link javax.management.MBeanServerConnection#getObjectInstance(ObjectName)}.
- *
- * @param name The object name of the MBean.
- * @param delegationSubject The <code>Subject</code> containing the
- * delegation principals or <code>null</code> if the authentication
- * principal is used instead.
- *
- * @return The <code>ObjectInstance</code> associated with the MBean
- * specified by <var>name</var>. The contained <code>ObjectName</code>
- * is <code>name</code> and the contained class name is
- * <code>{@link #getMBeanInfo getMBeanInfo(name)}.getClassName()</code>.
- *
- * @throws InstanceNotFoundException The MBean specified is not
- * registered in the MBean server.
- * @throws RuntimeOperationsException Wraps a
- * <code>java.lang.IllegalArgumentException</code>: The object
- * name in parameter is null.
- * @throws SecurityException if the client, or the delegated Subject
- * if any, does not have permission to perform this operation.
- * @throws IOException if a general communication exception occurred.
- */
- public ObjectInstance getObjectInstance(ObjectName name,
- Subject delegationSubject)
- throws InstanceNotFoundException, IOException;
-
- /**
- * Handles the method {@link
- * javax.management.MBeanServerConnection#queryMBeans(ObjectName,
- * QueryExp)}. The <code>QueryExp</code> is wrapped in a
- * <code>MarshalledObject</code>.
- *
- * @param name The object name pattern identifying the MBeans to
- * be retrieved. If null or no domain and key properties are
- * specified, all the MBeans registered will be retrieved.
- * @param query The query expression to be applied for selecting
- * MBeans, encapsulated into a <code>MarshalledObject</code>. If
- * the <code>MarshalledObject</code> encapsulates a null value no
- * query expression will be applied for selecting MBeans.
- * @param delegationSubject The <code>Subject</code> containing the
- * delegation principals or <code>null</code> if the authentication
- * principal is used instead.
- *
- * @return A set containing the <code>ObjectInstance</code>
- * objects for the selected MBeans. If no MBean satisfies the
- * query an empty list is returned.
- *
- * @throws SecurityException if the client, or the delegated Subject
- * if any, does not have permission to perform this operation.
- * @throws IOException if a general communication exception occurred.
- */
- public Set<ObjectInstance>
- queryMBeans(ObjectName name,
- MarshalledObject query,
- Subject delegationSubject)
- throws IOException;
-
- /**
- * Handles the method {@link
- * javax.management.MBeanServerConnection#queryNames(ObjectName,
- * QueryExp)}. The <code>QueryExp</code> is wrapped in a
- * <code>MarshalledObject</code>.
- *
- * @param name The object name pattern identifying the MBean names
- * to be retrieved. If null or no domain and key properties are
- * specified, the name of all registered MBeans will be retrieved.
- * @param query The query expression to be applied for selecting
- * MBeans, encapsulated into a <code>MarshalledObject</code>. If
- * the <code>MarshalledObject</code> encapsulates a null value no
- * query expression will be applied for selecting MBeans.
- * @param delegationSubject The <code>Subject</code> containing the
- * delegation principals or <code>null</code> if the authentication
- * principal is used instead.
- *
- * @return A set containing the ObjectNames for the MBeans
- * selected. If no MBean satisfies the query, an empty list is
- * returned.
- *
- * @throws SecurityException if the client, or the delegated Subject
- * if any, does not have permission to perform this operation.
- * @throws IOException if a general communication exception occurred.
- */
- public Set<ObjectName>
- queryNames(ObjectName name,
- MarshalledObject query,
- Subject delegationSubject)
- throws IOException;
-
- /**
- * Handles the method
- * {@link javax.management.MBeanServerConnection#isRegistered(ObjectName)}.
- *
- * @param name The object name of the MBean to be checked.
- * @param delegationSubject The <code>Subject</code> containing the
- * delegation principals or <code>null</code> if the authentication
- * principal is used instead.
- *
- * @return True if the MBean is already registered in the MBean
- * server, false otherwise.
- *
- * @throws RuntimeOperationsException Wraps a
- * <code>java.lang.IllegalArgumentException</code>: The object
- * name in parameter is null.
- * @throws SecurityException if the client, or the delegated Subject
- * if any, does not have permission to perform this operation.
- * @throws IOException if a general communication exception occurred.
- */
- public boolean isRegistered(ObjectName name, Subject delegationSubject)
- throws IOException;
-
- /**
- * Handles the method
- * {@link javax.management.MBeanServerConnection#getMBeanCount()}.
- *
- * @param delegationSubject The <code>Subject</code> containing the
- * delegation principals or <code>null</code> if the authentication
- * principal is used instead.
- *
- * @return the number of MBeans registered.
- *
- * @throws SecurityException if the client, or the delegated Subject
- * if any, does not have permission to perform this operation.
- * @throws IOException if a general communication exception occurred.
- */
- public Integer getMBeanCount(Subject delegationSubject)
- throws IOException;
-
- /**
- * Handles the method {@link
- * javax.management.MBeanServerConnection#getAttribute(ObjectName,
- * String)}.
- *
- * @param name The object name of the MBean from which the
- * attribute is to be retrieved.
- * @param attribute A String specifying the name of the attribute
- * to be retrieved.
- * @param delegationSubject The <code>Subject</code> containing the
- * delegation principals or <code>null</code> if the authentication
- * principal is used instead.
- *
- * @return The value of the retrieved attribute.
- *
- * @throws AttributeNotFoundException The attribute specified
- * is not accessible in the MBean.
- * @throws MBeanException Wraps an exception thrown by the
- * MBean's getter.
- * @throws InstanceNotFoundException The MBean specified is not
- * registered in the MBean server.
- * @throws ReflectionException Wraps a
- * <code>java.lang.Exception</code> thrown when trying to invoke
- * the getter.
- * @throws RuntimeOperationsException Wraps a
- * <code>java.lang.IllegalArgumentException</code>: The object
- * name in parameter is null or the attribute in parameter is
- * null.
- * @throws RuntimeMBeanException Wraps a runtime exception thrown
- * by the MBean's getter.
- * @throws SecurityException if the client, or the delegated Subject
- * if any, does not have permission to perform this operation.
- * @throws IOException if a general communication exception occurred.
- *
- * @see #setAttribute
- */
- public Object getAttribute(ObjectName name,
- String attribute,
- Subject delegationSubject)
- throws
- MBeanException,
- AttributeNotFoundException,
- InstanceNotFoundException,
- ReflectionException,
- IOException;
-
- /**
- * Handles the method {@link
- * javax.management.MBeanServerConnection#getAttributes(ObjectName,
- * String[])}.
- *
- * @param name The object name of the MBean from which the
- * attributes are retrieved.
- * @param attributes A list of the attributes to be retrieved.
- * @param delegationSubject The <code>Subject</code> containing the
- * delegation principals or <code>null</code> if the authentication
- * principal is used instead.
- *
- * @return The list of the retrieved attributes.
- *
- * @throws InstanceNotFoundException The MBean specified is not
- * registered in the MBean server.
- * @throws ReflectionException An exception occurred when
- * trying to invoke the getAttributes method of a Dynamic MBean.
- * @throws RuntimeOperationsException Wrap a
- * <code>java.lang.IllegalArgumentException</code>: The object
- * name in parameter is null or attributes in parameter is null.
- * @throws SecurityException if the client, or the delegated Subject
- * if any, does not have permission to perform this operation.
- * @throws IOException if a general communication exception occurred.
- *
- * @see #setAttributes
- */
- public AttributeList getAttributes(ObjectName name,
- String[] attributes,
- Subject delegationSubject)
- throws
- InstanceNotFoundException,
- ReflectionException,
- IOException;
-
- /**
- * Handles the method {@link
- * javax.management.MBeanServerConnection#setAttribute(ObjectName,
- * Attribute)}. The <code>Attribute</code> parameter is wrapped
- * in a <code>MarshalledObject</code>.
- *
- * @param name The name of the MBean within which the attribute is
- * to be set.
- * @param attribute The identification of the attribute to be set
- * and the value it is to be set to, encapsulated into a
- * <code>MarshalledObject</code>.
- * @param delegationSubject The <code>Subject</code> containing the
- * delegation principals or <code>null</code> if the authentication
- * principal is used instead.
- *
- * @throws InstanceNotFoundException The MBean specified is not
- * registered in the MBean server.
- * @throws AttributeNotFoundException The attribute specified
- * is not accessible in the MBean.
- * @throws InvalidAttributeValueException The value specified
- * for the attribute is not valid.
- * @throws MBeanException Wraps an exception thrown by the
- * MBean's setter.
- * @throws ReflectionException Wraps a
- * <code>java.lang.Exception</code> thrown when trying to invoke
- * the setter.
- * @throws RuntimeOperationsException Wraps a
- * <code>java.lang.IllegalArgumentException</code>: The object
- * name in parameter is null or the attribute in parameter is
- * null.
- * @throws SecurityException if the client, or the delegated Subject
- * if any, does not have permission to perform this operation.
- * @throws IOException if a general communication exception occurred.
- *
- * @see #getAttribute
- */
- public void setAttribute(ObjectName name,
- MarshalledObject attribute,
- Subject delegationSubject)
- throws
- InstanceNotFoundException,
- AttributeNotFoundException,
- InvalidAttributeValueException,
- MBeanException,
- ReflectionException,
- IOException;
-
- /**
- * Handles the method {@link
- * javax.management.MBeanServerConnection#setAttributes(ObjectName,
- * AttributeList)}. The <code>AttributeList</code> parameter is
- * wrapped in a <code>MarshalledObject</code>.
- *
- * @param name The object name of the MBean within which the
- * attributes are to be set.
- * @param attributes A list of attributes: The identification of
- * the attributes to be set and the values they are to be set to,
- * encapsulated into a <code>MarshalledObject</code>.
- * @param delegationSubject The <code>Subject</code> containing the
- * delegation principals or <code>null</code> if the authentication
- * principal is used instead.
- *
- * @return The list of attributes that were set, with their new
- * values.
- *
- * @throws InstanceNotFoundException The MBean specified is not
- * registered in the MBean server.
- * @throws ReflectionException An exception occurred when
- * trying to invoke the getAttributes method of a Dynamic MBean.
- * @throws RuntimeOperationsException Wraps a
- * <code>java.lang.IllegalArgumentException</code>: The object
- * name in parameter is null or attributes in parameter is null.
- * @throws SecurityException if the client, or the delegated Subject
- * if any, does not have permission to perform this operation.
- * @throws IOException if a general communication exception occurred.
- *
- * @see #getAttributes
- */
- public AttributeList setAttributes(ObjectName name,
- MarshalledObject attributes,
- Subject delegationSubject)
- throws
- InstanceNotFoundException,
- ReflectionException,
- IOException;
-
- /**
- * Handles the method {@link
- * javax.management.MBeanServerConnection#invoke(ObjectName,
- * String, Object[], String[])}. The <code>Object[]</code>
- * parameter is wrapped in a <code>MarshalledObject</code>.
- *
- * @param name The object name of the MBean on which the method is
- * to be invoked.
- * @param operationName The name of the operation to be invoked.
- * @param params An array containing the parameters to be set when
- * the operation is invoked, encapsulated into a
- * <code>MarshalledObject</code>. The encapsulated array can be
- * null, equivalent to an empty array.
- * @param signature An array containing the signature of the
- * operation. The class objects will be loaded using the same
- * class loader as the one used for loading the MBean on which the
- * operation was invoked. Can be null, equivalent to an empty
- * array.
- * @param delegationSubject The <code>Subject</code> containing the
- * delegation principals or <code>null</code> if the authentication
- * principal is used instead.
- *
- * @return The object returned by the operation, which represents
- * the result of invoking the operation on the MBean specified.
- *
- * @throws InstanceNotFoundException The MBean specified is not
- * registered in the MBean server.
- * @throws MBeanException Wraps an exception thrown by the
- * MBean's invoked method.
- * @throws ReflectionException Wraps a
- * <code>java.lang.Exception</code> thrown while trying to invoke
- * the method.
- * @throws SecurityException if the client, or the delegated Subject
- * if any, does not have permission to perform this operation.
- * @throws IOException if a general communication exception occurred.
- * @throws RuntimeOperationsException Wraps an {@link
- * IllegalArgumentException} when <code>name</code> or
- * <code>operationName</code> is null.
- */
- public Object invoke(ObjectName name,
- String operationName,
- MarshalledObject params,
- String signature[],
- Subject delegationSubject)
- throws
- InstanceNotFoundException,
- MBeanException,
- ReflectionException,
- IOException;
-
- /**
- * Handles the method
- * {@link javax.management.MBeanServerConnection#getDefaultDomain()}.
- *
- * @param delegationSubject The <code>Subject</code> containing the
- * delegation principals or <code>null</code> if the authentication
- * principal is used instead.
- *
- * @return the default domain.
- *
- * @throws SecurityException if the client, or the delegated Subject
- * if any, does not have permission to perform this operation.
- * @throws IOException if a general communication exception occurred.
- */
- public String getDefaultDomain(Subject delegationSubject)
- throws IOException;
-
- /**
- * Handles the method
- * {@link javax.management.MBeanServerConnection#getDomains()}.
- *
- * @param delegationSubject The <code>Subject</code> containing the
- * delegation principals or <code>null</code> if the authentication
- * principal is used instead.
- *
- * @return the list of domains.
- *
- * @throws SecurityException if the client, or the delegated Subject
- * if any, does not have permission to perform this operation.
- * @throws IOException if a general communication exception occurred.
- */
- public String[] getDomains(Subject delegationSubject)
- throws IOException;
-
- /**
- * Handles the method
- * {@link javax.management.MBeanServerConnection#getMBeanInfo(ObjectName)}.
- *
- * @param name The name of the MBean to analyze
- * @param delegationSubject The <code>Subject</code> containing the
- * delegation principals or <code>null</code> if the authentication
- * principal is used instead.
- *
- * @return An instance of <code>MBeanInfo</code> allowing the
- * retrieval of all attributes and operations of this MBean.
- *
- * @throws IntrospectionException An exception occurred during
- * introspection.
- * @throws InstanceNotFoundException The MBean specified was
- * not found.
- * @throws ReflectionException An exception occurred when
- * trying to invoke the getMBeanInfo of a Dynamic MBean.
- * @throws SecurityException if the client, or the delegated Subject
- * if any, does not have permission to perform this operation.
- * @throws IOException if a general communication exception occurred.
- * @throws RuntimeOperationsException Wraps a
- * <code>java.lang.IllegalArgumentException</code>: The object
- * name in parameter is null.
- */
- public MBeanInfo getMBeanInfo(ObjectName name, Subject delegationSubject)
- throws
- InstanceNotFoundException,
- IntrospectionException,
- ReflectionException,
- IOException;
-
- /**
- * Handles the method {@link
- * javax.management.MBeanServerConnection#isInstanceOf(ObjectName,
- * String)}.
- *
- * @param name The <code>ObjectName</code> of the MBean.
- * @param className The name of the class.
- * @param delegationSubject The <code>Subject</code> containing the
- * delegation principals or <code>null</code> if the authentication
- * principal is used instead.
- *
- * @return true if the MBean specified is an instance of the
- * specified class according to the rules above, false otherwise.
- *
- * @throws InstanceNotFoundException The MBean specified is not
- * registered in the MBean server.
- * @throws SecurityException if the client, or the delegated Subject
- * if any, does not have permission to perform this operation.
- * @throws IOException if a general communication exception occurred.
- * @throws RuntimeOperationsException Wraps a
- * <code>java.lang.IllegalArgumentException</code>: The object
- * name in parameter is null.
- */
- public boolean isInstanceOf(ObjectName name,
- String className,
- Subject delegationSubject)
- throws InstanceNotFoundException, IOException;
-
- /**
- * Handles the method {@link
- * javax.management.MBeanServerConnection#addNotificationListener(ObjectName,
- * ObjectName, NotificationFilter, Object)}. The
- * <code>NotificationFilter</code> parameter is wrapped in a
- * <code>MarshalledObject</code>. The <code>Object</code>
- * (handback) parameter is also wrapped in a
- * <code>MarshalledObject</code>.
- *
- * @param name The name of the MBean on which the listener should
- * be added.
- * @param listener The object name of the listener which will
- * handle the notifications emitted by the registered MBean.
- * @param filter The filter object, encapsulated into a
- * <code>MarshalledObject</code>. If filter encapsulated in the
- * <code>MarshalledObject</code> has a null value, no filtering
- * will be performed before handling notifications.
- * @param handback The context to be sent to the listener when a
- * notification is emitted, encapsulated into a
- * <code>MarshalledObject</code>.
- * @param delegationSubject The <code>Subject</code> containing the
- * delegation principals or <code>null</code> if the authentication
- * principal is used instead.
- *
- * @throws InstanceNotFoundException The MBean name of the
- * notification listener or of the notification broadcaster does
- * not match any of the registered MBeans.
- * @throws RuntimeOperationsException Wraps an {@link
- * IllegalArgumentException}. The MBean named by
- * <code>listener</code> exists but does not implement the
- * {@link javax.management.NotificationListener} interface,
- * or <code>name</code> or <code>listener</code> is null.
- * @throws SecurityException if the client, or the delegated Subject
- * if any, does not have permission to perform this operation.
- * @throws IOException if a general communication exception occurred.
- *
- * @see #removeNotificationListener(ObjectName, ObjectName, Subject)
- * @see #removeNotificationListener(ObjectName, ObjectName,
- * MarshalledObject, MarshalledObject, Subject)
- */
- public void addNotificationListener(ObjectName name,
- ObjectName listener,
- MarshalledObject filter,
- MarshalledObject handback,
- Subject delegationSubject)
- throws InstanceNotFoundException, IOException;
-
- /**
- * Handles the method {@link
- * javax.management.MBeanServerConnection#removeNotificationListener(ObjectName,
- * ObjectName)}.
- *
- * @param name The name of the MBean on which the listener should
- * be removed.
- * @param listener The object name of the listener to be removed.
- * @param delegationSubject The <code>Subject</code> containing the
- * delegation principals or <code>null</code> if the authentication
- * principal is used instead.
- *
- * @throws InstanceNotFoundException The MBean name provided
- * does not match any of the registered MBeans.
- * @throws ListenerNotFoundException The listener is not
- * registered in the MBean.
- * @throws SecurityException if the client, or the delegated Subject
- * if any, does not have permission to perform this operation.
- * @throws IOException if a general communication exception occurred.
- * @throws RuntimeOperationsException Wraps an {@link
- * IllegalArgumentException} when <code>name</code> or
- * <code>listener</code> is null.
- *
- * @see #addNotificationListener
- */
- public void removeNotificationListener(ObjectName name,
- ObjectName listener,
- Subject delegationSubject)
- throws
- InstanceNotFoundException,
- ListenerNotFoundException,
- IOException;
-
- /**
- * Handles the method {@link
- * javax.management.MBeanServerConnection#removeNotificationListener(ObjectName,
- * ObjectName, NotificationFilter, Object)}. The
- * <code>NotificationFilter</code> parameter is wrapped in a
- * <code>MarshalledObject</code>. The <code>Object</code>
- * parameter is also wrapped in a <code>MarshalledObject</code>.
- *
- * @param name The name of the MBean on which the listener should
- * be removed.
- * @param listener A listener that was previously added to this
- * MBean.
- * @param filter The filter that was specified when the listener
- * was added, encapsulated into a <code>MarshalledObject</code>.
- * @param handback The handback that was specified when the
- * listener was added, encapsulated into a <code>MarshalledObject</code>.
- * @param delegationSubject The <code>Subject</code> containing the
- * delegation principals or <code>null</code> if the authentication
- * principal is used instead.
- *
- * @throws InstanceNotFoundException The MBean name provided
- * does not match any of the registered MBeans.
- * @throws ListenerNotFoundException The listener is not
- * registered in the MBean, or it is not registered with the given
- * filter and handback.
- * @throws SecurityException if the client, or the delegated Subject
- * if any, does not have permission to perform this operation.
- * @throws IOException if a general communication exception occurred.
- * @throws RuntimeOperationsException Wraps an {@link
- * IllegalArgumentException} when <code>name</code> or
- * <code>listener</code> is null.
- *
- * @see #addNotificationListener
- */
- public void removeNotificationListener(ObjectName name,
- ObjectName listener,
- MarshalledObject filter,
- MarshalledObject handback,
- Subject delegationSubject)
- throws
- InstanceNotFoundException,
- ListenerNotFoundException,
- IOException;
-
- // Special Handling of Notifications -------------------------------------
-
- /**
- * <p>Handles the method {@link
- * javax.management.MBeanServerConnection#addNotificationListener(ObjectName,
- * NotificationListener, NotificationFilter, Object)}.</p>
- *
- * <p>Register for notifications from the given MBeans that match
- * the given filters. The remote client can subsequently retrieve
- * the notifications using the {@link #fetchNotifications
- * fetchNotifications} method.</p>
- *
- * <p>For each listener, the original
- * <code>NotificationListener</code> and <code>handback</code> are
- * kept on the client side; in order for the client to be able to
- * identify them, the server generates and returns a unique
- * <code>listenerID</code>. This <code>listenerID</code> is
- * forwarded with the <code>Notifications</code> to the remote
- * client.</p>
- *
- * <p>If any one of the given (name, filter) pairs cannot be
- * registered, then the operation fails with an exception, and no
- * names or filters are registered.</p>
- *
- * @param names the <code>ObjectNames</code> identifying the
- * MBeans emitting the Notifications.
- * @param filters an array of marshalled representations of the
- * <code>NotificationFilters</code>. Elements of this array can
- * be null.
- * @param delegationSubjects the <code>Subjects</code> on behalf
- * of which the listeners are being added. Elements of this array
- * can be null. Also, the <code>delegationSubjects</code>
- * parameter itself can be null, which is equivalent to an array
- * of null values with the same size as the <code>names</code> and
- * <code>filters</code> arrays.
- *
- * @return an array of <code>listenerIDs</code> identifying the
- * local listeners. This array has the same number of elements as
- * the parameters.
- *
- * @throws IllegalArgumentException if <code>names</code> or
- * <code>filters</code> is null, or if <code>names</code> contains
- * a null element, or if the three arrays do not all have the same
- * size.
- * @throws ClassCastException if one of the elements of
- * <code>filters</code> unmarshalls as a non-null object that is
- * not a <code>NotificationFilter</code>.
- * @throws InstanceNotFoundException if one of the
- * <code>names</code> does not correspond to any registered MBean.
- * @throws SecurityException if, for one of the MBeans, the
- * client, or the delegated Subject if any, does not have
- * permission to add a listener.
- * @throws IOException if a general communication exception occurred.
- */
- public Integer[] addNotificationListeners(ObjectName[] names,
- MarshalledObject[] filters,
- Subject[] delegationSubjects)
- throws InstanceNotFoundException, IOException;
-
- /**
- * <p>Handles the
- * {@link javax.management.MBeanServerConnection#removeNotificationListener(ObjectName,NotificationListener)
- * removeNotificationListener(ObjectName, NotificationListener)} and
- * {@link javax.management.MBeanServerConnection#removeNotificationListener(ObjectName,NotificationListener,NotificationFilter,Object)
- * removeNotificationListener(ObjectName, NotificationListener, NotificationFilter, Object)} methods.</p>
- *
- * <p>This method removes one or more
- * <code>NotificationListener</code>s from a given MBean in the
- * MBean server.</p>
- *
- * <p>The <code>NotificationListeners</code> are identified by the
- * IDs which were returned by the {@link
- * #addNotificationListeners(ObjectName[], MarshalledObject[],
- * Subject[])} method.</p>
- *
- * @param name the <code>ObjectName</code> identifying the MBean
- * emitting the Notifications.
- * @param listenerIDs the list of the IDs corresponding to the
- * listeners to remove.
- * @param delegationSubject The <code>Subject</code> containing the
- * delegation principals or <code>null</code> if the authentication
- * principal is used instead.
- *
- * @throws InstanceNotFoundException if the given
- * <code>name</code> does not correspond to any registered MBean.
- * @throws ListenerNotFoundException if one of the listeners was
- * not found on the server side. This exception can happen if the
- * MBean discarded a listener for some reason other than a call to
- * <code>MBeanServer.removeNotificationListener</code>.
- * @throws SecurityException if the client, or the delegated Subject
- * if any, does not have permission to remove the listeners.
- * @throws IOException if a general communication exception occurred.
- * @throws IllegalArgumentException if <code>ObjectName</code> or
- * <code>listenerIds</code> is null or if <code>listenerIds</code>
- * contains a null element.
- */
- public void removeNotificationListeners(ObjectName name,
- Integer[] listenerIDs,
- Subject delegationSubject)
- throws
- InstanceNotFoundException,
- ListenerNotFoundException,
- IOException;
-
- /**
- * <p>Retrieves notifications from the connector server. This
- * method can block until there is at least one notification or
- * until the specified timeout is reached. The method can also
- * return at any time with zero notifications.</p>
- *
- * <p>A notification can be included in the result if its sequence
- * number is no less than <code>clientSequenceNumber</code> and
- * this client has registered at least one listener for the MBean
- * generating the notification, with a filter that accepts the
- * notification. Each listener that is interested in the
- * notification is identified by an Integer ID that was returned
- * by {@link #addNotificationListeners(ObjectName[],
- * MarshalledObject[], Subject[])}.</p>
- *
- * @param clientSequenceNumber the first sequence number that the
- * client is interested in. If negative, it is interpreted as
- * meaning the sequence number that the next notification will
- * have.
- *
- * @param maxNotifications the maximum number of different
- * notifications to return. The <code>TargetedNotification</code>
- * array in the returned <code>NotificationResult</code> can have
- * more elements than this if the same notification appears more
- * than once. The behavior is unspecified if this parameter is
- * negative.
- *
- * @param timeout the maximum time in milliseconds to wait for a
- * notification to arrive. This can be 0 to indicate that the
- * method should not wait if there are no notifications, but
- * should return at once. It can be <code>Long.MAX_VALUE</code>
- * to indicate that there is no timeout. The behavior is
- * unspecified if this parameter is negative.
- *
- * @return A <code>NotificationResult</code>.
- *
- * @throws IOException if a general communication exception occurred.
- */
- public NotificationResult fetchNotifications(long clientSequenceNumber,
- int maxNotifications,
- long timeout)
- throws IOException;
-}
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1834 +0,0 @@
-/*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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 javax.management.remote.rmi;
-
-import java.io.IOException;
-import java.rmi.MarshalledObject;
-import java.rmi.UnmarshalException;
-import java.rmi.server.Unreferenced;
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.Permission;
-import java.security.Permissions;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.security.ProtectionDomain;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
-
-import javax.management.*;
-import javax.management.remote.JMXServerErrorException;
-import javax.management.remote.NotificationResult;
-import javax.security.auth.Subject;
-import sun.reflect.misc.ReflectUtil;
-
-import static com.sun.jmx.mbeanserver.Util.cast;
-import com.sun.jmx.remote.internal.ServerCommunicatorAdmin;
-import com.sun.jmx.remote.internal.ServerNotifForwarder;
-import com.sun.jmx.remote.security.JMXSubjectDomainCombiner;
-import com.sun.jmx.remote.security.SubjectDelegator;
-import com.sun.jmx.remote.util.ClassLoaderWithRepository;
-import com.sun.jmx.remote.util.ClassLogger;
-import com.sun.jmx.remote.util.EnvHelp;
-import com.sun.jmx.remote.util.OrderClassLoaders;
-import javax.management.loading.ClassLoaderRepository;
-
-/**
- * <p>Implementation of the {@link RMIConnection} interface. User
- * code will not usually reference this class.</p>
- *
- * @since 1.5
- */
-/*
- * Notice that we omit the type parameter from MarshalledObject everywhere,
- * even though it would add useful information to the documentation. The
- * reason is that it was only added in Mustang (Java SE 6), whereas versions
- * 1.4 and 2.0 of the JMX API must be implementable on Tiger per our
- * commitments for JSR 255.
- */
-public class RMIConnectionImpl implements RMIConnection, Unreferenced {
-
- /**
- * Constructs a new {@link RMIConnection}. This connection can be
- * used with the JRMP transport. This object does
- * not export itself: it is the responsibility of the caller to
- * export it appropriately (see {@link
- * RMIJRMPServerImpl#makeClient(String,Subject)}).
- *
- * @param rmiServer The RMIServerImpl object for which this
- * connection is created. The behavior is unspecified if this
- * parameter is null.
- * @param connectionId The ID for this connection. The behavior
- * is unspecified if this parameter is null.
- * @param defaultClassLoader The default ClassLoader to be used
- * when deserializing marshalled objects. Can be null, to signify
- * the bootstrap class loader.
- * @param subject the authenticated subject to be used for
- * authorization. Can be null, to signify that no subject has
- * been authenticated.
- * @param env the environment containing attributes for the new
- * <code>RMIServerImpl</code>. Can be null, equivalent to an
- * empty map.
- */
- public RMIConnectionImpl(RMIServerImpl rmiServer,
- String connectionId,
- ClassLoader defaultClassLoader,
- Subject subject,
- Map<String,?> env) {
- if (rmiServer == null || connectionId == null)
- throw new NullPointerException("Illegal null argument");
- if (env == null)
- env = Collections.emptyMap();
- this.rmiServer = rmiServer;
- this.connectionId = connectionId;
- this.defaultClassLoader = defaultClassLoader;
-
- this.subjectDelegator = new SubjectDelegator();
- this.subject = subject;
- if (subject == null) {
- this.acc = null;
- this.removeCallerContext = false;
- } else {
- this.removeCallerContext =
- SubjectDelegator.checkRemoveCallerContext(subject);
- if (this.removeCallerContext) {
- this.acc =
- JMXSubjectDomainCombiner.getDomainCombinerContext(subject);
- } else {
- this.acc =
- JMXSubjectDomainCombiner.getContext(subject);
- }
- }
- this.mbeanServer = rmiServer.getMBeanServer();
-
- final ClassLoader dcl = defaultClassLoader;
-
- ClassLoaderRepository repository = AccessController.doPrivileged(
- new PrivilegedAction<ClassLoaderRepository>() {
- public ClassLoaderRepository run() {
- return mbeanServer.getClassLoaderRepository();
- }
- },
- withPermissions(new MBeanPermission("*", "getClassLoaderRepository"))
- );
- this.classLoaderWithRepository = AccessController.doPrivileged(
- new PrivilegedAction<ClassLoaderWithRepository>() {
- public ClassLoaderWithRepository run() {
- return new ClassLoaderWithRepository(
- repository,
- dcl);
- }
- },
- withPermissions(new RuntimePermission("createClassLoader"))
- );
-
- this.defaultContextClassLoader =
- AccessController.doPrivileged(
- new PrivilegedAction<ClassLoader>() {
- @Override
- public ClassLoader run() {
- return new CombinedClassLoader(Thread.currentThread().getContextClassLoader(),
- dcl);
- }
- });
-
- serverCommunicatorAdmin = new
- RMIServerCommunicatorAdmin(EnvHelp.getServerConnectionTimeout(env));
-
- this.env = env;
- }
-
- private static AccessControlContext withPermissions(Permission ... perms){
- Permissions col = new Permissions();
-
- for (Permission thePerm : perms ) {
- col.add(thePerm);
- }
-
- final ProtectionDomain pd = new ProtectionDomain(null, col);
- return new AccessControlContext( new ProtectionDomain[] { pd });
- }
-
- private synchronized ServerNotifForwarder getServerNotifFwd() {
- // Lazily created when first use. Mainly when
- // addNotificationListener is first called.
- if (serverNotifForwarder == null)
- serverNotifForwarder =
- new ServerNotifForwarder(mbeanServer,
- env,
- rmiServer.getNotifBuffer(),
- connectionId);
- return serverNotifForwarder;
- }
-
- public String getConnectionId() throws IOException {
- // We should call reqIncomming() here... shouldn't we?
- return connectionId;
- }
-
- public void close() throws IOException {
- final boolean debug = logger.debugOn();
- final String idstr = (debug?"["+this.toString()+"]":null);
-
- synchronized (this) {
- if (terminated) {
- if (debug) logger.debug("close",idstr + " already terminated.");
- return;
- }
-
- if (debug) logger.debug("close",idstr + " closing.");
-
- terminated = true;
-
- if (serverCommunicatorAdmin != null) {
- serverCommunicatorAdmin.terminate();
- }
-
- if (serverNotifForwarder != null) {
- serverNotifForwarder.terminate();
- }
- }
-
- rmiServer.clientClosed(this);
-
- if (debug) logger.debug("close",idstr + " closed.");
- }
-
- public void unreferenced() {
- logger.debug("unreferenced", "called");
- try {
- close();
- logger.debug("unreferenced", "done");
- } catch (IOException e) {
- logger.fine("unreferenced", e);
- }
- }
-
- //-------------------------------------------------------------------------
- // MBeanServerConnection Wrapper
- //-------------------------------------------------------------------------
-
- public ObjectInstance createMBean(String className,
- ObjectName name,
- Subject delegationSubject)
- throws
- ReflectionException,
- InstanceAlreadyExistsException,
- MBeanRegistrationException,
- MBeanException,
- NotCompliantMBeanException,
- IOException {
- try {
- final Object params[] =
- new Object[] { className, name };
-
- if (logger.debugOn())
- logger.debug("createMBean(String,ObjectName)",
- "connectionId=" + connectionId +", className=" +
- className+", name=" + name);
-
- return (ObjectInstance)
- doPrivilegedOperation(
- CREATE_MBEAN,
- params,
- delegationSubject);
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof ReflectionException)
- throw (ReflectionException) e;
- if (e instanceof InstanceAlreadyExistsException)
- throw (InstanceAlreadyExistsException) e;
- if (e instanceof MBeanRegistrationException)
- throw (MBeanRegistrationException) e;
- if (e instanceof MBeanException)
- throw (MBeanException) e;
- if (e instanceof NotCompliantMBeanException)
- throw (NotCompliantMBeanException) e;
- if (e instanceof IOException)
- throw (IOException) e;
- throw newIOException("Got unexpected server exception: " + e, e);
- }
- }
-
- public ObjectInstance createMBean(String className,
- ObjectName name,
- ObjectName loaderName,
- Subject delegationSubject)
- throws
- ReflectionException,
- InstanceAlreadyExistsException,
- MBeanRegistrationException,
- MBeanException,
- NotCompliantMBeanException,
- InstanceNotFoundException,
- IOException {
- try {
- final Object params[] =
- new Object[] { className, name, loaderName };
-
- if (logger.debugOn())
- logger.debug("createMBean(String,ObjectName,ObjectName)",
- "connectionId=" + connectionId
- +", className=" + className
- +", name=" + name
- +", loaderName=" + loaderName);
-
- return (ObjectInstance)
- doPrivilegedOperation(
- CREATE_MBEAN_LOADER,
- params,
- delegationSubject);
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof ReflectionException)
- throw (ReflectionException) e;
- if (e instanceof InstanceAlreadyExistsException)
- throw (InstanceAlreadyExistsException) e;
- if (e instanceof MBeanRegistrationException)
- throw (MBeanRegistrationException) e;
- if (e instanceof MBeanException)
- throw (MBeanException) e;
- if (e instanceof NotCompliantMBeanException)
- throw (NotCompliantMBeanException) e;
- if (e instanceof InstanceNotFoundException)
- throw (InstanceNotFoundException) e;
- if (e instanceof IOException)
- throw (IOException) e;
- throw newIOException("Got unexpected server exception: " + e, e);
- }
- }
-
- @SuppressWarnings("rawtypes") // MarshalledObject
- public ObjectInstance createMBean(String className,
- ObjectName name,
- MarshalledObject params,
- String signature[],
- Subject delegationSubject)
- throws
- ReflectionException,
- InstanceAlreadyExistsException,
- MBeanRegistrationException,
- MBeanException,
- NotCompliantMBeanException,
- IOException {
-
- final Object[] values;
- final boolean debug = logger.debugOn();
-
- if (debug) logger.debug(
- "createMBean(String,ObjectName,Object[],String[])",
- "connectionId=" + connectionId
- +", unwrapping parameters using classLoaderWithRepository.");
-
- values =
- nullIsEmpty(unwrap(params, classLoaderWithRepository, Object[].class,delegationSubject));
-
- try {
- final Object params2[] =
- new Object[] { className, name, values,
- nullIsEmpty(signature) };
-
- if (debug)
- logger.debug("createMBean(String,ObjectName,Object[],String[])",
- "connectionId=" + connectionId
- +", className=" + className
- +", name=" + name
- +", signature=" + strings(signature));
-
- return (ObjectInstance)
- doPrivilegedOperation(
- CREATE_MBEAN_PARAMS,
- params2,
- delegationSubject);
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof ReflectionException)
- throw (ReflectionException) e;
- if (e instanceof InstanceAlreadyExistsException)
- throw (InstanceAlreadyExistsException) e;
- if (e instanceof MBeanRegistrationException)
- throw (MBeanRegistrationException) e;
- if (e instanceof MBeanException)
- throw (MBeanException) e;
- if (e instanceof NotCompliantMBeanException)
- throw (NotCompliantMBeanException) e;
- if (e instanceof IOException)
- throw (IOException) e;
- throw newIOException("Got unexpected server exception: " + e, e);
- }
- }
-
- @SuppressWarnings("rawtypes") // MarshalledObject
- public ObjectInstance createMBean(String className,
- ObjectName name,
- ObjectName loaderName,
- MarshalledObject params,
- String signature[],
- Subject delegationSubject)
- throws
- ReflectionException,
- InstanceAlreadyExistsException,
- MBeanRegistrationException,
- MBeanException,
- NotCompliantMBeanException,
- InstanceNotFoundException,
- IOException {
-
- final Object[] values;
- final boolean debug = logger.debugOn();
-
- if (debug) logger.debug(
- "createMBean(String,ObjectName,ObjectName,Object[],String[])",
- "connectionId=" + connectionId
- +", unwrapping params with MBean extended ClassLoader.");
-
- values = nullIsEmpty(unwrap(params,
- getClassLoader(loaderName),
- defaultClassLoader,
- Object[].class,delegationSubject));
-
- try {
- final Object params2[] =
- new Object[] { className, name, loaderName, values,
- nullIsEmpty(signature) };
-
- if (debug) logger.debug(
- "createMBean(String,ObjectName,ObjectName,Object[],String[])",
- "connectionId=" + connectionId
- +", className=" + className
- +", name=" + name
- +", loaderName=" + loaderName
- +", signature=" + strings(signature));
-
- return (ObjectInstance)
- doPrivilegedOperation(
- CREATE_MBEAN_LOADER_PARAMS,
- params2,
- delegationSubject);
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof ReflectionException)
- throw (ReflectionException) e;
- if (e instanceof InstanceAlreadyExistsException)
- throw (InstanceAlreadyExistsException) e;
- if (e instanceof MBeanRegistrationException)
- throw (MBeanRegistrationException) e;
- if (e instanceof MBeanException)
- throw (MBeanException) e;
- if (e instanceof NotCompliantMBeanException)
- throw (NotCompliantMBeanException) e;
- if (e instanceof InstanceNotFoundException)
- throw (InstanceNotFoundException) e;
- if (e instanceof IOException)
- throw (IOException) e;
- throw newIOException("Got unexpected server exception: " + e, e);
- }
- }
-
- public void unregisterMBean(ObjectName name, Subject delegationSubject)
- throws
- InstanceNotFoundException,
- MBeanRegistrationException,
- IOException {
- try {
- final Object params[] = new Object[] { name };
-
- if (logger.debugOn()) logger.debug("unregisterMBean",
- "connectionId=" + connectionId
- +", name="+name);
-
- doPrivilegedOperation(
- UNREGISTER_MBEAN,
- params,
- delegationSubject);
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof InstanceNotFoundException)
- throw (InstanceNotFoundException) e;
- if (e instanceof MBeanRegistrationException)
- throw (MBeanRegistrationException) e;
- if (e instanceof IOException)
- throw (IOException) e;
- throw newIOException("Got unexpected server exception: " + e, e);
- }
- }
-
- public ObjectInstance getObjectInstance(ObjectName name,
- Subject delegationSubject)
- throws
- InstanceNotFoundException,
- IOException {
-
- checkNonNull("ObjectName", name);
-
- try {
- final Object params[] = new Object[] { name };
-
- if (logger.debugOn()) logger.debug("getObjectInstance",
- "connectionId=" + connectionId
- +", name="+name);
-
- return (ObjectInstance)
- doPrivilegedOperation(
- GET_OBJECT_INSTANCE,
- params,
- delegationSubject);
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof InstanceNotFoundException)
- throw (InstanceNotFoundException) e;
- if (e instanceof IOException)
- throw (IOException) e;
- throw newIOException("Got unexpected server exception: " + e, e);
- }
- }
-
- @SuppressWarnings("rawtypes") // MarshalledObject
- public Set<ObjectInstance>
- queryMBeans(ObjectName name,
- MarshalledObject query,
- Subject delegationSubject)
- throws IOException {
- final QueryExp queryValue;
- final boolean debug=logger.debugOn();
-
- if (debug) logger.debug("queryMBeans",
- "connectionId=" + connectionId
- +" unwrapping query with defaultClassLoader.");
-
- queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class, delegationSubject);
-
- try {
- final Object params[] = new Object[] { name, queryValue };
-
- if (debug) logger.debug("queryMBeans",
- "connectionId=" + connectionId
- +", name="+name +", query="+query);
-
- return cast(
- doPrivilegedOperation(
- QUERY_MBEANS,
- params,
- delegationSubject));
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof IOException)
- throw (IOException) e;
- throw newIOException("Got unexpected server exception: " + e, e);
- }
- }
-
- @SuppressWarnings("rawtypes") // MarshalledObject
- public Set<ObjectName>
- queryNames(ObjectName name,
- MarshalledObject query,
- Subject delegationSubject)
- throws IOException {
- final QueryExp queryValue;
- final boolean debug=logger.debugOn();
-
- if (debug) logger.debug("queryNames",
- "connectionId=" + connectionId
- +" unwrapping query with defaultClassLoader.");
-
- queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class, delegationSubject);
-
- try {
- final Object params[] = new Object[] { name, queryValue };
-
- if (debug) logger.debug("queryNames",
- "connectionId=" + connectionId
- +", name="+name +", query="+query);
-
- return cast(
- doPrivilegedOperation(
- QUERY_NAMES,
- params,
- delegationSubject));
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof IOException)
- throw (IOException) e;
- throw newIOException("Got unexpected server exception: " + e, e);
- }
- }
-
- public boolean isRegistered(ObjectName name,
- Subject delegationSubject) throws IOException {
- try {
- final Object params[] = new Object[] { name };
- return ((Boolean)
- doPrivilegedOperation(
- IS_REGISTERED,
- params,
- delegationSubject)).booleanValue();
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof IOException)
- throw (IOException) e;
- throw newIOException("Got unexpected server exception: " + e, e);
- }
- }
-
- public Integer getMBeanCount(Subject delegationSubject)
- throws IOException {
- try {
- final Object params[] = new Object[] { };
-
- if (logger.debugOn()) logger.debug("getMBeanCount",
- "connectionId=" + connectionId);
-
- return (Integer)
- doPrivilegedOperation(
- GET_MBEAN_COUNT,
- params,
- delegationSubject);
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof IOException)
- throw (IOException) e;
- throw newIOException("Got unexpected server exception: " + e, e);
- }
- }
-
- public Object getAttribute(ObjectName name,
- String attribute,
- Subject delegationSubject)
- throws
- MBeanException,
- AttributeNotFoundException,
- InstanceNotFoundException,
- ReflectionException,
- IOException {
- try {
- final Object params[] = new Object[] { name, attribute };
- if (logger.debugOn()) logger.debug("getAttribute",
- "connectionId=" + connectionId
- +", name=" + name
- +", attribute="+ attribute);
-
- return
- doPrivilegedOperation(
- GET_ATTRIBUTE,
- params,
- delegationSubject);
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof MBeanException)
- throw (MBeanException) e;
- if (e instanceof AttributeNotFoundException)
- throw (AttributeNotFoundException) e;
- if (e instanceof InstanceNotFoundException)
- throw (InstanceNotFoundException) e;
- if (e instanceof ReflectionException)
- throw (ReflectionException) e;
- if (e instanceof IOException)
- throw (IOException) e;
- throw newIOException("Got unexpected server exception: " + e, e);
- }
- }
-
- public AttributeList getAttributes(ObjectName name,
- String[] attributes,
- Subject delegationSubject)
- throws
- InstanceNotFoundException,
- ReflectionException,
- IOException {
- try {
- final Object params[] = new Object[] { name, attributes };
-
- if (logger.debugOn()) logger.debug("getAttributes",
- "connectionId=" + connectionId
- +", name=" + name
- +", attributes="+ strings(attributes));
-
- return (AttributeList)
- doPrivilegedOperation(
- GET_ATTRIBUTES,
- params,
- delegationSubject);
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof InstanceNotFoundException)
- throw (InstanceNotFoundException) e;
- if (e instanceof ReflectionException)
- throw (ReflectionException) e;
- if (e instanceof IOException)
- throw (IOException) e;
- throw newIOException("Got unexpected server exception: " + e, e);
- }
- }
-
- @SuppressWarnings("rawtypes") // MarshalledObject
- public void setAttribute(ObjectName name,
- MarshalledObject attribute,
- Subject delegationSubject)
- throws
- InstanceNotFoundException,
- AttributeNotFoundException,
- InvalidAttributeValueException,
- MBeanException,
- ReflectionException,
- IOException {
- final Attribute attr;
- final boolean debug=logger.debugOn();
-
- if (debug) logger.debug("setAttribute",
- "connectionId=" + connectionId
- +" unwrapping attribute with MBean extended ClassLoader.");
-
- attr = unwrap(attribute,
- getClassLoaderFor(name),
- defaultClassLoader,
- Attribute.class, delegationSubject);
-
- try {
- final Object params[] = new Object[] { name, attr };
-
- if (debug) logger.debug("setAttribute",
- "connectionId=" + connectionId
- +", name="+name
- +", attribute name="+attr.getName());
-
- doPrivilegedOperation(
- SET_ATTRIBUTE,
- params,
- delegationSubject);
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof InstanceNotFoundException)
- throw (InstanceNotFoundException) e;
- if (e instanceof AttributeNotFoundException)
- throw (AttributeNotFoundException) e;
- if (e instanceof InvalidAttributeValueException)
- throw (InvalidAttributeValueException) e;
- if (e instanceof MBeanException)
- throw (MBeanException) e;
- if (e instanceof ReflectionException)
- throw (ReflectionException) e;
- if (e instanceof IOException)
- throw (IOException) e;
- throw newIOException("Got unexpected server exception: " + e, e);
- }
- }
-
- @SuppressWarnings("rawtypes") // MarshalledObject
- public AttributeList setAttributes(ObjectName name,
- MarshalledObject attributes,
- Subject delegationSubject)
- throws
- InstanceNotFoundException,
- ReflectionException,
- IOException {
- final AttributeList attrlist;
- final boolean debug=logger.debugOn();
-
- if (debug) logger.debug("setAttributes",
- "connectionId=" + connectionId
- +" unwrapping attributes with MBean extended ClassLoader.");
-
- attrlist =
- unwrap(attributes,
- getClassLoaderFor(name),
- defaultClassLoader,
- AttributeList.class, delegationSubject);
-
- try {
- final Object params[] = new Object[] { name, attrlist };
-
- if (debug) logger.debug("setAttributes",
- "connectionId=" + connectionId
- +", name="+name
- +", attribute names="+RMIConnector.getAttributesNames(attrlist));
-
- return (AttributeList)
- doPrivilegedOperation(
- SET_ATTRIBUTES,
- params,
- delegationSubject);
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof InstanceNotFoundException)
- throw (InstanceNotFoundException) e;
- if (e instanceof ReflectionException)
- throw (ReflectionException) e;
- if (e instanceof IOException)
- throw (IOException) e;
- throw newIOException("Got unexpected server exception: " + e, e);
- }
- }
-
- @SuppressWarnings("rawtypes") // MarshalledObject
- public Object invoke(ObjectName name,
- String operationName,
- MarshalledObject params,
- String signature[],
- Subject delegationSubject)
- throws
- InstanceNotFoundException,
- MBeanException,
- ReflectionException,
- IOException {
-
- checkNonNull("ObjectName", name);
- checkNonNull("Operation name", operationName);
-
- final Object[] values;
- final boolean debug=logger.debugOn();
-
- if (debug) logger.debug("invoke",
- "connectionId=" + connectionId
- +" unwrapping params with MBean extended ClassLoader.");
-
- values = nullIsEmpty(unwrap(params,
- getClassLoaderFor(name),
- defaultClassLoader,
- Object[].class, delegationSubject));
-
- try {
- final Object params2[] =
- new Object[] { name, operationName, values,
- nullIsEmpty(signature) };
-
- if (debug) logger.debug("invoke",
- "connectionId=" + connectionId
- +", name="+name
- +", operationName="+operationName
- +", signature="+strings(signature));
-
- return
- doPrivilegedOperation(
- INVOKE,
- params2,
- delegationSubject);
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof InstanceNotFoundException)
- throw (InstanceNotFoundException) e;
- if (e instanceof MBeanException)
- throw (MBeanException) e;
- if (e instanceof ReflectionException)
- throw (ReflectionException) e;
- if (e instanceof IOException)
- throw (IOException) e;
- throw newIOException("Got unexpected server exception: " + e, e);
- }
- }
-
- public String getDefaultDomain(Subject delegationSubject)
- throws IOException {
- try {
- final Object params[] = new Object[] { };
-
- if (logger.debugOn()) logger.debug("getDefaultDomain",
- "connectionId=" + connectionId);
-
- return (String)
- doPrivilegedOperation(
- GET_DEFAULT_DOMAIN,
- params,
- delegationSubject);
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof IOException)
- throw (IOException) e;
- throw newIOException("Got unexpected server exception: " + e, e);
- }
- }
-
- public String[] getDomains(Subject delegationSubject) throws IOException {
- try {
- final Object params[] = new Object[] { };
-
- if (logger.debugOn()) logger.debug("getDomains",
- "connectionId=" + connectionId);
-
- return (String[])
- doPrivilegedOperation(
- GET_DOMAINS,
- params,
- delegationSubject);
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof IOException)
- throw (IOException) e;
- throw newIOException("Got unexpected server exception: " + e, e);
- }
- }
-
- public MBeanInfo getMBeanInfo(ObjectName name, Subject delegationSubject)
- throws
- InstanceNotFoundException,
- IntrospectionException,
- ReflectionException,
- IOException {
-
- checkNonNull("ObjectName", name);
-
- try {
- final Object params[] = new Object[] { name };
-
- if (logger.debugOn()) logger.debug("getMBeanInfo",
- "connectionId=" + connectionId
- +", name="+name);
-
- return (MBeanInfo)
- doPrivilegedOperation(
- GET_MBEAN_INFO,
- params,
- delegationSubject);
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof InstanceNotFoundException)
- throw (InstanceNotFoundException) e;
- if (e instanceof IntrospectionException)
- throw (IntrospectionException) e;
- if (e instanceof ReflectionException)
- throw (ReflectionException) e;
- if (e instanceof IOException)
- throw (IOException) e;
- throw newIOException("Got unexpected server exception: " + e, e);
- }
- }
-
- public boolean isInstanceOf(ObjectName name,
- String className,
- Subject delegationSubject)
- throws InstanceNotFoundException, IOException {
-
- checkNonNull("ObjectName", name);
-
- try {
- final Object params[] = new Object[] { name, className };
-
- if (logger.debugOn()) logger.debug("isInstanceOf",
- "connectionId=" + connectionId
- +", name="+name
- +", className="+className);
-
- return ((Boolean)
- doPrivilegedOperation(
- IS_INSTANCE_OF,
- params,
- delegationSubject)).booleanValue();
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof InstanceNotFoundException)
- throw (InstanceNotFoundException) e;
- if (e instanceof IOException)
- throw (IOException) e;
- throw newIOException("Got unexpected server exception: " + e, e);
- }
- }
-
- @SuppressWarnings("rawtypes") // MarshalledObject
- public Integer[] addNotificationListeners(ObjectName[] names,
- MarshalledObject[] filters,
- Subject[] delegationSubjects)
- throws InstanceNotFoundException, IOException {
-
- if (names == null || filters == null) {
- throw new IllegalArgumentException("Got null arguments.");
- }
-
- Subject[] sbjs = (delegationSubjects != null) ? delegationSubjects :
- new Subject[names.length];
- if (names.length != filters.length || filters.length != sbjs.length) {
- final String msg =
- "The value lengths of 3 parameters are not same.";
- throw new IllegalArgumentException(msg);
- }
-
- for (int i=0; i<names.length; i++) {
- if (names[i] == null) {
- throw new IllegalArgumentException("Null Object name.");
- }
- }
-
- int i=0;
- ClassLoader targetCl;
- NotificationFilter[] filterValues =
- new NotificationFilter[names.length];
- Integer[] ids = new Integer[names.length];
- final boolean debug=logger.debugOn();
-
- try {
- for (; i<names.length; i++) {
- targetCl = getClassLoaderFor(names[i]);
-
- if (debug) logger.debug("addNotificationListener"+
- "(ObjectName,NotificationFilter)",
- "connectionId=" + connectionId +
- " unwrapping filter with target extended ClassLoader.");
-
- filterValues[i] =
- unwrap(filters[i], targetCl, defaultClassLoader,
- NotificationFilter.class, sbjs[i]);
-
- if (debug) logger.debug("addNotificationListener"+
- "(ObjectName,NotificationFilter)",
- "connectionId=" + connectionId
- +", name=" + names[i]
- +", filter=" + filterValues[i]);
-
- ids[i] = (Integer)
- doPrivilegedOperation(ADD_NOTIFICATION_LISTENERS,
- new Object[] { names[i],
- filterValues[i] },
- sbjs[i]);
- }
-
- return ids;
- } catch (Exception e) {
- // remove all registered listeners
- for (int j=0; j<i; j++) {
- try {
- getServerNotifFwd().removeNotificationListener(names[j],
- ids[j]);
- } catch (Exception eee) {
- // strange
- }
- }
-
- if (e instanceof PrivilegedActionException) {
- e = extractException(e);
- }
-
- if (e instanceof ClassCastException) {
- throw (ClassCastException) e;
- } else if (e instanceof IOException) {
- throw (IOException)e;
- } else if (e instanceof InstanceNotFoundException) {
- throw (InstanceNotFoundException) e;
- } else if (e instanceof RuntimeException) {
- throw (RuntimeException) e;
- } else {
- throw newIOException("Got unexpected server exception: "+e,e);
- }
- }
- }
-
- @SuppressWarnings("rawtypes") // MarshalledObject
- public void addNotificationListener(ObjectName name,
- ObjectName listener,
- MarshalledObject filter,
- MarshalledObject handback,
- Subject delegationSubject)
- throws InstanceNotFoundException, IOException {
-
- checkNonNull("Target MBean name", name);
- checkNonNull("Listener MBean name", listener);
-
- final NotificationFilter filterValue;
- final Object handbackValue;
- final boolean debug=logger.debugOn();
-
- final ClassLoader targetCl = getClassLoaderFor(name);
-
- if (debug) logger.debug("addNotificationListener"+
- "(ObjectName,ObjectName,NotificationFilter,Object)",
- "connectionId=" + connectionId
- +" unwrapping filter with target extended ClassLoader.");
-
- filterValue =
- unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class, delegationSubject);
-
- if (debug) logger.debug("addNotificationListener"+
- "(ObjectName,ObjectName,NotificationFilter,Object)",
- "connectionId=" + connectionId
- +" unwrapping handback with target extended ClassLoader.");
-
- handbackValue =
- unwrap(handback, targetCl, defaultClassLoader, Object.class, delegationSubject);
-
- try {
- final Object params[] =
- new Object[] { name, listener, filterValue, handbackValue };
-
- if (debug) logger.debug("addNotificationListener"+
- "(ObjectName,ObjectName,NotificationFilter,Object)",
- "connectionId=" + connectionId
- +", name=" + name
- +", listenerName=" + listener
- +", filter=" + filterValue
- +", handback=" + handbackValue);
-
- doPrivilegedOperation(
- ADD_NOTIFICATION_LISTENER_OBJECTNAME,
- params,
- delegationSubject);
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof InstanceNotFoundException)
- throw (InstanceNotFoundException) e;
- if (e instanceof IOException)
- throw (IOException) e;
- throw newIOException("Got unexpected server exception: " + e, e);
- }
- }
-
- public void removeNotificationListeners(ObjectName name,
- Integer[] listenerIDs,
- Subject delegationSubject)
- throws
- InstanceNotFoundException,
- ListenerNotFoundException,
- IOException {
-
- if (name == null || listenerIDs == null)
- throw new IllegalArgumentException("Illegal null parameter");
-
- for (int i = 0; i < listenerIDs.length; i++) {
- if (listenerIDs[i] == null)
- throw new IllegalArgumentException("Null listener ID");
- }
-
- try {
- final Object params[] = new Object[] { name, listenerIDs };
-
- if (logger.debugOn()) logger.debug("removeNotificationListener"+
- "(ObjectName,Integer[])",
- "connectionId=" + connectionId
- +", name=" + name
- +", listenerIDs=" + objects(listenerIDs));
-
- doPrivilegedOperation(
- REMOVE_NOTIFICATION_LISTENER,
- params,
- delegationSubject);
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof InstanceNotFoundException)
- throw (InstanceNotFoundException) e;
- if (e instanceof ListenerNotFoundException)
- throw (ListenerNotFoundException) e;
- if (e instanceof IOException)
- throw (IOException) e;
- throw newIOException("Got unexpected server exception: " + e, e);
- }
- }
-
- public void removeNotificationListener(ObjectName name,
- ObjectName listener,
- Subject delegationSubject)
- throws
- InstanceNotFoundException,
- ListenerNotFoundException,
- IOException {
-
- checkNonNull("Target MBean name", name);
- checkNonNull("Listener MBean name", listener);
-
- try {
- final Object params[] = new Object[] { name, listener };
-
- if (logger.debugOn()) logger.debug("removeNotificationListener"+
- "(ObjectName,ObjectName)",
- "connectionId=" + connectionId
- +", name=" + name
- +", listenerName=" + listener);
-
- doPrivilegedOperation(
- REMOVE_NOTIFICATION_LISTENER_OBJECTNAME,
- params,
- delegationSubject);
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof InstanceNotFoundException)
- throw (InstanceNotFoundException) e;
- if (e instanceof ListenerNotFoundException)
- throw (ListenerNotFoundException) e;
- if (e instanceof IOException)
- throw (IOException) e;
- throw newIOException("Got unexpected server exception: " + e, e);
- }
- }
-
- @SuppressWarnings("rawtypes") // MarshalledObject
- public void removeNotificationListener(ObjectName name,
- ObjectName listener,
- MarshalledObject filter,
- MarshalledObject handback,
- Subject delegationSubject)
- throws
- InstanceNotFoundException,
- ListenerNotFoundException,
- IOException {
-
- checkNonNull("Target MBean name", name);
- checkNonNull("Listener MBean name", listener);
-
- final NotificationFilter filterValue;
- final Object handbackValue;
- final boolean debug=logger.debugOn();
-
- final ClassLoader targetCl = getClassLoaderFor(name);
-
- if (debug) logger.debug("removeNotificationListener"+
- "(ObjectName,ObjectName,NotificationFilter,Object)",
- "connectionId=" + connectionId
- +" unwrapping filter with target extended ClassLoader.");
-
- filterValue =
- unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class, delegationSubject);
-
- if (debug) logger.debug("removeNotificationListener"+
- "(ObjectName,ObjectName,NotificationFilter,Object)",
- "connectionId=" + connectionId
- +" unwrapping handback with target extended ClassLoader.");
-
- handbackValue =
- unwrap(handback, targetCl, defaultClassLoader, Object.class, delegationSubject);
-
- try {
- final Object params[] =
- new Object[] { name, listener, filterValue, handbackValue };
-
- if (debug) logger.debug("removeNotificationListener"+
- "(ObjectName,ObjectName,NotificationFilter,Object)",
- "connectionId=" + connectionId
- +", name=" + name
- +", listenerName=" + listener
- +", filter=" + filterValue
- +", handback=" + handbackValue);
-
- doPrivilegedOperation(
- REMOVE_NOTIFICATION_LISTENER_OBJECTNAME_FILTER_HANDBACK,
- params,
- delegationSubject);
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof InstanceNotFoundException)
- throw (InstanceNotFoundException) e;
- if (e instanceof ListenerNotFoundException)
- throw (ListenerNotFoundException) e;
- if (e instanceof IOException)
- throw (IOException) e;
- throw newIOException("Got unexpected server exception: " + e, e);
- }
- }
-
- public NotificationResult fetchNotifications(long clientSequenceNumber,
- int maxNotifications,
- long timeout)
- throws IOException {
-
- if (logger.debugOn()) logger.debug("fetchNotifications",
- "connectionId=" + connectionId
- +", timeout=" + timeout);
-
- if (maxNotifications < 0 || timeout < 0)
- throw new IllegalArgumentException("Illegal negative argument");
-
- final boolean serverTerminated =
- serverCommunicatorAdmin.reqIncoming();
- try {
- if (serverTerminated) {
- // we must not call fetchNotifs() if the server is
- // terminated (timeout elapsed).
- // returns null to force the client to stop fetching
- if (logger.debugOn()) logger.debug("fetchNotifications",
- "The notification server has been closed, "
- + "returns null to force the client to stop fetching");
- return null;
- }
- final long csn = clientSequenceNumber;
- final int mn = maxNotifications;
- final long t = timeout;
- PrivilegedAction<NotificationResult> action =
- new PrivilegedAction<NotificationResult>() {
- public NotificationResult run() {
- return getServerNotifFwd().fetchNotifs(csn, t, mn);
- }
- };
- if (acc == null)
- return action.run();
- else
- return AccessController.doPrivileged(action, acc);
- } finally {
- serverCommunicatorAdmin.rspOutgoing();
- }
- }
-
- /**
- * <p>Returns a string representation of this object. In general,
- * the <code>toString</code> method returns a string that
- * "textually represents" this object. The result should be a
- * concise but informative representation that is easy for a
- * person to read.</p>
- *
- * @return a String representation of this object.
- **/
- @Override
- public String toString() {
- return super.toString() + ": connectionId=" + connectionId;
- }
-
- //------------------------------------------------------------------------
- // private classes
- //------------------------------------------------------------------------
-
- private class PrivilegedOperation
- implements PrivilegedExceptionAction<Object> {
-
- public PrivilegedOperation(int operation, Object[] params) {
- this.operation = operation;
- this.params = params;
- }
-
- public Object run() throws Exception {
- return doOperation(operation, params);
- }
-
- private int operation;
- private Object[] params;
- }
-
- //------------------------------------------------------------------------
- // private classes
- //------------------------------------------------------------------------
- private class RMIServerCommunicatorAdmin extends ServerCommunicatorAdmin {
- public RMIServerCommunicatorAdmin(long timeout) {
- super(timeout);
- }
-
- protected void doStop() {
- try {
- close();
- } catch (IOException ie) {
- logger.warning("RMIServerCommunicatorAdmin-doStop",
- "Failed to close: " + ie);
- logger.debug("RMIServerCommunicatorAdmin-doStop",ie);
- }
- }
-
- }
-
-
- //------------------------------------------------------------------------
- // private methods
- //------------------------------------------------------------------------
-
- private ClassLoader getClassLoader(final ObjectName name)
- throws InstanceNotFoundException {
- try {
- return
- AccessController.doPrivileged(
- new PrivilegedExceptionAction<ClassLoader>() {
- public ClassLoader run() throws InstanceNotFoundException {
- return mbeanServer.getClassLoader(name);
- }
- },
- withPermissions(new MBeanPermission("*", "getClassLoader"))
- );
- } catch (PrivilegedActionException pe) {
- throw (InstanceNotFoundException) extractException(pe);
- }
- }
-
- private ClassLoader getClassLoaderFor(final ObjectName name)
- throws InstanceNotFoundException {
- try {
- return (ClassLoader)
- AccessController.doPrivileged(
- new PrivilegedExceptionAction<Object>() {
- public Object run() throws InstanceNotFoundException {
- return mbeanServer.getClassLoaderFor(name);
- }
- },
- withPermissions(new MBeanPermission("*", "getClassLoaderFor"))
- );
- } catch (PrivilegedActionException pe) {
- throw (InstanceNotFoundException) extractException(pe);
- }
- }
-
- private Object doPrivilegedOperation(final int operation,
- final Object[] params,
- final Subject delegationSubject)
- throws PrivilegedActionException, IOException {
-
- serverCommunicatorAdmin.reqIncoming();
- try {
-
- final AccessControlContext reqACC;
- if (delegationSubject == null)
- reqACC = acc;
- else {
- if (subject == null) {
- final String msg =
- "Subject delegation cannot be enabled unless " +
- "an authenticated subject is put in place";
- throw new SecurityException(msg);
- }
- reqACC = subjectDelegator.delegatedContext(
- acc, delegationSubject, removeCallerContext);
- }
-
- PrivilegedOperation op =
- new PrivilegedOperation(operation, params);
- if (reqACC == null) {
- try {
- return op.run();
- } catch (Exception e) {
- if (e instanceof RuntimeException)
- throw (RuntimeException) e;
- throw new PrivilegedActionException(e);
- }
- } else {
- return AccessController.doPrivileged(op, reqACC);
- }
- } catch (Error e) {
- throw new JMXServerErrorException(e.toString(),e);
- } finally {
- serverCommunicatorAdmin.rspOutgoing();
- }
- }
-
- private Object doOperation(int operation, Object[] params)
- throws Exception {
-
- switch (operation) {
-
- case CREATE_MBEAN:
- return mbeanServer.createMBean((String)params[0],
- (ObjectName)params[1]);
-
- case CREATE_MBEAN_LOADER:
- return mbeanServer.createMBean((String)params[0],
- (ObjectName)params[1],
- (ObjectName)params[2]);
-
- case CREATE_MBEAN_PARAMS:
- return mbeanServer.createMBean((String)params[0],
- (ObjectName)params[1],
- (Object[])params[2],
- (String[])params[3]);
-
- case CREATE_MBEAN_LOADER_PARAMS:
- return mbeanServer.createMBean((String)params[0],
- (ObjectName)params[1],
- (ObjectName)params[2],
- (Object[])params[3],
- (String[])params[4]);
-
- case GET_ATTRIBUTE:
- return mbeanServer.getAttribute((ObjectName)params[0],
- (String)params[1]);
-
- case GET_ATTRIBUTES:
- return mbeanServer.getAttributes((ObjectName)params[0],
- (String[])params[1]);
-
- case GET_DEFAULT_DOMAIN:
- return mbeanServer.getDefaultDomain();
-
- case GET_DOMAINS:
- return mbeanServer.getDomains();
-
- case GET_MBEAN_COUNT:
- return mbeanServer.getMBeanCount();
-
- case GET_MBEAN_INFO:
- return mbeanServer.getMBeanInfo((ObjectName)params[0]);
-
- case GET_OBJECT_INSTANCE:
- return mbeanServer.getObjectInstance((ObjectName)params[0]);
-
- case INVOKE:
- return mbeanServer.invoke((ObjectName)params[0],
- (String)params[1],
- (Object[])params[2],
- (String[])params[3]);
-
- case IS_INSTANCE_OF:
- return mbeanServer.isInstanceOf((ObjectName)params[0],
- (String)params[1])
- ? Boolean.TRUE : Boolean.FALSE;
-
- case IS_REGISTERED:
- return mbeanServer.isRegistered((ObjectName)params[0])
- ? Boolean.TRUE : Boolean.FALSE;
-
- case QUERY_MBEANS:
- return mbeanServer.queryMBeans((ObjectName)params[0],
- (QueryExp)params[1]);
-
- case QUERY_NAMES:
- return mbeanServer.queryNames((ObjectName)params[0],
- (QueryExp)params[1]);
-
- case SET_ATTRIBUTE:
- mbeanServer.setAttribute((ObjectName)params[0],
- (Attribute)params[1]);
- return null;
-
- case SET_ATTRIBUTES:
- return mbeanServer.setAttributes((ObjectName)params[0],
- (AttributeList)params[1]);
-
- case UNREGISTER_MBEAN:
- mbeanServer.unregisterMBean((ObjectName)params[0]);
- return null;
-
- case ADD_NOTIFICATION_LISTENERS:
- return getServerNotifFwd().addNotificationListener(
- (ObjectName)params[0],
- (NotificationFilter)params[1]);
-
- case ADD_NOTIFICATION_LISTENER_OBJECTNAME:
- mbeanServer.addNotificationListener((ObjectName)params[0],
- (ObjectName)params[1],
- (NotificationFilter)params[2],
- params[3]);
- return null;
-
- case REMOVE_NOTIFICATION_LISTENER:
- getServerNotifFwd().removeNotificationListener(
- (ObjectName)params[0],
- (Integer[])params[1]);
- return null;
-
- case REMOVE_NOTIFICATION_LISTENER_OBJECTNAME:
- mbeanServer.removeNotificationListener((ObjectName)params[0],
- (ObjectName)params[1]);
- return null;
-
- case REMOVE_NOTIFICATION_LISTENER_OBJECTNAME_FILTER_HANDBACK:
- mbeanServer.removeNotificationListener(
- (ObjectName)params[0],
- (ObjectName)params[1],
- (NotificationFilter)params[2],
- params[3]);
- return null;
-
- default:
- throw new IllegalArgumentException("Invalid operation");
- }
- }
-
- private static class SetCcl implements PrivilegedExceptionAction<ClassLoader> {
- private final ClassLoader classLoader;
-
- SetCcl(ClassLoader classLoader) {
- this.classLoader = classLoader;
- }
-
- public ClassLoader run() {
- Thread currentThread = Thread.currentThread();
- ClassLoader old = currentThread.getContextClassLoader();
- currentThread.setContextClassLoader(classLoader);
- return old;
- }
- }
-
- private <T> T unwrap(final MarshalledObject<?> mo,
- final ClassLoader cl,
- final Class<T> wrappedClass,
- Subject delegationSubject)
- throws IOException {
- if (mo == null) {
- return null;
- }
- try {
- final ClassLoader old = AccessController.doPrivileged(new SetCcl(cl));
- try{
- final AccessControlContext reqACC;
- if (delegationSubject == null)
- reqACC = acc;
- else {
- if (subject == null) {
- final String msg =
- "Subject delegation cannot be enabled unless " +
- "an authenticated subject is put in place";
- throw new SecurityException(msg);
- }
- reqACC = subjectDelegator.delegatedContext(
- acc, delegationSubject, removeCallerContext);
- }
- if(reqACC != null){
- return AccessController.doPrivileged(
- (PrivilegedExceptionAction<T>) () ->
- wrappedClass.cast(mo.get()), reqACC);
- }else{
- return wrappedClass.cast(mo.get());
- }
- }finally{
- AccessController.doPrivileged(new SetCcl(old));
- }
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof IOException) {
- throw (IOException) e;
- }
- if (e instanceof ClassNotFoundException) {
- throw new UnmarshalException(e.toString(), e);
- }
- logger.warning("unwrap", "Failed to unmarshall object: " + e);
- logger.debug("unwrap", e);
- }catch (ClassNotFoundException ex) {
- logger.warning("unwrap", "Failed to unmarshall object: " + ex);
- logger.debug("unwrap", ex);
- throw new UnmarshalException(ex.toString(), ex);
- }
- return null;
- }
-
- private <T> T unwrap(final MarshalledObject<?> mo,
- final ClassLoader cl1,
- final ClassLoader cl2,
- final Class<T> wrappedClass,
- Subject delegationSubject)
- throws IOException {
- if (mo == null) {
- return null;
- }
- try {
- ClassLoader orderCL = AccessController.doPrivileged(
- new PrivilegedExceptionAction<ClassLoader>() {
- public ClassLoader run() throws Exception {
- return new CombinedClassLoader(Thread.currentThread().getContextClassLoader(),
- new OrderClassLoaders(cl1, cl2));
- }
- }
- );
- return unwrap(mo, orderCL, wrappedClass,delegationSubject);
- } catch (PrivilegedActionException pe) {
- Exception e = extractException(pe);
- if (e instanceof IOException) {
- throw (IOException) e;
- }
- if (e instanceof ClassNotFoundException) {
- throw new UnmarshalException(e.toString(), e);
- }
- logger.warning("unwrap", "Failed to unmarshall object: " + e);
- logger.debug("unwrap", e);
- }
- return null;
- }
-
- /**
- * Construct a new IOException with a nested exception.
- * The nested exception is set only if JDK {@literal >= 1.4}
- */
- private static IOException newIOException(String message,
- Throwable cause) {
- final IOException x = new IOException(message);
- return EnvHelp.initCause(x,cause);
- }
-
- /**
- * Iterate until we extract the real exception
- * from a stack of PrivilegedActionExceptions.
- */
- private static Exception extractException(Exception e) {
- while (e instanceof PrivilegedActionException) {
- e = ((PrivilegedActionException)e).getException();
- }
- return e;
- }
-
- private static final Object[] NO_OBJECTS = new Object[0];
- private static final String[] NO_STRINGS = new String[0];
-
- /*
- * The JMX spec doesn't explicitly say that a null Object[] or
- * String[] in e.g. MBeanServer.invoke is equivalent to an empty
- * array, but the RI behaves that way. In the interests of
- * maximal interoperability, we make it so even when we're
- * connected to some other JMX implementation that might not do
- * that. This should be clarified in the next version of JMX.
- */
- private static Object[] nullIsEmpty(Object[] array) {
- return (array == null) ? NO_OBJECTS : array;
- }
-
- private static String[] nullIsEmpty(String[] array) {
- return (array == null) ? NO_STRINGS : array;
- }
-
- /*
- * Similarly, the JMX spec says for some but not all methods in
- * MBeanServer that take an ObjectName target, that if it's null
- * you get this exception. We specify it for all of them, and
- * make it so for the ones where it's not specified in JMX even if
- * the JMX implementation doesn't do so.
- */
- private static void checkNonNull(String what, Object x) {
- if (x == null) {
- RuntimeException wrapped =
- new IllegalArgumentException(what + " must not be null");
- throw new RuntimeOperationsException(wrapped);
- }
- }
-
- //------------------------------------------------------------------------
- // private variables
- //------------------------------------------------------------------------
-
- private final Subject subject;
-
- private final SubjectDelegator subjectDelegator;
-
- private final boolean removeCallerContext;
-
- private final AccessControlContext acc;
-
- private final RMIServerImpl rmiServer;
-
- private final MBeanServer mbeanServer;
-
- private final ClassLoader defaultClassLoader;
-
- private final ClassLoader defaultContextClassLoader;
-
- private final ClassLoaderWithRepository classLoaderWithRepository;
-
- private boolean terminated = false;
-
- private final String connectionId;
-
- private final ServerCommunicatorAdmin serverCommunicatorAdmin;
-
- // Method IDs for doOperation
- //---------------------------
-
- private final static int
- ADD_NOTIFICATION_LISTENERS = 1;
- private final static int
- ADD_NOTIFICATION_LISTENER_OBJECTNAME = 2;
- private final static int
- CREATE_MBEAN = 3;
- private final static int
- CREATE_MBEAN_PARAMS = 4;
- private final static int
- CREATE_MBEAN_LOADER = 5;
- private final static int
- CREATE_MBEAN_LOADER_PARAMS = 6;
- private final static int
- GET_ATTRIBUTE = 7;
- private final static int
- GET_ATTRIBUTES = 8;
- private final static int
- GET_DEFAULT_DOMAIN = 9;
- private final static int
- GET_DOMAINS = 10;
- private final static int
- GET_MBEAN_COUNT = 11;
- private final static int
- GET_MBEAN_INFO = 12;
- private final static int
- GET_OBJECT_INSTANCE = 13;
- private final static int
- INVOKE = 14;
- private final static int
- IS_INSTANCE_OF = 15;
- private final static int
- IS_REGISTERED = 16;
- private final static int
- QUERY_MBEANS = 17;
- private final static int
- QUERY_NAMES = 18;
- private final static int
- REMOVE_NOTIFICATION_LISTENER = 19;
- private final static int
- REMOVE_NOTIFICATION_LISTENER_OBJECTNAME = 20;
- private final static int
- REMOVE_NOTIFICATION_LISTENER_OBJECTNAME_FILTER_HANDBACK = 21;
- private final static int
- SET_ATTRIBUTE = 22;
- private final static int
- SET_ATTRIBUTES = 23;
- private final static int
- UNREGISTER_MBEAN = 24;
-
- // SERVER NOTIFICATION
- //--------------------
-
- private ServerNotifForwarder serverNotifForwarder;
- private Map<String, ?> env;
-
- // TRACES & DEBUG
- //---------------
-
- private static String objects(final Object[] objs) {
- if (objs == null)
- return "null";
- else
- return Arrays.asList(objs).toString();
- }
-
- private static String strings(final String[] strs) {
- return objects(strs);
- }
-
- private static final ClassLogger logger =
- new ClassLogger("javax.management.remote.rmi", "RMIConnectionImpl");
-
- private static final class CombinedClassLoader extends ClassLoader {
-
- private final static class ClassLoaderWrapper extends ClassLoader {
- ClassLoaderWrapper(ClassLoader cl) {
- super(cl);
- }
-
- @Override
- protected Class<?> loadClass(String name, boolean resolve)
- throws ClassNotFoundException {
- return super.loadClass(name, resolve);
- }
- };
-
- final ClassLoaderWrapper defaultCL;
-
- private CombinedClassLoader(ClassLoader parent, ClassLoader defaultCL) {
- super(parent);
- this.defaultCL = new ClassLoaderWrapper(defaultCL);
- }
-
- @Override
- protected Class<?> loadClass(String name, boolean resolve)
- throws ClassNotFoundException {
- ReflectUtil.checkPackageAccess(name);
- try {
- super.loadClass(name, resolve);
- } catch(Exception e) {
- for(Throwable t = e; t != null; t = t.getCause()) {
- if(t instanceof SecurityException) {
- throw t==e?(SecurityException)t:new SecurityException(t.getMessage(), e);
- }
- }
- }
- final Class<?> cl = defaultCL.loadClass(name, resolve);
- return cl;
- }
-
- }
-}
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnector.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2289 +0,0 @@
-/*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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 javax.management.remote.rmi;
-
-import com.sun.jmx.mbeanserver.Util;
-import com.sun.jmx.remote.internal.ClientCommunicatorAdmin;
-import com.sun.jmx.remote.internal.ClientListenerInfo;
-import com.sun.jmx.remote.internal.ClientNotifForwarder;
-import com.sun.jmx.remote.internal.ProxyRef;
-import com.sun.jmx.remote.util.ClassLogger;
-import com.sun.jmx.remote.util.EnvHelp;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InvalidObjectException;
-import java.io.ObjectInputStream;
-import java.io.ObjectStreamClass;
-import java.io.Serializable;
-import java.lang.ref.WeakReference;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Module;
-import java.lang.reflect.Proxy;
-import java.net.MalformedURLException;
-import java.rmi.MarshalledObject;
-import java.rmi.NoSuchObjectException;
-import java.rmi.Remote;
-import java.rmi.ServerException;
-import java.rmi.UnmarshalException;
-import java.rmi.server.RMIClientSocketFactory;
-import java.rmi.server.RemoteObject;
-import java.rmi.server.RemoteObjectInvocationHandler;
-import java.rmi.server.RemoteRef;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedExceptionAction;
-import java.security.ProtectionDomain;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.WeakHashMap;
-import java.util.stream.Collectors;
-import javax.management.Attribute;
-import javax.management.AttributeList;
-import javax.management.AttributeNotFoundException;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.IntrospectionException;
-import javax.management.InvalidAttributeValueException;
-import javax.management.ListenerNotFoundException;
-import javax.management.MBeanException;
-import javax.management.MBeanInfo;
-import javax.management.MBeanRegistrationException;
-import javax.management.MBeanServerConnection;
-import javax.management.MBeanServerDelegate;
-import javax.management.MBeanServerNotification;
-import javax.management.NotCompliantMBeanException;
-import javax.management.Notification;
-import javax.management.NotificationBroadcasterSupport;
-import javax.management.NotificationFilter;
-import javax.management.NotificationFilterSupport;
-import javax.management.NotificationListener;
-import javax.management.ObjectInstance;
-import javax.management.ObjectName;
-import javax.management.QueryExp;
-import javax.management.ReflectionException;
-import javax.management.remote.JMXConnectionNotification;
-import javax.management.remote.JMXConnector;
-import javax.management.remote.JMXConnectorFactory;
-import javax.management.remote.JMXServiceURL;
-import javax.management.remote.NotificationResult;
-import javax.management.remote.JMXAddressable;
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
-import javax.rmi.ssl.SslRMIClientSocketFactory;
-import javax.security.auth.Subject;
-import jdk.internal.module.Modules;
-import sun.reflect.misc.ReflectUtil;
-import sun.rmi.server.UnicastRef2;
-import sun.rmi.transport.LiveRef;
-
-/**
- * <p>A connection to a remote RMI connector. Usually, such
- * connections are made using {@link
- * javax.management.remote.JMXConnectorFactory JMXConnectorFactory}.
- * However, specialized applications can use this class directly, for
- * example with an {@link RMIServer} stub obtained without going
- * through JNDI.</p>
- *
- * @since 1.5
- */
-public class RMIConnector implements JMXConnector, Serializable, JMXAddressable {
-
- private static final ClassLogger logger =
- new ClassLogger("javax.management.remote.rmi", "RMIConnector");
-
- private static final long serialVersionUID = 817323035842634473L;
-
- private RMIConnector(RMIServer rmiServer, JMXServiceURL address,
- Map<String, ?> environment) {
- if (rmiServer == null && address == null) throw new
- IllegalArgumentException("rmiServer and jmxServiceURL both null");
- initTransients();
-
- this.rmiServer = rmiServer;
- this.jmxServiceURL = address;
- if (environment == null) {
- this.env = Collections.emptyMap();
- } else {
- EnvHelp.checkAttributes(environment);
- this.env = Collections.unmodifiableMap(environment);
- }
- }
-
- /**
- * <p>Constructs an {@code RMIConnector} that will connect
- * the RMI connector server with the given address.</p>
- *
- * <p>The address can refer directly to the connector server,
- * using the following syntax:</p>
- *
- * <pre>
- * service:jmx:rmi://<em>[host[:port]]</em>/stub/<em>encoded-stub</em>
- * </pre>
- *
- * <p>(Here, the square brackets {@code []} are not part of the
- * address but indicate that the host and port are optional.)</p>
- *
- * <p>The address can instead indicate where to find an RMI stub
- * through JNDI, using the following syntax:</p>
- *
- * <pre>
- * service:jmx:rmi://<em>[host[:port]]</em>/jndi/<em>jndi-name</em>
- * </pre>
- *
- * <p>An implementation may also recognize additional address
- * syntaxes, for example:</p>
- *
- * <pre>
- * service:jmx:iiop://<em>[host[:port]]</em>/stub/<em>encoded-stub</em>
- * </pre>
- *
- * @param url the address of the RMI connector server.
- *
- * @param environment additional attributes specifying how to make
- * the connection. For JNDI-based addresses, these attributes can
- * usefully include JNDI attributes recognized by {@link
- * InitialContext#InitialContext(Hashtable) InitialContext}. This
- * parameter can be null, which is equivalent to an empty Map.
- *
- * @exception IllegalArgumentException if {@code url}
- * is null.
- */
- public RMIConnector(JMXServiceURL url, Map<String,?> environment) {
- this(null, url, environment);
- }
-
- /**
- * <p>Constructs an {@code RMIConnector} using the given RMI stub.
- *
- * @param rmiServer an RMI stub representing the RMI connector server.
- * @param environment additional attributes specifying how to make
- * the connection. This parameter can be null, which is
- * equivalent to an empty Map.
- *
- * @exception IllegalArgumentException if {@code rmiServer}
- * is null.
- */
- public RMIConnector(RMIServer rmiServer, Map<String,?> environment) {
- this(rmiServer, null, environment);
- }
-
- /**
- * <p>Returns a string representation of this object. In general,
- * the {@code toString} method returns a string that
- * "textually represents" this object. The result should be a
- * concise but informative representation that is easy for a
- * person to read.</p>
- *
- * @return a String representation of this object.
- **/
- @Override
- public String toString() {
- final StringBuilder b = new StringBuilder(this.getClass().getName());
- b.append(":");
- if (rmiServer != null) {
- b.append(" rmiServer=").append(rmiServer.toString());
- }
- if (jmxServiceURL != null) {
- if (rmiServer!=null) b.append(",");
- b.append(" jmxServiceURL=").append(jmxServiceURL.toString());
- }
- return b.toString();
- }
-
- /**
- * <p>The address of this connector.</p>
- *
- * @return the address of this connector, or null if it
- * does not have one.
- *
- * @since 1.6
- */
- public JMXServiceURL getAddress() {
- return jmxServiceURL;
- }
-
- //--------------------------------------------------------------------
- // implements JMXConnector interface
- //--------------------------------------------------------------------
-
- /**
- * @throws IOException if the connection could not be made because of a
- * communication problem
- */
- public void connect() throws IOException {
- connect(null);
- }
-
- /**
- * @throws IOException if the connection could not be made because of a
- * communication problem
- */
- public synchronized void connect(Map<String,?> environment)
- throws IOException {
- final boolean tracing = logger.traceOn();
- String idstr = (tracing?"["+this.toString()+"]":null);
-
- if (terminated) {
- logger.trace("connect",idstr + " already closed.");
- throw new IOException("Connector closed");
- }
- if (connected) {
- logger.trace("connect",idstr + " already connected.");
- return;
- }
-
- try {
- if (tracing) logger.trace("connect",idstr + " connecting...");
-
- final Map<String, Object> usemap =
- new HashMap<String, Object>((this.env==null) ?
- Collections.<String, Object>emptyMap() : this.env);
-
-
- if (environment != null) {
- EnvHelp.checkAttributes(environment);
- usemap.putAll(environment);
- }
-
- // Get RMIServer stub from directory or URL encoding if needed.
- if (tracing) logger.trace("connect",idstr + " finding stub...");
- RMIServer stub = (rmiServer!=null)?rmiServer:
- findRMIServer(jmxServiceURL, usemap);
-
- // Check for secure RMIServer stub if the corresponding
- // client-side environment property is set to "true".
- //
- String stringBoolean = (String) usemap.get("jmx.remote.x.check.stub");
- boolean checkStub = EnvHelp.computeBooleanFromString(stringBoolean);
-
- if (checkStub) checkStub(stub, rmiServerImplStubClass);
-
- if (tracing) logger.trace("connect",idstr + " connecting stub...");
- idstr = (tracing?"["+this.toString()+"]":null);
-
- // Calling newClient on the RMIServer stub.
- if (tracing)
- logger.trace("connect",idstr + " getting connection...");
- Object credentials = usemap.get(CREDENTIALS);
-
- try {
- connection = getConnection(stub, credentials, checkStub);
- } catch (java.rmi.RemoteException re) {
- throw re;
- }
-
- // Always use one of:
- // ClassLoader provided in Map at connect time,
- // or contextClassLoader at connect time.
- if (tracing)
- logger.trace("connect",idstr + " getting class loader...");
- defaultClassLoader = EnvHelp.resolveClientClassLoader(usemap);
-
- usemap.put(JMXConnectorFactory.DEFAULT_CLASS_LOADER,
- defaultClassLoader);
-
- rmiNotifClient = new RMINotifClient(defaultClassLoader, usemap);
-
- env = usemap;
- final long checkPeriod = EnvHelp.getConnectionCheckPeriod(usemap);
- communicatorAdmin = new RMIClientCommunicatorAdmin(checkPeriod);
-
- connected = true;
-
- // The connectionId variable is used in doStart(), when
- // reconnecting, to identify the "old" connection.
- //
- connectionId = getConnectionId();
-
- Notification connectedNotif =
- new JMXConnectionNotification(JMXConnectionNotification.OPENED,
- this,
- connectionId,
- clientNotifSeqNo++,
- "Successful connection",
- null);
- sendNotification(connectedNotif);
-
- if (tracing) logger.trace("connect",idstr + " done...");
- } catch (IOException e) {
- if (tracing)
- logger.trace("connect",idstr + " failed to connect: " + e);
- throw e;
- } catch (RuntimeException e) {
- if (tracing)
- logger.trace("connect",idstr + " failed to connect: " + e);
- throw e;
- } catch (NamingException e) {
- final String msg = "Failed to retrieve RMIServer stub: " + e;
- if (tracing) logger.trace("connect",idstr + " " + msg);
- throw EnvHelp.initCause(new IOException(msg),e);
- }
- }
-
- public synchronized String getConnectionId() throws IOException {
- if (terminated || !connected) {
- if (logger.traceOn())
- logger.trace("getConnectionId","["+this.toString()+
- "] not connected.");
-
- throw new IOException("Not connected");
- }
-
- // we do a remote call to have an IOException if the connection is broken.
- // see the bug 4939578
- return connection.getConnectionId();
- }
-
- public synchronized MBeanServerConnection getMBeanServerConnection()
- throws IOException {
- return getMBeanServerConnection(null);
- }
-
- public synchronized MBeanServerConnection
- getMBeanServerConnection(Subject delegationSubject)
- throws IOException {
-
- if (terminated) {
- if (logger.traceOn())
- logger.trace("getMBeanServerConnection","[" + this.toString() +
- "] already closed.");
- throw new IOException("Connection closed");
- } else if (!connected) {
- if (logger.traceOn())
- logger.trace("getMBeanServerConnection","[" + this.toString() +
- "] is not connected.");
- throw new IOException("Not connected");
- }
-
- return getConnectionWithSubject(delegationSubject);
- }
-
- public void
- addConnectionNotificationListener(NotificationListener listener,
- NotificationFilter filter,
- Object handback) {
- if (listener == null)
- throw new NullPointerException("listener");
- connectionBroadcaster.addNotificationListener(listener, filter,
- handback);
- }
-
- public void
- removeConnectionNotificationListener(NotificationListener listener)
- throws ListenerNotFoundException {
- if (listener == null)
- throw new NullPointerException("listener");
- connectionBroadcaster.removeNotificationListener(listener);
- }
-
- public void
- removeConnectionNotificationListener(NotificationListener listener,
- NotificationFilter filter,
- Object handback)
- throws ListenerNotFoundException {
- if (listener == null)
- throw new NullPointerException("listener");
- connectionBroadcaster.removeNotificationListener(listener, filter,
- handback);
- }
-
- private void sendNotification(Notification n) {
- connectionBroadcaster.sendNotification(n);
- }
-
- public synchronized void close() throws IOException {
- close(false);
- }
-
- // allows to do close after setting the flag "terminated" to true.
- // It is necessary to avoid a deadlock, see 6296324
- private synchronized void close(boolean intern) throws IOException {
- final boolean tracing = logger.traceOn();
- final boolean debug = logger.debugOn();
- final String idstr = (tracing?"["+this.toString()+"]":null);
-
- if (!intern) {
- // Return if already cleanly closed.
- //
- if (terminated) {
- if (closeException == null) {
- if (tracing) logger.trace("close",idstr + " already closed.");
- return;
- }
- } else {
- terminated = true;
- }
- }
-
- if (closeException != null && tracing) {
- // Already closed, but not cleanly. Attempt again.
- //
- if (tracing) {
- logger.trace("close",idstr + " had failed: " + closeException);
- logger.trace("close",idstr + " attempting to close again.");
- }
- }
-
- String savedConnectionId = null;
- if (connected) {
- savedConnectionId = connectionId;
- }
-
- closeException = null;
-
- if (tracing) logger.trace("close",idstr + " closing.");
-
- if (communicatorAdmin != null) {
- communicatorAdmin.terminate();
- }
-
- if (rmiNotifClient != null) {
- try {
- rmiNotifClient.terminate();
- if (tracing) logger.trace("close",idstr +
- " RMI Notification client terminated.");
- } catch (RuntimeException x) {
- closeException = x;
- if (tracing) logger.trace("close",idstr +
- " Failed to terminate RMI Notification client: " + x);
- if (debug) logger.debug("close",x);
- }
- }
-
- if (connection != null) {
- try {
- connection.close();
- if (tracing) logger.trace("close",idstr + " closed.");
- } catch (NoSuchObjectException nse) {
- // OK, the server maybe closed itself.
- } catch (IOException e) {
- closeException = e;
- if (tracing) logger.trace("close",idstr +
- " Failed to close RMIServer: " + e);
- if (debug) logger.debug("close",e);
- }
- }
-
- // Clean up MBeanServerConnection table
- //
- rmbscMap.clear();
-
- /* Send notification of closure. We don't do this if the user
- * never called connect() on the connector, because there's no
- * connection id in that case. */
-
- if (savedConnectionId != null) {
- Notification closedNotif =
- new JMXConnectionNotification(JMXConnectionNotification.CLOSED,
- this,
- savedConnectionId,
- clientNotifSeqNo++,
- "Client has been closed",
- null);
- sendNotification(closedNotif);
- }
-
- // throw exception if needed
- //
- if (closeException != null) {
- if (tracing) logger.trace("close",idstr + " failed to close: " +
- closeException);
- if (closeException instanceof IOException)
- throw (IOException) closeException;
- if (closeException instanceof RuntimeException)
- throw (RuntimeException) closeException;
- final IOException x =
- new IOException("Failed to close: " + closeException);
- throw EnvHelp.initCause(x,closeException);
- }
- }
-
- // added for re-connection
- private Integer addListenerWithSubject(ObjectName name,
- MarshalledObject<NotificationFilter> filter,
- Subject delegationSubject,
- boolean reconnect)
- throws InstanceNotFoundException, IOException {
-
- final boolean debug = logger.debugOn();
- if (debug)
- logger.debug("addListenerWithSubject",
- "(ObjectName,MarshalledObject,Subject)");
-
- final ObjectName[] names = new ObjectName[] {name};
- final MarshalledObject<NotificationFilter>[] filters =
- Util.cast(new MarshalledObject<?>[] {filter});
- final Subject[] delegationSubjects = new Subject[] {
- delegationSubject
- };
-
- final Integer[] listenerIDs =
- addListenersWithSubjects(names,filters,delegationSubjects,
- reconnect);
-
- if (debug) logger.debug("addListenerWithSubject","listenerID="
- + listenerIDs[0]);
- return listenerIDs[0];
- }
-
- // added for re-connection
- private Integer[] addListenersWithSubjects(ObjectName[] names,
- MarshalledObject<NotificationFilter>[] filters,
- Subject[] delegationSubjects,
- boolean reconnect)
- throws InstanceNotFoundException, IOException {
-
- final boolean debug = logger.debugOn();
- if (debug)
- logger.debug("addListenersWithSubjects",
- "(ObjectName[],MarshalledObject[],Subject[])");
-
- final ClassLoader old = pushDefaultClassLoader();
- Integer[] listenerIDs = null;
-
- try {
- listenerIDs = connection.addNotificationListeners(names,
- filters,
- delegationSubjects);
- } catch (NoSuchObjectException noe) {
- // maybe reconnect
- if (reconnect) {
- communicatorAdmin.gotIOException(noe);
-
- listenerIDs = connection.addNotificationListeners(names,
- filters,
- delegationSubjects);
- } else {
- throw noe;
- }
- } catch (IOException ioe) {
- // send a failed notif if necessary
- communicatorAdmin.gotIOException(ioe);
- } finally {
- popDefaultClassLoader(old);
- }
-
- if (debug) logger.debug("addListenersWithSubjects","registered "
- + ((listenerIDs==null)?0:listenerIDs.length)
- + " listener(s)");
- return listenerIDs;
- }
-
- //--------------------------------------------------------------------
- // Implementation of MBeanServerConnection
- //--------------------------------------------------------------------
- private class RemoteMBeanServerConnection implements MBeanServerConnection {
- private Subject delegationSubject;
-
- public RemoteMBeanServerConnection() {
- this(null);
- }
-
- public RemoteMBeanServerConnection(Subject delegationSubject) {
- this.delegationSubject = delegationSubject;
- }
-
- public ObjectInstance createMBean(String className,
- ObjectName name)
- throws ReflectionException,
- InstanceAlreadyExistsException,
- MBeanRegistrationException,
- MBeanException,
- NotCompliantMBeanException,
- IOException {
- if (logger.debugOn())
- logger.debug("createMBean(String,ObjectName)",
- "className=" + className + ", name=" +
- name);
-
- final ClassLoader old = pushDefaultClassLoader();
- try {
- return connection.createMBean(className,
- name,
- delegationSubject);
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- return connection.createMBean(className,
- name,
- delegationSubject);
- } finally {
- popDefaultClassLoader(old);
- }
- }
-
- public ObjectInstance createMBean(String className,
- ObjectName name,
- ObjectName loaderName)
- throws ReflectionException,
- InstanceAlreadyExistsException,
- MBeanRegistrationException,
- MBeanException,
- NotCompliantMBeanException,
- InstanceNotFoundException,
- IOException {
-
- if (logger.debugOn())
- logger.debug("createMBean(String,ObjectName,ObjectName)",
- "className=" + className + ", name="
- + name + ", loaderName="
- + loaderName + ")");
-
- final ClassLoader old = pushDefaultClassLoader();
- try {
- return connection.createMBean(className,
- name,
- loaderName,
- delegationSubject);
-
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- return connection.createMBean(className,
- name,
- loaderName,
- delegationSubject);
-
- } finally {
- popDefaultClassLoader(old);
- }
- }
-
- public ObjectInstance createMBean(String className,
- ObjectName name,
- Object params[],
- String signature[])
- throws ReflectionException,
- InstanceAlreadyExistsException,
- MBeanRegistrationException,
- MBeanException,
- NotCompliantMBeanException,
- IOException {
- if (logger.debugOn())
- logger.debug("createMBean(String,ObjectName,Object[],String[])",
- "className=" + className + ", name="
- + name + ", signature=" + strings(signature));
-
- final MarshalledObject<Object[]> sParams =
- new MarshalledObject<Object[]>(params);
- final ClassLoader old = pushDefaultClassLoader();
- try {
- return connection.createMBean(className,
- name,
- sParams,
- signature,
- delegationSubject);
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- return connection.createMBean(className,
- name,
- sParams,
- signature,
- delegationSubject);
- } finally {
- popDefaultClassLoader(old);
- }
- }
-
- public ObjectInstance createMBean(String className,
- ObjectName name,
- ObjectName loaderName,
- Object params[],
- String signature[])
- throws ReflectionException,
- InstanceAlreadyExistsException,
- MBeanRegistrationException,
- MBeanException,
- NotCompliantMBeanException,
- InstanceNotFoundException,
- IOException {
- if (logger.debugOn()) logger.debug(
- "createMBean(String,ObjectName,ObjectName,Object[],String[])",
- "className=" + className + ", name=" + name + ", loaderName="
- + loaderName + ", signature=" + strings(signature));
-
- final MarshalledObject<Object[]> sParams =
- new MarshalledObject<Object[]>(params);
- final ClassLoader old = pushDefaultClassLoader();
- try {
- return connection.createMBean(className,
- name,
- loaderName,
- sParams,
- signature,
- delegationSubject);
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- return connection.createMBean(className,
- name,
- loaderName,
- sParams,
- signature,
- delegationSubject);
- } finally {
- popDefaultClassLoader(old);
- }
- }
-
- public void unregisterMBean(ObjectName name)
- throws InstanceNotFoundException,
- MBeanRegistrationException,
- IOException {
- if (logger.debugOn())
- logger.debug("unregisterMBean", "name=" + name);
-
- final ClassLoader old = pushDefaultClassLoader();
- try {
- connection.unregisterMBean(name, delegationSubject);
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- connection.unregisterMBean(name, delegationSubject);
- } finally {
- popDefaultClassLoader(old);
- }
- }
-
- public ObjectInstance getObjectInstance(ObjectName name)
- throws InstanceNotFoundException,
- IOException {
- if (logger.debugOn())
- logger.debug("getObjectInstance", "name=" + name);
-
- final ClassLoader old = pushDefaultClassLoader();
- try {
- return connection.getObjectInstance(name, delegationSubject);
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- return connection.getObjectInstance(name, delegationSubject);
- } finally {
- popDefaultClassLoader(old);
- }
- }
-
- public Set<ObjectInstance> queryMBeans(ObjectName name,
- QueryExp query)
- throws IOException {
- if (logger.debugOn()) logger.debug("queryMBeans",
- "name=" + name + ", query=" + query);
-
- final MarshalledObject<QueryExp> sQuery =
- new MarshalledObject<QueryExp>(query);
- final ClassLoader old = pushDefaultClassLoader();
- try {
- return connection.queryMBeans(name, sQuery, delegationSubject);
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- return connection.queryMBeans(name, sQuery, delegationSubject);
- } finally {
- popDefaultClassLoader(old);
- }
- }
-
- public Set<ObjectName> queryNames(ObjectName name,
- QueryExp query)
- throws IOException {
- if (logger.debugOn()) logger.debug("queryNames",
- "name=" + name + ", query=" + query);
-
- final MarshalledObject<QueryExp> sQuery =
- new MarshalledObject<QueryExp>(query);
- final ClassLoader old = pushDefaultClassLoader();
- try {
- return connection.queryNames(name, sQuery, delegationSubject);
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- return connection.queryNames(name, sQuery, delegationSubject);
- } finally {
- popDefaultClassLoader(old);
- }
- }
-
- public boolean isRegistered(ObjectName name)
- throws IOException {
- if (logger.debugOn())
- logger.debug("isRegistered", "name=" + name);
-
- final ClassLoader old = pushDefaultClassLoader();
- try {
- return connection.isRegistered(name, delegationSubject);
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- return connection.isRegistered(name, delegationSubject);
- } finally {
- popDefaultClassLoader(old);
- }
- }
-
- public Integer getMBeanCount()
- throws IOException {
- if (logger.debugOn()) logger.debug("getMBeanCount", "");
-
- final ClassLoader old = pushDefaultClassLoader();
- try {
- return connection.getMBeanCount(delegationSubject);
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- return connection.getMBeanCount(delegationSubject);
- } finally {
- popDefaultClassLoader(old);
- }
- }
-
- public Object getAttribute(ObjectName name,
- String attribute)
- throws MBeanException,
- AttributeNotFoundException,
- InstanceNotFoundException,
- ReflectionException,
- IOException {
- if (logger.debugOn()) logger.debug("getAttribute",
- "name=" + name + ", attribute="
- + attribute);
-
- final ClassLoader old = pushDefaultClassLoader();
- try {
- return connection.getAttribute(name,
- attribute,
- delegationSubject);
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- return connection.getAttribute(name,
- attribute,
- delegationSubject);
- } finally {
- popDefaultClassLoader(old);
- }
- }
-
- public AttributeList getAttributes(ObjectName name,
- String[] attributes)
- throws InstanceNotFoundException,
- ReflectionException,
- IOException {
- if (logger.debugOn()) logger.debug("getAttributes",
- "name=" + name + ", attributes="
- + strings(attributes));
-
- final ClassLoader old = pushDefaultClassLoader();
- try {
- return connection.getAttributes(name,
- attributes,
- delegationSubject);
-
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- return connection.getAttributes(name,
- attributes,
- delegationSubject);
- } finally {
- popDefaultClassLoader(old);
- }
- }
-
-
- public void setAttribute(ObjectName name,
- Attribute attribute)
- throws InstanceNotFoundException,
- AttributeNotFoundException,
- InvalidAttributeValueException,
- MBeanException,
- ReflectionException,
- IOException {
-
- if (logger.debugOn()) logger.debug("setAttribute",
- "name=" + name + ", attribute name="
- + attribute.getName());
-
- final MarshalledObject<Attribute> sAttribute =
- new MarshalledObject<Attribute>(attribute);
- final ClassLoader old = pushDefaultClassLoader();
- try {
- connection.setAttribute(name, sAttribute, delegationSubject);
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- connection.setAttribute(name, sAttribute, delegationSubject);
- } finally {
- popDefaultClassLoader(old);
- }
- }
-
- public AttributeList setAttributes(ObjectName name,
- AttributeList attributes)
- throws InstanceNotFoundException,
- ReflectionException,
- IOException {
-
- if (logger.debugOn()) {
- logger.debug("setAttributes",
- "name=" + name + ", attribute names="
- + getAttributesNames(attributes));
- }
-
- final MarshalledObject<AttributeList> sAttributes =
- new MarshalledObject<AttributeList>(attributes);
- final ClassLoader old = pushDefaultClassLoader();
- try {
- return connection.setAttributes(name,
- sAttributes,
- delegationSubject);
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- return connection.setAttributes(name,
- sAttributes,
- delegationSubject);
- } finally {
- popDefaultClassLoader(old);
- }
- }
-
-
- public Object invoke(ObjectName name,
- String operationName,
- Object params[],
- String signature[])
- throws InstanceNotFoundException,
- MBeanException,
- ReflectionException,
- IOException {
-
- if (logger.debugOn()) logger.debug("invoke",
- "name=" + name
- + ", operationName=" + operationName
- + ", signature=" + strings(signature));
-
- final MarshalledObject<Object[]> sParams =
- new MarshalledObject<Object[]>(params);
- final ClassLoader old = pushDefaultClassLoader();
- try {
- return connection.invoke(name,
- operationName,
- sParams,
- signature,
- delegationSubject);
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- return connection.invoke(name,
- operationName,
- sParams,
- signature,
- delegationSubject);
- } finally {
- popDefaultClassLoader(old);
- }
- }
-
-
- public String getDefaultDomain()
- throws IOException {
- if (logger.debugOn()) logger.debug("getDefaultDomain", "");
-
- final ClassLoader old = pushDefaultClassLoader();
- try {
- return connection.getDefaultDomain(delegationSubject);
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- return connection.getDefaultDomain(delegationSubject);
- } finally {
- popDefaultClassLoader(old);
- }
- }
-
- public String[] getDomains() throws IOException {
- if (logger.debugOn()) logger.debug("getDomains", "");
-
- final ClassLoader old = pushDefaultClassLoader();
- try {
- return connection.getDomains(delegationSubject);
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- return connection.getDomains(delegationSubject);
- } finally {
- popDefaultClassLoader(old);
- }
- }
-
- public MBeanInfo getMBeanInfo(ObjectName name)
- throws InstanceNotFoundException,
- IntrospectionException,
- ReflectionException,
- IOException {
-
- if (logger.debugOn()) logger.debug("getMBeanInfo", "name=" + name);
- final ClassLoader old = pushDefaultClassLoader();
- try {
- return connection.getMBeanInfo(name, delegationSubject);
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- return connection.getMBeanInfo(name, delegationSubject);
- } finally {
- popDefaultClassLoader(old);
- }
- }
-
-
- public boolean isInstanceOf(ObjectName name,
- String className)
- throws InstanceNotFoundException,
- IOException {
- if (logger.debugOn())
- logger.debug("isInstanceOf", "name=" + name +
- ", className=" + className);
-
- final ClassLoader old = pushDefaultClassLoader();
- try {
- return connection.isInstanceOf(name,
- className,
- delegationSubject);
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- return connection.isInstanceOf(name,
- className,
- delegationSubject);
- } finally {
- popDefaultClassLoader(old);
- }
- }
-
- public void addNotificationListener(ObjectName name,
- ObjectName listener,
- NotificationFilter filter,
- Object handback)
- throws InstanceNotFoundException,
- IOException {
-
- if (logger.debugOn())
- logger.debug("addNotificationListener" +
- "(ObjectName,ObjectName,NotificationFilter,Object)",
- "name=" + name + ", listener=" + listener
- + ", filter=" + filter + ", handback=" + handback);
-
- final MarshalledObject<NotificationFilter> sFilter =
- new MarshalledObject<NotificationFilter>(filter);
- final MarshalledObject<Object> sHandback =
- new MarshalledObject<Object>(handback);
- final ClassLoader old = pushDefaultClassLoader();
- try {
- connection.addNotificationListener(name,
- listener,
- sFilter,
- sHandback,
- delegationSubject);
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- connection.addNotificationListener(name,
- listener,
- sFilter,
- sHandback,
- delegationSubject);
- } finally {
- popDefaultClassLoader(old);
- }
- }
-
- public void removeNotificationListener(ObjectName name,
- ObjectName listener)
- throws InstanceNotFoundException,
- ListenerNotFoundException,
- IOException {
-
- if (logger.debugOn()) logger.debug("removeNotificationListener" +
- "(ObjectName,ObjectName)",
- "name=" + name
- + ", listener=" + listener);
-
- final ClassLoader old = pushDefaultClassLoader();
- try {
- connection.removeNotificationListener(name,
- listener,
- delegationSubject);
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- connection.removeNotificationListener(name,
- listener,
- delegationSubject);
- } finally {
- popDefaultClassLoader(old);
- }
- }
-
- public void removeNotificationListener(ObjectName name,
- ObjectName listener,
- NotificationFilter filter,
- Object handback)
- throws InstanceNotFoundException,
- ListenerNotFoundException,
- IOException {
- if (logger.debugOn())
- logger.debug("removeNotificationListener" +
- "(ObjectName,ObjectName,NotificationFilter,Object)",
- "name=" + name
- + ", listener=" + listener
- + ", filter=" + filter
- + ", handback=" + handback);
-
- final MarshalledObject<NotificationFilter> sFilter =
- new MarshalledObject<NotificationFilter>(filter);
- final MarshalledObject<Object> sHandback =
- new MarshalledObject<Object>(handback);
- final ClassLoader old = pushDefaultClassLoader();
- try {
- connection.removeNotificationListener(name,
- listener,
- sFilter,
- sHandback,
- delegationSubject);
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- connection.removeNotificationListener(name,
- listener,
- sFilter,
- sHandback,
- delegationSubject);
- } finally {
- popDefaultClassLoader(old);
- }
- }
-
- // Specific Notification Handle ----------------------------------
-
- public void addNotificationListener(ObjectName name,
- NotificationListener listener,
- NotificationFilter filter,
- Object handback)
- throws InstanceNotFoundException,
- IOException {
-
- final boolean debug = logger.debugOn();
-
- if (debug)
- logger.debug("addNotificationListener" +
- "(ObjectName,NotificationListener,"+
- "NotificationFilter,Object)",
- "name=" + name
- + ", listener=" + listener
- + ", filter=" + filter
- + ", handback=" + handback);
-
- final Integer listenerID =
- addListenerWithSubject(name,
- new MarshalledObject<NotificationFilter>(filter),
- delegationSubject,true);
- rmiNotifClient.addNotificationListener(listenerID, name, listener,
- filter, handback,
- delegationSubject);
- }
-
- public void removeNotificationListener(ObjectName name,
- NotificationListener listener)
- throws InstanceNotFoundException,
- ListenerNotFoundException,
- IOException {
-
- final boolean debug = logger.debugOn();
-
- if (debug) logger.debug("removeNotificationListener"+
- "(ObjectName,NotificationListener)",
- "name=" + name
- + ", listener=" + listener);
-
- final Integer[] ret =
- rmiNotifClient.removeNotificationListener(name, listener);
-
- if (debug) logger.debug("removeNotificationListener",
- "listenerIDs=" + objects(ret));
-
- final ClassLoader old = pushDefaultClassLoader();
-
- try {
- connection.removeNotificationListeners(name,
- ret,
- delegationSubject);
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- connection.removeNotificationListeners(name,
- ret,
- delegationSubject);
- } finally {
- popDefaultClassLoader(old);
- }
-
- }
-
- public void removeNotificationListener(ObjectName name,
- NotificationListener listener,
- NotificationFilter filter,
- Object handback)
- throws InstanceNotFoundException,
- ListenerNotFoundException,
- IOException {
- final boolean debug = logger.debugOn();
-
- if (debug)
- logger.debug("removeNotificationListener"+
- "(ObjectName,NotificationListener,"+
- "NotificationFilter,Object)",
- "name=" + name
- + ", listener=" + listener
- + ", filter=" + filter
- + ", handback=" + handback);
-
- final Integer ret =
- rmiNotifClient.removeNotificationListener(name, listener,
- filter, handback);
-
- if (debug) logger.debug("removeNotificationListener",
- "listenerID=" + ret);
-
- final ClassLoader old = pushDefaultClassLoader();
- try {
- connection.removeNotificationListeners(name,
- new Integer[] {ret},
- delegationSubject);
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- connection.removeNotificationListeners(name,
- new Integer[] {ret},
- delegationSubject);
- } finally {
- popDefaultClassLoader(old);
- }
-
- }
- }
-
- //--------------------------------------------------------------------
- private class RMINotifClient extends ClientNotifForwarder {
- public RMINotifClient(ClassLoader cl, Map<String, ?> env) {
- super(cl, env);
- }
-
- protected NotificationResult fetchNotifs(long clientSequenceNumber,
- int maxNotifications,
- long timeout)
- throws IOException, ClassNotFoundException {
-
- boolean retried = false;
- while (true) { // used for a successful re-connection
- // or a transient network problem
- try {
- return connection.fetchNotifications(clientSequenceNumber,
- maxNotifications,
- timeout); // return normally
- } catch (IOException ioe) {
- // Examine the chain of exceptions to determine whether this
- // is a deserialization issue. If so - we propagate the
- // appropriate exception to the caller, who will then
- // proceed with fetching notifications one by one
- rethrowDeserializationException(ioe);
-
- try {
- communicatorAdmin.gotIOException(ioe);
- // reconnection OK, back to "while" to do again
- } catch (IOException ee) {
- boolean toClose = false;
-
- synchronized (this) {
- if (terminated) {
- // the connection is closed.
- throw ioe;
- } else if (retried) {
- toClose = true;
- }
- }
-
- if (toClose) {
- // JDK-8049303
- // We received an IOException - but the communicatorAdmin
- // did not close the connection - possibly because
- // the original exception was raised by a transient network
- // problem?
- // We already know that this exception is not due to a deserialization
- // issue as we already took care of that before involving the
- // communicatorAdmin. Moreover - we already made one retry attempt
- // at fetching the same batch of notifications - and the
- // problem persisted.
- // Since trying again doesn't seem to solve the issue, we will now
- // close the connection. Doing otherwise might cause the
- // NotifFetcher thread to die silently.
- final Notification failedNotif =
- new JMXConnectionNotification(
- JMXConnectionNotification.FAILED,
- this,
- connectionId,
- clientNotifSeqNo++,
- "Failed to communicate with the server: " + ioe.toString(),
- ioe);
-
- sendNotification(failedNotif);
-
- try {
- close(true);
- } catch (Exception e) {
- // OK.
- // We are closing
- }
- throw ioe; // the connection is closed here.
- } else {
- // JDK-8049303 possible transient network problem,
- // let's try one more time
- retried = true;
- }
- }
- }
- }
- }
-
- private void rethrowDeserializationException(IOException ioe)
- throws ClassNotFoundException, IOException {
- // specially treating for an UnmarshalException
- if (ioe instanceof UnmarshalException) {
- throw ioe; // the fix of 6937053 made ClientNotifForwarder.fetchNotifs
- // fetch one by one with UnmarshalException
- }
-
- // Not serialization problem, return.
- }
-
- protected Integer addListenerForMBeanRemovedNotif()
- throws IOException, InstanceNotFoundException {
- NotificationFilterSupport clientFilter =
- new NotificationFilterSupport();
- clientFilter.enableType(
- MBeanServerNotification.UNREGISTRATION_NOTIFICATION);
- MarshalledObject<NotificationFilter> sFilter =
- new MarshalledObject<NotificationFilter>(clientFilter);
-
- Integer[] listenerIDs;
- final ObjectName[] names =
- new ObjectName[] {MBeanServerDelegate.DELEGATE_NAME};
- final MarshalledObject<NotificationFilter>[] filters =
- Util.cast(new MarshalledObject<?>[] {sFilter});
- final Subject[] subjects = new Subject[] {null};
- try {
- listenerIDs =
- connection.addNotificationListeners(names,
- filters,
- subjects);
-
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- listenerIDs =
- connection.addNotificationListeners(names,
- filters,
- subjects);
- }
- return listenerIDs[0];
- }
-
- protected void removeListenerForMBeanRemovedNotif(Integer id)
- throws IOException, InstanceNotFoundException,
- ListenerNotFoundException {
- try {
- connection.removeNotificationListeners(
- MBeanServerDelegate.DELEGATE_NAME,
- new Integer[] {id},
- null);
- } catch (IOException ioe) {
- communicatorAdmin.gotIOException(ioe);
-
- connection.removeNotificationListeners(
- MBeanServerDelegate.DELEGATE_NAME,
- new Integer[] {id},
- null);
- }
-
- }
-
- protected void lostNotifs(String message, long number) {
- final String notifType = JMXConnectionNotification.NOTIFS_LOST;
-
- final JMXConnectionNotification n =
- new JMXConnectionNotification(notifType,
- RMIConnector.this,
- connectionId,
- clientNotifCounter++,
- message,
- Long.valueOf(number));
- sendNotification(n);
- }
- }
-
- private class RMIClientCommunicatorAdmin extends ClientCommunicatorAdmin {
- public RMIClientCommunicatorAdmin(long period) {
- super(period);
- }
-
- @Override
- public void gotIOException(IOException ioe) throws IOException {
- if (ioe instanceof NoSuchObjectException) {
- // need to restart
- super.gotIOException(ioe);
-
- return;
- }
-
- // check if the connection is broken
- try {
- connection.getDefaultDomain(null);
- } catch (IOException ioexc) {
- boolean toClose = false;
-
- synchronized(this) {
- if (!terminated) {
- terminated = true;
-
- toClose = true;
- }
- }
-
- if (toClose) {
- // we should close the connection,
- // but send a failed notif at first
- final Notification failedNotif =
- new JMXConnectionNotification(
- JMXConnectionNotification.FAILED,
- this,
- connectionId,
- clientNotifSeqNo++,
- "Failed to communicate with the server: "+ioe.toString(),
- ioe);
-
- sendNotification(failedNotif);
-
- try {
- close(true);
- } catch (Exception e) {
- // OK.
- // We are closing
- }
- }
- }
-
- // forward the exception
- if (ioe instanceof ServerException) {
- /* Need to unwrap the exception.
- Some user-thrown exception at server side will be wrapped by
- rmi into a ServerException.
- For example, a RMIConnnectorServer will wrap a
- ClassNotFoundException into a UnmarshalException, and rmi
- will throw a ServerException at client side which wraps this
- UnmarshalException.
- No failed notif here.
- */
- Throwable tt = ((ServerException)ioe).detail;
-
- if (tt instanceof IOException) {
- throw (IOException)tt;
- } else if (tt instanceof RuntimeException) {
- throw (RuntimeException)tt;
- }
- }
-
- throw ioe;
- }
-
- public void reconnectNotificationListeners(ClientListenerInfo[] old) throws IOException {
- final int len = old.length;
- int i;
-
- ClientListenerInfo[] clis = new ClientListenerInfo[len];
-
- final Subject[] subjects = new Subject[len];
- final ObjectName[] names = new ObjectName[len];
- final NotificationListener[] listeners = new NotificationListener[len];
- final NotificationFilter[] filters = new NotificationFilter[len];
- final MarshalledObject<NotificationFilter>[] mFilters =
- Util.cast(new MarshalledObject<?>[len]);
- final Object[] handbacks = new Object[len];
-
- for (i=0;i<len;i++) {
- subjects[i] = old[i].getDelegationSubject();
- names[i] = old[i].getObjectName();
- listeners[i] = old[i].getListener();
- filters[i] = old[i].getNotificationFilter();
- mFilters[i] = new MarshalledObject<NotificationFilter>(filters[i]);
- handbacks[i] = old[i].getHandback();
- }
-
- try {
- Integer[] ids = addListenersWithSubjects(names,mFilters,subjects,false);
-
- for (i=0;i<len;i++) {
- clis[i] = new ClientListenerInfo(ids[i],
- names[i],
- listeners[i],
- filters[i],
- handbacks[i],
- subjects[i]);
- }
-
- rmiNotifClient.postReconnection(clis);
-
- return;
- } catch (InstanceNotFoundException infe) {
- // OK, we will do one by one
- }
-
- int j = 0;
- for (i=0;i<len;i++) {
- try {
- Integer id = addListenerWithSubject(names[i],
- new MarshalledObject<NotificationFilter>(filters[i]),
- subjects[i],
- false);
-
- clis[j++] = new ClientListenerInfo(id,
- names[i],
- listeners[i],
- filters[i],
- handbacks[i],
- subjects[i]);
- } catch (InstanceNotFoundException infe) {
- logger.warning("reconnectNotificationListeners",
- "Can't reconnect listener for " +
- names[i]);
- }
- }
-
- if (j != len) {
- ClientListenerInfo[] tmp = clis;
- clis = new ClientListenerInfo[j];
- System.arraycopy(tmp, 0, clis, 0, j);
- }
-
- rmiNotifClient.postReconnection(clis);
- }
-
- protected void checkConnection() throws IOException {
- if (logger.debugOn())
- logger.debug("RMIClientCommunicatorAdmin-checkConnection",
- "Calling the method getDefaultDomain.");
-
- connection.getDefaultDomain(null);
- }
-
- protected void doStart() throws IOException {
- // Get RMIServer stub from directory or URL encoding if needed.
- RMIServer stub;
- try {
- stub = (rmiServer!=null)?rmiServer:
- findRMIServer(jmxServiceURL, env);
- } catch (NamingException ne) {
- throw new IOException("Failed to get a RMI stub: "+ne);
- }
-
- // Calling newClient on the RMIServer stub.
- Object credentials = env.get(CREDENTIALS);
- connection = stub.newClient(credentials);
-
- // notif issues
- final ClientListenerInfo[] old = rmiNotifClient.preReconnection();
-
- reconnectNotificationListeners(old);
-
- connectionId = getConnectionId();
-
- Notification reconnectedNotif =
- new JMXConnectionNotification(JMXConnectionNotification.OPENED,
- this,
- connectionId,
- clientNotifSeqNo++,
- "Reconnected to server",
- null);
- sendNotification(reconnectedNotif);
-
- }
-
- protected void doStop() {
- try {
- close();
- } catch (IOException ioe) {
- logger.warning("RMIClientCommunicatorAdmin-doStop",
- "Failed to call the method close():" + ioe);
- logger.debug("RMIClientCommunicatorAdmin-doStop",ioe);
- }
- }
- }
-
- //--------------------------------------------------------------------
- // Private stuff - Serialization
- //--------------------------------------------------------------------
- /**
- * Read RMIConnector fields from an {@link java.io.ObjectInputStream
- * ObjectInputStream}.
- * Calls {@code s.defaultReadObject()} and then initializes
- * all transient variables that need initializing.
- * @param s The ObjectInputStream to read from.
- * @exception InvalidObjectException if none of <var>rmiServer</var> stub
- * or <var>jmxServiceURL</var> are set.
- * @see #RMIConnector(JMXServiceURL,Map)
- * @see #RMIConnector(RMIServer,Map)
- **/
- private void readObject(java.io.ObjectInputStream s)
- throws IOException, ClassNotFoundException {
- s.defaultReadObject();
-
- if (rmiServer == null && jmxServiceURL == null) throw new
- InvalidObjectException("rmiServer and jmxServiceURL both null");
-
- initTransients();
- }
-
- /**
- * Writes the RMIConnector fields to an {@link java.io.ObjectOutputStream
- * ObjectOutputStream}.
- * <p>Connects the underlying RMIServer stub to an ORB, if needed,
- * before serializing it. This is done using the environment
- * map that was provided to the constructor, if any, and as documented
- * in {@link javax.management.remote.rmi}.</p>
- * <p>This method then calls {@code s.defaultWriteObject()}.
- * Usually, <var>rmiServer</var> is null if this object
- * was constructed with a JMXServiceURL, and <var>jmxServiceURL</var>
- * is null if this object is constructed with a RMIServer stub.
- * <p>Note that the environment Map is not serialized, since the objects
- * it contains are assumed to be contextual and relevant only
- * with respect to the local environment (class loader, ORB, etc...).</p>
- * <p>After an RMIConnector is deserialized, it is assumed that the
- * user will call {@link #connect(Map)}, providing a new Map that
- * can contain values which are contextually relevant to the new
- * local environment.</p>
- * <p>Since connection to the ORB is needed prior to serializing, and
- * since the ORB to connect to is one of those contextual parameters,
- * it is not recommended to re-serialize a just de-serialized object -
- * as the de-serialized object has no map. Thus, when an RMIConnector
- * object is needed for serialization or transmission to a remote
- * application, it is recommended to obtain a new RMIConnector stub
- * by calling {@link RMIConnectorServer#toJMXConnector(Map)}.</p>
- * @param s The ObjectOutputStream to write to.
- * @exception InvalidObjectException if none of <var>rmiServer</var> stub
- * or <var>jmxServiceURL</var> are set.
- * @see #RMIConnector(JMXServiceURL,Map)
- * @see #RMIConnector(RMIServer,Map)
- **/
- private void writeObject(java.io.ObjectOutputStream s)
- throws IOException {
- if (rmiServer == null && jmxServiceURL == null) throw new
- InvalidObjectException("rmiServer and jmxServiceURL both null.");
- s.defaultWriteObject();
- }
-
- // Initialization of transient variables.
- private void initTransients() {
- rmbscMap = new WeakHashMap<Subject, WeakReference<MBeanServerConnection>>();
- connected = false;
- terminated = false;
-
- connectionBroadcaster = new NotificationBroadcasterSupport();
- }
-
- //--------------------------------------------------------------------
- // Private stuff - Check if stub can be trusted.
- //--------------------------------------------------------------------
-
- private static void checkStub(Remote stub,
- Class<?> stubClass) {
-
- // Check remote stub is from the expected class.
- //
- if (stub.getClass() != stubClass) {
- if (!Proxy.isProxyClass(stub.getClass())) {
- throw new SecurityException(
- "Expecting a " + stubClass.getName() + " stub!");
- } else {
- InvocationHandler handler = Proxy.getInvocationHandler(stub);
- if (handler.getClass() != RemoteObjectInvocationHandler.class)
- throw new SecurityException(
- "Expecting a dynamic proxy instance with a " +
- RemoteObjectInvocationHandler.class.getName() +
- " invocation handler!");
- else
- stub = (Remote) handler;
- }
- }
-
- // Check RemoteRef in stub is from the expected class
- // "sun.rmi.server.UnicastRef2".
- //
- RemoteRef ref = ((RemoteObject)stub).getRef();
- if (ref.getClass() != UnicastRef2.class)
- throw new SecurityException(
- "Expecting a " + UnicastRef2.class.getName() +
- " remote reference in stub!");
-
- // Check RMIClientSocketFactory in stub is from the expected class
- // "javax.rmi.ssl.SslRMIClientSocketFactory".
- //
- LiveRef liveRef = ((UnicastRef2)ref).getLiveRef();
- RMIClientSocketFactory csf = liveRef.getClientSocketFactory();
- if (csf == null || csf.getClass() != SslRMIClientSocketFactory.class)
- throw new SecurityException(
- "Expecting a " + SslRMIClientSocketFactory.class.getName() +
- " RMI client socket factory in stub!");
- }
-
- //--------------------------------------------------------------------
- // Private stuff - RMIServer creation
- //--------------------------------------------------------------------
-
- private RMIServer findRMIServer(JMXServiceURL directoryURL,
- Map<String, Object> environment)
- throws NamingException, IOException {
-
- String path = directoryURL.getURLPath();
- int end = path.indexOf(';');
- if (end < 0) end = path.length();
- if (path.startsWith("/jndi/"))
- return findRMIServerJNDI(path.substring(6,end), environment);
- else if (path.startsWith("/stub/"))
- return findRMIServerJRMP(path.substring(6,end), environment);
- else {
- final String msg = "URL path must begin with /jndi/ or /stub/ " +
- "or /ior/: " + path;
- throw new MalformedURLException(msg);
- }
- }
-
- /**
- * Lookup the RMIServer stub in a directory.
- * @param jndiURL A JNDI URL indicating the location of the Stub
- * (see {@link javax.management.remote.rmi}), e.g.:
- * <ul><li>{@code rmi://registry-host:port/rmi-stub-name}</li>
- * <li>or {@code ldap://ldap-host:port/java-container-dn}</li>
- * </ul>
- * @param env the environment Map passed to the connector.
- * @return The retrieved RMIServer stub.
- * @exception NamingException if the stub couldn't be found.
- **/
- private RMIServer findRMIServerJNDI(String jndiURL, Map<String, ?> env)
- throws NamingException {
-
- InitialContext ctx = new InitialContext(EnvHelp.mapToHashtable(env));
-
- Object objref = ctx.lookup(jndiURL);
- ctx.close();
-
- return narrowJRMPServer(objref);
- }
-
- private static RMIServer narrowJRMPServer(Object objref) {
-
- return (RMIServer) objref;
- }
-
- private RMIServer findRMIServerJRMP(String base64, Map<String, ?> env)
- throws IOException {
- final byte[] serialized;
- try {
- serialized = base64ToByteArray(base64);
- } catch (IllegalArgumentException e) {
- throw new MalformedURLException("Bad BASE64 encoding: " +
- e.getMessage());
- }
- final ByteArrayInputStream bin = new ByteArrayInputStream(serialized);
-
- final ClassLoader loader = EnvHelp.resolveClientClassLoader(env);
- final ObjectInputStream oin =
- (loader == null) ?
- new ObjectInputStream(bin) :
- new ObjectInputStreamWithLoader(bin, loader);
- final Object stub;
- try {
- stub = oin.readObject();
- } catch (ClassNotFoundException e) {
- throw new MalformedURLException("Class not found: " + e);
- }
- return (RMIServer)stub;
- }
-
- private static final class ObjectInputStreamWithLoader
- extends ObjectInputStream {
- ObjectInputStreamWithLoader(InputStream in, ClassLoader cl)
- throws IOException, IllegalArgumentException {
- super(in);
- if (cl == null ) {
- throw new IllegalArgumentException("class loader is null");
- }
- this.loader = cl;
- }
-
- @Override
- protected Class<?> resolveClass(ObjectStreamClass classDesc)
- throws IOException, ClassNotFoundException {
- String name = classDesc.getName();
- ReflectUtil.checkPackageAccess(name);
- return Class.forName(name, false, Objects.requireNonNull(loader));
- }
-
- private final ClassLoader loader;
- }
-
- private MBeanServerConnection getConnectionWithSubject(Subject delegationSubject) {
- MBeanServerConnection conn = null;
-
- if (delegationSubject == null) {
- if (nullSubjectConnRef == null
- || (conn = nullSubjectConnRef.get()) == null) {
- conn = new RemoteMBeanServerConnection(null);
- nullSubjectConnRef = new WeakReference<MBeanServerConnection>(conn);
- }
- } else {
- WeakReference<MBeanServerConnection> wr = rmbscMap.get(delegationSubject);
- if (wr == null || (conn = wr.get()) == null) {
- conn = new RemoteMBeanServerConnection(delegationSubject);
- rmbscMap.put(delegationSubject, new WeakReference<MBeanServerConnection>(conn));
- }
- }
- return conn;
- }
-
- /*
- The following section of code avoids a class loading problem
- with RMI. The problem is that an RMI stub, when deserializing
- a remote method return value or exception, will first of all
- consult the first non-bootstrap class loader it finds in the
- call stack. This can lead to behavior that is not portable
- between implementations of the JMX Remote API. Notably, an
- implementation on J2SE 1.4 will find the RMI stub's loader on
- the stack. But in J2SE 5, this stub is loaded by the
- bootstrap loader, so RMI will find the loader of the user code
- that called an MBeanServerConnection method.
-
- To avoid this problem, we take advantage of what the RMI stub
- is doing internally. Each remote call will end up calling
- ref.invoke(...), where ref is the RemoteRef parameter given to
- the RMI stub's constructor. It is within this call that the
- deserialization will happen. So we fabricate our own RemoteRef
- that delegates everything to the "real" one but that is loaded
- by a class loader that knows no other classes. The class
- loader NoCallStackClassLoader does this: the RemoteRef is an
- instance of the class named by proxyRefClassName, which is
- fabricated by the class loader using byte code that is defined
- by the string below.
-
- The call stack when the deserialization happens is thus this:
- MBeanServerConnection.getAttribute (or whatever)
- -> RMIConnectionImpl_Stub.getAttribute
- -> ProxyRef.invoke(...getAttribute...)
- -> UnicastRef.invoke(...getAttribute...)
- -> internal RMI stuff
-
- Here UnicastRef is the RemoteRef created when the stub was
- deserialized (which is of some RMI internal class). It and the
- "internal RMI stuff" are loaded by the bootstrap loader, so are
- transparent to the stack search. The first non-bootstrap
- loader found is our ProxyRefLoader, as required.
-
- In a future version of this code as integrated into J2SE 5,
- this workaround could be replaced by direct access to the
- internals of RMI. For now, we use the same code base for J2SE
- and for the standalone Reference Implementation.
-
- The byte code below encodes the following class, compiled using
- J2SE 1.4.2 with the -g:none option.
-
- package com.sun.jmx.remote.internal;
-
- import java.lang.reflect.Method;
- import java.rmi.Remote;
- import java.rmi.server.RemoteRef;
- import com.sun.jmx.remote.internal.ProxyRef;
-
- public class PRef extends ProxyRef {
- public PRef(RemoteRef ref) {
- super(ref);
- }
-
- public Object invoke(Remote obj, Method method,
- Object[] params, long opnum)
- throws Exception {
- return ref.invoke(obj, method, params, opnum);
- }
- }
- */
-
- private static final String rmiServerImplStubClassName =
- RMIServer.class.getName() + "Impl_Stub";
- private static final Class<?> rmiServerImplStubClass;
- private static final String rmiConnectionImplStubClassName =
- RMIConnection.class.getName() + "Impl_Stub";
- private static final Class<?> rmiConnectionImplStubClass;
- private static final String pRefClassName =
- "jdk.jmx.remote.internal.PRef";
- private static final Constructor<?> proxyRefConstructor;
- static {
- final String pRefByteCodeString =
- "\312\376\272\276\0\0\0\60\0\27\12\0\5\0\15\11\0\4\0\16\13\0\17"+
- "\0\20\7\0\21\7\0\22\1\0\6<init>\1\0\36(Ljava/rmi/server/Remote"+
- "Ref;)V\1\0\4Code\1\0\6invoke\1\0S(Ljava/rmi/Remote;Ljava/lang/"+
- "reflect/Method;[Ljava/lang/Object;J)Ljava/lang/Object;\1\0\12E"+
- "xceptions\7\0\23\14\0\6\0\7\14\0\24\0\25\7\0\26\14\0\11\0\12\1"+
- "\0\34jdk/jmx/remote/internal/PRef\1\0$com/sun/jmx/remote/inter"+
- "nal/ProxyRef\1\0\23java/lang/Exception\1\0\3ref\1\0\33Ljava/rm"+
- "i/server/RemoteRef;\1\0\31java/rmi/server/RemoteRef\0!\0\4\0\5"+
- "\0\0\0\0\0\2\0\1\0\6\0\7\0\1\0\10\0\0\0\22\0\2\0\2\0\0\0\6*+\267"+
- "\0\1\261\0\0\0\0\0\1\0\11\0\12\0\2\0\10\0\0\0\33\0\6\0\6\0\0\0"+
- "\17*\264\0\2+,-\26\4\271\0\3\6\0\260\0\0\0\0\0\13\0\0\0\4\0\1\0"+
- "\14\0\0";
- final byte[] pRefByteCode =
- NoCallStackClassLoader.stringToBytes(pRefByteCodeString);
- PrivilegedExceptionAction<Constructor<?>> action =
- new PrivilegedExceptionAction<Constructor<?>>() {
- public Constructor<?> run() throws Exception {
- Class<RMIConnector> thisClass = RMIConnector.class;
- ClassLoader thisLoader = thisClass.getClassLoader();
- ProtectionDomain thisProtectionDomain =
- thisClass.getProtectionDomain();
-
- String proxyRefCName = ProxyRef.class.getName();
- ClassLoader cl =
- new NoCallStackClassLoader(pRefClassName,
- pRefByteCode,
- new String[] { proxyRefCName },
- thisLoader,
- thisProtectionDomain);
-
- Module jmxModule = ProxyRef.class.getModule();
- Module rmiModule = RemoteRef.class.getModule();
-
- String pkg = packageOf(pRefClassName);
- assert pkg != null && pkg.length() > 0 && !pkg.equals(packageOf(proxyRefCName));
- Module m = Modules.defineModule(cl, "jdk.remoteref", Collections.singleton(pkg));
-
- // jdk.remoteref needs to read to java.base and jmxModule
- Modules.addReads(m, Object.class.getModule());
- Modules.addReads(m, jmxModule);
- Modules.addReads(m, rmiModule);
-
- // jdk.remoteref needs access to ProxyRef class
- Modules.addExports(jmxModule, packageOf(proxyRefCName), m);
-
- // java.management needs to instantiate the fabricated RemoteRef class
- Modules.addReads(jmxModule, m);
- Modules.addExports(m, pkg, jmxModule);
-
- Class<?> c = cl.loadClass(pRefClassName);
- return c.getConstructor(RemoteRef.class);
- }
- };
-
- Class<?> serverStubClass;
- try {
- serverStubClass = Class.forName(rmiServerImplStubClassName);
- } catch (Exception e) {
- logger.error("<clinit>",
- "Failed to instantiate " +
- rmiServerImplStubClassName + ": " + e);
- logger.debug("<clinit>",e);
- serverStubClass = null;
- }
- rmiServerImplStubClass = serverStubClass;
-
- Class<?> stubClass;
- Constructor<?> constr;
- try {
- stubClass = Class.forName(rmiConnectionImplStubClassName);
- constr = (Constructor<?>) AccessController.doPrivileged(action);
- } catch (Exception e) {
- logger.error("<clinit>",
- "Failed to initialize proxy reference constructor "+
- "for " + rmiConnectionImplStubClassName + ": " + e);
- logger.debug("<clinit>",e);
- stubClass = null;
- constr = null;
- }
- rmiConnectionImplStubClass = stubClass;
- proxyRefConstructor = constr;
- }
-
- private static String packageOf(String cn) {
- int i = cn.lastIndexOf('.');
- return i > 0 ? cn.substring(0, i) : "";
- }
-
- private static RMIConnection shadowJrmpStub(RemoteObject stub)
- throws InstantiationException, IllegalAccessException,
- InvocationTargetException, ClassNotFoundException,
- NoSuchMethodException {
- RemoteRef ref = stub.getRef();
- RemoteRef proxyRef = (RemoteRef)
- proxyRefConstructor.newInstance(new Object[] {ref});
- final Constructor<?> rmiConnectionImplStubConstructor =
- rmiConnectionImplStubClass.getConstructor(RemoteRef.class);
- Object[] args = {proxyRef};
- RMIConnection proxyStub = (RMIConnection)
- rmiConnectionImplStubConstructor.newInstance(args);
- return proxyStub;
- }
-
- private static RMIConnection getConnection(RMIServer server,
- Object credentials,
- boolean checkStub)
- throws IOException {
- RMIConnection c = server.newClient(credentials);
- if (checkStub) checkStub(c, rmiConnectionImplStubClass);
- try {
- if (c.getClass() == rmiConnectionImplStubClass)
- return shadowJrmpStub((RemoteObject) c);
- logger.trace("getConnection",
- "Did not wrap " + c.getClass() + " to foil " +
- "stack search for classes: class loading semantics " +
- "may be incorrect");
- } catch (Exception e) {
- logger.error("getConnection",
- "Could not wrap " + c.getClass() + " to foil " +
- "stack search for classes: class loading semantics " +
- "may be incorrect: " + e);
- logger.debug("getConnection",e);
- // so just return the original stub, which will work for all
- // but the most exotic class loading situations
- }
- return c;
- }
-
- private static byte[] base64ToByteArray(String s) {
- int sLen = s.length();
- int numGroups = sLen/4;
- if (4*numGroups != sLen)
- throw new IllegalArgumentException(
- "String length must be a multiple of four.");
- int missingBytesInLastGroup = 0;
- int numFullGroups = numGroups;
- if (sLen != 0) {
- if (s.charAt(sLen-1) == '=') {
- missingBytesInLastGroup++;
- numFullGroups--;
- }
- if (s.charAt(sLen-2) == '=')
- missingBytesInLastGroup++;
- }
- byte[] result = new byte[3*numGroups - missingBytesInLastGroup];
-
- // Translate all full groups from base64 to byte array elements
- int inCursor = 0, outCursor = 0;
- for (int i=0; i<numFullGroups; i++) {
- int ch0 = base64toInt(s.charAt(inCursor++));
- int ch1 = base64toInt(s.charAt(inCursor++));
- int ch2 = base64toInt(s.charAt(inCursor++));
- int ch3 = base64toInt(s.charAt(inCursor++));
- result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
- result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
- result[outCursor++] = (byte) ((ch2 << 6) | ch3);
- }
-
- // Translate partial group, if present
- if (missingBytesInLastGroup != 0) {
- int ch0 = base64toInt(s.charAt(inCursor++));
- int ch1 = base64toInt(s.charAt(inCursor++));
- result[outCursor++] = (byte) ((ch0 << 2) | (ch1 >> 4));
-
- if (missingBytesInLastGroup == 1) {
- int ch2 = base64toInt(s.charAt(inCursor++));
- result[outCursor++] = (byte) ((ch1 << 4) | (ch2 >> 2));
- }
- }
- // assert inCursor == s.length()-missingBytesInLastGroup;
- // assert outCursor == result.length;
- return result;
- }
-
- /**
- * Translates the specified character, which is assumed to be in the
- * "Base 64 Alphabet" into its equivalent 6-bit positive integer.
- *
- * @throws IllegalArgumentException if
- * c is not in the Base64 Alphabet.
- */
- private static int base64toInt(char c) {
- int result;
-
- if (c >= base64ToInt.length)
- result = -1;
- else
- result = base64ToInt[c];
-
- if (result < 0)
- throw new IllegalArgumentException("Illegal character " + c);
- return result;
- }
-
- /**
- * This array is a lookup table that translates unicode characters
- * drawn from the "Base64 Alphabet" (as specified in Table 1 of RFC 2045)
- * into their 6-bit positive integer equivalents. Characters that
- * are not in the Base64 alphabet but fall within the bounds of the
- * array are translated to -1.
- */
- private static final byte base64ToInt[] = {
- -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, 62, -1, -1, -1, 63, 52, 53, 54,
- 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
- 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
- };
-
- //--------------------------------------------------------------------
- // Private stuff - Find / Set default class loader
- //--------------------------------------------------------------------
- private ClassLoader pushDefaultClassLoader() {
- final Thread t = Thread.currentThread();
- final ClassLoader old = t.getContextClassLoader();
- if (defaultClassLoader != null)
- AccessController.doPrivileged(new PrivilegedAction<Void>() {
- public Void run() {
- t.setContextClassLoader(defaultClassLoader);
- return null;
- }
- });
- return old;
- }
-
- private void popDefaultClassLoader(final ClassLoader old) {
- AccessController.doPrivileged(new PrivilegedAction<Void>() {
- public Void run() {
- Thread.currentThread().setContextClassLoader(old);
- return null;
- }
- });
- }
-
- //--------------------------------------------------------------------
- // Private variables
- //--------------------------------------------------------------------
- /**
- * @serial The RMIServer stub of the RMI JMX Connector server to
- * which this client connector is (or will be) connected. This
- * field can be null when <var>jmxServiceURL</var> is not
- * null. This includes the case where <var>jmxServiceURL</var>
- * contains a serialized RMIServer stub. If both
- * <var>rmiServer</var> and <var>jmxServiceURL</var> are null then
- * serialization will fail.
- *
- * @see #RMIConnector(RMIServer,Map)
- **/
- private final RMIServer rmiServer;
-
- /**
- * @serial The JMXServiceURL of the RMI JMX Connector server to
- * which this client connector will be connected. This field can
- * be null when <var>rmiServer</var> is not null. If both
- * <var>rmiServer</var> and <var>jmxServiceURL</var> are null then
- * serialization will fail.
- *
- * @see #RMIConnector(JMXServiceURL,Map)
- **/
- private final JMXServiceURL jmxServiceURL;
-
- // ---------------------------------------------------------
- // WARNING - WARNING - WARNING - WARNING - WARNING - WARNING
- // ---------------------------------------------------------
- // Any transient variable which needs to be initialized should
- // be initialized in the method initTransient()
- private transient Map<String, Object> env;
- private transient ClassLoader defaultClassLoader;
- private transient RMIConnection connection;
- private transient String connectionId;
-
- private transient long clientNotifSeqNo = 0;
-
- private transient WeakHashMap<Subject, WeakReference<MBeanServerConnection>> rmbscMap;
- private transient WeakReference<MBeanServerConnection> nullSubjectConnRef = null;
-
- private transient RMINotifClient rmiNotifClient;
- // = new RMINotifClient(new Integer(0));
-
- private transient long clientNotifCounter = 0;
-
- private transient boolean connected;
- // = false;
- private transient boolean terminated;
- // = false;
-
- private transient Exception closeException;
-
- private transient NotificationBroadcasterSupport connectionBroadcaster;
-
- private transient ClientCommunicatorAdmin communicatorAdmin;
-
- /**
- * A static WeakReference to an {@link org.omg.CORBA.ORB ORB} to
- * connect unconnected stubs.
- **/
- private static volatile WeakReference<Object> orb = null;
-
- // TRACES & DEBUG
- //---------------
- private static String objects(final Object[] objs) {
- if (objs == null)
- return "null";
- else
- return Arrays.asList(objs).toString();
- }
-
- private static String strings(final String[] strs) {
- return objects(strs);
- }
-
- static String getAttributesNames(AttributeList attributes) {
- return attributes != null ?
- attributes.asList().stream()
- .map(Attribute::getName)
- .collect(Collectors.joining(", ", "[", "]"))
- : "[]";
- }
-}
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIConnectorServer.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,819 +0,0 @@
-/*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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 javax.management.remote.rmi;
-
-
-import com.sun.jmx.remote.security.MBeanServerFileAccessController;
-import com.sun.jmx.remote.util.ClassLogger;
-import com.sun.jmx.remote.util.EnvHelp;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectOutputStream;
-import java.net.MalformedURLException;
-import java.rmi.server.RMIClientSocketFactory;
-import java.rmi.server.RMIServerSocketFactory;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Map;
-import java.util.Set;
-
-import javax.management.InstanceNotFoundException;
-import javax.management.MBeanServer;
-import javax.management.remote.JMXAuthenticator;
-
-import javax.management.remote.JMXConnectionNotification;
-import javax.management.remote.JMXConnector;
-import javax.management.remote.JMXConnectorServer;
-import javax.management.remote.JMXServiceURL;
-import javax.management.remote.MBeanServerForwarder;
-
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
-
-/**
- * <p>A JMX API connector server that creates RMI-based connections
- * from remote clients. Usually, such connector servers are made
- * using {@link javax.management.remote.JMXConnectorServerFactory
- * JMXConnectorServerFactory}. However, specialized applications can
- * use this class directly, for example with an {@link RMIServerImpl}
- * object.</p>
- *
- * @since 1.5
- */
-public class RMIConnectorServer extends JMXConnectorServer {
- /**
- * <p>Name of the attribute that specifies whether the {@link
- * RMIServer} stub that represents an RMI connector server should
- * override an existing stub at the same address. The value
- * associated with this attribute, if any, should be a string that
- * is equal, ignoring case, to <code>"true"</code> or
- * <code>"false"</code>. The default value is false.</p>
- */
- public static final String JNDI_REBIND_ATTRIBUTE =
- "jmx.remote.jndi.rebind";
-
- /**
- * <p>Name of the attribute that specifies the {@link
- * RMIClientSocketFactory} for the RMI objects created in
- * conjunction with this connector. The value associated with this
- * attribute must be of type <code>RMIClientSocketFactory</code> and can
- * only be specified in the <code>Map</code> argument supplied when
- * creating a connector server.</p>
- */
- public static final String RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE =
- "jmx.remote.rmi.client.socket.factory";
-
- /**
- * <p>Name of the attribute that specifies the {@link
- * RMIServerSocketFactory} for the RMI objects created in
- * conjunction with this connector. The value associated with this
- * attribute must be of type <code>RMIServerSocketFactory</code> and can
- * only be specified in the <code>Map</code> argument supplied when
- * creating a connector server.</p>
- */
- public static final String RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE =
- "jmx.remote.rmi.server.socket.factory";
-
- /**
- * Name of the attribute that specifies a list of class names acceptable
- * as parameters to the {@link RMIServer#newClient(java.lang.Object) RMIServer.newClient()}
- * remote method call.
- * <p>
- * This list of classes should correspond to the transitive closure of the
- * credentials class (or classes) used by the installed {@linkplain JMXAuthenticator}
- * associated with the {@linkplain RMIServer} implementation.
- * <p>
- * If the attribute is not set, or is null, then any class is
- * deemed acceptable.
- */
- public static final String CREDENTIAL_TYPES =
- "jmx.remote.rmi.server.credential.types";
-
- /**
- * <p>Makes an <code>RMIConnectorServer</code>.
- * This is equivalent to calling {@link #RMIConnectorServer(
- * JMXServiceURL,Map,RMIServerImpl,MBeanServer)
- * RMIConnectorServer(directoryURL,environment,null,null)}</p>
- *
- * @param url the URL defining how to create the connector server.
- * Cannot be null.
- *
- * @param environment attributes governing the creation and
- * storing of the RMI object. Can be null, which is equivalent to
- * an empty Map.
- *
- * @exception IllegalArgumentException if <code>url</code> is null.
- *
- * @exception MalformedURLException if <code>url</code> does not
- * conform to the syntax for an RMI connector, or if its protocol
- * is not recognized by this implementation. Only "rmi" is valid when
- * this constructor is used.
- *
- * @exception IOException if the connector server cannot be created
- * for some reason or if it is inevitable that its {@link #start()
- * start} method will fail.
- */
- public RMIConnectorServer(JMXServiceURL url, Map<String,?> environment)
- throws IOException {
- this(url, environment, (MBeanServer) null);
- }
-
- /**
- * <p>Makes an <code>RMIConnectorServer</code> for the given MBean
- * server.
- * This is equivalent to calling {@link #RMIConnectorServer(
- * JMXServiceURL,Map,RMIServerImpl,MBeanServer)
- * RMIConnectorServer(directoryURL,environment,null,mbeanServer)}</p>
- *
- * @param url the URL defining how to create the connector server.
- * Cannot be null.
- *
- * @param environment attributes governing the creation and
- * storing of the RMI object. Can be null, which is equivalent to
- * an empty Map.
- *
- * @param mbeanServer the MBean server to which the new connector
- * server is attached, or null if it will be attached by being
- * registered as an MBean in the MBean server.
- *
- * @exception IllegalArgumentException if <code>url</code> is null.
- *
- * @exception MalformedURLException if <code>url</code> does not
- * conform to the syntax for an RMI connector, or if its protocol
- * is not recognized by this implementation. Only "rmi" is valid
- * when this constructor is used.
- *
- * @exception IOException if the connector server cannot be created
- * for some reason or if it is inevitable that its {@link #start()
- * start} method will fail.
- */
- public RMIConnectorServer(JMXServiceURL url, Map<String,?> environment,
- MBeanServer mbeanServer)
- throws IOException {
- this(url, environment, (RMIServerImpl) null, mbeanServer);
- }
-
- /**
- * <p>Makes an <code>RMIConnectorServer</code> for the given MBean
- * server.</p>
- *
- * @param url the URL defining how to create the connector server.
- * Cannot be null.
- *
- * @param environment attributes governing the creation and
- * storing of the RMI object. Can be null, which is equivalent to
- * an empty Map.
- *
- * @param rmiServerImpl An implementation of the RMIServer interface,
- * consistent with the protocol type specified in <var>url</var>.
- * If this parameter is non null, the protocol type specified by
- * <var>url</var> is not constrained, and is assumed to be valid.
- * Otherwise, only "rmi" will be recognized.
- *
- * @param mbeanServer the MBean server to which the new connector
- * server is attached, or null if it will be attached by being
- * registered as an MBean in the MBean server.
- *
- * @exception IllegalArgumentException if <code>url</code> is null.
- *
- * @exception MalformedURLException if <code>url</code> does not
- * conform to the syntax for an RMI connector, or if its protocol
- * is not recognized by this implementation. Only "rmi" is recognized
- * when <var>rmiServerImpl</var> is null.
- *
- * @exception IOException if the connector server cannot be created
- * for some reason or if it is inevitable that its {@link #start()
- * start} method will fail.
- *
- * @see #start
- */
- public RMIConnectorServer(JMXServiceURL url, Map<String,?> environment,
- RMIServerImpl rmiServerImpl,
- MBeanServer mbeanServer)
- throws IOException {
- super(mbeanServer);
-
- if (url == null) throw new
- IllegalArgumentException("Null JMXServiceURL");
- if (rmiServerImpl == null) {
- final String prt = url.getProtocol();
- if (prt == null || !(prt.equals("rmi"))) {
- final String msg = "Invalid protocol type: " + prt;
- throw new MalformedURLException(msg);
- }
- final String urlPath = url.getURLPath();
- if (!urlPath.equals("")
- && !urlPath.equals("/")
- && !urlPath.startsWith("/jndi/")) {
- final String msg = "URL path must be empty or start with " +
- "/jndi/";
- throw new MalformedURLException(msg);
- }
- }
-
- if (environment == null)
- this.attributes = Collections.emptyMap();
- else {
- EnvHelp.checkAttributes(environment);
- this.attributes = Collections.unmodifiableMap(environment);
- }
-
- this.address = url;
- this.rmiServerImpl = rmiServerImpl;
- }
-
- /**
- * <p>Returns a client stub for this connector server. A client
- * stub is a serializable object whose {@link
- * JMXConnector#connect(Map) connect} method can be used to make
- * one new connection to this connector server.</p>
- *
- * @param env client connection parameters of the same sort that
- * could be provided to {@link JMXConnector#connect(Map)
- * JMXConnector.connect(Map)}. Can be null, which is equivalent
- * to an empty map.
- *
- * @return a client stub that can be used to make a new connection
- * to this connector server.
- *
- * @exception UnsupportedOperationException if this connector
- * server does not support the generation of client stubs.
- *
- * @exception IllegalStateException if the JMXConnectorServer is
- * not started (see {@link #isActive()}).
- *
- * @exception IOException if a communications problem means that a
- * stub cannot be created.
- **/
- public JMXConnector toJMXConnector(Map<String,?> env) throws IOException {
- // The serialized for of rmiServerImpl is automatically
- // a RMI server stub.
- if (!isActive()) throw new
- IllegalStateException("Connector is not active");
-
- // Merge maps
- Map<String, Object> usemap = new HashMap<String, Object>(
- (this.attributes==null)?Collections.<String, Object>emptyMap():
- this.attributes);
-
- if (env != null) {
- EnvHelp.checkAttributes(env);
- usemap.putAll(env);
- }
-
- usemap = EnvHelp.filterAttributes(usemap);
-
- final RMIServer stub=(RMIServer)rmiServerImpl.toStub();
-
- return new RMIConnector(stub, usemap);
- }
-
- /**
- * <p>Activates the connector server, that is starts listening for
- * client connections. Calling this method when the connector
- * server is already active has no effect. Calling this method
- * when the connector server has been stopped will generate an
- * <code>IOException</code>.</p>
- *
- * <p>The behavior of this method when called for the first time
- * depends on the parameters that were supplied at construction,
- * as described below.</p>
- *
- * <p>First, an object of a subclass of {@link RMIServerImpl} is
- * required, to export the connector server through RMI:</p>
- *
- * <ul>
- *
- * <li>If an <code>RMIServerImpl</code> was supplied to the
- * constructor, it is used.
- *
- * <li>Otherwise, if the <code>JMXServiceURL</code>
- * was null, or its protocol part was <code>rmi</code>, an object
- * of type {@link RMIJRMPServerImpl} is created.
- *
- * <li>Otherwise, the implementation can create an
- * implementation-specific {@link RMIServerImpl} or it can throw
- * {@link MalformedURLException}.
- *
- * </ul>
- *
- * <p>If the given address includes a JNDI directory URL as
- * specified in the package documentation for {@link
- * javax.management.remote.rmi}, then this
- * <code>RMIConnectorServer</code> will bootstrap by binding the
- * <code>RMIServerImpl</code> to the given address.</p>
- *
- * <p>If the URL path part of the <code>JMXServiceURL</code> was
- * empty or a single slash (<code>/</code>), then the RMI object
- * will not be bound to a directory. Instead, a reference to it
- * will be encoded in the URL path of the RMIConnectorServer
- * address (returned by {@link #getAddress()}). The encodings for
- * <code>rmi</code> are described in the package documentation for
- * {@link javax.management.remote.rmi}.</p>
- *
- * <p>The behavior when the URL path is neither empty nor a JNDI
- * directory URL, or when the protocol is not <code>rmi</code>,
- * is implementation defined, and may include throwing
- * {@link MalformedURLException} when the connector server is created
- * or when it is started.</p>
- *
- * @exception IllegalStateException if the connector server has
- * not been attached to an MBean server.
- * @exception IOException if the connector server cannot be
- * started.
- */
- public synchronized void start() throws IOException {
- final boolean tracing = logger.traceOn();
-
- if (state == STARTED) {
- if (tracing) logger.trace("start", "already started");
- return;
- } else if (state == STOPPED) {
- if (tracing) logger.trace("start", "already stopped");
- throw new IOException("The server has been stopped.");
- }
-
- if (getMBeanServer() == null)
- throw new IllegalStateException("This connector server is not " +
- "attached to an MBean server");
-
- // Check the internal access file property to see
- // if an MBeanServerForwarder is to be provided
- //
- if (attributes != null) {
- // Check if access file property is specified
- //
- String accessFile =
- (String) attributes.get("jmx.remote.x.access.file");
- if (accessFile != null) {
- // Access file property specified, create an instance
- // of the MBeanServerFileAccessController class
- //
- MBeanServerForwarder mbsf;
- try {
- mbsf = new MBeanServerFileAccessController(accessFile);
- } catch (IOException e) {
- throw EnvHelp.initCause(
- new IllegalArgumentException(e.getMessage()), e);
- }
- // Set the MBeanServerForwarder
- //
- setMBeanServerForwarder(mbsf);
- }
- }
-
- try {
- if (tracing) logger.trace("start", "setting default class loader");
- defaultClassLoader = EnvHelp.resolveServerClassLoader(
- attributes, getMBeanServer());
- } catch (InstanceNotFoundException infc) {
- IllegalArgumentException x = new
- IllegalArgumentException("ClassLoader not found: "+infc);
- throw EnvHelp.initCause(x,infc);
- }
-
- if (tracing) logger.trace("start", "setting RMIServer object");
- final RMIServerImpl rmiServer;
-
- if (rmiServerImpl != null)
- rmiServer = rmiServerImpl;
- else
- rmiServer = newServer();
-
- rmiServer.setMBeanServer(getMBeanServer());
- rmiServer.setDefaultClassLoader(defaultClassLoader);
- rmiServer.setRMIConnectorServer(this);
- rmiServer.export();
-
- try {
- if (tracing) logger.trace("start", "getting RMIServer object to export");
- final RMIServer objref = objectToBind(rmiServer, attributes);
-
- if (address != null && address.getURLPath().startsWith("/jndi/")) {
- final String jndiUrl = address.getURLPath().substring(6);
-
- if (tracing)
- logger.trace("start", "Using external directory: " + jndiUrl);
-
- String stringBoolean = (String) attributes.get(JNDI_REBIND_ATTRIBUTE);
- final boolean rebind = EnvHelp.computeBooleanFromString( stringBoolean );
-
- if (tracing)
- logger.trace("start", JNDI_REBIND_ATTRIBUTE + "=" + rebind);
-
- try {
- if (tracing) logger.trace("start", "binding to " + jndiUrl);
-
- final Hashtable<?, ?> usemap = EnvHelp.mapToHashtable(attributes);
-
- bind(jndiUrl, usemap, objref, rebind);
-
- boundJndiUrl = jndiUrl;
- } catch (NamingException e) {
- // fit e in the nested exception if we are on 1.4
- throw newIOException("Cannot bind to URL ["+jndiUrl+"]: "
- + e, e);
- }
- } else {
- // if jndiURL is null, we must encode the stub into the URL.
- if (tracing) logger.trace("start", "Encoding URL");
-
- encodeStubInAddress(objref, attributes);
-
- if (tracing) logger.trace("start", "Encoded URL: " + this.address);
- }
- } catch (Exception e) {
- try {
- rmiServer.close();
- } catch (Exception x) {
- // OK: we are already throwing another exception
- }
- if (e instanceof RuntimeException)
- throw (RuntimeException) e;
- else if (e instanceof IOException)
- throw (IOException) e;
- else
- throw newIOException("Got unexpected exception while " +
- "starting the connector server: "
- + e, e);
- }
-
- rmiServerImpl = rmiServer;
-
- synchronized(openedServers) {
- openedServers.add(this);
- }
-
- state = STARTED;
-
- if (tracing) {
- logger.trace("start", "Connector Server Address = " + address);
- logger.trace("start", "started.");
- }
- }
-
- /**
- * <p>Deactivates the connector server, that is, stops listening for
- * client connections. Calling this method will also close all
- * client connections that were made by this server. After this
- * method returns, whether normally or with an exception, the
- * connector server will not create any new client
- * connections.</p>
- *
- * <p>Once a connector server has been stopped, it cannot be started
- * again.</p>
- *
- * <p>Calling this method when the connector server has already
- * been stopped has no effect. Calling this method when the
- * connector server has not yet been started will disable the
- * connector server object permanently.</p>
- *
- * <p>If closing a client connection produces an exception, that
- * exception is not thrown from this method. A {@link
- * JMXConnectionNotification} is emitted from this MBean with the
- * connection ID of the connection that could not be closed.</p>
- *
- * <p>Closing a connector server is a potentially slow operation.
- * For example, if a client machine with an open connection has
- * crashed, the close operation might have to wait for a network
- * protocol timeout. Callers that do not want to block in a close
- * operation should do it in a separate thread.</p>
- *
- * <p>This method calls the method {@link RMIServerImpl#close()
- * close} on the connector server's <code>RMIServerImpl</code>
- * object.</p>
- *
- * <p>If the <code>RMIServerImpl</code> was bound to a JNDI
- * directory by the {@link #start() start} method, it is unbound
- * from the directory by this method.</p>
- *
- * @exception IOException if the server cannot be closed cleanly,
- * or if the <code>RMIServerImpl</code> cannot be unbound from the
- * directory. When this exception is thrown, the server has
- * already attempted to close all client connections, if
- * appropriate; to call {@link RMIServerImpl#close()}; and to
- * unbind the <code>RMIServerImpl</code> from its directory, if
- * appropriate. All client connections are closed except possibly
- * those that generated exceptions when the server attempted to
- * close them.
- */
- public void stop() throws IOException {
- final boolean tracing = logger.traceOn();
-
- synchronized (this) {
- if (state == STOPPED) {
- if (tracing) logger.trace("stop","already stopped.");
- return;
- } else if (state == CREATED) {
- if (tracing) logger.trace("stop","not started yet.");
- }
-
- if (tracing) logger.trace("stop", "stopping.");
- state = STOPPED;
- }
-
- synchronized(openedServers) {
- openedServers.remove(this);
- }
-
- IOException exception = null;
-
- // rmiServerImpl can be null if stop() called without start()
- if (rmiServerImpl != null) {
- try {
- if (tracing) logger.trace("stop", "closing RMI server.");
- rmiServerImpl.close();
- } catch (IOException e) {
- if (tracing) logger.trace("stop", "failed to close RMI server: " + e);
- if (logger.debugOn()) logger.debug("stop",e);
- exception = e;
- }
- }
-
- if (boundJndiUrl != null) {
- try {
- if (tracing)
- logger.trace("stop",
- "unbind from external directory: " + boundJndiUrl);
-
- final Hashtable<?, ?> usemap = EnvHelp.mapToHashtable(attributes);
-
- InitialContext ctx =
- new InitialContext(usemap);
-
- ctx.unbind(boundJndiUrl);
-
- ctx.close();
- } catch (NamingException e) {
- if (tracing) logger.trace("stop", "failed to unbind RMI server: "+e);
- if (logger.debugOn()) logger.debug("stop",e);
- // fit e in as the nested exception if we are on 1.4
- if (exception == null)
- exception = newIOException("Cannot bind to URL: " + e, e);
- }
- }
-
- if (exception != null) throw exception;
-
- if (tracing) logger.trace("stop", "stopped");
- }
-
- public synchronized boolean isActive() {
- return (state == STARTED);
- }
-
- public JMXServiceURL getAddress() {
- if (!isActive())
- return null;
- return address;
- }
-
- public Map<String,?> getAttributes() {
- Map<String, ?> map = EnvHelp.filterAttributes(attributes);
- return Collections.unmodifiableMap(map);
- }
-
- @Override
- public synchronized
- void setMBeanServerForwarder(MBeanServerForwarder mbsf) {
- super.setMBeanServerForwarder(mbsf);
- if (rmiServerImpl != null)
- rmiServerImpl.setMBeanServer(getMBeanServer());
- }
-
- /* We repeat the definitions of connection{Opened,Closed,Failed}
- here so that they are accessible to other classes in this package
- even though they have protected access. */
-
- @Override
- protected void connectionOpened(String connectionId, String message,
- Object userData) {
- super.connectionOpened(connectionId, message, userData);
- }
-
- @Override
- protected void connectionClosed(String connectionId, String message,
- Object userData) {
- super.connectionClosed(connectionId, message, userData);
- }
-
- @Override
- protected void connectionFailed(String connectionId, String message,
- Object userData) {
- super.connectionFailed(connectionId, message, userData);
- }
-
- /**
- * Bind a stub to a registry.
- * @param jndiUrl URL of the stub in the registry, extracted
- * from the <code>JMXServiceURL</code>.
- * @param attributes A Hashtable containing environment parameters,
- * built from the Map specified at this object creation.
- * @param rmiServer The object to bind in the registry
- * @param rebind true if the object must be rebound.
- **/
- void bind(String jndiUrl, Hashtable<?, ?> attributes,
- RMIServer rmiServer, boolean rebind)
- throws NamingException, MalformedURLException {
- // if jndiURL is not null, we nust bind the stub to a
- // directory.
- InitialContext ctx =
- new InitialContext(attributes);
-
- if (rebind)
- ctx.rebind(jndiUrl, rmiServer);
- else
- ctx.bind(jndiUrl, rmiServer);
- ctx.close();
- }
-
- /**
- * Creates a new RMIServerImpl.
- **/
- RMIServerImpl newServer() throws IOException {
- final int port;
- if (address == null)
- port = 0;
- else
- port = address.getPort();
-
- return newJRMPServer(attributes, port);
- }
-
- /**
- * Encode a stub into the JMXServiceURL.
- * @param rmiServer The stub object to encode in the URL
- * @param attributes A Map containing environment parameters,
- * built from the Map specified at this object creation.
- **/
- private void encodeStubInAddress(
- RMIServer rmiServer, Map<String, ?> attributes)
- throws IOException {
-
- final String protocol, host;
- final int port;
-
- if (address == null) {
- protocol = "rmi";
- host = null; // will default to local host name
- port = 0;
- } else {
- protocol = address.getProtocol();
- host = (address.getHost().equals("")) ? null : address.getHost();
- port = address.getPort();
- }
-
- final String urlPath = encodeStub(rmiServer, attributes);
-
- address = new JMXServiceURL(protocol, host, port, urlPath);
- }
-
- /**
- * Returns the IOR of the given rmiServer.
- **/
- static String encodeStub(
- RMIServer rmiServer, Map<String, ?> env) throws IOException {
- return "/stub/" + encodeJRMPStub(rmiServer, env);
- }
-
- static String encodeJRMPStub(
- RMIServer rmiServer, Map<String, ?> env)
- throws IOException {
- ByteArrayOutputStream bout = new ByteArrayOutputStream();
- ObjectOutputStream oout = new ObjectOutputStream(bout);
- oout.writeObject(rmiServer);
- oout.close();
- byte[] bytes = bout.toByteArray();
- return byteArrayToBase64(bytes);
- }
-
- /**
- * Object that we will bind to the registry.
- * This object is a stub connected to our RMIServerImpl.
- **/
- private static RMIServer objectToBind(
- RMIServerImpl rmiServer, Map<String, ?> env)
- throws IOException {
- return (RMIServer)rmiServer.toStub();
- }
-
- private static RMIServerImpl newJRMPServer(Map<String, ?> env, int port)
- throws IOException {
- RMIClientSocketFactory csf = (RMIClientSocketFactory)
- env.get(RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE);
- RMIServerSocketFactory ssf = (RMIServerSocketFactory)
- env.get(RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE);
- return new RMIJRMPServerImpl(port, csf, ssf, env);
- }
-
- private static String byteArrayToBase64(byte[] a) {
- int aLen = a.length;
- int numFullGroups = aLen/3;
- int numBytesInPartialGroup = aLen - 3*numFullGroups;
- int resultLen = 4*((aLen + 2)/3);
- final StringBuilder result = new StringBuilder(resultLen);
-
- // Translate all full groups from byte array elements to Base64
- int inCursor = 0;
- for (int i=0; i<numFullGroups; i++) {
- int byte0 = a[inCursor++] & 0xff;
- int byte1 = a[inCursor++] & 0xff;
- int byte2 = a[inCursor++] & 0xff;
- result.append(intToAlpha[byte0 >> 2]);
- result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
- result.append(intToAlpha[(byte1 << 2)&0x3f | (byte2 >> 6)]);
- result.append(intToAlpha[byte2 & 0x3f]);
- }
-
- // Translate partial group if present
- if (numBytesInPartialGroup != 0) {
- int byte0 = a[inCursor++] & 0xff;
- result.append(intToAlpha[byte0 >> 2]);
- if (numBytesInPartialGroup == 1) {
- result.append(intToAlpha[(byte0 << 4) & 0x3f]);
- result.append("==");
- } else {
- // assert numBytesInPartialGroup == 2;
- int byte1 = a[inCursor++] & 0xff;
- result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
- result.append(intToAlpha[(byte1 << 2)&0x3f]);
- result.append('=');
- }
- }
- // assert inCursor == a.length;
- // assert result.length() == resultLen;
- return result.toString();
- }
-
- /**
- * This array is a lookup table that translates 6-bit positive integer
- * index values into their "Base64 Alphabet" equivalents as specified
- * in Table 1 of RFC 2045.
- */
- private static final char intToAlpha[] = {
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
- 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
- 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
- };
-
- /**
- * Construct a new IOException with a nested exception.
- * The nested exception is set only if JDK {@literal >= 1.4}
- */
- private static IOException newIOException(String message,
- Throwable cause) {
- final IOException x = new IOException(message);
- return EnvHelp.initCause(x,cause);
- }
-
-
- // Private variables
- // -----------------
-
- private static ClassLogger logger =
- new ClassLogger("javax.management.remote.rmi", "RMIConnectorServer");
-
- private JMXServiceURL address;
- private RMIServerImpl rmiServerImpl;
- private final Map<String, ?> attributes;
- private ClassLoader defaultClassLoader = null;
-
- private String boundJndiUrl;
-
- // state
- private static final int CREATED = 0;
- private static final int STARTED = 1;
- private static final int STOPPED = 2;
-
- private int state = CREATED;
- private final static Set<RMIConnectorServer> openedServers =
- new HashSet<RMIConnectorServer>();
-}
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIIIOPServerImpl.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2003, 2015, 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 javax.management.remote.rmi;
-
-import java.io.IOException;
-import java.rmi.Remote;
-import java.util.Map;
-import javax.security.auth.Subject;
-
-/**
- * <p>An {@link RMIServerImpl} that is exported through IIOP and that
- * creates client connections as RMI objects exported through IIOP.
- * User code does not usually reference this class directly.</p>
- *
- * @see RMIServerImpl
- *
- * @since 1.5
- * @deprecated This transport is no longer supported.
- */
-@Deprecated
-public class RMIIIOPServerImpl extends RMIServerImpl {
- /**
- * Throws {@linkplain UnsupportedOperationException}
- *
- * @param env the environment containing attributes for the new
- * <code>RMIServerImpl</code>. Can be null, which is equivalent
- * to an empty Map.
- *
- * @throws IOException if the RMI object cannot be created.
- */
- public RMIIIOPServerImpl(Map<String,?> env)
- throws IOException {
- super(env);
-
- throw new UnsupportedOperationException();
- }
-
- @Override
- protected void export() throws IOException {
- throw new UnsupportedOperationException("Method not supported. JMX RMI-IIOP is deprecated");
- }
-
- @Override
- protected String getProtocol() {
- return "iiop";
- }
-
- @Override
- public Remote toStub() throws IOException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- protected RMIConnection makeClient(String connectionId, Subject subject)
- throws IOException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- protected void closeClient(RMIConnection client) throws IOException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- protected void closeServer() throws IOException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- RMIConnection doNewClient(final Object credentials) throws IOException {
- throw new UnsupportedOperationException();
- }
-}
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIJRMPServerImpl.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,279 +0,0 @@
-/*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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 javax.management.remote.rmi;
-
-import java.io.IOException;
-import java.rmi.NoSuchObjectException;
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-import java.rmi.server.RMIClientSocketFactory;
-import java.rmi.server.RMIServerSocketFactory;
-import java.rmi.server.UnicastRemoteObject;
-import java.rmi.server.RemoteObject;
-import java.util.Map;
-import java.util.Collections;
-import javax.security.auth.Subject;
-
-import com.sun.jmx.remote.internal.RMIExporter;
-import com.sun.jmx.remote.util.EnvHelp;
-import java.io.ObjectStreamClass;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import sun.reflect.misc.ReflectUtil;
-import sun.rmi.server.DeserializationChecker;
-import sun.rmi.server.UnicastServerRef;
-import sun.rmi.server.UnicastServerRef2;
-
-/**
- * <p>An {@link RMIServer} object that is exported through JRMP and that
- * creates client connections as RMI objects exported through JRMP.
- * User code does not usually reference this class directly.</p>
- *
- * @see RMIServerImpl
- *
- * @since 1.5
- */
-public class RMIJRMPServerImpl extends RMIServerImpl {
-
- private final ExportedWrapper exportedWrapper;
-
- /**
- * <p>Creates a new {@link RMIServer} object that will be exported
- * on the given port using the given socket factories.</p>
- *
- * @param port the port on which this object and the {@link
- * RMIConnectionImpl} objects it creates will be exported. Can be
- * zero, to indicate any available port.
- *
- * @param csf the client socket factory for the created RMI
- * objects. Can be null.
- *
- * @param ssf the server socket factory for the created RMI
- * objects. Can be null.
- *
- * @param env the environment map. Can be null.
- *
- * @exception IOException if the {@link RMIServer} object
- * cannot be created.
- *
- * @exception IllegalArgumentException if <code>port</code> is
- * negative.
- */
- public RMIJRMPServerImpl(int port,
- RMIClientSocketFactory csf,
- RMIServerSocketFactory ssf,
- Map<String,?> env)
- throws IOException {
-
- super(env);
-
- if (port < 0)
- throw new IllegalArgumentException("Negative port: " + port);
-
- this.port = port;
- this.csf = csf;
- this.ssf = ssf;
- this.env = (env == null) ? Collections.<String, Object>emptyMap() : env;
-
- String[] credentialsTypes
- = (String[]) this.env.get(RMIConnectorServer.CREDENTIAL_TYPES);
- List<String> types = null;
- if (credentialsTypes != null) {
- types = new ArrayList<>();
- for (String type : credentialsTypes) {
- if (type == null) {
- throw new IllegalArgumentException("A credential type is null.");
- }
- ReflectUtil.checkPackageAccess(type);
- types.add(type);
- }
- }
- exportedWrapper = types != null ?
- new ExportedWrapper(this, types) :
- null;
- }
-
- protected void export() throws IOException {
- if (exportedWrapper != null) {
- export(exportedWrapper);
- } else {
- export(this);
- }
- }
-
- private void export(Remote obj) throws RemoteException {
- final RMIExporter exporter =
- (RMIExporter) env.get(RMIExporter.EXPORTER_ATTRIBUTE);
- final boolean daemon = EnvHelp.isServerDaemon(env);
-
- if (daemon && exporter != null) {
- throw new IllegalArgumentException("If "+EnvHelp.JMX_SERVER_DAEMON+
- " is specified as true, "+RMIExporter.EXPORTER_ATTRIBUTE+
- " cannot be used to specify an exporter!");
- }
-
- if (daemon) {
- if (csf == null && ssf == null) {
- new UnicastServerRef(port).exportObject(obj, null, true);
- } else {
- new UnicastServerRef2(port, csf, ssf).exportObject(obj, null, true);
- }
- } else if (exporter != null) {
- exporter.exportObject(obj, port, csf, ssf);
- } else {
- UnicastRemoteObject.exportObject(obj, port, csf, ssf);
- }
- }
-
- private void unexport(Remote obj, boolean force)
- throws NoSuchObjectException {
- RMIExporter exporter =
- (RMIExporter) env.get(RMIExporter.EXPORTER_ATTRIBUTE);
- if (exporter == null)
- UnicastRemoteObject.unexportObject(obj, force);
- else
- exporter.unexportObject(obj, force);
- }
-
- protected String getProtocol() {
- return "rmi";
- }
-
- /**
- * <p>Returns a serializable stub for this {@link RMIServer} object.</p>
- *
- * @return a serializable stub.
- *
- * @exception IOException if the stub cannot be obtained - e.g the
- * RMIJRMPServerImpl has not been exported yet.
- */
- public Remote toStub() throws IOException {
- if (exportedWrapper != null) {
- return RemoteObject.toStub(exportedWrapper);
- } else {
- return RemoteObject.toStub(this);
- }
- }
-
- /**
- * <p>Creates a new client connection as an RMI object exported
- * through JRMP. The port and socket factories for the new
- * {@link RMIConnection} object are the ones supplied
- * to the <code>RMIJRMPServerImpl</code> constructor.</p>
- *
- * @param connectionId the ID of the new connection. Every
- * connection opened by this connector server will have a
- * different id. The behavior is unspecified if this parameter is
- * null.
- *
- * @param subject the authenticated subject. Can be null.
- *
- * @return the newly-created <code>RMIConnection</code>.
- *
- * @exception IOException if the new {@link RMIConnection}
- * object cannot be created or exported.
- */
- protected RMIConnection makeClient(String connectionId, Subject subject)
- throws IOException {
-
- if (connectionId == null)
- throw new NullPointerException("Null connectionId");
-
- RMIConnection client =
- new RMIConnectionImpl(this, connectionId, getDefaultClassLoader(),
- subject, env);
- export(client);
- return client;
- }
-
- protected void closeClient(RMIConnection client) throws IOException {
- unexport(client, true);
- }
-
- /**
- * <p>Called by {@link #close()} to close the connector server by
- * unexporting this object. After returning from this method, the
- * connector server must not accept any new connections.</p>
- *
- * @exception IOException if the attempt to close the connector
- * server failed.
- */
- protected void closeServer() throws IOException {
- if (exportedWrapper != null) {
- unexport(exportedWrapper, true);
- } else {
- unexport(this, true);
- }
- }
-
- private final int port;
- private final RMIClientSocketFactory csf;
- private final RMIServerSocketFactory ssf;
- private final Map<String, ?> env;
-
- private static class ExportedWrapper implements RMIServer, DeserializationChecker {
- private final RMIServer impl;
- private final List<String> allowedTypes;
-
- private ExportedWrapper(RMIServer impl, List<String> credentialsTypes) {
- this.impl = impl;
- allowedTypes = credentialsTypes;
- }
-
- @Override
- public String getVersion() throws RemoteException {
- return impl.getVersion();
- }
-
- @Override
- public RMIConnection newClient(Object credentials) throws IOException {
- return impl.newClient(credentials);
- }
-
- @Override
- public void check(Method method, ObjectStreamClass descriptor,
- int paramIndex, int callID) {
- String type = descriptor.getName();
- if (!allowedTypes.contains(type)) {
- throw new ClassCastException("Unsupported type: " + type);
- }
- }
-
- @Override
- public void checkProxyClass(Method method, String[] ifaces,
- int paramIndex, int callID) {
- if (ifaces != null && ifaces.length > 0) {
- for (String iface : ifaces) {
- if (!allowedTypes.contains(iface)) {
- throw new ClassCastException("Unsupported type: " + iface);
- }
- }
- }
- }
- }
-}
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIServer.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2002, 2007, 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 javax.management.remote.rmi;
-
-import java.io.IOException;
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-
-/**
- * <p>RMI object used to establish connections to an RMI connector.
- * There is one Remote object implementing this interface for each RMI
- * connector.</p>
- *
- * <p>User code does not usually refer to this interface. It is
- * specified as part of the public API so that different
- * implementations of that API will interoperate.</p>
- *
- * @since 1.5
- */
-public interface RMIServer extends Remote {
- /**
- * <p>The version of the RMI Connector Protocol understood by this
- * connector server. This is a string with the following format:</p>
- *
- * <pre>
- * <em>protocol-version</em> <em>implementation-name</em>
- * </pre>
- *
- * <p>The <code><em>protocol-version</em></code> is a series of
- * two or more non-negative integers separated by periods
- * (<code>.</code>). An implementation of the version described
- * by this documentation must use the string <code>1.0</code>
- * here.</p>
- *
- * <p>After the protocol version there must be a space, followed
- * by the implementation name. The format of the implementation
- * name is unspecified. It is recommended that it include an
- * implementation version number. An implementation can use an
- * empty string as its implementation name, for example for
- * security reasons.</p>
- *
- * @return a string with the format described here.
- *
- * @exception RemoteException if there is a communication
- * exception during the remote method call.
- */
- public String getVersion() throws RemoteException;
-
- /**
- * <p>Makes a new connection through this RMI connector. Each
- * remote client calls this method to obtain a new RMI object
- * representing its connection.</p>
- *
- * @param credentials this object specifies the user-defined credentials
- * to be passed in to the server in order to authenticate the user before
- * creating the <code>RMIConnection</code>. Can be null.
- *
- * @return the newly-created connection object.
- *
- * @exception IOException if the new client object cannot be
- * created or exported, or if there is a communication exception
- * during the remote method call.
- *
- * @exception SecurityException if the given credentials do not
- * allow the server to authenticate the caller successfully.
- */
- public RMIConnection newClient(Object credentials) throws IOException;
-}
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/RMIServerImpl.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,550 +0,0 @@
-/*
- * Copyright (c) 2002, 2015, 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 javax.management.remote.rmi;
-
-import com.sun.jmx.remote.internal.ArrayNotificationBuffer;
-import com.sun.jmx.remote.internal.NotificationBuffer;
-import com.sun.jmx.remote.security.JMXPluggableAuthenticator;
-import com.sun.jmx.remote.util.ClassLogger;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.lang.ref.WeakReference;
-import java.rmi.Remote;
-import java.rmi.server.RemoteServer;
-import java.rmi.server.ServerNotActiveException;
-import java.security.Principal;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.management.MBeanServer;
-import javax.management.remote.JMXAuthenticator;
-import javax.management.remote.JMXConnectorServer;
-import javax.security.auth.Subject;
-
-/**
- * <p>An RMI object representing a connector server. Remote clients
- * can make connections using the {@link #newClient(Object)} method. This
- * method returns an RMI object representing the connection.</p>
- *
- * <p>User code does not usually reference this class directly.
- * RMI connection servers are usually created with the class {@link
- * RMIConnectorServer}. Remote clients usually create connections
- * either with {@link javax.management.remote.JMXConnectorFactory}
- * or by instantiating {@link RMIConnector}.</p>
- *
- * <p>This is an abstract class. Concrete subclasses define the
- * details of the client connection objects.</p>
- *
- * @since 1.5
- */
-public abstract class RMIServerImpl implements Closeable, RMIServer {
- /**
- * <p>Constructs a new <code>RMIServerImpl</code>.</p>
- *
- * @param env the environment containing attributes for the new
- * <code>RMIServerImpl</code>. Can be null, which is equivalent
- * to an empty Map.
- */
- public RMIServerImpl(Map<String,?> env) {
- this.env = (env == null) ? Collections.<String,Object>emptyMap() : env;
- }
-
- void setRMIConnectorServer(RMIConnectorServer connServer)
- throws IOException {
- this.connServer = connServer;
- }
-
- /**
- * <p>Exports this RMI object.</p>
- *
- * @exception IOException if this RMI object cannot be exported.
- */
- protected abstract void export() throws IOException;
-
- /**
- * Returns a remotable stub for this server object.
- * @return a remotable stub.
- * @exception IOException if the stub cannot be obtained - e.g the
- * RMIServerImpl has not been exported yet.
- **/
- public abstract Remote toStub() throws IOException;
-
- /**
- * <p>Sets the default <code>ClassLoader</code> for this connector
- * server. New client connections will use this classloader.
- * Existing client connections are unaffected.</p>
- *
- * @param cl the new <code>ClassLoader</code> to be used by this
- * connector server.
- *
- * @see #getDefaultClassLoader
- */
- public synchronized void setDefaultClassLoader(ClassLoader cl) {
- this.cl = cl;
- }
-
- /**
- * <p>Gets the default <code>ClassLoader</code> used by this connector
- * server.</p>
- *
- * @return the default <code>ClassLoader</code> used by this
- * connector server.
- *
- * @see #setDefaultClassLoader
- */
- public synchronized ClassLoader getDefaultClassLoader() {
- return cl;
- }
-
- /**
- * <p>Sets the <code>MBeanServer</code> to which this connector
- * server is attached. New client connections will interact
- * with this <code>MBeanServer</code>. Existing client connections are
- * unaffected.</p>
- *
- * @param mbs the new <code>MBeanServer</code>. Can be null, but
- * new client connections will be refused as long as it is.
- *
- * @see #getMBeanServer
- */
- public synchronized void setMBeanServer(MBeanServer mbs) {
- this.mbeanServer = mbs;
- }
-
- /**
- * <p>The <code>MBeanServer</code> to which this connector server
- * is attached. This is the last value passed to {@link
- * #setMBeanServer} on this object, or null if that method has
- * never been called.</p>
- *
- * @return the <code>MBeanServer</code> to which this connector
- * is attached.
- *
- * @see #setMBeanServer
- */
- public synchronized MBeanServer getMBeanServer() {
- return mbeanServer;
- }
-
- public String getVersion() {
- // Expected format is: "protocol-version implementation-name"
- try {
- return "1.0 java_runtime_" +
- System.getProperty("java.runtime.version");
- } catch (SecurityException e) {
- return "1.0 ";
- }
- }
-
- /**
- * <p>Creates a new client connection. This method calls {@link
- * #makeClient makeClient} and adds the returned client connection
- * object to an internal list. When this
- * <code>RMIServerImpl</code> is shut down via its {@link
- * #close()} method, the {@link RMIConnection#close() close()}
- * method of each object remaining in the list is called.</p>
- *
- * <p>The fact that a client connection object is in this internal
- * list does not prevent it from being garbage collected.</p>
- *
- * @param credentials this object specifies the user-defined
- * credentials to be passed in to the server in order to
- * authenticate the caller before creating the
- * <code>RMIConnection</code>. Can be null.
- *
- * @return the newly-created <code>RMIConnection</code>. This is
- * usually the object created by <code>makeClient</code>, though
- * an implementation may choose to wrap that object in another
- * object implementing <code>RMIConnection</code>.
- *
- * @exception IOException if the new client object cannot be
- * created or exported.
- *
- * @exception SecurityException if the given credentials do not allow
- * the server to authenticate the user successfully.
- *
- * @exception IllegalStateException if {@link #getMBeanServer()}
- * is null.
- */
- public RMIConnection newClient(Object credentials) throws IOException {
- return doNewClient(credentials);
- }
-
- /**
- * This method could be overridden by subclasses defined in this package
- * to perform additional operations specific to the underlying transport
- * before creating the new client connection.
- */
- RMIConnection doNewClient(Object credentials) throws IOException {
- final boolean tracing = logger.traceOn();
-
- if (tracing) logger.trace("newClient","making new client");
-
- if (getMBeanServer() == null)
- throw new IllegalStateException("Not attached to an MBean server");
-
- Subject subject = null;
- JMXAuthenticator authenticator =
- (JMXAuthenticator) env.get(JMXConnectorServer.AUTHENTICATOR);
- if (authenticator == null) {
- /*
- * Create the JAAS-based authenticator only if authentication
- * has been enabled
- */
- if (env.get("jmx.remote.x.password.file") != null ||
- env.get("jmx.remote.x.login.config") != null) {
- authenticator = new JMXPluggableAuthenticator(env);
- }
- }
- if (authenticator != null) {
- if (tracing) logger.trace("newClient","got authenticator: " +
- authenticator.getClass().getName());
- try {
- subject = authenticator.authenticate(credentials);
- } catch (SecurityException e) {
- logger.trace("newClient", "Authentication failed: " + e);
- throw e;
- }
- }
-
- if (tracing) {
- if (subject != null)
- logger.trace("newClient","subject is not null");
- else logger.trace("newClient","no subject");
- }
-
- final String connectionId = makeConnectionId(getProtocol(), subject);
-
- if (tracing)
- logger.trace("newClient","making new connection: " + connectionId);
-
- RMIConnection client = makeClient(connectionId, subject);
-
- dropDeadReferences();
- WeakReference<RMIConnection> wr = new WeakReference<RMIConnection>(client);
- synchronized (clientList) {
- clientList.add(wr);
- }
-
- connServer.connectionOpened(connectionId, "Connection opened", null);
-
- synchronized (clientList) {
- if (!clientList.contains(wr)) {
- // can be removed only by a JMXConnectionNotification listener
- throw new IOException("The connection is refused.");
- }
- }
-
- if (tracing)
- logger.trace("newClient","new connection done: " + connectionId );
-
- return client;
- }
-
- /**
- * <p>Creates a new client connection. This method is called by
- * the public method {@link #newClient(Object)}.</p>
- *
- * @param connectionId the ID of the new connection. Every
- * connection opened by this connector server will have a
- * different ID. The behavior is unspecified if this parameter is
- * null.
- *
- * @param subject the authenticated subject. Can be null.
- *
- * @return the newly-created <code>RMIConnection</code>.
- *
- * @exception IOException if the new client object cannot be
- * created or exported.
- */
- protected abstract RMIConnection makeClient(String connectionId,
- Subject subject)
- throws IOException;
-
- /**
- * <p>Closes a client connection made by {@link #makeClient makeClient}.
- *
- * @param client a connection previously returned by
- * <code>makeClient</code> on which the <code>closeClient</code>
- * method has not previously been called. The behavior is
- * unspecified if these conditions are violated, including the
- * case where <code>client</code> is null.
- *
- * @exception IOException if the client connection cannot be
- * closed.
- */
- protected abstract void closeClient(RMIConnection client)
- throws IOException;
-
- /**
- * <p>Returns the protocol string for this object. The string is
- * <code>rmi</code> for RMI/JRMP.
- *
- * @return the protocol string for this object.
- */
- protected abstract String getProtocol();
-
- /**
- * <p>Method called when a client connection created by {@link
- * #makeClient makeClient} is closed. A subclass that defines
- * <code>makeClient</code> must arrange for this method to be
- * called when the resultant object's {@link RMIConnection#close()
- * close} method is called. This enables it to be removed from
- * the <code>RMIServerImpl</code>'s list of connections. It is
- * not an error for <code>client</code> not to be in that
- * list.</p>
- *
- * <p>After removing <code>client</code> from the list of
- * connections, this method calls {@link #closeClient
- * closeClient(client)}.</p>
- *
- * @param client the client connection that has been closed.
- *
- * @exception IOException if {@link #closeClient} throws this
- * exception.
- *
- * @exception NullPointerException if <code>client</code> is null.
- */
- protected void clientClosed(RMIConnection client) throws IOException {
- final boolean debug = logger.debugOn();
-
- if (debug) logger.trace("clientClosed","client="+client);
-
- if (client == null)
- throw new NullPointerException("Null client");
-
- synchronized (clientList) {
- dropDeadReferences();
- for (Iterator<WeakReference<RMIConnection>> it = clientList.iterator();
- it.hasNext(); ) {
- WeakReference<RMIConnection> wr = it.next();
- if (wr.get() == client) {
- it.remove();
- break;
- }
- }
- /* It is not a bug for this loop not to find the client. In
- our close() method, we remove a client from the list before
- calling its close() method. */
- }
-
- if (debug) logger.trace("clientClosed", "closing client.");
- closeClient(client);
-
- if (debug) logger.trace("clientClosed", "sending notif");
- connServer.connectionClosed(client.getConnectionId(),
- "Client connection closed", null);
-
- if (debug) logger.trace("clientClosed","done");
- }
-
- /**
- * <p>Closes this connection server. This method first calls the
- * {@link #closeServer()} method so that no new client connections
- * will be accepted. Then, for each remaining {@link
- * RMIConnection} object returned by {@link #makeClient
- * makeClient}, its {@link RMIConnection#close() close} method is
- * called.</p>
- *
- * <p>The behavior when this method is called more than once is
- * unspecified.</p>
- *
- * <p>If {@link #closeServer()} throws an
- * <code>IOException</code>, the individual connections are
- * nevertheless closed, and then the <code>IOException</code> is
- * thrown from this method.</p>
- *
- * <p>If {@link #closeServer()} returns normally but one or more
- * of the individual connections throws an
- * <code>IOException</code>, then, after closing all the
- * connections, one of those <code>IOException</code>s is thrown
- * from this method. If more than one connection throws an
- * <code>IOException</code>, it is unspecified which one is thrown
- * from this method.</p>
- *
- * @exception IOException if {@link #closeServer()} or one of the
- * {@link RMIConnection#close()} calls threw
- * <code>IOException</code>.
- */
- public synchronized void close() throws IOException {
- final boolean tracing = logger.traceOn();
- final boolean debug = logger.debugOn();
-
- if (tracing) logger.trace("close","closing");
-
- IOException ioException = null;
- try {
- if (debug) logger.debug("close","closing Server");
- closeServer();
- } catch (IOException e) {
- if (tracing) logger.trace("close","Failed to close server: " + e);
- if (debug) logger.debug("close",e);
- ioException = e;
- }
-
- if (debug) logger.debug("close","closing Clients");
- // Loop to close all clients
- while (true) {
- synchronized (clientList) {
- if (debug) logger.debug("close","droping dead references");
- dropDeadReferences();
-
- if (debug) logger.debug("close","client count: "+clientList.size());
- if (clientList.size() == 0)
- break;
- /* Loop until we find a non-null client. Because we called
- dropDeadReferences(), this will usually be the first
- element of the list, but a garbage collection could have
- happened in between. */
- for (Iterator<WeakReference<RMIConnection>> it = clientList.iterator();
- it.hasNext(); ) {
- WeakReference<RMIConnection> wr = it.next();
- RMIConnection client = wr.get();
- it.remove();
- if (client != null) {
- try {
- client.close();
- } catch (IOException e) {
- if (tracing)
- logger.trace("close","Failed to close client: " + e);
- if (debug) logger.debug("close",e);
- if (ioException == null)
- ioException = e;
- }
- break;
- }
- }
- }
- }
-
- if(notifBuffer != null)
- notifBuffer.dispose();
-
- if (ioException != null) {
- if (tracing) logger.trace("close","close failed.");
- throw ioException;
- }
-
- if (tracing) logger.trace("close","closed.");
- }
-
- /**
- * <p>Called by {@link #close()} to close the connector server.
- * After returning from this method, the connector server must
- * not accept any new connections.</p>
- *
- * @exception IOException if the attempt to close the connector
- * server failed.
- */
- protected abstract void closeServer() throws IOException;
-
- private static synchronized String makeConnectionId(String protocol,
- Subject subject) {
- connectionIdNumber++;
-
- String clientHost = "";
- try {
- clientHost = RemoteServer.getClientHost();
- /*
- * According to the rules specified in the javax.management.remote
- * package description, a numeric IPv6 address (detected by the
- * presence of otherwise forbidden ":" character) forming a part
- * of the connection id must be enclosed in square brackets.
- */
- if (clientHost.contains(":")) {
- clientHost = "[" + clientHost + "]";
- }
- } catch (ServerNotActiveException e) {
- logger.trace("makeConnectionId", "getClientHost", e);
- }
-
- final StringBuilder buf = new StringBuilder();
- buf.append(protocol).append(":");
- if (clientHost.length() > 0)
- buf.append("//").append(clientHost);
- buf.append(" ");
- if (subject != null) {
- Set<Principal> principals = subject.getPrincipals();
- String sep = "";
- for (Iterator<Principal> it = principals.iterator(); it.hasNext(); ) {
- Principal p = it.next();
- String name = p.getName().replace(' ', '_').replace(';', ':');
- buf.append(sep).append(name);
- sep = ";";
- }
- }
- buf.append(" ").append(connectionIdNumber);
- if (logger.traceOn())
- logger.trace("newConnectionId","connectionId="+buf);
- return buf.toString();
- }
-
- private void dropDeadReferences() {
- synchronized (clientList) {
- for (Iterator<WeakReference<RMIConnection>> it = clientList.iterator();
- it.hasNext(); ) {
- WeakReference<RMIConnection> wr = it.next();
- if (wr.get() == null)
- it.remove();
- }
- }
- }
-
- synchronized NotificationBuffer getNotifBuffer() {
- //Notification buffer is lazily created when the first client connects
- if(notifBuffer == null)
- notifBuffer =
- ArrayNotificationBuffer.getNotificationBuffer(mbeanServer,
- env);
- return notifBuffer;
- }
-
- private static final ClassLogger logger =
- new ClassLogger("javax.management.remote.rmi", "RMIServerImpl");
-
- /** List of WeakReference values. Each one references an
- RMIConnection created by this object, or null if the
- RMIConnection has been garbage-collected. */
- private final List<WeakReference<RMIConnection>> clientList =
- new ArrayList<WeakReference<RMIConnection>>();
-
- private ClassLoader cl;
-
- private MBeanServer mbeanServer;
-
- private final Map<String, ?> env;
-
- private RMIConnectorServer connServer;
-
- private static int connectionIdNumber;
-
- private NotificationBuffer notifBuffer;
-}
--- a/jdk/src/java.management/share/classes/javax/management/remote/rmi/package.html Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,340 +0,0 @@
-<html>
-<head>
- <title>RMI connector</title>
-<!--
-Copyright (c) 2002, 2015, 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.
--->
-</head>
-<body bgcolor="white">
- <p>The RMI connector is a connector for the JMX Remote API that
- uses RMI to transmit client requests to a remote MBean server.
- This package defines the classes that the user of an RMI
- connector needs to reference directly, for both the client and
- server sides. It also defines certain classes that the user
- will not usually reference directly, but that must be defined so
- that different implementations of the RMI connector can
- interoperate.</p>
-
- <p>The RMI connector supports the JRMP transport for RMI.</p>
-
- <p>Like most connectors in the JMX Remote API, an RMI connector
- usually has an address, which
- is a {@link javax.management.remote.JMXServiceURL
- JMXServiceURL}. The protocol part of this address is
- <code>rmi</code> for a connector that uses the default RMI
- transport (JRMP).</p>
-
- <p>There are two forms for RMI connector addresses:</p>
-
- <ul>
- <li>
- In the <em>JNDI form</em>, the URL indicates <em>where to find
- an RMI stub for the connector</em>. This RMI stub is a Java
- object of type {@link javax.management.remote.rmi.RMIServer
- RMIServer} that gives remote access to the connector server.
- With this address form, the RMI stub is obtained from an
- external directory entry included in the URL. An external
- directory is any directory recognized by {@link javax.naming
- JNDI}, typically the RMI registry, LDAP, or COS Naming.
-
- <li>
- In the <em>encoded form</em>, the URL directly includes the
- information needed to connect to the connector server. When
- using RMI/JRMP, the encoded form is the serialized RMI stub
- for the server object, encoded using BASE64 without embedded
- newlines.
- </ul>
-
- <p>Addresses are covered in more detail below.</p>
-
-
- <h3>Creating an RMI connector server</h3>
-
- <p>The usual way to create an RMI connector server is to supply an
- RMI connector address to the method {@link
- javax.management.remote.JMXConnectorServerFactory#newJMXConnectorServer
- JMXConnectorServerFactory.newJMXConnectorServer}. The MBean
- server to which the connector server is attached can be
- specified as a parameter to that method. Alternatively, the
- connector server can be registered as an MBean in that MBean
- server.</p>
-
- <p>An RMI connector server can also be created by constructing an
- instance of {@link
- javax.management.remote.rmi.RMIConnectorServer
- RMIConnectorServer}, explicitly or through the MBean server's
- <code>createMBean</code> method.</p>
-
- <h4>Choosing the RMI transport</h4>
-
- <p>You can choose the RMI transport by specifying
- <code>rmi</code> in the <code><em>protocol</em></code> part of the
- <code>serviceURL</code> when creating the connector server. You
- can also create specialized connector servers by instantiating
- an appropriate subclass of {@link
- javax.management.remote.rmi.RMIServerImpl RMIServerImpl} and
- supplying it to the <code>RMIConnectorServer</code>
- constructor.</p>
-
-
- <h4><a name="servergen">Connector addresses generated by the
- server</a></h4>
-
- <p>If the <code>serviceURL</code> you specify has an empty URL
- path (after the optional host and port), or if you do not
- specify a <code>serviceURL</code>, then the connector server
- will fabricate a new <code>JMXServiceURL</code> that clients can
- use to connect:</p>
-
- <ul>
-
- <li><p>If the <code>serviceURL</code> looks like:</p>
-
- <pre>
- <code>service:jmx:rmi://<em>host</em>:<em>port</em></code>
- </pre>
-
- <p>then the connector server will generate an {@link
- javax.management.remote.rmi.RMIJRMPServerImpl
- RMIJRMPServerImpl} and the returned <code>JMXServiceURL</code>
- looks like:</p>
-
- <pre>
- <code>service:jmx:rmi://<em>host</em>:<em>port</em>/stub/<em>XXXX</em></code>
- </pre>
-
- <p>where <code><em>XXXX</em></code> is the serialized form of the
- stub for the generated object, encoded in BASE64 without
- newlines.</p>
-
- <li><p>If there is no <code>serviceURL</code>, there must be a
- user-provided <code>RMIServerImpl</code>. The connector server
- will generate a <code>JMXServiceURL</code> using the <code>rmi</code>
- form.</p>
-
- </ul>
-
- <p>The <code><em>host</em></code> in a user-provided
- <code>serviceURL</code> is optional. If present, it is copied
- into the generated <code>JMXServiceURL</code> but otherwise
- ignored. If absent, the generated <code>JXMServiceURL</code>
- will have the local host name.</p>
-
- <p>The <code><em>port</em></code> in a user-provided
- <code>serviceURL</code> is also optional. If present, it is
- also copied into the generated <code>JMXServiceURL</code>;
- otherwise, the generated <code>JMXServiceURL</code> has no port.
- For an <code>serviceURL</code> using the <code>rmi</code>
- protocol, the <code><em>port</em></code>, if present, indicates
- what port the generated remote object should be exported on. It
- has no other effect.</p>
-
- <p>If the user provides an <code>RMIServerImpl</code> rather than a
- <code>JMXServiceURL</code>, then the generated
- <code>JMXServiceURL</code> will have the local host name in its
- <code><em>host</em></code> part and no
- <code><em>port</em></code>.</p>
-
-
- <h4><a name="directory">Connector addresses based on directory
- entries</a></h4>
-
- <p>As an alternative to the generated addresses just described,
- the <code>serviceURL</code> address supplied when creating a
- connector server can specify a <em>directory address</em> in
- which to store the provided or generated <code>RMIServer</code>
- stub. This directory address is then used by both client and
- server.</p>
-
- <p>In this case, the <code>serviceURL</code> has the following form:</p>
-
- <pre>
- <code>service:jmx:rmi://<em>host</em>:<em>port</em>/jndi/<em>jndi-name</em></code>
- </pre>
-
- <p>Here, <code><em>jndi-name</em></code> is a string that can be
- supplied to {@link javax.naming.InitialContext#bind
- javax.naming.InitialContext.bind}.</p>
-
- <p>As usual, the <code><em>host</em></code> and
- <code>:<em>port</em></code> can be omitted.</p>
-
- <p>The connector server will generate an
- <code>RMIServerImpl</code> based on the protocol
- (<code>rmi</code>) and the <code><em>port</em></code> if any. When
- the connector server is started, it will derive a stub from this
- object using its {@link
- javax.management.remote.rmi.RMIServerImpl#toStub toStub} method
- and store the object using the given
- <code><em>jndi-name</em></code>. The properties defined by the
- JNDI API are consulted as usual.</p>
-
- <p>For example, if the <code>JMXServiceURL</code> is:
-
- <pre>
- <code>service:jmx:rmi://ignoredhost/jndi/rmi://myhost/myname</code>
- </pre>
-
- then the connector server will generate an
- <code>RMIJRMPServerImpl</code> and store its stub using the JNDI
- name
-
- <pre>
- <code>rmi://myhost/myname</code>
- </pre>
-
- which means entry <code>myname</code> in the RMI registry
- running on the default port of host <code>myhost</code>. Note
- that the RMI registry only allows registration from the local
- host. So, in this case, <code>myhost</code> must be the name
- (or a name) of the host that the connector server is running
- on.
-
- <p>In this <code>JMXServiceURL</code>, the first <code>rmi:</code>
- specifies the RMI
- connector, while the second <code>rmi:</code> specifies the RMI
- registry.
-
- <p>As another example, if the <code>JMXServiceURL</code> is:
-
- <pre>
- <code>service:jmx:rmi://ignoredhost/jndi/ldap://dirhost:9999/cn=this,ou=that</code>
- </pre>
-
- then the connector server will generate an
- <code>RMIJRMPServerImpl</code> and store its stub using the JNDI
- name
-
- <pre>
- <code>ldap://dirhost:9999/cn=this,ou=that</code>
- </pre>
-
- which means entry <code>cn=this,ou=that</code> in the LDAP
- directory running on port 9999 of host <code>dirhost</code>.
-
- <p>If the <code>JMXServiceURL</code> is:
-
- <pre>
- <code>service:jmx:rmi://ignoredhost/jndi/cn=this,ou=that</code>
- </pre>
-
- then the connector server will generate an
- <code>RMIJRMPServerImpl</code> and store its stub using the JNDI
- name
-
- <pre>
- <code>cn=this,ou=that</code>
- </pre>
-
- For this case to work, the JNDI API must have been configured
- appropriately to supply the information about what directory to
- use.
-
- <p>In these examples, the host name <code>ignoredhost</code> is
- not used by the connector server or its clients. It can be
- omitted, for example:</p>
-
- <pre>
- <code>service:jmx:rmi:///jndi/cn=this,ou=that</code>
- </pre>
-
- <p>However, it is good practice to use the name of the host
- where the connector server is running. This is often different
- from the name of the directory host.</p>
-
-
- <h4>Connector server attributes</h4>
-
- <p>When using the default JRMP transport, RMI socket factories can
- be specified using the attributes
- <code>jmx.remote.rmi.client.socket.factory</code> and
- <code>jmx.remote.rmi.server.socket.factory</code> in the
- <code>environment</code> given to the
- <code>RMIConnectorServer</code> constructor. The values of these
- attributes must be of type {@link
- java.rmi.server.RMIClientSocketFactory} and {@link
- java.rmi.server.RMIServerSocketFactory}, respectively. These
- factories are used when creating the RMI objects associated with
- the connector.</p>
-
- <h3>Creating an RMI connector client</h3>
-
- <p>An RMI connector client is usually constructed using {@link
- javax.management.remote.JMXConnectorFactory}, with a
- <code>JMXServiceURL</code> that has <code>rmi</code> as its protocol.</p>
-
- <p>If the <code>JMXServiceURL</code> was generated by the server,
- as described above under <a href="#servergen">"connector
- addresses generated by the server"</a>, then the client will
- need to obtain it directly or indirectly from the server.
- Typically, the server makes the <code>JMXServiceURL</code>
- available by storing it in a file or a lookup service.</p>
-
- <p>If the <code>JMXServiceURL</code> uses the directory syntax, as
- described above under <a href="#directory">"connector addresses
- based on directory entries"</a>, then the client may obtain it
- as just explained, or client and server may both know the
- appropriate directory entry to use. For example, if the
- connector server for the Whatsit agent uses the entry
- <code>whatsit-agent-connector</code> in the RMI registry on host
- <code>myhost</code>, then client and server can both know
- that the appropriate <code>JMXServiceURL</code> is:</p>
-
- <pre>
- <code>service:jmx:rmi:///jndi/rmi://myhost/whatsit-agent-connector</code>
- </pre>
-
- <p>If you have an RMI stub of type {@link
- javax.management.remote.rmi.RMIServer RMIServer}, you can
- construct an RMI connection directly by using the appropriate
- constructor of {@link javax.management.remote.rmi.RMIConnector
- RMIConnector}.</p>
-
- <h3>Dynamic code downloading</h3>
-
- <p>If an RMI connector client or server receives from its peer an
- instance of a class that it does not know, and if dynamic code
- downloading is active for the RMI connection, then the class can
- be downloaded from a codebase specified by the peer. The
- article <a
- href="{@docRoot}/../technotes/guides/rmi/codebase.html"><em>Dynamic
- code downloading using Java RMI</em></a> explains this in more
- detail.</p>
-
-
- @see <a href="{@docRoot}/../technotes/guides/rmi/index.html">
- Java™ Remote Method
- Invocation (RMI)</a>
-
- @see <a href="{@docRoot}/../technotes/guides/jndi/index.html">
- Java Naming and Directory Interface™ (JNDI)</a>
-
- @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045,
- section 6.8, "Base64 Content-Transfer-Encoding"</a>
-
-
- @since 1.5
-
- </body>
-</html>
--- a/jdk/src/java.management/share/classes/module-info.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.management/share/classes/module-info.java Thu Feb 09 23:15:52 2017 +0100
@@ -30,8 +30,6 @@
* JVM and other components in the Java runtime.
*/
module java.management {
- requires transitive java.rmi;
- requires java.naming;
exports java.lang.management;
exports javax.management;
@@ -41,15 +39,25 @@
exports javax.management.openmbean;
exports javax.management.relation;
exports javax.management.remote;
- exports javax.management.remote.rmi;
exports javax.management.timer;
- exports sun.management to jdk.jconsole, jdk.management;
+ exports com.sun.jmx.remote.internal to
+ java.management.rmi,
+ jdk.management.agent;
+ exports com.sun.jmx.remote.security to
+ java.management.rmi,
+ jdk.management.agent;
+ exports com.sun.jmx.remote.util to java.management.rmi;
+ exports sun.management to
+ jdk.jconsole,
+ jdk.management,
+ jdk.management.agent;
+ exports sun.management.counter to jdk.management.agent;
+ exports sun.management.counter.perf to jdk.management.agent;
exports sun.management.spi to jdk.management;
uses javax.management.remote.JMXConnectorProvider;
uses javax.management.remote.JMXConnectorServerProvider;
uses sun.management.spi.PlatformMBeanProvider;
- uses sun.management.spi.AgentProvider;
provides javax.security.auth.spi.LoginModule
with com.sun.jmx.remote.security.FileLoginModule;
--- a/jdk/src/java.management/share/classes/sun/management/Agent.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,729 +0,0 @@
-/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.management;
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.management.ManagementFactory;
-import java.lang.reflect.Method;
-import java.net.InetAddress;
-import java.net.MalformedURLException;
-import java.net.UnknownHostException;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.text.MessageFormat;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.MissingResourceException;
-import java.util.Properties;
-import java.util.ResourceBundle;
-import java.util.ServiceLoader;
-import java.util.function.Function;
-import java.util.function.Predicate;
-
-import javax.management.remote.JMXConnectorServer;
-import javax.management.remote.JMXServiceURL;
-
-import static sun.management.AgentConfigurationError.*;
-import sun.management.jmxremote.ConnectorBootstrap;
-import sun.management.jdp.JdpController;
-import sun.management.jdp.JdpException;
-import jdk.internal.vm.VMSupport;
-import sun.management.spi.AgentProvider;
-
-/**
- * This Agent is started by the VM when -Dcom.sun.management.snmp or
- * -Dcom.sun.management.jmxremote is set. This class will be loaded by the
- * system class loader. Also jmx framework could be started by jcmd
- */
-public class Agent {
- /**
- * Agent status collector strategy class
- */
- private static abstract class StatusCollector {
- protected static final Map<String, String> DEFAULT_PROPS = new HashMap<>();
-
- static {
- DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.PORT,
- ConnectorBootstrap.DefaultValues.PORT);
- DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.USE_LOCAL_ONLY,
- ConnectorBootstrap.DefaultValues.USE_LOCAL_ONLY);
- DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.USE_AUTHENTICATION,
- ConnectorBootstrap.DefaultValues.USE_AUTHENTICATION);
- DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.USE_SSL,
- ConnectorBootstrap.DefaultValues.USE_SSL);
- DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.USE_REGISTRY_SSL,
- ConnectorBootstrap.DefaultValues.USE_REGISTRY_SSL);
- DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.SSL_NEED_CLIENT_AUTH,
- ConnectorBootstrap.DefaultValues.SSL_NEED_CLIENT_AUTH);
- DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.CONFIG_FILE_NAME,
- ConnectorBootstrap.DefaultValues.CONFIG_FILE_NAME);
- DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.PASSWORD_FILE_NAME,
- ConnectorBootstrap.DefaultValues.PASSWORD_FILE_NAME);
- DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.ACCESS_FILE_NAME,
- ConnectorBootstrap.DefaultValues.ACCESS_FILE_NAME);
-
- }
-
- final protected StringBuilder sb = new StringBuilder();
- final public String collect() {
- Properties agentProps = VMSupport.getAgentProperties();
- String localConnAddr = (String)agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP);
- if (localConnAddr != null || jmxServer != null) {
- addAgentStatus(true);
- appendConnections(localConnAddr);
- } else {
- addAgentStatus(false);
- }
- return sb.toString();
- }
-
- private void appendConnections(String localConnAddr) {
- appendConnectionsHeader();
- if (localConnAddr != null) {
- try {
- JMXServiceURL u = new JMXServiceURL(localConnAddr);
- addConnection(false, u);
- } catch (MalformedURLException e) {
- // will never happen
- }
-
- }
- if (jmxServer != null) {
- addConnection(true, jmxServer.getAddress());
- }
- appendConnectionsFooter();
- }
-
- private void addConnection(boolean remote, JMXServiceURL u) {
- appendConnectionHeader(remote);
- addConnectionDetails(u);
- addConfigProperties();
- appendConnectionFooter(remote);
- }
-
- private void addConfigProperties() {
- appendConfigPropsHeader();
-
- Properties remoteProps = configProps != null ?
- configProps : getManagementProperties();
- Map<Object, Object> props = new HashMap<>(DEFAULT_PROPS);
-
- if (remoteProps == null) {
- // local connector only
- String loc_only = System.getProperty(
- ConnectorBootstrap.PropertyNames.USE_LOCAL_ONLY
- );
-
- if (loc_only != null &&
- !ConnectorBootstrap.DefaultValues.USE_LOCAL_ONLY.equals(loc_only)) {
- props.put(
- ConnectorBootstrap.PropertyNames.USE_LOCAL_ONLY,
- loc_only
- );
- }
- } else {
- props.putAll(remoteProps);
- }
-
- props.entrySet().stream()
- .filter(preprocess(Map.Entry::getKey, StatusCollector::isManagementProp))
- .forEach(this::addConfigProp);
-
- appendConfigPropsFooter();
- }
-
- private static boolean isManagementProp(Object pName) {
- return pName != null && pName.toString().startsWith("com.sun.management.");
- }
-
- private static <T, V> Predicate<T> preprocess(Function<T, V> f, Predicate<V> p) {
- return (T t) -> p.test(f.apply(t));
- }
-
- abstract protected void addAgentStatus(boolean enabled);
- abstract protected void appendConnectionsHeader();
- abstract protected void appendConnectionsFooter();
- abstract protected void addConnectionDetails(JMXServiceURL u);
- abstract protected void appendConnectionHeader(boolean remote);
- abstract protected void appendConnectionFooter(boolean remote);
- abstract protected void appendConfigPropsHeader();
- abstract protected void appendConfigPropsFooter();
- abstract protected void addConfigProp(Map.Entry<?, ?> prop);
- }
-
- /**
- * Free-text status collector strategy implementation
- */
- final private static class TextStatusCollector extends StatusCollector {
-
- @Override
- protected void addAgentStatus(boolean enabled) {
- sb.append("Agent: ").append(enabled ? "enabled" : "disabled").append('\n');
- }
-
- @Override
- protected void appendConnectionsHeader() {
- sb.append('\n');
- }
-
- @Override
- protected void addConnectionDetails(JMXServiceURL u) {
- sb.append("Protocol : ").append(u.getProtocol()).append('\n')
- .append("Host : ").append(u.getHost()).append('\n')
- .append("URL : ").append(u).append('\n');
- }
-
- @Override
- protected void appendConnectionHeader(boolean remote) {
- sb.append("Connection Type: ").append(remote ? "remote" : "local").append('\n');
- }
-
- @Override
- protected void appendConfigPropsHeader() {
- sb.append("Properties :\n");
- }
-
- @Override
- protected void addConfigProp(Map.Entry<?, ?> prop) {
- sb.append(" ").append(prop.getKey()).append(" = ")
- .append(prop.getValue());
- Object defVal = DEFAULT_PROPS.get(prop.getKey());
- if (defVal != null && defVal.equals(prop.getValue())) {
- sb.append(" [default]");
- }
- sb.append("\n");
- }
-
- @Override
- protected void appendConnectionsFooter() {}
-
- @Override
- protected void appendConnectionFooter(boolean remote) {
- sb.append('\n');
- }
-
- @Override
- protected void appendConfigPropsFooter() {}
- }
-
- // management properties
-
- private static Properties mgmtProps;
- private static ResourceBundle messageRB;
- private static final String CONFIG_FILE =
- "com.sun.management.config.file";
- private static final String SNMP_PORT =
- "com.sun.management.snmp.port";
- private static final String JMXREMOTE =
- "com.sun.management.jmxremote";
- private static final String JMXREMOTE_PORT =
- "com.sun.management.jmxremote.port";
- private static final String RMI_PORT =
- "com.sun.management.jmxremote.rmi.port";
- private static final String ENABLE_THREAD_CONTENTION_MONITORING =
- "com.sun.management.enableThreadContentionMonitoring";
- private static final String LOCAL_CONNECTOR_ADDRESS_PROP =
- "com.sun.management.jmxremote.localConnectorAddress";
- private static final String SNMP_AGENT_NAME =
- "SnmpAgent";
-
- private static final String JDP_DEFAULT_ADDRESS = "224.0.23.178";
- private static final int JDP_DEFAULT_PORT = 7095;
-
- // The only active agent allowed
- private static JMXConnectorServer jmxServer = null;
- // The properties used to configure the server
- private static Properties configProps = null;
-
- // Parse string com.sun.management.prop=xxx,com.sun.management.prop=yyyy
- // and return property set if args is null or empty
- // return empty property set
- private static Properties parseString(String args) {
- Properties argProps = new Properties();
- if (args != null && !args.trim().equals("")) {
- for (String option : args.split(",")) {
- String s[] = option.split("=", 2);
- String name = s[0].trim();
- String value = (s.length > 1) ? s[1].trim() : "";
-
- if (!name.startsWith("com.sun.management.")) {
- error(INVALID_OPTION, name);
- }
-
- argProps.setProperty(name, value);
- }
- }
-
- return argProps;
- }
-
- // invoked by -javaagent or -Dcom.sun.management.agent.class
- public static void premain(String args) throws Exception {
- agentmain(args);
- }
-
- // invoked by attach mechanism
- public static void agentmain(String args) throws Exception {
- if (args == null || args.length() == 0) {
- args = JMXREMOTE; // default to local management
- }
-
- Properties arg_props = parseString(args);
-
- // Read properties from the config file
- Properties config_props = new Properties();
- String fname = arg_props.getProperty(CONFIG_FILE);
- readConfiguration(fname, config_props);
-
- // Arguments override config file
- config_props.putAll(arg_props);
- startAgent(config_props);
- }
-
- // jcmd ManagementAgent.start_local entry point
- // Also called due to command-line via startAgent()
- private static synchronized void startLocalManagementAgent() {
- Properties agentProps = VMSupport.getAgentProperties();
-
- // start local connector if not started
- if (agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP) == null) {
- JMXConnectorServer cs = ConnectorBootstrap.startLocalConnectorServer();
- String address = cs.getAddress().toString();
- // Add the local connector address to the agent properties
- agentProps.put(LOCAL_CONNECTOR_ADDRESS_PROP, address);
-
- try {
- // export the address to the instrumentation buffer
- ConnectorAddressLink.export(address);
- } catch (Exception x) {
- // Connector server started but unable to export address
- // to instrumentation buffer - non-fatal error.
- warning(EXPORT_ADDRESS_FAILED, x.getMessage());
- }
- }
- }
-
- // jcmd ManagementAgent.start entry point
- // This method starts the remote JMX agent and starts neither
- // the local JMX agent nor the SNMP agent
- // @see #startLocalManagementAgent and also @see #startAgent.
- private static synchronized void startRemoteManagementAgent(String args) throws Exception {
- if (jmxServer != null) {
- throw new RuntimeException(getText(INVALID_STATE, "Agent already started"));
- }
-
- try {
- Properties argProps = parseString(args);
- configProps = new Properties();
-
- // Load the management properties from the config file
- // if config file is not specified readConfiguration implicitly
- // reads <java.home>/conf/management/management.properties
-
- String fname = System.getProperty(CONFIG_FILE);
- readConfiguration(fname, configProps);
-
- // management properties can be overridden by system properties
- // which take precedence
- Properties sysProps = System.getProperties();
- synchronized (sysProps) {
- configProps.putAll(sysProps);
- }
-
- // if user specifies config file into command line for either
- // jcmd utilities or attach command it overrides properties set in
- // command line at the time of VM start
- String fnameUser = argProps.getProperty(CONFIG_FILE);
- if (fnameUser != null) {
- readConfiguration(fnameUser, configProps);
- }
-
- // arguments specified in command line of jcmd utilities
- // override both system properties and one set by config file
- // specified in jcmd command line
- configProps.putAll(argProps);
-
- // jcmd doesn't allow to change ThreadContentionMonitoring, but user
- // can specify this property inside config file, so enable optional
- // monitoring functionality if this property is set
- final String enableThreadContentionMonitoring =
- configProps.getProperty(ENABLE_THREAD_CONTENTION_MONITORING);
-
- if (enableThreadContentionMonitoring != null) {
- ManagementFactory.getThreadMXBean().
- setThreadContentionMonitoringEnabled(true);
- }
-
- String jmxremotePort = configProps.getProperty(JMXREMOTE_PORT);
- if (jmxremotePort != null) {
- jmxServer = ConnectorBootstrap.
- startRemoteConnectorServer(jmxremotePort, configProps);
-
- startDiscoveryService(configProps);
- } else {
- throw new AgentConfigurationError(INVALID_JMXREMOTE_PORT, "No port specified");
- }
- } catch (JdpException e) {
- error(e);
- } catch (AgentConfigurationError err) {
- error(err.getError(), err.getParams());
- }
- }
-
- private static synchronized void stopRemoteManagementAgent() throws Exception {
-
- JdpController.stopDiscoveryService();
-
- if (jmxServer != null) {
- ConnectorBootstrap.unexportRegistry();
- ConnectorAddressLink.unexportRemote();
-
- // Attempt to stop already stopped agent
- // Don't cause any errors.
- jmxServer.stop();
- jmxServer = null;
- configProps = null;
- }
- }
-
- private static synchronized String getManagementAgentStatus() throws Exception {
- return new TextStatusCollector().collect();
- }
-
- private static void startAgent(Properties props) throws Exception {
- String snmpPort = props.getProperty(SNMP_PORT);
- String jmxremote = props.getProperty(JMXREMOTE);
- String jmxremotePort = props.getProperty(JMXREMOTE_PORT);
-
- // Enable optional monitoring functionality if requested
- final String enableThreadContentionMonitoring =
- props.getProperty(ENABLE_THREAD_CONTENTION_MONITORING);
- if (enableThreadContentionMonitoring != null) {
- ManagementFactory.getThreadMXBean().
- setThreadContentionMonitoringEnabled(true);
- }
-
- try {
- if (snmpPort != null) {
- loadSnmpAgent(props);
- }
-
- /*
- * If the jmxremote.port property is set then we start the
- * RMIConnectorServer for remote M&M.
- *
- * If the jmxremote or jmxremote.port properties are set then
- * we start a RMIConnectorServer for local M&M. The address
- * of this "local" server is exported as a counter to the jstat
- * instrumentation buffer.
- */
- if (jmxremote != null || jmxremotePort != null) {
- if (jmxremotePort != null) {
- jmxServer = ConnectorBootstrap.
- startRemoteConnectorServer(jmxremotePort, props);
- startDiscoveryService(props);
- }
- startLocalManagementAgent();
- }
-
- } catch (AgentConfigurationError e) {
- error(e.getError(), e.getParams());
- } catch (Exception e) {
- error(e);
- }
- }
-
- private static void startDiscoveryService(Properties props)
- throws IOException, JdpException {
- // Start discovery service if requested
- String discoveryPort = props.getProperty("com.sun.management.jdp.port");
- String discoveryAddress = props.getProperty("com.sun.management.jdp.address");
- String discoveryShouldStart = props.getProperty("com.sun.management.jmxremote.autodiscovery");
-
- // Decide whether we should start autodicovery service.
- // To start autodiscovery following conditions should be met:
- // autodiscovery==true OR (autodicovery==null AND jdp.port != NULL)
-
- boolean shouldStart = false;
- if (discoveryShouldStart == null){
- shouldStart = (discoveryPort != null);
- }
- else{
- try{
- shouldStart = Boolean.parseBoolean(discoveryShouldStart);
- } catch (NumberFormatException e) {
- throw new AgentConfigurationError(AGENT_EXCEPTION, "Couldn't parse autodiscovery argument");
- }
- }
-
- if (shouldStart) {
- // port and address are required arguments and have no default values
- InetAddress address;
- try {
- address = (discoveryAddress == null) ?
- InetAddress.getByName(JDP_DEFAULT_ADDRESS) : InetAddress.getByName(discoveryAddress);
- } catch (UnknownHostException e) {
- throw new AgentConfigurationError(AGENT_EXCEPTION, e, "Unable to broadcast to requested address");
- }
-
- int port = JDP_DEFAULT_PORT;
- if (discoveryPort != null) {
- try {
- port = Integer.parseInt(discoveryPort);
- } catch (NumberFormatException e) {
- throw new AgentConfigurationError(AGENT_EXCEPTION, "Couldn't parse JDP port argument");
- }
- }
-
- // Get service URL to broadcast it
- Map<String,String> remoteProps = ConnectorAddressLink.importRemoteFrom(0);
- String jmxUrlStr = remoteProps.get("sun.management.JMXConnectorServer.0.remoteAddress");
-
- String instanceName = props.getProperty("com.sun.management.jdp.name");
-
- JdpController.startDiscoveryService(address, port, instanceName, jmxUrlStr);
- }
- }
-
- public static Properties loadManagementProperties() {
- Properties props = new Properties();
-
- // Load the management properties from the config file
-
- String fname = System.getProperty(CONFIG_FILE);
- readConfiguration(fname, props);
-
- // management properties can be overridden by system properties
- // which take precedence
- Properties sysProps = System.getProperties();
- synchronized (sysProps) {
- props.putAll(sysProps);
- }
-
- return props;
- }
-
- public static synchronized Properties getManagementProperties() {
- if (mgmtProps == null) {
- String configFile = System.getProperty(CONFIG_FILE);
- String snmpPort = System.getProperty(SNMP_PORT);
- String jmxremote = System.getProperty(JMXREMOTE);
- String jmxremotePort = System.getProperty(JMXREMOTE_PORT);
-
- if (configFile == null && snmpPort == null
- && jmxremote == null && jmxremotePort == null) {
- // return if out-of-the-management option is not specified
- return null;
- }
- mgmtProps = loadManagementProperties();
- }
- return mgmtProps;
- }
-
- private static void loadSnmpAgent(Properties props) {
- /*
- * Load the jdk.snmp service
- */
- AgentProvider provider = AccessController.doPrivileged(
- (PrivilegedAction<AgentProvider>) () -> {
- for(AgentProvider aProvider : ServiceLoader.loadInstalled(AgentProvider.class)) {
- if(aProvider.getName().equals(SNMP_AGENT_NAME))
- return aProvider;
- }
- return null;
- }, null
- );
-
- if (provider != null) {
- provider.startAgent(props);
- } else { // snmp runtime doesn't exist - initialization fails
- throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT);
- }
- }
-
- // read config file and initialize the properties
- private static void readConfiguration(String fname, Properties p) {
- if (fname == null) {
- String home = System.getProperty("java.home");
- if (home == null) {
- throw new Error("Can't find java.home ??");
- }
- StringBuilder defaultFileName = new StringBuilder(home);
- defaultFileName.append(File.separator).append("conf");
- defaultFileName.append(File.separator).append("management");
- defaultFileName.append(File.separator).append("management.properties");
- // Set file name
- fname = defaultFileName.toString();
- }
- final File configFile = new File(fname);
- if (!configFile.exists()) {
- error(CONFIG_FILE_NOT_FOUND, fname);
- }
-
- InputStream in = null;
- try {
- in = new FileInputStream(configFile);
- BufferedInputStream bin = new BufferedInputStream(in);
- p.load(bin);
- } catch (FileNotFoundException e) {
- error(CONFIG_FILE_OPEN_FAILED, e.getMessage());
- } catch (IOException e) {
- error(CONFIG_FILE_OPEN_FAILED, e.getMessage());
- } catch (SecurityException e) {
- error(CONFIG_FILE_ACCESS_DENIED, fname);
- } finally {
- if (in != null) {
- try {
- in.close();
- } catch (IOException e) {
- error(CONFIG_FILE_CLOSE_FAILED, fname);
- }
- }
- }
- }
-
- public static void startAgent() throws Exception {
- String prop = System.getProperty("com.sun.management.agent.class");
-
- // -Dcom.sun.management.agent.class not set so read management
- // properties and start agent
- if (prop == null) {
- // initialize management properties
- Properties props = getManagementProperties();
- if (props != null) {
- startAgent(props);
- }
- return;
- }
-
- // -Dcom.sun.management.agent.class=<agent classname>:<agent args>
- String[] values = prop.split(":");
- if (values.length < 1 || values.length > 2) {
- error(AGENT_CLASS_INVALID, "\"" + prop + "\"");
- }
- String cname = values[0];
- String args = (values.length == 2 ? values[1] : null);
-
- if (cname == null || cname.length() == 0) {
- error(AGENT_CLASS_INVALID, "\"" + prop + "\"");
- }
-
- if (cname != null) {
- try {
- // Instantiate the named class.
- // invoke the premain(String args) method
- Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(cname);
- Method premain = clz.getMethod("premain",
- new Class<?>[]{String.class});
- premain.invoke(null, /* static */
- new Object[]{args});
- } catch (ClassNotFoundException ex) {
- error(AGENT_CLASS_NOT_FOUND, "\"" + cname + "\"");
- } catch (NoSuchMethodException ex) {
- error(AGENT_CLASS_PREMAIN_NOT_FOUND, "\"" + cname + "\"");
- } catch (SecurityException ex) {
- error(AGENT_CLASS_ACCESS_DENIED);
- } catch (Exception ex) {
- String msg = (ex.getCause() == null
- ? ex.getMessage()
- : ex.getCause().getMessage());
- error(AGENT_CLASS_FAILED, msg);
- }
- }
- }
-
- public static void error(String key) {
- String keyText = getText(key);
- System.err.print(getText("agent.err.error") + ": " + keyText);
- throw new RuntimeException(keyText);
- }
-
- public static void error(String key, String[] params) {
- if (params == null || params.length == 0) {
- error(key);
- } else {
- StringBuilder message = new StringBuilder(params[0]);
- for (int i = 1; i < params.length; i++) {
- message.append(' ').append(params[i]);
- }
- error(key, message.toString());
- }
- }
-
- public static void error(String key, String message) {
- String keyText = getText(key);
- System.err.print(getText("agent.err.error") + ": " + keyText);
- System.err.println(": " + message);
- throw new RuntimeException(keyText + ": " + message);
- }
-
- public static void error(Exception e) {
- e.printStackTrace();
- System.err.println(getText(AGENT_EXCEPTION) + ": " + e.toString());
- throw new RuntimeException(e);
- }
-
- public static void warning(String key, String message) {
- System.err.print(getText("agent.err.warning") + ": " + getText(key));
- System.err.println(": " + message);
- }
-
- private static void initResource() {
- try {
- messageRB =
- ResourceBundle.getBundle("sun.management.resources.agent");
- } catch (MissingResourceException e) {
- throw new Error("Fatal: Resource for management agent is missing");
- }
- }
-
- public static String getText(String key) {
- if (messageRB == null) {
- initResource();
- }
- try {
- return messageRB.getString(key);
- } catch (MissingResourceException e) {
- return "Missing management agent resource bundle: key = \"" + key + "\"";
- }
- }
-
- public static String getText(String key, String... args) {
- if (messageRB == null) {
- initResource();
- }
- String format = messageRB.getString(key);
- if (format == null) {
- format = "missing resource key: key = \"" + key + "\", "
- + "arguments = \"{0}\", \"{1}\", \"{2}\"";
- }
- return MessageFormat.format(format, (Object[]) args);
- }
-}
--- a/jdk/src/java.management/share/classes/sun/management/AgentConfigurationError.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-/*
- * Copyright (c) 2004, 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.
- */
-
-package sun.management;
-
-/**
- * Configuration Error thrown by a management agent.
- */
-public class AgentConfigurationError extends Error {
- public static final String AGENT_EXCEPTION =
- "agent.err.exception";
- public static final String CONFIG_FILE_NOT_FOUND =
- "agent.err.configfile.notfound";
- public static final String CONFIG_FILE_OPEN_FAILED =
- "agent.err.configfile.failed";
- public static final String CONFIG_FILE_CLOSE_FAILED =
- "agent.err.configfile.closed.failed";
- public static final String CONFIG_FILE_ACCESS_DENIED =
- "agent.err.configfile.access.denied";
- public static final String EXPORT_ADDRESS_FAILED =
- "agent.err.exportaddress.failed";
- public static final String AGENT_CLASS_NOT_FOUND =
- "agent.err.agentclass.notfound";
- public static final String AGENT_CLASS_FAILED =
- "agent.err.agentclass.failed";
- public static final String AGENT_CLASS_PREMAIN_NOT_FOUND =
- "agent.err.premain.notfound";
- public static final String AGENT_CLASS_ACCESS_DENIED =
- "agent.err.agentclass.access.denied";
- public static final String AGENT_CLASS_INVALID =
- "agent.err.invalid.agentclass";
- public static final String INVALID_JMXREMOTE_PORT =
- "agent.err.invalid.jmxremote.port";
- public static final String INVALID_JMXREMOTE_RMI_PORT =
- "agent.err.invalid.jmxremote.rmi.port";
- public static final String PASSWORD_FILE_NOT_SET =
- "agent.err.password.file.notset";
- public static final String PASSWORD_FILE_NOT_READABLE =
- "agent.err.password.file.not.readable";
- public static final String PASSWORD_FILE_READ_FAILED =
- "agent.err.password.file.read.failed";
- public static final String PASSWORD_FILE_NOT_FOUND =
- "agent.err.password.file.notfound";
- public static final String ACCESS_FILE_NOT_SET =
- "agent.err.access.file.notset";
- public static final String ACCESS_FILE_NOT_READABLE =
- "agent.err.access.file.not.readable";
- public static final String ACCESS_FILE_READ_FAILED =
- "agent.err.access.file.read.failed";
- public static final String ACCESS_FILE_NOT_FOUND =
- "agent.err.access.file.notfound";
- public static final String PASSWORD_FILE_ACCESS_NOT_RESTRICTED =
- "agent.err.password.file.access.notrestricted";
- public static final String FILE_ACCESS_NOT_RESTRICTED =
- "agent.err.file.access.not.restricted";
- public static final String FILE_NOT_FOUND =
- "agent.err.file.not.found";
- public static final String FILE_NOT_READABLE =
- "agent.err.file.not.readable";
- public static final String FILE_NOT_SET =
- "agent.err.file.not.set";
- public static final String FILE_READ_FAILED =
- "agent.err.file.read.failed";
- public static final String CONNECTOR_SERVER_IO_ERROR =
- "agent.err.connector.server.io.error";
- public static final String INVALID_OPTION =
- "agent.err.invalid.option";
- public static final String INVALID_STATE =
- "agent.err.invalid.state";
-
- private final String error;
- private final String[] params;
-
- public AgentConfigurationError(String error) {
- super();
- this.error = error;
- this.params = null;
- }
-
- public AgentConfigurationError(String error, Throwable cause) {
- super(cause);
- this.error = error;
- this.params = null;
- }
-
- public AgentConfigurationError(String error, String... params) {
- super();
- this.error = error;
- this.params = params.clone();
- }
-
- public AgentConfigurationError(String error, Throwable cause, String... params) {
- super(cause);
- this.error = error;
- this.params = params.clone();
- }
-
- public String getError() {
- return error;
- }
-
- public String[] getParams() {
- return params.clone();
- }
-
- private static final long serialVersionUID = 1211605593516195475L;
-}
--- a/jdk/src/java.management/share/classes/sun/management/ConnectorAddressLink.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,218 +0,0 @@
-/*
- * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.management;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import jdk.internal.perf.Perf;
-import sun.management.counter.Units;
-import sun.management.counter.Counter;
-import sun.management.counter.perf.PerfInstrumentation;
-
-/**
- * A utility class to support the exporting and importing of the address
- * of a connector server using the instrumentation buffer.
- *
- * @since 1.5
- */
-public class ConnectorAddressLink {
- /**
- * A simple wrapper for the perf-counter backing {@linkplain ByteBuffer}
- */
- private static final class PerfHandle {
- private ByteBuffer bb;
-
- private PerfHandle(ByteBuffer bb) {
- this.bb = bb.order(ByteOrder.nativeOrder());
- }
-
- private void putLong(long l) {
- this.bb = bb.clear();
- this.bb.asLongBuffer().put(l);
- }
- }
-
- private static final String CONNECTOR_ADDRESS_COUNTER =
- "sun.management.JMXConnectorServer.address";
- private static final String REMOTE_CONNECTOR_STATE_COUNTER =
- "sun.management.JMXConnectorServer.remote.enabled";
-
- /*
- * The format of the jvmstat counters representing the properties of
- * a given out-of-the-box JMX remote connector will be as follows:
- *
- * sun.management.JMXConnectorServer.<counter>.<key>=<value>
- *
- * where:
- *
- * counter = index computed by this class which uniquely identifies
- * an out-of-the-box JMX remote connector running in this
- * Java virtual machine.
- * key/value = a given key/value pair in the map supplied to the
- * exportRemote() method.
- *
- * For example,
- *
- * sun.management.JMXConnectorServer.0.remoteAddress=service:jmx:rmi:///jndi/rmi://myhost:5000/jmxrmi
- * sun.management.JMXConnectorServer.0.authenticate=false
- * sun.management.JMXConnectorServer.0.ssl=false
- * sun.management.JMXConnectorServer.0.sslRegistry=false
- * sun.management.JMXConnectorServer.0.sslNeedClientAuth=false
- */
- private static final String REMOTE_CONNECTOR_COUNTER_PREFIX =
- "sun.management.JMXConnectorServer.";
-
- /*
- * JMX remote connector counter (it will be incremented every
- * time a new out-of-the-box JMX remote connector is created).
- */
- private static final AtomicInteger counter = new AtomicInteger();
-
- private static PerfHandle remotePerfHandle = null;
-
- /**
- * Exports the specified connector address to the instrumentation buffer
- * so that it can be read by this or other Java virtual machines running
- * on the same system.
- *
- * @param address The connector address.
- */
- public static void export(String address) {
- if (address == null || address.length() == 0) {
- throw new IllegalArgumentException("address not specified");
- }
- Perf perf = Perf.getPerf();
- perf.createString(
- CONNECTOR_ADDRESS_COUNTER, 1, Units.STRING.intValue(), address);
- }
-
- public static void unexportRemote() {
- unexport(remotePerfHandle);
- }
-
- private static void unexport(PerfHandle ph) {
- if (ph != null) {
- ph.putLong(-1L);
- }
- }
-
- /**
- * Imports the connector address from the instrument buffer
- * of the specified Java virtual machine.
- *
- * @param vmid an identifier that uniquely identifies a local Java virtual
- * machine, or <code>0</code> to indicate the current Java virtual machine.
- *
- * @return the value of the connector address, or <code>null</code> if the
- * target VM has not exported a connector address.
- *
- * @throws IOException An I/O error occurred while trying to acquire the
- * instrumentation buffer.
- */
- public static String importFrom(int vmid) throws IOException {
- Perf perf = Perf.getPerf();
- ByteBuffer bb;
- try {
- bb = perf.attach(vmid, "r");
- } catch (IllegalArgumentException iae) {
- throw new IOException(iae.getMessage());
- }
- List<Counter> counters =
- new PerfInstrumentation(bb).findByPattern(CONNECTOR_ADDRESS_COUNTER);
- Iterator<Counter> i = counters.iterator();
- if (i.hasNext()) {
- Counter c = i.next();
- return (String) c.getValue();
- } else {
- return null;
- }
- }
-
- /**
- * Exports the specified remote connector address and associated
- * configuration properties to the instrumentation buffer so that
- * it can be read by this or other Java virtual machines running
- * on the same system.
- *
- * @param properties The remote connector address properties.
- */
- public static void exportRemote(Map<String, String> properties) {
- final int index = counter.getAndIncrement();
- Perf perf = Perf.getPerf();
- for (Map.Entry<String, String> entry : properties.entrySet()) {
- perf.createString(REMOTE_CONNECTOR_COUNTER_PREFIX + index + "." +
- entry.getKey(), 1, Units.STRING.intValue(), entry.getValue());
- }
- if (remotePerfHandle != null) {
- remotePerfHandle.putLong(index);
- } else {
- remotePerfHandle = new PerfHandle(
- perf.createLong(REMOTE_CONNECTOR_STATE_COUNTER, 1, Units.NONE.intValue(), (long)index)
- );
- }
- }
-
- /**
- * Imports the remote connector address and associated
- * configuration properties from the instrument buffer
- * of the specified Java virtual machine.
- *
- * @param vmid an identifier that uniquely identifies a local Java virtual
- * machine, or <code>0</code> to indicate the current Java virtual machine.
- *
- * @return a map containing the remote connector's properties, or an empty
- * map if the target VM has not exported the remote connector's properties.
- *
- * @throws IOException An I/O error occurred while trying to acquire the
- * instrumentation buffer.
- */
- public static Map<String, String> importRemoteFrom(int vmid) throws IOException {
- Perf perf = Perf.getPerf();
- ByteBuffer bb;
- try {
- bb = perf.attach(vmid, "r");
- } catch (IllegalArgumentException iae) {
- throw new IOException(iae.getMessage());
- }
- List<Counter> counters = new PerfInstrumentation(bb).getAllCounters();
- Map<String, String> properties = new HashMap<>();
- for (Counter c : counters) {
- String name = c.getName();
- if (name.startsWith(REMOTE_CONNECTOR_COUNTER_PREFIX) &&
- !name.equals(CONNECTOR_ADDRESS_COUNTER)) {
- properties.put(name, c.getValue().toString());
- }
- }
- return properties;
- }
-}
--- a/jdk/src/java.management/share/classes/sun/management/FileSystem.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.management;
-
-import java.io.File;
-import java.io.IOException;
-
-/*
- * Utility class to support file system operations
- *
- * @since 1.5
- */
-public abstract class FileSystem {
-
- private static final Object lock = new Object();
- private static FileSystem fs;
-
- protected FileSystem() { }
-
- /**
- * Opens the file system
- */
- public static FileSystem open() {
- synchronized (lock) {
- if (fs == null) {
- fs = new FileSystemImpl();
- }
- return fs;
- }
- }
-
- /**
- * Tells whether or not the specified file is located on a
- * file system that supports file security or not.
- *
- * @throws IOException if an I/O error occurs.
- */
- public abstract boolean supportsFileSecurity(File f) throws IOException;
-
- /**
- * Tell whether or not the specified file is accessible
- * by anything other than the file owner.
- *
- * @throws IOException if an I/O error occurs.
- *
- * @throws UnsupportedOperationException
- * If file is located on a file system that doesn't support
- * file security.
- */
- public abstract boolean isAccessUserOnly(File f) throws IOException;
-}
--- a/jdk/src/java.management/share/classes/sun/management/jdp/JdpBroadcaster.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-package sun.management.jdp;
-
-import java.io.IOException;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.NetworkInterface;
-import java.net.ProtocolFamily;
-import java.net.StandardProtocolFamily;
-import java.net.StandardSocketOptions;
-import java.nio.ByteBuffer;
-import java.nio.channels.DatagramChannel;
-import java.nio.channels.UnsupportedAddressTypeException;
-import java.util.Enumeration;
-
-/**
- * JdpBroadcaster is responsible for sending pre-built JDP packet across a Net
- *
- * <p> Multicast group address, port number and ttl have to be chosen on upper
- * level and passed to broadcaster constructor. Also it's possible to specify
- * source address to broadcast from. </p>
- *
- * <p>JdpBradcaster doesn't perform any validation on a supplied {@code port} and {@code ttl} because
- * the allowed values depend on an operating system setup</p>
- *
- */
-public final class JdpBroadcaster {
-
- private final InetAddress addr;
- private final int port;
- private final DatagramChannel channel;
-
- /**
- * Create a new broadcaster
- *
- * @param address - multicast group address
- * @param srcAddress - address of interface we should use to broadcast.
- * @param port - udp port to use
- * @param ttl - packet ttl
- * @throws IOException
- */
- public JdpBroadcaster(InetAddress address, InetAddress srcAddress, int port, int ttl)
- throws IOException, JdpException {
- this.addr = address;
- this.port = port;
-
- ProtocolFamily family = (address instanceof Inet6Address)
- ? StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
-
- channel = DatagramChannel.open(family);
- channel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
- channel.setOption(StandardSocketOptions.IP_MULTICAST_TTL, ttl);
-
- // with srcAddress equal to null, this constructor do exactly the same as
- // if srcAddress is not passed
- if (srcAddress != null) {
- // User requests particular interface to bind to
- NetworkInterface interf = NetworkInterface.getByInetAddress(srcAddress);
-
- if (interf == null) {
- throw new JdpException("Unable to get network interface for " + srcAddress.toString());
- }
-
- if (!interf.isUp()) {
- throw new JdpException(interf.getName() + " is not up.");
- }
-
- if (!interf.supportsMulticast()) {
- throw new JdpException(interf.getName() + " does not support multicast.");
- }
-
- try {
- channel.bind(new InetSocketAddress(srcAddress, 0));
- } catch (UnsupportedAddressTypeException ex) {
- throw new JdpException("Unable to bind to source address");
- }
- channel.setOption(StandardSocketOptions.IP_MULTICAST_IF, interf);
- }
- }
-
- /**
- * Create a new broadcaster
- *
- * @param address - multicast group address
- * @param port - udp port to use
- * @param ttl - packet ttl
- * @throws IOException
- */
- public JdpBroadcaster(InetAddress address, int port, int ttl)
- throws IOException, JdpException {
- this(address, null, port, ttl);
- }
-
- /**
- * Broadcast pre-built packet
- *
- * @param packet - instance of JdpPacket
- * @throws IOException
- */
- public void sendPacket(JdpPacket packet)
- throws IOException {
- byte[] data = packet.getPacketData();
- // Unlike allocate/put wrap don't need a flip afterward
- ByteBuffer b = ByteBuffer.wrap(data);
- channel.send(b, new InetSocketAddress(addr, port));
- }
-
- /**
- * Shutdown broadcaster and close underlying socket channel
- *
- * @throws IOException
- */
- public void shutdown() throws IOException {
- channel.close();
- }
-}
--- a/jdk/src/java.management/share/classes/sun/management/jdp/JdpController.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,236 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-package sun.management.jdp;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.UUID;
-
-import java.lang.management.ManagementFactory;
-import java.lang.management.RuntimeMXBean;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import sun.management.VMManagement;
-
-/**
- * JdpController is responsible to create and manage a broadcast loop.
- *
- * <p> Other part of code has no access to broadcast loop and have to use
- * provided static methods
- * {@link #startDiscoveryService(InetAddress,int,String,String) startDiscoveryService}
- * and {@link #stopDiscoveryService() stopDiscoveryService}
- * <p>{@link #startDiscoveryService(InetAddress,int,String,String) startDiscoveryService} could be called multiple
- * times as it stops the running service if it is necessary.
- * Call to {@link #stopDiscoveryService() stopDiscoveryService}
- * ignored if service isn't run.
- *
- *
- * <p> System properties below could be used to control broadcast loop behavior.
- * Property below have to be set explicitly in command line. It's not possible to
- * set it in management.config file. Careless changes of these properties could
- * lead to security or network issues.
- * <ul>
- * <li>com.sun.management.jdp.ttl - set ttl for broadcast packet</li>
- * <li>com.sun.management.jdp.pause - set broadcast interval in seconds</li>
- * <li>com.sun.management.jdp.source_addr - an address of interface to use for broadcast</li>
- * </ul>
- *
- * <p>null parameters values are filtered out on {@link JdpPacketWriter} level and
- * corresponding keys are not placed to packet.
- */
-public final class JdpController {
-
- private static class JDPControllerRunner implements Runnable {
-
- private final JdpJmxPacket packet;
- private final JdpBroadcaster bcast;
- private final int pause;
- private volatile boolean shutdown = false;
-
- private JDPControllerRunner(JdpBroadcaster bcast, JdpJmxPacket packet, int pause) {
- this.bcast = bcast;
- this.packet = packet;
- this.pause = pause;
- }
-
- @Override
- public void run() {
- try {
- while (!shutdown) {
- bcast.sendPacket(packet);
- try {
- Thread.sleep(this.pause);
- } catch (InterruptedException e) {
- // pass
- }
- }
-
- } catch (IOException e) {
- // pass;
- }
-
- // It's not possible to re-use controller,
- // nevertheless reset shutdown variable
- try {
- stop();
- bcast.shutdown();
- } catch (IOException ex) {
- // pass - ignore IOException during shutdown
- }
- }
-
- public void stop() {
- shutdown = true;
- }
- }
- private static JDPControllerRunner controller = null;
-
- private JdpController(){
- // Don't allow to instantiate this class.
- }
-
- // Utility to handle optional system properties
- // Parse an integer from string or return default if provided string is null
- private static int getInteger(String val, int dflt, String msg) throws JdpException {
- try {
- return (val == null) ? dflt : Integer.parseInt(val);
- } catch (NumberFormatException ex) {
- throw new JdpException(msg);
- }
- }
-
- // Parse an inet address from string or return default if provided string is null
- private static InetAddress getInetAddress(String val, InetAddress dflt, String msg) throws JdpException {
- try {
- return (val == null) ? dflt : InetAddress.getByName(val);
- } catch (UnknownHostException ex) {
- throw new JdpException(msg);
- }
- }
-
- // Get the process id of the current running Java process
- private static Integer getProcessId() {
- try {
- // Get the current process id using a reflection hack
- RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
- Field jvm = runtime.getClass().getDeclaredField("jvm");
- jvm.setAccessible(true);
-
- VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime);
- Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId");
- pid_method.setAccessible(true);
- Integer pid = (Integer) pid_method.invoke(mgmt);
- return pid;
- } catch(Exception ex) {
- return null;
- }
- }
-
-
- /**
- * Starts discovery service
- *
- * @param address - multicast group address
- * @param port - udp port to use
- * @param instanceName - name of running JVM instance
- * @param url - JMX service url
- * @throws IOException
- */
- public static synchronized void startDiscoveryService(InetAddress address, int port, String instanceName, String url)
- throws IOException, JdpException {
-
- // Limit packet to local subnet by default
- int ttl = getInteger(
- System.getProperty("com.sun.management.jdp.ttl"), 1,
- "Invalid jdp packet ttl");
-
- // Broadcast once a 5 seconds by default
- int pause = getInteger(
- System.getProperty("com.sun.management.jdp.pause"), 5,
- "Invalid jdp pause");
-
- // Converting seconds to milliseconds
- pause = pause * 1000;
-
- // Allow OS to choose broadcast source
- InetAddress sourceAddress = getInetAddress(
- System.getProperty("com.sun.management.jdp.source_addr"), null,
- "Invalid source address provided");
-
- // Generate session id
- UUID id = UUID.randomUUID();
-
- JdpJmxPacket packet = new JdpJmxPacket(id, url);
-
- // Don't broadcast whole command line for security reason.
- // Strip everything after first space
- String javaCommand = System.getProperty("sun.java.command");
- if (javaCommand != null) {
- String[] arr = javaCommand.split(" ", 2);
- packet.setMainClass(arr[0]);
- }
-
- // Put optional explicit java instance name to packet, if user doesn't specify
- // it the key is skipped. PacketWriter is responsible to skip keys having null value.
- packet.setInstanceName(instanceName);
-
- // Set rmi server hostname if it explicitly specified by user with
- // java.rmi.server.hostname
- String rmiHostname = System.getProperty("java.rmi.server.hostname");
- packet.setRmiHostname(rmiHostname);
-
- // Set broadcast interval
- packet.setBroadcastInterval(Integer.toString(pause));
-
- // Set process id
- Integer pid = getProcessId();
- if (pid != null) {
- packet.setProcessId(pid.toString());
- }
-
- JdpBroadcaster bcast = new JdpBroadcaster(address, sourceAddress, port, ttl);
-
- // Stop discovery service if it's already running
- stopDiscoveryService();
-
- controller = new JDPControllerRunner(bcast, packet, pause);
-
- Thread t = new Thread(null, controller, "JDP broadcaster", 0, false);
- t.setDaemon(true);
- t.start();
- }
-
- /**
- * Stop running discovery service,
- * it's safe to attempt to stop not started service
- */
- public static synchronized void stopDiscoveryService() {
- if ( controller != null ){
- controller.stop();
- controller = null;
- }
- }
-}
--- a/jdk/src/java.management/share/classes/sun/management/jdp/JdpException.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-package sun.management.jdp;
-
-/**
- * An Exception thrown if a JDP implementation encounters a problem.
- */
-public final class JdpException extends Exception {
-
- private static final long serialVersionUID = 1L;
-
- /**
- * Construct a new JDP exception with a meaningful message
- *
- * @param msg - message
- */
- public JdpException(String msg) {
- super(msg);
- }
-}
--- a/jdk/src/java.management/share/classes/sun/management/jdp/JdpGenericPacket.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-package sun.management.jdp;
-
-/**
- * JdpGenericPacket responsible to provide fields
- * common for all Jdp packets
- */
-public abstract class JdpGenericPacket implements JdpPacket {
-
- /**
- * JDP protocol magic. Magic allows a reader to quickly select
- * JDP packets from a bunch of broadcast packets addressed to the same port
- * and broadcast group. Any packet intended to be parsed by JDP client
- * has to start from this magic.
- */
- private static final int MAGIC = 0xC0FFEE42;
-
- /**
- * Current version of protocol. Any implementation of this protocol has to
- * conform with the packet structure and the flow described in JEP-168
- */
- private static final short PROTOCOL_VERSION = 1;
-
- /**
- * Default do-nothing constructor
- */
- protected JdpGenericPacket(){
- // do nothing
- }
-
-
- /**
- * Validate protocol header magic field
- *
- * @param magic - value to validate
- * @throws JdpException
- */
- public static void checkMagic(int magic)
- throws JdpException {
- if (magic != MAGIC) {
- throw new JdpException("Invalid JDP magic header: " + magic);
- }
- }
-
- /**
- * Validate protocol header version field
- *
- * @param version - value to validate
- * @throws JdpException
- */
- public static void checkVersion(short version)
- throws JdpException {
-
- if (version > PROTOCOL_VERSION) {
- throw new JdpException("Unsupported protocol version: " + version);
- }
- }
-
- /**
- *
- * @return protocol magic
- */
- public static int getMagic() {
- return MAGIC;
- }
-
- /**
- *
- * @return current protocol version
- */
- public static short getVersion() {
- return PROTOCOL_VERSION;
- }
-}
--- a/jdk/src/java.management/share/classes/sun/management/jdp/JdpJmxPacket.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,245 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-package sun.management.jdp;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.UUID;
-
-/**
- * A packet to broadcasts JMX URL
- *
- * Fields:
- *
- * <ul>
- * <li>UUID - broadcast session ID, changed every time when we start/stop
- * discovery service</li>
- * <li>JMX_URL - URL to connect to JMX service</li>
- * <li>MAIN_CLASS - optional name of main class, filled from sun.java.command stripped for
- * security reason to first space</li>
- * <li>INSTANCE_NAME - optional custom name of particular instance as provided by customer</li>
- * </ul>
- */
-public final class JdpJmxPacket
- extends JdpGenericPacket
- implements JdpPacket {
-
- /**
- * Session ID
- */
- public final static String UUID_KEY = "DISCOVERABLE_SESSION_UUID";
- /**
- * Name of main class
- */
- public final static String MAIN_CLASS_KEY = "MAIN_CLASS";
- /**
- * JMX service URL
- */
- public final static String JMX_SERVICE_URL_KEY = "JMX_SERVICE_URL";
- /**
- * Name of Java instance
- */
- public final static String INSTANCE_NAME_KEY = "INSTANCE_NAME";
- /**
- * PID of java process, optional presented if it could be obtained
- */
- public final static String PROCESS_ID_KEY = "PROCESS_ID";
- /**
- * Hostname of rmi server, optional presented if user overrides rmi server
- * hostname by java.rmi.server.hostname property
- */
- public final static String RMI_HOSTNAME_KEY = "RMI_HOSTNAME";
- /**
- * Configured broadcast interval, optional
- */
- public final static String BROADCAST_INTERVAL_KEY = "BROADCAST_INTERVAL";
-
- private UUID id;
- private String mainClass;
- private String jmxServiceUrl;
- private String instanceName;
- private String processId;
- private String rmiHostname;
- private String broadcastInterval;
-
- /**
- * Create new instance from user provided data. Set mandatory fields
- *
- * @param id - java instance id
- * @param jmxServiceUrl - JMX service url
- */
- public JdpJmxPacket(UUID id, String jmxServiceUrl) {
- this.id = id;
- this.jmxServiceUrl = jmxServiceUrl;
- }
-
- /**
- * Create new instance from network data Parse packet and set fields.
- *
- * @param data - raw packet data as it came from a Net
- * @throws JdpException
- */
- public JdpJmxPacket(byte[] data)
- throws JdpException {
- JdpPacketReader reader;
-
- reader = new JdpPacketReader(data);
- Map<String, String> p = reader.getDiscoveryDataAsMap();
-
- String sId = p.get(UUID_KEY);
- this.id = (sId == null) ? null : UUID.fromString(sId);
- this.jmxServiceUrl = p.get(JMX_SERVICE_URL_KEY);
- this.mainClass = p.get(MAIN_CLASS_KEY);
- this.instanceName = p.get(INSTANCE_NAME_KEY);
- this.processId = p.get(PROCESS_ID_KEY);
- this.rmiHostname = p.get(RMI_HOSTNAME_KEY);
- this.broadcastInterval = p.get(BROADCAST_INTERVAL_KEY);
- }
-
- /**
- * Set main class field
- *
- * @param mainClass - main class of running app
- */
- public void setMainClass(String mainClass) {
- this.mainClass = mainClass;
- }
-
- /**
- * Set instance name field
- *
- * @param instanceName - name of instance as provided by customer
- */
- public void setInstanceName(String instanceName) {
- this.instanceName = instanceName;
- }
-
- /**
- * @return id of discovery session
- */
- public UUID getId() {
- return id;
- }
-
- /**
- *
- * @return main class field
- */
- public String getMainClass() {
- return mainClass;
- }
-
- /**
- *
- * @return JMX service URL
- */
- public String getJmxServiceUrl() {
- return jmxServiceUrl;
- }
-
- /**
- *
- * @return instance name
- */
- public String getInstanceName() {
- return instanceName;
- }
-
- public String getProcessId() {
- return processId;
- }
-
- public void setProcessId(String processId) {
- this.processId = processId;
- }
-
- public String getRmiHostname() {
- return rmiHostname;
- }
-
- public void setRmiHostname(String rmiHostname) {
- this.rmiHostname = rmiHostname;
- }
-
- public String getBroadcastInterval() {
- return broadcastInterval;
- }
-
- public void setBroadcastInterval(String broadcastInterval) {
- this.broadcastInterval = broadcastInterval;
- }
-
- /**
- *
- * @return assembled packet ready to be sent across a Net
- * @throws IOException
- */
- @Override
- public byte[] getPacketData() throws IOException {
- // Assemble packet from fields to byte array
- JdpPacketWriter writer;
- writer = new JdpPacketWriter();
- writer.addEntry(UUID_KEY, (id == null) ? null : id.toString());
- writer.addEntry(MAIN_CLASS_KEY, mainClass);
- writer.addEntry(JMX_SERVICE_URL_KEY, jmxServiceUrl);
- writer.addEntry(INSTANCE_NAME_KEY, instanceName);
- writer.addEntry(PROCESS_ID_KEY, processId);
- writer.addEntry(RMI_HOSTNAME_KEY, rmiHostname);
- writer.addEntry(BROADCAST_INTERVAL_KEY, broadcastInterval);
-
- return writer.getPacketBytes();
- }
-
- /**
- *
- * @return packet hash code
- */
- @Override
- public int hashCode() {
- int hash = 1;
- hash = hash * 31 + id.hashCode();
- hash = hash * 31 + jmxServiceUrl.hashCode();
- return hash;
- }
-
- /**
- * Compare two packets
- *
- * @param o - packet to compare
- * @return either packet equals or not
- */
- @Override
- public boolean equals(Object o) {
-
- if (o == null || ! (o instanceof JdpJmxPacket) ){
- return false;
- }
-
- JdpJmxPacket p = (JdpJmxPacket) o;
- return Objects.equals(id, p.getId()) && Objects.equals(jmxServiceUrl, p.getJmxServiceUrl());
- }
-}
--- a/jdk/src/java.management/share/classes/sun/management/jdp/JdpPacket.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-package sun.management.jdp;
-
-import java.io.IOException;
-
-/**
- * Packet to broadcast
- *
- * <p>Each packet have to contain MAGIC and PROTOCOL_VERSION in order to be
- * recognized as a valid JDP packet.</p>
- *
- * <p>Default implementation build packet as a set of UTF-8 encoded Key/Value pairs
- * are stored as an ordered list of values, and are sent to the server
- * in that order.</p>
- *
- * <p>
- * Packet structure:
- *
- * 4 bytes JDP magic (0xC0FFE42)
- * 2 bytes JDP protocol version (01)
- *
- * 2 bytes size of key
- * x bytes key (UTF-8 encoded)
- * 2 bytes size of value
- * x bytes value (UTF-8 encoded)
- *
- * repeat as many times as necessary ...
- * </p>
- */
-public interface JdpPacket {
-
- /**
- * This method responsible to assemble packet and return a byte array
- * ready to be sent across a Net.
- *
- * @return assembled packet as an array of bytes
- * @throws IOException
- */
- public byte[] getPacketData() throws IOException;
-
-}
--- a/jdk/src/java.management/share/classes/sun/management/jdp/JdpPacketReader.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-package sun.management.jdp;
-
-import java.io.ByteArrayInputStream;
-import java.io.DataInputStream;
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * JdpPacketReader responsible for reading a packet <p>This class gets a byte
- * array as it came from a Net, validates it and breaks a part </p>
- */
-public final class JdpPacketReader {
-
- private final DataInputStream pkt;
- private Map<String, String> pmap = null;
-
- /**
- * Create packet reader, extract and check magic and version
- *
- * @param packet - packet received from a Net
- * @throws JdpException
- */
- public JdpPacketReader(byte[] packet)
- throws JdpException {
- ByteArrayInputStream bais = new ByteArrayInputStream(packet);
- pkt = new DataInputStream(bais);
-
- try {
- int magic = pkt.readInt();
- JdpGenericPacket.checkMagic(magic);
- } catch (IOException e) {
- throw new JdpException("Invalid JDP packet received, bad magic");
- }
-
- try {
- short version = pkt.readShort();
- JdpGenericPacket.checkVersion(version);
- } catch (IOException e) {
- throw new JdpException("Invalid JDP packet received, bad protocol version");
- }
- }
-
- /**
- * Get next entry from packet
- *
- * @return the entry
- * @throws EOFException
- * @throws JdpException
- */
- public String getEntry()
- throws EOFException, JdpException {
-
- try {
- short len = pkt.readShort();
- // Artificial setting the "len" field to Short.MAX_VALUE may cause a reader to allocate
- // to much memory. Prevent this possible DOS attack.
- if (len < 1 && len > pkt.available()) {
- throw new JdpException("Broken JDP packet. Invalid entry length field.");
- }
-
- byte[] b = new byte[len];
- if (pkt.read(b) != len) {
- throw new JdpException("Broken JDP packet. Unable to read entry.");
- }
- return new String(b, "UTF-8");
-
- } catch (EOFException e) {
- throw e;
- } catch (UnsupportedEncodingException ex) {
- throw new JdpException("Broken JDP packet. Unable to decode entry.");
- } catch (IOException e) {
- throw new JdpException("Broken JDP packet. Unable to read entry.");
- }
-
-
- }
-
- /**
- * return packet content as a key/value map
- *
- * @return map containing packet entries pair of entries treated as
- * key,value
- * @throws IOException
- * @throws JdpException
- */
- public Map<String, String> getDiscoveryDataAsMap()
- throws JdpException {
- // return cached map if possible
- if (pmap != null) {
- return pmap;
- }
-
- String key = null, value = null;
-
- final Map<String, String> tmpMap = new HashMap<>();
- try {
- while (true) {
- key = getEntry();
- value = getEntry();
- tmpMap.put(key, value);
- }
- } catch (EOFException e) {
- // EOF reached on reading value, report broken packet
- // otherwise ignore it.
- if (value == null) {
- throw new JdpException("Broken JDP packet. Key without value." + key);
- }
- }
-
- pmap = Collections.unmodifiableMap(tmpMap);
- return pmap;
- }
-}
--- a/jdk/src/java.management/share/classes/sun/management/jdp/JdpPacketWriter.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-package sun.management.jdp;
-
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-/**
- * JdpPacketWriter responsible for writing a packet
- * <p>This class assembles a set of key/value pairs to valid JDP packet,
- * ready to be sent across a Net</p>
- */
-public final class JdpPacketWriter {
-
- private final ByteArrayOutputStream baos;
- private final DataOutputStream pkt;
-
- /**
- * Create a JDP packet, add mandatory magic and version headers
- *
- * @throws IOException
- */
- public JdpPacketWriter()
- throws IOException {
- baos = new ByteArrayOutputStream();
- pkt = new DataOutputStream(baos);
-
- pkt.writeInt(JdpGenericPacket.getMagic());
- pkt.writeShort(JdpGenericPacket.getVersion());
- }
-
- /**
- * Put string entry to packet
- *
- * @param entry - string to put (utf-8 encoded)
- * @throws IOException
- */
- public void addEntry(String entry)
- throws IOException {
- /* DataOutputStream.writeUTF() do essentially
- * the same as:
- * pkt.writeShort(entry.getBytes("UTF-8").length);
- * pkt.write(entry.getBytes("UTF-8"));
- */
- pkt.writeUTF(entry);
- }
-
- /**
- * Put key/value pair to packet
- *
- * @param key - key to put (utf-8 encoded)
- * @param val - value to put (utf-8 encoded)
- * @throws IOException
- */
- public void addEntry(String key, String val)
- throws IOException {
- /* Silently skip key if value is null.
- * We don't need to distinguish between key missing
- * and key has no value cases
- */
- if (val != null) {
- addEntry(key);
- addEntry(val);
- }
- }
-
- /**
- * Return assembled packet as a byte array
- *
- * @return packet bytes
- */
- public byte[] getPacketBytes() {
- return baos.toByteArray();
- }
-}
--- a/jdk/src/java.management/share/classes/sun/management/jdp/package-info.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-/**
- * Summary
- * -------
- *
- * Define a lightweight network protocol for discovering running and
- * manageable Java processes within a network subnet.
- *
- *
- * Description
- * -----------
- *
- * The protocol is lightweight multicast based, and works like a beacon,
- * broadcasting the JMXService URL needed to connect to the external JMX
- * agent if an application is started with appropriate parameters.
- *
- * The payload is structured like this:
- *
- * 4 bytes JDP magic (0xC0FFEE42)
- * 2 bytes JDP protocol version (1)
- * 2 bytes size of the next entry
- * x bytes next entry (UTF-8 encoded)
- * 2 bytes size of next entry
- * ... Rinse and repeat...
- *
- * The payload will be parsed as even entries being keys, odd entries being
- * values.
- *
- * The standard JDP packet contains four entries:
- *
- * - `DISCOVERABLE_SESSION_UUID` -- Unique id of the instance; this id changes every time
- * the discovery protocol starts and stops
- *
- * - `MAIN_CLASS` -- The value of the `sun.java.command` property
- *
- * - `JMX_SERVICE_URL` -- The URL to connect to the JMX agent
- *
- * - `INSTANCE_NAME` -- The user-provided name of the running instance
- *
- * The protocol sends packets to 224.0.23.178:7095 by default.
- *
- * The protocol uses system properties to control it's behaviour:
- * - `com.sun.management.jdp.port` -- override default port
- *
- * - `com.sun.management.jdp.address` -- override default address
- *
- * - `com.sun.management.jmxremote.autodiscovery` -- whether we should start autodiscovery or
- * not. Autodiscovery starts if and only if following conditions are met: (autodiscovery is
- * true OR (autodiscovery is not set AND jdp.port is set))
- *
- * - `com.sun.management.jdp.ttl` -- set ttl for broadcast packet, default is 1
- * - `com.sun.management.jdp.pause` -- set broadcast interval in seconds default is 5
- * - `com.sun.management.jdp.source_addr` -- an address of interface to use for broadcast
- */
-
-package sun.management.jdp;
--- a/jdk/src/java.management/share/classes/sun/management/jmxremote/ConnectorBootstrap.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1016 +0,0 @@
-/*
- * Copyright (c) 2003, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.management.jmxremote;
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Serializable;
-import java.lang.management.ManagementFactory;
-import java.net.InetAddress;
-import java.net.MalformedURLException;
-import java.net.Socket;
-import java.net.ServerSocket;
-import java.net.UnknownHostException;
-import java.rmi.NoSuchObjectException;
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-import java.rmi.registry.Registry;
-import java.rmi.server.RMIClientSocketFactory;
-import java.rmi.server.RMIServerSocketFactory;
-import java.rmi.server.RMISocketFactory;
-import java.rmi.server.RemoteObject;
-import java.rmi.server.UnicastRemoteObject;
-import java.security.KeyStore;
-import java.security.Principal;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.StringTokenizer;
-
-import javax.management.MBeanServer;
-import javax.management.remote.JMXAuthenticator;
-import javax.management.remote.JMXConnectorServer;
-import javax.management.remote.JMXConnectorServerFactory;
-import javax.management.remote.JMXServiceURL;
-import javax.management.remote.rmi.RMIConnectorServer;
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManagerFactory;
-import javax.rmi.ssl.SslRMIClientSocketFactory;
-import javax.rmi.ssl.SslRMIServerSocketFactory;
-import javax.security.auth.Subject;
-
-import com.sun.jmx.remote.internal.RMIExporter;
-import com.sun.jmx.remote.security.JMXPluggableAuthenticator;
-import com.sun.jmx.remote.util.ClassLogger;
-
-import sun.management.Agent;
-import sun.management.AgentConfigurationError;
-import static sun.management.AgentConfigurationError.*;
-import sun.management.ConnectorAddressLink;
-import sun.management.FileSystem;
-import sun.rmi.server.UnicastRef;
-import sun.rmi.server.UnicastServerRef;
-import sun.rmi.server.UnicastServerRef2;
-
-/**
- * This class initializes and starts the RMIConnectorServer for JSR 163
- * JMX Monitoring.
- **/
-public final class ConnectorBootstrap {
-
- /**
- * Default values for JMX configuration properties.
- **/
- public static interface DefaultValues {
-
- public static final String PORT = "0";
- public static final String CONFIG_FILE_NAME = "management.properties";
- public static final String USE_SSL = "true";
- public static final String USE_LOCAL_ONLY = "true";
- public static final String USE_REGISTRY_SSL = "false";
- public static final String USE_AUTHENTICATION = "true";
- public static final String PASSWORD_FILE_NAME = "jmxremote.password";
- public static final String ACCESS_FILE_NAME = "jmxremote.access";
- public static final String SSL_NEED_CLIENT_AUTH = "false";
- }
-
- /**
- * Names of JMX configuration properties.
- **/
- public static interface PropertyNames {
-
- public static final String PORT =
- "com.sun.management.jmxremote.port";
- public static final String HOST =
- "com.sun.management.jmxremote.host";
- public static final String RMI_PORT =
- "com.sun.management.jmxremote.rmi.port";
- public static final String CONFIG_FILE_NAME =
- "com.sun.management.config.file";
- public static final String USE_LOCAL_ONLY =
- "com.sun.management.jmxremote.local.only";
- public static final String USE_SSL =
- "com.sun.management.jmxremote.ssl";
- public static final String USE_REGISTRY_SSL =
- "com.sun.management.jmxremote.registry.ssl";
- public static final String USE_AUTHENTICATION =
- "com.sun.management.jmxremote.authenticate";
- public static final String PASSWORD_FILE_NAME =
- "com.sun.management.jmxremote.password.file";
- public static final String ACCESS_FILE_NAME =
- "com.sun.management.jmxremote.access.file";
- public static final String LOGIN_CONFIG_NAME =
- "com.sun.management.jmxremote.login.config";
- public static final String SSL_ENABLED_CIPHER_SUITES =
- "com.sun.management.jmxremote.ssl.enabled.cipher.suites";
- public static final String SSL_ENABLED_PROTOCOLS =
- "com.sun.management.jmxremote.ssl.enabled.protocols";
- public static final String SSL_NEED_CLIENT_AUTH =
- "com.sun.management.jmxremote.ssl.need.client.auth";
- public static final String SSL_CONFIG_FILE_NAME =
- "com.sun.management.jmxremote.ssl.config.file";
- }
-
- /**
- * JMXConnectorServer associated data.
- */
- private static class JMXConnectorServerData {
-
- public JMXConnectorServerData(
- JMXConnectorServer jmxConnectorServer,
- JMXServiceURL jmxRemoteURL) {
- this.jmxConnectorServer = jmxConnectorServer;
- this.jmxRemoteURL = jmxRemoteURL;
- }
- JMXConnectorServer jmxConnectorServer;
- JMXServiceURL jmxRemoteURL;
- }
-
- /**
- * <p>Prevents our RMI server objects from keeping the JVM alive.</p>
- *
- * <p>We use a private interface in Sun's JMX Remote API implementation
- * that allows us to specify how to export RMI objects. We do so using
- * UnicastServerRef, a class in Sun's RMI implementation. This is all
- * non-portable, of course, so this is only valid because we are inside
- * Sun's JRE.</p>
- *
- * <p>Objects are exported using {@link
- * UnicastServerRef#exportObject(Remote, Object, boolean)}. The
- * boolean parameter is called <code>permanent</code> and means
- * both that the object is not eligible for Distributed Garbage
- * Collection, and that its continued existence will not prevent
- * the JVM from exiting. It is the latter semantics we want (we
- * already have the former because of the way the JMX Remote API
- * works). Hence the somewhat misleading name of this class.</p>
- */
- private static class PermanentExporter implements RMIExporter {
-
- public Remote exportObject(Remote obj,
- int port,
- RMIClientSocketFactory csf,
- RMIServerSocketFactory ssf)
- throws RemoteException {
-
- synchronized (this) {
- if (firstExported == null) {
- firstExported = obj;
- }
- }
-
- final UnicastServerRef ref;
- if (csf == null && ssf == null) {
- ref = new UnicastServerRef(port);
- } else {
- ref = new UnicastServerRef2(port, csf, ssf);
- }
- return ref.exportObject(obj, null, true);
- }
-
- // Nothing special to be done for this case
- public boolean unexportObject(Remote obj, boolean force)
- throws NoSuchObjectException {
- return UnicastRemoteObject.unexportObject(obj, force);
- }
- Remote firstExported;
- }
-
- /**
- * This JMXAuthenticator wraps the JMXPluggableAuthenticator and verifies
- * that at least one of the principal names contained in the authenticated
- * Subject is present in the access file.
- */
- private static class AccessFileCheckerAuthenticator
- implements JMXAuthenticator {
-
- public AccessFileCheckerAuthenticator(Map<String, Object> env) throws IOException {
- environment = env;
- accessFile = (String) env.get("jmx.remote.x.access.file");
- properties = propertiesFromFile(accessFile);
- }
-
- public Subject authenticate(Object credentials) {
- final JMXAuthenticator authenticator =
- new JMXPluggableAuthenticator(environment);
- final Subject subject = authenticator.authenticate(credentials);
- checkAccessFileEntries(subject);
- return subject;
- }
-
- private void checkAccessFileEntries(Subject subject) {
- if (subject == null) {
- throw new SecurityException(
- "Access denied! No matching entries found in " +
- "the access file [" + accessFile + "] as the " +
- "authenticated Subject is null");
- }
- final Set<Principal> principals = subject.getPrincipals();
- for (Principal p1: principals) {
- if (properties.containsKey(p1.getName())) {
- return;
- }
- }
-
- final Set<String> principalsStr = new HashSet<>();
- for (Principal p2: principals) {
- principalsStr.add(p2.getName());
- }
- throw new SecurityException(
- "Access denied! No entries found in the access file [" +
- accessFile + "] for any of the authenticated identities " +
- principalsStr);
- }
-
- private static Properties propertiesFromFile(String fname)
- throws IOException {
- Properties p = new Properties();
- if (fname == null) {
- return p;
- }
- try (FileInputStream fin = new FileInputStream(fname)) {
- p.load(fin);
- }
- return p;
- }
- private final Map<String, Object> environment;
- private final Properties properties;
- private final String accessFile;
- }
-
- // The variable below is here to support stop functionality
- // It would be overriten if you call startRemoteCommectionServer second
- // time. It's OK for now as logic in Agent.java forbids mutiple agents
- private static Registry registry = null;
-
- public static void unexportRegistry() {
- // Remove the entry from registry
- try {
- if (registry != null) {
- UnicastRemoteObject.unexportObject(registry, true);
- registry = null;
- }
- } catch(NoSuchObjectException ex) {
- // This exception can appears only if we attempt
- // to unexportRegistry second time. So it's safe
- // to ignore it without additional messages.
- }
- }
-
- /**
- * Initializes and starts the JMX Connector Server.
- * If the com.sun.management.jmxremote.port property is not defined,
- * simply return. Otherwise, attempts to load the config file, and
- * then calls {@link #startRemoteConnectorServer
- * (java.lang.String, java.util.Properties)}.
- *
- * This method is used by some jtreg tests.
- **/
- public static synchronized JMXConnectorServer initialize() {
-
- // Load a new management properties
- final Properties props = Agent.loadManagementProperties();
- if (props == null) {
- return null;
- }
-
- final String portStr = props.getProperty(PropertyNames.PORT);
- return startRemoteConnectorServer(portStr, props);
- }
-
- /**
- * This method is used by some jtreg tests.
- *
- * @see #startRemoteConnectorServer
- * (String portStr, Properties props)
- */
- public static synchronized JMXConnectorServer initialize(String portStr, Properties props) {
- return startRemoteConnectorServer(portStr, props);
- }
-
- /**
- * Initializes and starts a JMX Connector Server for remote
- * monitoring and management.
- **/
- public static synchronized JMXConnectorServer startRemoteConnectorServer(String portStr, Properties props) {
-
- // Get port number
- final int port;
- try {
- port = Integer.parseInt(portStr);
- } catch (NumberFormatException x) {
- throw new AgentConfigurationError(INVALID_JMXREMOTE_PORT, x, portStr);
- }
- if (port < 0) {
- throw new AgentConfigurationError(INVALID_JMXREMOTE_PORT, portStr);
- }
-
- // User can specify a port to be used to export rmi object,
- // in order to simplify firewall rules
- // if port is not specified random one will be allocated.
- int rmiPort = 0;
- String rmiPortStr = props.getProperty(PropertyNames.RMI_PORT);
- try {
- if (rmiPortStr != null) {
- rmiPort = Integer.parseInt(rmiPortStr);
- }
- } catch (NumberFormatException x) {
- throw new AgentConfigurationError(INVALID_JMXREMOTE_RMI_PORT, x, rmiPortStr);
- }
- if (rmiPort < 0) {
- throw new AgentConfigurationError(INVALID_JMXREMOTE_RMI_PORT, rmiPortStr);
- }
-
- // Do we use authentication?
- final String useAuthenticationStr =
- props.getProperty(PropertyNames.USE_AUTHENTICATION,
- DefaultValues.USE_AUTHENTICATION);
- final boolean useAuthentication =
- Boolean.valueOf(useAuthenticationStr).booleanValue();
-
- // Do we use SSL?
- final String useSslStr =
- props.getProperty(PropertyNames.USE_SSL,
- DefaultValues.USE_SSL);
- final boolean useSsl =
- Boolean.valueOf(useSslStr).booleanValue();
-
- // Do we use RMI Registry SSL?
- final String useRegistrySslStr =
- props.getProperty(PropertyNames.USE_REGISTRY_SSL,
- DefaultValues.USE_REGISTRY_SSL);
- final boolean useRegistrySsl =
- Boolean.valueOf(useRegistrySslStr).booleanValue();
-
- final String enabledCipherSuites =
- props.getProperty(PropertyNames.SSL_ENABLED_CIPHER_SUITES);
- String enabledCipherSuitesList[] = null;
- if (enabledCipherSuites != null) {
- StringTokenizer st = new StringTokenizer(enabledCipherSuites, ",");
- int tokens = st.countTokens();
- enabledCipherSuitesList = new String[tokens];
- for (int i = 0; i < tokens; i++) {
- enabledCipherSuitesList[i] = st.nextToken();
- }
- }
-
- final String enabledProtocols =
- props.getProperty(PropertyNames.SSL_ENABLED_PROTOCOLS);
- String enabledProtocolsList[] = null;
- if (enabledProtocols != null) {
- StringTokenizer st = new StringTokenizer(enabledProtocols, ",");
- int tokens = st.countTokens();
- enabledProtocolsList = new String[tokens];
- for (int i = 0; i < tokens; i++) {
- enabledProtocolsList[i] = st.nextToken();
- }
- }
-
- final String sslNeedClientAuthStr =
- props.getProperty(PropertyNames.SSL_NEED_CLIENT_AUTH,
- DefaultValues.SSL_NEED_CLIENT_AUTH);
- final boolean sslNeedClientAuth =
- Boolean.valueOf(sslNeedClientAuthStr).booleanValue();
-
- // Read SSL config file name
- final String sslConfigFileName =
- props.getProperty(PropertyNames.SSL_CONFIG_FILE_NAME);
-
- String loginConfigName = null;
- String passwordFileName = null;
- String accessFileName = null;
-
- // Initialize settings when authentication is active
- if (useAuthentication) {
-
- // Get non-default login configuration
- loginConfigName =
- props.getProperty(PropertyNames.LOGIN_CONFIG_NAME);
-
- if (loginConfigName == null) {
- // Get password file
- passwordFileName =
- props.getProperty(PropertyNames.PASSWORD_FILE_NAME,
- getDefaultFileName(DefaultValues.PASSWORD_FILE_NAME));
- checkPasswordFile(passwordFileName);
- }
-
- // Get access file
- accessFileName = props.getProperty(PropertyNames.ACCESS_FILE_NAME,
- getDefaultFileName(DefaultValues.ACCESS_FILE_NAME));
- checkAccessFile(accessFileName);
- }
-
- final String bindAddress =
- props.getProperty(PropertyNames.HOST);
-
- if (log.debugOn()) {
- log.debug("startRemoteConnectorServer",
- Agent.getText("jmxremote.ConnectorBootstrap.starting") +
- "\n\t" + PropertyNames.PORT + "=" + port +
- (bindAddress == null ? "" : "\n\t" + PropertyNames.HOST + "=" + bindAddress) +
- "\n\t" + PropertyNames.RMI_PORT + "=" + rmiPort +
- "\n\t" + PropertyNames.USE_SSL + "=" + useSsl +
- "\n\t" + PropertyNames.USE_REGISTRY_SSL + "=" + useRegistrySsl +
- "\n\t" + PropertyNames.SSL_CONFIG_FILE_NAME + "=" + sslConfigFileName +
- "\n\t" + PropertyNames.SSL_ENABLED_CIPHER_SUITES + "=" +
- enabledCipherSuites +
- "\n\t" + PropertyNames.SSL_ENABLED_PROTOCOLS + "=" +
- enabledProtocols +
- "\n\t" + PropertyNames.SSL_NEED_CLIENT_AUTH + "=" +
- sslNeedClientAuth +
- "\n\t" + PropertyNames.USE_AUTHENTICATION + "=" +
- useAuthentication +
- (useAuthentication ? (loginConfigName == null ? ("\n\t" + PropertyNames.PASSWORD_FILE_NAME + "=" +
- passwordFileName) : ("\n\t" + PropertyNames.LOGIN_CONFIG_NAME + "=" +
- loginConfigName)) : "\n\t" +
- Agent.getText("jmxremote.ConnectorBootstrap.noAuthentication")) +
- (useAuthentication ? ("\n\t" + PropertyNames.ACCESS_FILE_NAME + "=" +
- accessFileName) : "") +
- "");
- }
-
- final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
- JMXConnectorServer cs = null;
- JMXServiceURL url = null;
- try {
- final JMXConnectorServerData data = exportMBeanServer(
- mbs, port, rmiPort, useSsl, useRegistrySsl,
- sslConfigFileName, enabledCipherSuitesList,
- enabledProtocolsList, sslNeedClientAuth,
- useAuthentication, loginConfigName,
- passwordFileName, accessFileName, bindAddress);
- cs = data.jmxConnectorServer;
- url = data.jmxRemoteURL;
- log.config("startRemoteConnectorServer",
- Agent.getText("jmxremote.ConnectorBootstrap.ready",
- url.toString()));
- } catch (Exception e) {
- throw new AgentConfigurationError(AGENT_EXCEPTION, e, e.toString());
- }
- try {
- // Export remote connector address and associated configuration
- // properties to the instrumentation buffer.
- Map<String, String> properties = new HashMap<>();
- properties.put("remoteAddress", url.toString());
- properties.put("authenticate", useAuthenticationStr);
- properties.put("ssl", useSslStr);
- properties.put("sslRegistry", useRegistrySslStr);
- properties.put("sslNeedClientAuth", sslNeedClientAuthStr);
- ConnectorAddressLink.exportRemote(properties);
- } catch (Exception e) {
- // Remote connector server started but unable to export remote
- // connector address and associated configuration properties to
- // the instrumentation buffer - non-fatal error.
- log.debug("startRemoteConnectorServer", e);
- }
- return cs;
- }
-
- /*
- * Creates and starts a RMI Connector Server for "local" monitoring
- * and management.
- */
- public static JMXConnectorServer startLocalConnectorServer() {
- // Ensure cryptographically strong random number generater used
- // to choose the object number - see java.rmi.server.ObjID
- System.setProperty("java.rmi.server.randomIDs", "true");
-
- // This RMI server should not keep the VM alive
- Map<String, Object> env = new HashMap<>();
- env.put(RMIExporter.EXPORTER_ATTRIBUTE, new PermanentExporter());
- env.put(RMIConnectorServer.CREDENTIAL_TYPES, new String[]{
- String[].class.getName(), String.class.getName()
- });
-
- // The local connector server need only be available via the
- // loopback connection.
- String localhost = "localhost";
- InetAddress lh = null;
- try {
- lh = InetAddress.getByName(localhost);
- localhost = lh.getHostAddress();
- } catch (UnknownHostException x) {
- }
-
- // localhost unknown or (somehow) didn't resolve to
- // a loopback address.
- if (lh == null || !lh.isLoopbackAddress()) {
- localhost = "127.0.0.1";
- }
-
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
- try {
- JMXServiceURL url = new JMXServiceURL("rmi", localhost, 0);
- // Do we accept connections from local interfaces only?
- Properties props = Agent.getManagementProperties();
- if (props == null) {
- props = new Properties();
- }
- String useLocalOnlyStr = props.getProperty(
- PropertyNames.USE_LOCAL_ONLY, DefaultValues.USE_LOCAL_ONLY);
- boolean useLocalOnly = Boolean.valueOf(useLocalOnlyStr).booleanValue();
- if (useLocalOnly) {
- env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE,
- new LocalRMIServerSocketFactory());
- }
- JMXConnectorServer server =
- JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
- server.start();
- return server;
- } catch (Exception e) {
- throw new AgentConfigurationError(AGENT_EXCEPTION, e, e.toString());
- }
- }
-
- private static void checkPasswordFile(String passwordFileName) {
- if (passwordFileName == null || passwordFileName.length() == 0) {
- throw new AgentConfigurationError(PASSWORD_FILE_NOT_SET);
- }
- File file = new File(passwordFileName);
- if (!file.exists()) {
- throw new AgentConfigurationError(PASSWORD_FILE_NOT_FOUND, passwordFileName);
- }
-
- if (!file.canRead()) {
- throw new AgentConfigurationError(PASSWORD_FILE_NOT_READABLE, passwordFileName);
- }
-
- FileSystem fs = FileSystem.open();
- try {
- if (fs.supportsFileSecurity(file)) {
- if (!fs.isAccessUserOnly(file)) {
- final String msg = Agent.getText("jmxremote.ConnectorBootstrap.password.readonly",
- passwordFileName);
- log.config("startRemoteConnectorServer", msg);
- throw new AgentConfigurationError(PASSWORD_FILE_ACCESS_NOT_RESTRICTED,
- passwordFileName);
- }
- }
- } catch (IOException e) {
- throw new AgentConfigurationError(PASSWORD_FILE_READ_FAILED,
- e, passwordFileName);
- }
- }
-
- private static void checkAccessFile(String accessFileName) {
- if (accessFileName == null || accessFileName.length() == 0) {
- throw new AgentConfigurationError(ACCESS_FILE_NOT_SET);
- }
- File file = new File(accessFileName);
- if (!file.exists()) {
- throw new AgentConfigurationError(ACCESS_FILE_NOT_FOUND, accessFileName);
- }
-
- if (!file.canRead()) {
- throw new AgentConfigurationError(ACCESS_FILE_NOT_READABLE, accessFileName);
- }
- }
-
- private static void checkRestrictedFile(String restrictedFileName) {
- if (restrictedFileName == null || restrictedFileName.length() == 0) {
- throw new AgentConfigurationError(FILE_NOT_SET);
- }
- File file = new File(restrictedFileName);
- if (!file.exists()) {
- throw new AgentConfigurationError(FILE_NOT_FOUND, restrictedFileName);
- }
- if (!file.canRead()) {
- throw new AgentConfigurationError(FILE_NOT_READABLE, restrictedFileName);
- }
- FileSystem fs = FileSystem.open();
- try {
- if (fs.supportsFileSecurity(file)) {
- if (!fs.isAccessUserOnly(file)) {
- final String msg = Agent.getText(
- "jmxremote.ConnectorBootstrap.file.readonly",
- restrictedFileName);
- log.config("startRemoteConnectorServer", msg);
- throw new AgentConfigurationError(
- FILE_ACCESS_NOT_RESTRICTED, restrictedFileName);
- }
- }
- } catch (IOException e) {
- throw new AgentConfigurationError(
- FILE_READ_FAILED, e, restrictedFileName);
- }
- }
-
- /**
- * Compute the full path name for a default file.
- * @param basename basename (with extension) of the default file.
- * @return ${JRE}/conf/management/${basename}
- **/
- private static String getDefaultFileName(String basename) {
- final String fileSeparator = File.separator;
- return System.getProperty("java.home") + fileSeparator + "conf" +
- fileSeparator + "management" + fileSeparator +
- basename;
- }
-
- private static SslRMIServerSocketFactory createSslRMIServerSocketFactory(
- String sslConfigFileName,
- String[] enabledCipherSuites,
- String[] enabledProtocols,
- boolean sslNeedClientAuth,
- String bindAddress) {
- if (sslConfigFileName == null) {
- return new HostAwareSslSocketFactory(
- enabledCipherSuites,
- enabledProtocols,
- sslNeedClientAuth, bindAddress);
- } else {
- checkRestrictedFile(sslConfigFileName);
- try {
- // Load the SSL keystore properties from the config file
- Properties p = new Properties();
- try (InputStream in = new FileInputStream(sslConfigFileName)) {
- BufferedInputStream bin = new BufferedInputStream(in);
- p.load(bin);
- }
- String keyStore =
- p.getProperty("javax.net.ssl.keyStore");
- String keyStorePassword =
- p.getProperty("javax.net.ssl.keyStorePassword", "");
- String trustStore =
- p.getProperty("javax.net.ssl.trustStore");
- String trustStorePassword =
- p.getProperty("javax.net.ssl.trustStorePassword", "");
-
- char[] keyStorePasswd = null;
- if (keyStorePassword.length() != 0) {
- keyStorePasswd = keyStorePassword.toCharArray();
- }
-
- char[] trustStorePasswd = null;
- if (trustStorePassword.length() != 0) {
- trustStorePasswd = trustStorePassword.toCharArray();
- }
-
- KeyStore ks = null;
- if (keyStore != null) {
- ks = KeyStore.getInstance(KeyStore.getDefaultType());
- try (FileInputStream ksfis = new FileInputStream(keyStore)) {
- ks.load(ksfis, keyStorePasswd);
- }
- }
- KeyManagerFactory kmf = KeyManagerFactory.getInstance(
- KeyManagerFactory.getDefaultAlgorithm());
- kmf.init(ks, keyStorePasswd);
-
- KeyStore ts = null;
- if (trustStore != null) {
- ts = KeyStore.getInstance(KeyStore.getDefaultType());
- try (FileInputStream tsfis = new FileInputStream(trustStore)) {
- ts.load(tsfis, trustStorePasswd);
- }
- }
- TrustManagerFactory tmf = TrustManagerFactory.getInstance(
- TrustManagerFactory.getDefaultAlgorithm());
- tmf.init(ts);
-
- SSLContext ctx = SSLContext.getInstance("SSL");
- ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
-
- return new HostAwareSslSocketFactory(
- ctx,
- enabledCipherSuites,
- enabledProtocols,
- sslNeedClientAuth, bindAddress);
- } catch (Exception e) {
- throw new AgentConfigurationError(AGENT_EXCEPTION, e, e.toString());
- }
- }
- }
-
- private static JMXConnectorServerData exportMBeanServer(
- MBeanServer mbs,
- int port,
- int rmiPort,
- boolean useSsl,
- boolean useRegistrySsl,
- String sslConfigFileName,
- String[] enabledCipherSuites,
- String[] enabledProtocols,
- boolean sslNeedClientAuth,
- boolean useAuthentication,
- String loginConfigName,
- String passwordFileName,
- String accessFileName,
- String bindAddress)
- throws IOException, MalformedURLException {
-
- /* Make sure we use non-guessable RMI object IDs. Otherwise
- * attackers could hijack open connections by guessing their
- * IDs. */
- System.setProperty("java.rmi.server.randomIDs", "true");
-
- JMXServiceURL url = new JMXServiceURL("rmi", bindAddress, rmiPort);
-
- Map<String, Object> env = new HashMap<>();
-
- PermanentExporter exporter = new PermanentExporter();
-
- env.put(RMIExporter.EXPORTER_ATTRIBUTE, exporter);
- env.put(RMIConnectorServer.CREDENTIAL_TYPES, new String[]{
- String[].class.getName(), String.class.getName()
- });
-
- boolean useSocketFactory = bindAddress != null && !useSsl;
-
- if (useAuthentication) {
- if (loginConfigName != null) {
- env.put("jmx.remote.x.login.config", loginConfigName);
- }
- if (passwordFileName != null) {
- env.put("jmx.remote.x.password.file", passwordFileName);
- }
-
- env.put("jmx.remote.x.access.file", accessFileName);
-
- if (env.get("jmx.remote.x.password.file") != null ||
- env.get("jmx.remote.x.login.config") != null) {
- env.put(JMXConnectorServer.AUTHENTICATOR,
- new AccessFileCheckerAuthenticator(env));
- }
- }
-
- RMIClientSocketFactory csf = null;
- RMIServerSocketFactory ssf = null;
-
- if (useSsl || useRegistrySsl) {
- csf = new SslRMIClientSocketFactory();
- ssf = createSslRMIServerSocketFactory(
- sslConfigFileName, enabledCipherSuites,
- enabledProtocols, sslNeedClientAuth, bindAddress);
- }
-
- if (useSsl) {
- env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE,
- csf);
- env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE,
- ssf);
- }
-
- if (useSocketFactory) {
- ssf = new HostAwareSocketFactory(bindAddress);
- env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE,
- ssf);
- }
-
- JMXConnectorServer connServer = null;
- try {
- connServer =
- JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
- connServer.start();
- } catch (IOException e) {
- if (connServer == null || connServer.getAddress() == null) {
- throw new AgentConfigurationError(CONNECTOR_SERVER_IO_ERROR,
- e, url.toString());
- } else {
- throw new AgentConfigurationError(CONNECTOR_SERVER_IO_ERROR,
- e, connServer.getAddress().toString());
- }
- }
-
- if (useRegistrySsl) {
- registry =
- new SingleEntryRegistry(port, csf, ssf,
- "jmxrmi", exporter.firstExported);
- } else if (useSocketFactory) {
- registry =
- new SingleEntryRegistry(port, csf, ssf,
- "jmxrmi", exporter.firstExported);
- } else {
- registry =
- new SingleEntryRegistry(port,
- "jmxrmi", exporter.firstExported);
- }
-
-
- int registryPort =
- ((UnicastRef) ((RemoteObject) registry).getRef()).getLiveRef().getPort();
- String jmxUrlStr = String.format("service:jmx:rmi:///jndi/rmi://%s:%d/jmxrmi",
- url.getHost(), registryPort);
- JMXServiceURL remoteURL = new JMXServiceURL(jmxUrlStr);
-
- /* Our exporter remembers the first object it was asked to
- export, which will be an RMIServerImpl appropriate for
- publication in our special registry. We could
- alternatively have constructed the RMIServerImpl explicitly
- and then constructed an RMIConnectorServer passing it as a
- parameter, but that's quite a bit more verbose and pulls in
- lots of knowledge of the RMI connector. */
-
- return new JMXConnectorServerData(connServer, remoteURL);
- }
-
- /**
- * This class cannot be instantiated.
- **/
- private ConnectorBootstrap() {
- }
-
- private static final ClassLogger log =
- new ClassLogger(ConnectorBootstrap.class.getPackage().getName(),
- "ConnectorBootstrap");
-
- private static class HostAwareSocketFactory implements RMIServerSocketFactory {
-
- private final String bindAddress;
-
- private HostAwareSocketFactory(String bindAddress) {
- this.bindAddress = bindAddress;
- }
-
- @Override
- public ServerSocket createServerSocket(int port) throws IOException {
- if (bindAddress == null) {
- return new ServerSocket(port);
- } else {
- try {
- InetAddress addr = InetAddress.getByName(bindAddress);
- return new ServerSocket(port, 0, addr);
- } catch (UnknownHostException e) {
- return new ServerSocket(port);
- }
- }
- }
- }
-
- private static class HostAwareSslSocketFactory extends SslRMIServerSocketFactory {
-
- private final String bindAddress;
- private final String[] enabledCipherSuites;
- private final String[] enabledProtocols;
- private final boolean needClientAuth;
- private final SSLContext context;
-
- private HostAwareSslSocketFactory(String[] enabledCipherSuites,
- String[] enabledProtocols,
- boolean sslNeedClientAuth,
- String bindAddress) throws IllegalArgumentException {
- this(null, enabledCipherSuites, enabledProtocols, sslNeedClientAuth, bindAddress);
- }
-
- private HostAwareSslSocketFactory(SSLContext ctx,
- String[] enabledCipherSuites,
- String[] enabledProtocols,
- boolean sslNeedClientAuth,
- String bindAddress) throws IllegalArgumentException {
- this.context = ctx;
- this.bindAddress = bindAddress;
- this.enabledProtocols = enabledProtocols;
- this.enabledCipherSuites = enabledCipherSuites;
- this.needClientAuth = sslNeedClientAuth;
- checkValues(ctx, enabledCipherSuites, enabledProtocols);
- }
-
- @Override
- public ServerSocket createServerSocket(int port) throws IOException {
- if (bindAddress != null) {
- try {
- InetAddress addr = InetAddress.getByName(bindAddress);
- return new SslServerSocket(port, 0, addr, context,
- enabledCipherSuites, enabledProtocols, needClientAuth);
- } catch (UnknownHostException e) {
- return new SslServerSocket(port, context,
- enabledCipherSuites, enabledProtocols, needClientAuth);
- }
- } else {
- return new SslServerSocket(port, context,
- enabledCipherSuites, enabledProtocols, needClientAuth);
- }
- }
-
- private static void checkValues(SSLContext context,
- String[] enabledCipherSuites,
- String[] enabledProtocols) throws IllegalArgumentException {
- // Force the initialization of the default at construction time,
- // rather than delaying it to the first time createServerSocket()
- // is called.
- //
- final SSLSocketFactory sslSocketFactory =
- context == null ?
- (SSLSocketFactory)SSLSocketFactory.getDefault() : context.getSocketFactory();
- SSLSocket sslSocket = null;
- if (enabledCipherSuites != null || enabledProtocols != null) {
- try {
- sslSocket = (SSLSocket) sslSocketFactory.createSocket();
- } catch (Exception e) {
- final String msg = "Unable to check if the cipher suites " +
- "and protocols to enable are supported";
- throw (IllegalArgumentException)
- new IllegalArgumentException(msg).initCause(e);
- }
- }
-
- // Check if all the cipher suites and protocol versions to enable
- // are supported by the underlying SSL/TLS implementation and if
- // true create lists from arrays.
- //
- if (enabledCipherSuites != null) {
- sslSocket.setEnabledCipherSuites(enabledCipherSuites);
- }
- if (enabledProtocols != null) {
- sslSocket.setEnabledProtocols(enabledProtocols);
- }
- }
- }
-
- private static class SslServerSocket extends ServerSocket {
-
- private static SSLSocketFactory defaultSSLSocketFactory;
- private final String[] enabledCipherSuites;
- private final String[] enabledProtocols;
- private final boolean needClientAuth;
- private final SSLContext context;
-
- private SslServerSocket(int port,
- SSLContext ctx,
- String[] enabledCipherSuites,
- String[] enabledProtocols,
- boolean needClientAuth) throws IOException {
- super(port);
- this.enabledProtocols = enabledProtocols;
- this.enabledCipherSuites = enabledCipherSuites;
- this.needClientAuth = needClientAuth;
- this.context = ctx;
- }
-
- private SslServerSocket(int port,
- int backlog,
- InetAddress bindAddr,
- SSLContext ctx,
- String[] enabledCipherSuites,
- String[] enabledProtocols,
- boolean needClientAuth) throws IOException {
- super(port, backlog, bindAddr);
- this.enabledProtocols = enabledProtocols;
- this.enabledCipherSuites = enabledCipherSuites;
- this.needClientAuth = needClientAuth;
- this.context = ctx;
- }
-
- @Override
- public Socket accept() throws IOException {
- final SSLSocketFactory sslSocketFactory =
- context == null ?
- getDefaultSSLSocketFactory() : context.getSocketFactory();
- Socket socket = super.accept();
- SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(
- socket, socket.getInetAddress().getHostName(),
- socket.getPort(), true);
- sslSocket.setUseClientMode(false);
- if (enabledCipherSuites != null) {
- sslSocket.setEnabledCipherSuites(enabledCipherSuites);
- }
- if (enabledProtocols != null) {
- sslSocket.setEnabledProtocols(enabledProtocols);
- }
- sslSocket.setNeedClientAuth(needClientAuth);
- return sslSocket;
- }
-
- private static synchronized SSLSocketFactory getDefaultSSLSocketFactory() {
- if (defaultSSLSocketFactory == null) {
- defaultSSLSocketFactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
- return defaultSSLSocketFactory;
- } else {
- return defaultSSLSocketFactory;
- }
- }
-
- }
-}
--- a/jdk/src/java.management/share/classes/sun/management/jmxremote/LocalRMIServerSocketFactory.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*
- * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.management.jmxremote;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.SocketException;
-import java.rmi.server.RMIServerSocketFactory;
-import java.util.Enumeration;
-
-/**
- * This RMI server socket factory creates server sockets that
- * will only accept connection requests from clients running
- * on the host where the RMI remote objects have been exported.
- */
-public final class LocalRMIServerSocketFactory implements RMIServerSocketFactory {
- /**
- * Creates a server socket that only accepts connection requests from
- * clients running on the host where the RMI remote objects have been
- * exported.
- */
- public ServerSocket createServerSocket(int port) throws IOException {
- return new ServerSocket(port) {
- @Override
- public Socket accept() throws IOException {
- final Socket socket = super.accept();
- final InetAddress remoteAddr = socket.getInetAddress();
- final String msg = "The server sockets created using the " +
- "LocalRMIServerSocketFactory only accept connections " +
- "from clients running on the host where the RMI " +
- "remote objects have been exported.";
-
- if (remoteAddr == null) {
- // Though unlikeky, the socket could be already
- // closed... Send a more detailed message in
- // this case. Also avoid throwing NullPointerExceptiion
- //
- String details = "";
- if (socket.isClosed()) {
- details = " Socket is closed.";
- } else if (!socket.isConnected()) {
- details = " Socket is not connected";
- }
- try {
- socket.close();
- } catch (Exception ok) {
- // ok - this is just cleanup before throwing detailed
- // exception.
- }
- throw new IOException(msg +
- " Couldn't determine client address." +
- details);
- } else if (remoteAddr.isLoopbackAddress()) {
- // local address: accept the connection.
- return socket;
- }
- // Retrieve all the network interfaces on this host.
- Enumeration<NetworkInterface> nis;
- try {
- nis = NetworkInterface.getNetworkInterfaces();
- } catch (SocketException e) {
- try {
- socket.close();
- } catch (IOException ioe) {
- // Ignore...
- }
- throw new IOException(msg, e);
- }
- // Walk through the network interfaces to see
- // if any of them matches the client's address.
- // If true, then the client's address is local.
- while (nis.hasMoreElements()) {
- NetworkInterface ni = nis.nextElement();
- Enumeration<InetAddress> addrs = ni.getInetAddresses();
- while (addrs.hasMoreElements()) {
- InetAddress localAddr = addrs.nextElement();
- if (localAddr.equals(remoteAddr)) {
- return socket;
- }
- }
- }
- // The client's address is remote so refuse the connection.
- try {
- socket.close();
- } catch (IOException ioe) {
- // Ignore...
- }
- throw new IOException(msg);
- }
- };
- }
-
- /**
- * Two LocalRMIServerSocketFactory objects
- * are equal if they are of the same type.
- */
- @Override
- public boolean equals(Object obj) {
- return (obj instanceof LocalRMIServerSocketFactory);
- }
-
- /**
- * Returns a hash code value for this LocalRMIServerSocketFactory.
- */
- @Override
- public int hashCode() {
- return getClass().hashCode();
- }
-}
--- a/jdk/src/java.management/share/classes/sun/management/jmxremote/SingleEntryRegistry.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2003, 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.
- */
-
-/*
- * @author Sun Microsystems, Inc.
- * @build @BUILD_TAG_PLACEHOLDER@
- *
- * @COPYRIGHT_MINI_LEGAL_NOTICE_PLACEHOLDER@
- */
-
-package sun.management.jmxremote;
-
-import java.rmi.AccessException;
-import java.rmi.NotBoundException;
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-import java.rmi.server.RMIClientSocketFactory;
-import java.rmi.server.RMIServerSocketFactory;
-
-import sun.rmi.registry.RegistryImpl;
-
-/** A Registry that consists of a single entry that never changes. */
-public class SingleEntryRegistry extends RegistryImpl {
- SingleEntryRegistry(int port, String name, Remote object)
- throws RemoteException {
- super(port);
- this.name = name;
- this.object = object;
- }
-
- SingleEntryRegistry(int port,
- RMIClientSocketFactory csf,
- RMIServerSocketFactory ssf,
- String name,
- Remote object)
- throws RemoteException {
- super(port, csf, ssf);
- this.name = name;
- this.object = object;
- }
-
- public String[] list() {
- return new String[] {name};
- }
-
- public Remote lookup(String name) throws NotBoundException {
- if (name.equals(this.name))
- return object;
- throw new NotBoundException("Not bound: \"" + name + "\" (only " +
- "bound name is \"" + this.name + "\")");
- }
-
- public void bind(String name, Remote obj) throws AccessException {
- throw new AccessException("Cannot modify this registry");
- }
-
- public void rebind(String name, Remote obj) throws AccessException {
- throw new AccessException("Cannot modify this registry");
- }
-
- public void unbind(String name) throws AccessException {
- throw new AccessException("Cannot modify this registry");
- }
-
- private final String name;
- private final Remote object;
-
- private static final long serialVersionUID = -4897238949499730950L;
-}
--- a/jdk/src/java.management/share/classes/sun/management/jmxremote/package.html Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<html>
-<head>
-<!--
-
- Copyright (c) 2003, 2007, 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.
-
--->
-
-</head>
-<body bgcolor="white">
-
-Provides classes that make it possible to create a JMX RMI Connector Server
-at bootstrap for the JSR 163 instrumentation.
-
-@since 1.5
-</body>
-</html>
--- a/jdk/src/java.management/share/classes/sun/management/resources/agent.properties Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-#
-# Copyright (c) 2004, 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. 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.
-#
-
-agent.err.error = Error
-agent.err.exception = Exception thrown by the agent
-agent.err.warning = Warning
-
-agent.err.configfile.notfound = Config file not found
-agent.err.configfile.failed = Failed in reading the config file
-agent.err.configfile.closed.failed = Failed in closing the config file
-agent.err.configfile.access.denied = Access to the config file is denied
-
-agent.err.exportaddress.failed = Export of JMX connector address to instrumentation buffer failed
-
-agent.err.agentclass.notfound = Management agent class not found
-agent.err.agentclass.failed = Management agent class failed
-agent.err.premain.notfound = premain(String) does not exist in agent class
-agent.err.agentclass.access.denied = Access to premain(String) is denied
-agent.err.invalid.agentclass = Invalid com.sun.management.agent.class property value
-agent.err.invalid.state = Invalid agent state: {0}
-agent.err.invalid.jmxremote.port = Invalid com.sun.management.jmxremote.port number
-agent.err.invalid.jmxremote.rmi.port = Invalid com.sun.management.jmxremote.rmi.port number
-
-agent.err.file.not.set = File not specified
-agent.err.file.not.readable = File not readable
-agent.err.file.read.failed = Failed in reading the file
-agent.err.file.not.found = File not found
-agent.err.file.access.not.restricted = File read access must be restricted
-
-agent.err.password.file.notset = Password file is not specified but com.sun.management.jmxremote.authenticate=true
-agent.err.password.file.not.readable = Password file not readable
-agent.err.password.file.read.failed = Failed in reading the password file
-agent.err.password.file.notfound = Password file not found
-agent.err.password.file.access.notrestricted = Password file read access must be restricted
-
-agent.err.access.file.notset = Access file is not specified but com.sun.management.jmxremote.authenticate=true
-agent.err.access.file.not.readable = Access file not readable
-agent.err.access.file.read.failed = Failed in reading the access file
-agent.err.access.file.notfound = Access file not found
-
-agent.err.connector.server.io.error = JMX connector server communication error
-
-agent.err.invalid.option = Invalid option specified
-
-jmxremote.ConnectorBootstrap.starting = Starting JMX Connector Server:
-jmxremote.ConnectorBootstrap.noAuthentication = No Authentication
-jmxremote.ConnectorBootstrap.ready = JMX Connector ready at: {0}
-jmxremote.ConnectorBootstrap.password.readonly = Password file read access must be restricted: {0}
-jmxremote.ConnectorBootstrap.file.readonly = File read access must be restricted: {0}
--- a/jdk/src/java.management/share/classes/sun/management/resources/agent_de.properties Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-#
-# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-agent.err.error = Fehler
-agent.err.exception = Ausnahme von Agent ausgel\u00F6st
-agent.err.warning = Warnung
-
-agent.err.configfile.notfound = Konfigurationsdatei wurde nicht gefunden
-agent.err.configfile.failed = Konfigurationsdatei konnte nicht gelesen werden
-agent.err.configfile.closed.failed = Konfigurationsdatei konnte nicht geschlossen werden
-agent.err.configfile.access.denied = Zugriff auf Konfigurationsdatei wurde abgelehnt
-
-agent.err.exportaddress.failed = Export der JMX-Connector-Adresse in Instrumentierungspuffer nicht erfolgreich
-
-agent.err.agentclass.notfound = Management Agent-Klasse nicht gefunden
-agent.err.agentclass.failed = Management Agent-Klasse nicht erfolgreich
-agent.err.premain.notfound = premain(String) ist in Agent-Klasse nicht vorhanden
-agent.err.agentclass.access.denied = Zugriff auf premain(String) wurde abgelehnt
-agent.err.invalid.agentclass = Ung\u00FCltiger Eigenschaftswert f\u00FCr com.sun.management.agent.class
-agent.err.invalid.state = Ung\u00FCltiger Agent-Zustand: {0}
-agent.err.invalid.jmxremote.port = Ung\u00FCltige Nummer f\u00FCr com.sun.management.jmxremote.port
-agent.err.invalid.jmxremote.rmi.port = Ung\u00FCltige Nummer f\u00FCr com.sun.management.jmxremote.rmi.port
-
-agent.err.file.not.set = Datei nicht angegeben
-agent.err.file.not.readable = Datei nicht lesbar
-agent.err.file.read.failed = Datei konnte nicht gelesen werden
-agent.err.file.not.found = Datei wurde nicht gefunden
-agent.err.file.access.not.restricted = Lesezugriff auf Datei muss eingeschr\u00E4nkt werden
-
-agent.err.password.file.notset = Es wurde keine Kennwortdatei angegeben, obwohl com.sun.management.jmxremote.authenticate auf "true" gesetzt ist
-agent.err.password.file.not.readable = Kennwortdatei nicht lesbar
-agent.err.password.file.read.failed = Kennwortdatei konnte nicht gelesen werden
-agent.err.password.file.notfound = Kennwortdatei nicht gefunden
-agent.err.password.file.access.notrestricted = Lesezugriff auf Kennwortdatei muss eingeschr\u00E4nkt werden
-
-agent.err.access.file.notset = Es wurde keine Zugriffsdatei angegeben, obwohl com.sun.management.jmxremote.authenticate auf "true" gesetzt ist
-agent.err.access.file.not.readable = Zugriffsdatei kann nicht gelesen werden
-agent.err.access.file.read.failed = Zugriffsdatei konnte nicht gelesen werden
-agent.err.access.file.notfound = Zugriffsdatei nicht gefunden
-
-agent.err.connector.server.io.error = Fehler bei JMX-Connector-Serverkommunikation
-
-agent.err.invalid.option = Ung\u00FCltige Option angegeben
-
-jmxremote.ConnectorBootstrap.starting = JMX-Connector-Server starten:
-jmxremote.ConnectorBootstrap.noAuthentication = Keine Authentifizierung
-jmxremote.ConnectorBootstrap.ready = JMX-Connector bereit unter: {0}
-jmxremote.ConnectorBootstrap.password.readonly = Lesezugriff auf Kennwortdatei muss eingeschr\u00E4nkt werden: {0}
-jmxremote.ConnectorBootstrap.file.readonly = Lesezugriff auf Datei muss eingeschr\u00E4nkt werden: {0}
--- a/jdk/src/java.management/share/classes/sun/management/resources/agent_es.properties Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-#
-# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-agent.err.error = Error
-agent.err.exception = Excepci\u00F3n devuelta por el agente
-agent.err.warning = Advertencia
-
-agent.err.configfile.notfound = No se ha encontrado el archivo de configuraci\u00F3n
-agent.err.configfile.failed = Fallo al leer el archivo de configuraci\u00F3n
-agent.err.configfile.closed.failed = Fallo al cerrar el archivo de configuraci\u00F3n
-agent.err.configfile.access.denied = Acceso denegado al archivo de configuraci\u00F3n
-
-agent.err.exportaddress.failed = Fallo al exportar la direcci\u00F3n del conector JMX al buffer de instrumentaci\u00F3n
-
-agent.err.agentclass.notfound = Clase de agente de gesti\u00F3n no encontrada
-agent.err.agentclass.failed = Fallo de clase de agente de gesti\u00F3n
-agent.err.premain.notfound = premain(String) no existe en la clase del agente
-agent.err.agentclass.access.denied = Acceso denegado a premain(String)
-agent.err.invalid.agentclass = Valor de propiedad com.sun.management.agent.class no v\u00E1lido
-agent.err.invalid.state = Estado de agente no v\u00E1lido: {0}
-agent.err.invalid.jmxremote.port = N\u00FAmero com.sun.management.jmxremote.port no v\u00E1lido
-agent.err.invalid.jmxremote.rmi.port = N\u00FAmero com.sun.management.jmxremote.rmi.port no v\u00E1lido
-
-agent.err.file.not.set = Archivo no especificado
-agent.err.file.not.readable = Archivo ilegible
-agent.err.file.read.failed = Fallo al leer el archivo
-agent.err.file.not.found = Archivo no encontrado
-agent.err.file.access.not.restricted = El acceso de lectura al archivo debe ser restringido
-
-agent.err.password.file.notset = El archivo de contrase\u00F1as no se ha especificado, pero com.sun.management.jmxremote.authenticate=true
-agent.err.password.file.not.readable = No se puede leer el archivo de contrase\u00F1as
-agent.err.password.file.read.failed = Fallo al leer el archivo de contrase\u00F1as
-agent.err.password.file.notfound = Archivo de contrase\u00F1as no encontrado
-agent.err.password.file.access.notrestricted = Se debe restringir el acceso de lectura al archivo de contrase\u00F1as
-
-agent.err.access.file.notset = El archivo de acceso no se ha especificado, pero com.sun.management.jmxremote.authenticate=true
-agent.err.access.file.not.readable = No se puede leer el archivo de acceso
-agent.err.access.file.read.failed = Fallo al leer el archivo de acceso
-agent.err.access.file.notfound = Archivo de acceso no encontrado
-
-agent.err.connector.server.io.error = Error de comunicaci\u00F3n con el servidor de conector JMX
-
-agent.err.invalid.option = Opci\u00F3n especificada no v\u00E1lida
-
-jmxremote.ConnectorBootstrap.starting = Iniciando servidor de conector JMX:
-jmxremote.ConnectorBootstrap.noAuthentication = Sin autenticaci\u00F3n
-jmxremote.ConnectorBootstrap.ready = Conector JMX listo en: {0}
-jmxremote.ConnectorBootstrap.password.readonly = Se debe restringir el acceso de lectura al archivo de contrase\u00F1as: {0}
-jmxremote.ConnectorBootstrap.file.readonly = El acceso de lectura al archivo debe ser restringido: {0}
--- a/jdk/src/java.management/share/classes/sun/management/resources/agent_fr.properties Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-#
-# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-agent.err.error = Erreur
-agent.err.exception = Exception envoy\u00E9e par l'agent
-agent.err.warning = Avertissement
-
-agent.err.configfile.notfound = Fichier de configuration introuvable
-agent.err.configfile.failed = Impossible de lire le fichier de configuration
-agent.err.configfile.closed.failed = Impossible de fermer le fichier de configuration
-agent.err.configfile.access.denied = Acc\u00E8s refus\u00E9 au fichier de configuration
-
-agent.err.exportaddress.failed = Impossible d'exporter l'adresse du connecteur JMX dans le tampon d'instrumentation
-
-agent.err.agentclass.notfound = Classe d'agents de gestion introuvable
-agent.err.agentclass.failed = Echec de la classe d'agents de gestion
-agent.err.premain.notfound = premain(String) n'existe pas dans la classe d'agents
-agent.err.agentclass.access.denied = Acc\u00E8s \u00E0 premain(String) refus\u00E9
-agent.err.invalid.agentclass = Valeur de propri\u00E9t\u00E9 com.sun.management.agent.class incorrecte
-agent.err.invalid.state = Etat de l''agent non valide : {0}
-agent.err.invalid.jmxremote.port = Num\u00E9ro com.sun.management.jmxremote.port incorrect
-agent.err.invalid.jmxremote.rmi.port = Num\u00E9ro com.sun.management.jmxremote.rmi.port non valide
-
-agent.err.file.not.set = Fichier non sp\u00E9cifi\u00E9
-agent.err.file.not.readable = Fichier illisible
-agent.err.file.read.failed = Impossible de lire le fichier
-agent.err.file.not.found = Fichier introuvable
-agent.err.file.access.not.restricted = L'acc\u00E8s en lecture au fichier doit \u00EAtre limit\u00E9
-
-agent.err.password.file.notset = Le fichier de mots de passe n'est pas sp\u00E9cifi\u00E9 mais com.sun.management.jmxremote.authenticate=true
-agent.err.password.file.not.readable = Fichier de mots de passe illisible
-agent.err.password.file.read.failed = Impossible de lire le fichier de mots de passe
-agent.err.password.file.notfound = Fichier de mots de passe introuvable
-agent.err.password.file.access.notrestricted = L'acc\u00E8s en lecture au fichier de mots de passe doit \u00EAtre limit\u00E9
-
-agent.err.access.file.notset = Le fichier d'acc\u00E8s n'est pas sp\u00E9cifi\u00E9 mais com.sun.management.jmxremote.authenticate=true
-agent.err.access.file.not.readable = Fichier d'acc\u00E8s illisible
-agent.err.access.file.read.failed = Impossible de lire le fichier d'acc\u00E8s
-agent.err.access.file.notfound = Fichier d'acc\u00E8s introuvable
-
-agent.err.connector.server.io.error = Erreur de communication avec le serveur du connecteur JMX
-
-agent.err.invalid.option = Option sp\u00E9cifi\u00E9e non valide
-
-jmxremote.ConnectorBootstrap.starting = D\u00E9marrage du serveur du connecteur JMX :
-jmxremote.ConnectorBootstrap.noAuthentication = Pas d'authentification
-jmxremote.ConnectorBootstrap.ready = Connecteur JMX pr\u00EAt \u00E0 : {0}
-jmxremote.ConnectorBootstrap.password.readonly = L''acc\u00E8s en lecture au fichier de mots de passe doit \u00EAtre limit\u00E9 : {0}
-jmxremote.ConnectorBootstrap.file.readonly = L''acc\u00E8s en lecture au fichier doit \u00EAtre limit\u00E9 : {0}
--- a/jdk/src/java.management/share/classes/sun/management/resources/agent_it.properties Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-#
-# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-agent.err.error = Errore
-agent.err.exception = Eccezione dell'agente
-agent.err.warning = Avvertenza
-
-agent.err.configfile.notfound = File di configurazione non trovato
-agent.err.configfile.failed = Errore di lettura file di configurazione
-agent.err.configfile.closed.failed = Errore di chiusura file di configurazione
-agent.err.configfile.access.denied = Accesso negato al file di configurazione
-
-agent.err.exportaddress.failed = Errore di esportazione dell'indirizzo connettore JMX nel buffer strumenti
-
-agent.err.agentclass.notfound = Classe agente gestione non trovata
-agent.err.agentclass.failed = Errore classe agente gestione
-agent.err.premain.notfound = premain(String) non esiste nella classe agente
-agent.err.agentclass.access.denied = Accesso negato a premain(String)
-agent.err.invalid.agentclass = Valore propriet\u00E0 com.sun.management.agent.class non valido
-agent.err.invalid.state = Stato agente non valido: {0}
-agent.err.invalid.jmxremote.port = Numero com.sun.management.jmxremote.port non valido
-agent.err.invalid.jmxremote.rmi.port = Numero com.sun.management.jmxremote.rmi.port non valido
-
-agent.err.file.not.set = File non specificato
-agent.err.file.not.readable = File non leggibile
-agent.err.file.read.failed = Errore di lettura file
-agent.err.file.not.found = File non trovato
-agent.err.file.access.not.restricted = Limitare l'accesso in lettura al file
-
-agent.err.password.file.notset = Il password file non \u00E8 specificato ma com.sun.management.jmxremote.authenticate=true
-agent.err.password.file.not.readable = Password file non leggibile
-agent.err.password.file.read.failed = Errore di lettura password file
-agent.err.password.file.notfound = Password file non trovato
-agent.err.password.file.access.notrestricted = Limitare l'accesso in lettura al password file
-
-agent.err.access.file.notset = Il file di accesso non \u00E8 specificato ma com.sun.management.jmxremote.authenticate=true
-agent.err.access.file.not.readable = File di accesso non leggibile
-agent.err.access.file.read.failed = Errore di lettura file di accesso
-agent.err.access.file.notfound = File di accesso non trovato
-
-agent.err.connector.server.io.error = Errore di comunicazione server del connettore JMX
-
-agent.err.invalid.option = Specificata opzione non valida
-
-jmxremote.ConnectorBootstrap.starting = Avvio del server connettore JMX:
-jmxremote.ConnectorBootstrap.noAuthentication = Nessuna autenticazione
-jmxremote.ConnectorBootstrap.ready = Connettore JMX pronto in: {0}
-jmxremote.ConnectorBootstrap.password.readonly = Limitare l''accesso in lettura al password file: {0}
-jmxremote.ConnectorBootstrap.file.readonly = Limitare l''accesso in lettura al file: {0}
--- a/jdk/src/java.management/share/classes/sun/management/resources/agent_ja.properties Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-#
-# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-agent.err.error = \u30A8\u30E9\u30FC
-agent.err.exception = \u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u304C\u4F8B\u5916\u3092\u30B9\u30ED\u30FC\u3057\u307E\u3057\u305F
-agent.err.warning = \u8B66\u544A
-
-agent.err.configfile.notfound = \u69CB\u6210\u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
-agent.err.configfile.failed = \u69CB\u6210\u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u53D6\u308A\u306B\u5931\u6557\u3057\u307E\u3057\u305F
-agent.err.configfile.closed.failed = \u69CB\u6210\u30D5\u30A1\u30A4\u30EB\u3092\u9589\u3058\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F
-agent.err.configfile.access.denied = \u69CB\u6210\u30D5\u30A1\u30A4\u30EB\u3078\u306E\u30A2\u30AF\u30BB\u30B9\u304C\u62D2\u5426\u3055\u308C\u307E\u3057\u305F
-
-agent.err.exportaddress.failed = JMX\u30B3\u30CD\u30AF\u30BF\u30FB\u30A2\u30C9\u30EC\u30B9\u306E\u8A08\u6E2C\u30D0\u30C3\u30D5\u30A1\u3078\u306E\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u304C\u5931\u6557\u3057\u307E\u3057\u305F
-
-agent.err.agentclass.notfound = \u7BA1\u7406\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u30FB\u30AF\u30E9\u30B9\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
-agent.err.agentclass.failed = \u7BA1\u7406\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u30FB\u30AF\u30E9\u30B9\u304C\u5931\u6557\u3057\u307E\u3057\u305F
-agent.err.premain.notfound = premain(String)\u304C\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u30FB\u30AF\u30E9\u30B9\u306B\u5B58\u5728\u3057\u307E\u305B\u3093
-agent.err.agentclass.access.denied = premain(String)\u3078\u306E\u30A2\u30AF\u30BB\u30B9\u304C\u62D2\u5426\u3055\u308C\u307E\u3057\u305F
-agent.err.invalid.agentclass = com.sun.management.agent.class\u30D7\u30ED\u30D1\u30C6\u30A3\u306E\u5024\u304C\u7121\u52B9\u3067\u3059
-agent.err.invalid.state = \u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u306E\u72B6\u614B\u304C\u7121\u52B9\u3067\u3059: {0}
-agent.err.invalid.jmxremote.port = com.sun.management.jmxremote.port\u306E\u756A\u53F7\u304C\u7121\u52B9\u3067\u3059
-agent.err.invalid.jmxremote.rmi.port = com.sun.management.jmxremote.rmi.port\u306E\u756A\u53F7\u304C\u7121\u52B9\u3067\u3059
-
-agent.err.file.not.set = \u30D5\u30A1\u30A4\u30EB\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093
-agent.err.file.not.readable = \u30D5\u30A1\u30A4\u30EB\u3092\u8AAD\u307F\u53D6\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u305B\u3093
-agent.err.file.read.failed = \u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u53D6\u308A\u306B\u5931\u6557\u3057\u307E\u3057\u305F
-agent.err.file.not.found = \u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F
-agent.err.file.access.not.restricted = \u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u53D6\u308A\u30A2\u30AF\u30BB\u30B9\u306F\u5236\u9650\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059
-
-agent.err.password.file.notset = \u30D1\u30B9\u30EF\u30FC\u30C9\u30FB\u30D5\u30A1\u30A4\u30EB\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u304C\u3001com.sun.management.jmxremote.authenticate=true\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u3059
-agent.err.password.file.not.readable = \u30D1\u30B9\u30EF\u30FC\u30C9\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u8AAD\u307F\u53D6\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u305B\u3093
-agent.err.password.file.read.failed = \u30D1\u30B9\u30EF\u30FC\u30C9\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u53D6\u308A\u306B\u5931\u6557\u3057\u307E\u3057\u305F
-agent.err.password.file.notfound = \u30D1\u30B9\u30EF\u30FC\u30C9\u30FB\u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
-agent.err.password.file.access.notrestricted = \u30D1\u30B9\u30EF\u30FC\u30C9\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u53D6\u308A\u30A2\u30AF\u30BB\u30B9\u306F\u5236\u9650\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059
-
-agent.err.access.file.notset = \u30A2\u30AF\u30BB\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u304C\u3001com.sun.management.jmxremote.authenticate=true\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u3059
-agent.err.access.file.not.readable = \u30A2\u30AF\u30BB\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u8AAD\u307F\u53D6\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u305B\u3093
-agent.err.access.file.read.failed = \u30A2\u30AF\u30BB\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u53D6\u308A\u306B\u5931\u6557\u3057\u307E\u3057\u305F
-agent.err.access.file.notfound = \u30A2\u30AF\u30BB\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
-
-agent.err.connector.server.io.error = JMX\u30B3\u30CD\u30AF\u30BF\u30FB\u30B5\u30FC\u30D0\u30FC\u306E\u901A\u4FE1\u30A8\u30E9\u30FC
-
-agent.err.invalid.option = \u7121\u52B9\u306A\u30AA\u30D7\u30B7\u30E7\u30F3\u304C\u6307\u5B9A\u3055\u308C\u307E\u3057\u305F
-
-jmxremote.ConnectorBootstrap.starting = JMX\u30B3\u30CD\u30AF\u30BF\u30FB\u30B5\u30FC\u30D0\u30FC\u3092\u8D77\u52D5\u3057\u3066\u3044\u307E\u3059:
-jmxremote.ConnectorBootstrap.noAuthentication = \u8A8D\u8A3C\u306A\u3057
-jmxremote.ConnectorBootstrap.ready = JMX\u30B3\u30CD\u30AF\u30BF\u306E\u6E96\u5099\u304C\u3067\u304D\u307E\u3057\u305F: {0}
-jmxremote.ConnectorBootstrap.password.readonly = \u30D1\u30B9\u30EF\u30FC\u30C9\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u53D6\u308A\u30A2\u30AF\u30BB\u30B9\u306F\u5236\u9650\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059: {0}
-jmxremote.ConnectorBootstrap.file.readonly = \u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u53D6\u308A\u30A2\u30AF\u30BB\u30B9\u306F\u5236\u9650\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059: {0}
--- a/jdk/src/java.management/share/classes/sun/management/resources/agent_ko.properties Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-#
-# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-agent.err.error = \uC624\uB958
-agent.err.exception = \uC5D0\uC774\uC804\uD2B8\uC5D0 \uC608\uC678\uC0AC\uD56D\uC774 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.
-agent.err.warning = \uACBD\uACE0
-
-agent.err.configfile.notfound = \uAD6C\uC131 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
-agent.err.configfile.failed = \uAD6C\uC131 \uD30C\uC77C \uC77D\uAE30\uB97C \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.
-agent.err.configfile.closed.failed = \uAD6C\uC131 \uD30C\uC77C \uB2EB\uAE30\uB97C \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.
-agent.err.configfile.access.denied = \uAD6C\uC131 \uD30C\uC77C\uC5D0 \uB300\uD55C \uC561\uC138\uC2A4\uAC00 \uAC70\uBD80\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
-
-agent.err.exportaddress.failed = \uAE30\uAE30 \uBC84\uD37C\uB85C JMX \uCEE4\uB125\uD130 \uC8FC\uC18C \uC775\uC2A4\uD3EC\uD2B8\uB97C \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.
-
-agent.err.agentclass.notfound = \uAD00\uB9AC \uC5D0\uC774\uC804\uD2B8 \uD074\uB798\uC2A4\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
-agent.err.agentclass.failed = \uAD00\uB9AC \uC5D0\uC774\uC804\uD2B8 \uD074\uB798\uC2A4\uB97C \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.
-agent.err.premain.notfound = \uC5D0\uC774\uC804\uD2B8 \uD074\uB798\uC2A4\uC5D0 premain(\uBB38\uC790\uC5F4)\uC774 \uC874\uC7AC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
-agent.err.agentclass.access.denied = premain(\uBB38\uC790\uC5F4)\uC5D0 \uB300\uD55C \uC561\uC138\uC2A4\uAC00 \uAC70\uBD80\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
-agent.err.invalid.agentclass = com.sun.management.agent.class \uC18D\uC131 \uAC12\uC774 \uBD80\uC801\uD569\uD569\uB2C8\uB2E4.
-agent.err.invalid.state = \uBD80\uC801\uD569\uD55C \uC5D0\uC774\uC804\uD2B8 \uC0C1\uD0DC: {0}
-agent.err.invalid.jmxremote.port = com.sun.management.jmxremote.port \uBC88\uD638\uAC00 \uBD80\uC801\uD569\uD569\uB2C8\uB2E4.
-agent.err.invalid.jmxremote.rmi.port = \uBD80\uC801\uD569\uD55C com.sun.management.jmxremote.rmi.port \uBC88\uD638
-
-agent.err.file.not.set = \uD30C\uC77C\uC774 \uC9C0\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.
-agent.err.file.not.readable = \uD30C\uC77C\uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
-agent.err.file.read.failed = \uD30C\uC77C \uC77D\uAE30\uB97C \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.
-agent.err.file.not.found = \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
-agent.err.file.access.not.restricted = \uD30C\uC77C \uC77D\uAE30 \uC561\uC138\uC2A4\uB294 \uC81C\uD55C\uB418\uC5B4\uC57C \uD569\uB2C8\uB2E4.
-
-agent.err.password.file.notset = \uBE44\uBC00\uBC88\uD638 \uD30C\uC77C\uC774 \uC9C0\uC815\uB418\uC9C0 \uC54A\uC558\uC9C0\uB9CC com.sun.management.jmxremote.authenticate=true\uC785\uB2C8\uB2E4.
-agent.err.password.file.not.readable = \uBE44\uBC00\uBC88\uD638 \uD30C\uC77C\uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
-agent.err.password.file.read.failed = \uBE44\uBC00\uBC88\uD638 \uD30C\uC77C \uC77D\uAE30\uB97C \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.
-agent.err.password.file.notfound = \uBE44\uBC00\uBC88\uD638 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
-agent.err.password.file.access.notrestricted = \uBE44\uBC00\uBC88\uD638 \uD30C\uC77C \uC77D\uAE30 \uC561\uC138\uC2A4\uB294 \uC81C\uD55C\uB418\uC5B4\uC57C \uD569\uB2C8\uB2E4.
-
-agent.err.access.file.notset = \uC561\uC138\uC2A4 \uD30C\uC77C\uC774 \uC9C0\uC815\uB418\uC9C0 \uC54A\uC558\uC9C0\uB9CC com.sun.management.jmxremote.authenticate=true\uC785\uB2C8\uB2E4.
-agent.err.access.file.not.readable = \uC561\uC138\uC2A4 \uD30C\uC77C\uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
-agent.err.access.file.read.failed = \uC561\uC138\uC2A4 \uD30C\uC77C \uC77D\uAE30\uB97C \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.
-agent.err.access.file.notfound = \uC561\uC138\uC2A4 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
-
-agent.err.connector.server.io.error = JMX \uCEE4\uB125\uD130 \uC11C\uBC84 \uD1B5\uC2E0 \uC624\uB958
-
-agent.err.invalid.option = \uBD80\uC801\uD569\uD55C \uC635\uC158\uC774 \uC9C0\uC815\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
-
-jmxremote.ConnectorBootstrap.starting = JMX \uCEE4\uB125\uD130 \uC11C\uBC84\uB97C \uC2DC\uC791\uD558\uB294 \uC911:
-jmxremote.ConnectorBootstrap.noAuthentication = \uC778\uC99D \uC5C6\uC74C
-jmxremote.ConnectorBootstrap.ready = {0}\uC5D0\uC11C JMX \uCEE4\uB125\uD130\uAC00 \uC900\uBE44\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
-jmxremote.ConnectorBootstrap.password.readonly = \uBE44\uBC00\uBC88\uD638 \uD30C\uC77C \uC77D\uAE30 \uC561\uC138\uC2A4\uB294 \uC81C\uD55C\uB418\uC5B4\uC57C \uD568: {0}
-jmxremote.ConnectorBootstrap.file.readonly = \uD30C\uC77C \uC77D\uAE30 \uC561\uC138\uC2A4\uB294 \uC81C\uD55C\uB418\uC5B4\uC57C \uD568: {0}
--- a/jdk/src/java.management/share/classes/sun/management/resources/agent_pt_BR.properties Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-#
-# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-agent.err.error = Erro
-agent.err.exception = Exce\u00E7\u00E3o gerada pelo agente
-agent.err.warning = Advert\u00EAncia
-
-agent.err.configfile.notfound = Arquivo de configura\u00E7\u00E3o n\u00E3o encontrado
-agent.err.configfile.failed = Falha ao ler o arquivo de configura\u00E7\u00E3o
-agent.err.configfile.closed.failed = Falha ao fechar o arquivo de configura\u00E7\u00E3o
-agent.err.configfile.access.denied = Acesso negado ao arquivo de configura\u00E7\u00E3o
-
-agent.err.exportaddress.failed = Falha na exporta\u00E7\u00E3o do endere\u00E7o do conector JMX para o buffer de instrumenta\u00E7\u00E3o
-
-agent.err.agentclass.notfound = Classe do agente de gerenciamento n\u00E3o encontrada
-agent.err.agentclass.failed = Falha na classe do agente de gerenciamento
-agent.err.premain.notfound = premain(String) n\u00E3o existe na classe do agente
-agent.err.agentclass.access.denied = Acesso negado a premain(String)
-agent.err.invalid.agentclass = Valor inv\u00E1lido da propriedade com.sun.management.agent.class
-agent.err.invalid.state = Estado inv\u00E1lido do agente: {0}
-agent.err.invalid.jmxremote.port = N\u00FAmero inv\u00E1lido de com.sun.management.jmxremote.port
-agent.err.invalid.jmxremote.rmi.port = N\u00FAmero inv\u00E1lido do com.sun.management.jmxremote.rmi.port
-
-agent.err.file.not.set = Arquivo n\u00E3o especificado
-agent.err.file.not.readable = Arquivo ileg\u00EDvel
-agent.err.file.read.failed = Falha ao ler o arquivo
-agent.err.file.not.found = Arquivo n\u00E3o encontrado
-agent.err.file.access.not.restricted = O acesso de leitura do arquivo deve ser limitado
-
-agent.err.password.file.notset = O arquivo de senha n\u00E3o est\u00E1 especificado, mas com.sun.management.jmxremote.authenticate=true
-agent.err.password.file.not.readable = Arquivo de senha ileg\u00EDvel
-agent.err.password.file.read.failed = Falha ao ler o arquivo de senha
-agent.err.password.file.notfound = Arquivo de senha n\u00E3o encontrado
-agent.err.password.file.access.notrestricted = O acesso de leitura do arquivo de senha deve ser limitado
-
-agent.err.access.file.notset = O arquivo de acesso n\u00E3o est\u00E1 especificado, mas com.sun.management.jmxremote.authenticate=true
-agent.err.access.file.not.readable = Arquivo de acesso ileg\u00EDvel
-agent.err.access.file.read.failed = Falha ao ler o arquivo de acesso
-agent.err.access.file.notfound = Arquivo de acesso n\u00E3o encontrado
-
-agent.err.connector.server.io.error = Erro de comunica\u00E7\u00E3o do servidor do conector JMX
-
-agent.err.invalid.option = Op\u00E7\u00E3o especificada inv\u00E1lida
-
-jmxremote.ConnectorBootstrap.starting = Iniciando o Servidor do Conector JMX:
-jmxremote.ConnectorBootstrap.noAuthentication = Sem autentica\u00E7\u00E3o
-jmxremote.ConnectorBootstrap.ready = Conector JMX pronto em: {0}
-jmxremote.ConnectorBootstrap.password.readonly = O acesso de leitura do arquivo de senha deve ser limitado: {0}
-jmxremote.ConnectorBootstrap.file.readonly = O acesso de leitura do arquivo deve ser limitado: {0}
--- a/jdk/src/java.management/share/classes/sun/management/resources/agent_sv.properties Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-#
-# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-agent.err.error = Fel
-agent.err.exception = Agenten orsakade ett undantag
-agent.err.warning = Varning
-
-agent.err.configfile.notfound = Konfigurationsfilen hittades inte
-agent.err.configfile.failed = Kunde inte l\u00E4sa konfigurationsfilen
-agent.err.configfile.closed.failed = Kunde inte st\u00E4nga konfigurationsfilen
-agent.err.configfile.access.denied = \u00C5tkomst till konfigurationsfilen nekad
-
-agent.err.exportaddress.failed = Kunde inte exportera JMX-anslutningsadressen till instrumentbufferten
-
-agent.err.agentclass.notfound = Administrationsagentklassen hittades inte
-agent.err.agentclass.failed = Administrationsagentklassen utf\u00F6rdes inte
-agent.err.premain.notfound = premain(String) finns inte i agentklassen
-agent.err.agentclass.access.denied = \u00C5tkomst till premain(String) nekad
-agent.err.invalid.agentclass = Ogiltigt egenskapsv\u00E4rde f\u00F6r com.sun.management.agent.class
-agent.err.invalid.state = Ogiltig agentstatus: {0}
-agent.err.invalid.jmxremote.port = Ogiltigt com.sun.management.jmxremote.port-nummer
-agent.err.invalid.jmxremote.rmi.port = Ogiltigt com.sun.management.jmxremote.rmi.port-nummer
-
-agent.err.file.not.set = Filen \u00E4r inte angiven
-agent.err.file.not.readable = Filen \u00E4r inte l\u00E4sbar
-agent.err.file.read.failed = Kunde inte l\u00E4sa filen
-agent.err.file.not.found = Filen hittades inte
-agent.err.file.access.not.restricted = Fill\u00E4snings\u00E5tkomst m\u00E5ste begr\u00E4nsas
-
-agent.err.password.file.notset = L\u00F6senordsfilen har inte angetts men com.sun.management.jmxremote.authenticate=true
-agent.err.password.file.not.readable = L\u00F6senordsfilen \u00E4r inte l\u00E4sbar
-agent.err.password.file.read.failed = Kunde inte l\u00E4sa l\u00F6senordsfilen
-agent.err.password.file.notfound = Hittar inte l\u00F6senordsfilen
-agent.err.password.file.access.notrestricted = L\u00E4sbeh\u00F6righeten f\u00F6r filen m\u00E5ste begr\u00E4nsas
-
-agent.err.access.file.notset = \u00C5tkomstfilen har inte angetts men com.sun.management.jmxremote.authenticate=true
-agent.err.access.file.not.readable = Access-filen \u00E4r inte l\u00E4sbar
-agent.err.access.file.read.failed = Kunde inte l\u00E4sa \u00E5tkomstfilen
-agent.err.access.file.notfound = Access-filen hittades inte
-
-agent.err.connector.server.io.error = Serverkommunikationsfel f\u00F6r JMX-anslutning
-
-agent.err.invalid.option = Det angivna alternativet \u00E4r ogiltigt
-
-jmxremote.ConnectorBootstrap.starting = Startar server f\u00F6r JMX-anslutning:
-jmxremote.ConnectorBootstrap.noAuthentication = Ingen autentisering
-jmxremote.ConnectorBootstrap.ready = JMX-anslutning redo p\u00E5: {0}
-jmxremote.ConnectorBootstrap.password.readonly = L\u00E4sbeh\u00F6righeten f\u00F6r l\u00F6senordsfilen m\u00E5ste begr\u00E4nsas: {0}
-jmxremote.ConnectorBootstrap.file.readonly = Fill\u00E4snings\u00E5tkomst m\u00E5ste begr\u00E4nsas {0}
--- a/jdk/src/java.management/share/classes/sun/management/resources/agent_zh_CN.properties Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-#
-# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-agent.err.error = \u9519\u8BEF
-agent.err.exception = \u4EE3\u7406\u629B\u51FA\u5F02\u5E38\u9519\u8BEF
-agent.err.warning = \u8B66\u544A
-
-agent.err.configfile.notfound = \u627E\u4E0D\u5230\u914D\u7F6E\u6587\u4EF6
-agent.err.configfile.failed = \u672A\u80FD\u8BFB\u53D6\u914D\u7F6E\u6587\u4EF6
-agent.err.configfile.closed.failed = \u672A\u80FD\u5173\u95ED\u914D\u7F6E\u6587\u4EF6
-agent.err.configfile.access.denied = \u62D2\u7EDD\u8BBF\u95EE\u914D\u7F6E\u6587\u4EF6
-
-agent.err.exportaddress.failed = \u672A\u80FD\u5C06 JMX \u8FDE\u63A5\u5668\u5730\u5740\u5BFC\u51FA\u5230\u68C0\u6D4B\u7F13\u51B2\u533A
-
-agent.err.agentclass.notfound = \u627E\u4E0D\u5230\u7BA1\u7406\u4EE3\u7406\u7C7B
-agent.err.agentclass.failed = \u7BA1\u7406\u4EE3\u7406\u7C7B\u5931\u8D25
-agent.err.premain.notfound = \u4EE3\u7406\u7C7B\u4E2D\u4E0D\u5B58\u5728 premain(String)
-agent.err.agentclass.access.denied = \u62D2\u7EDD\u8BBF\u95EE premain(String)
-agent.err.invalid.agentclass = com.sun.management.agent.class \u5C5E\u6027\u503C\u65E0\u6548
-agent.err.invalid.state = \u65E0\u6548\u7684\u4EE3\u7406\u72B6\u6001: {0}
-agent.err.invalid.jmxremote.port = com.sun.management.jmxremote.port \u7F16\u53F7\u65E0\u6548
-agent.err.invalid.jmxremote.rmi.port = com.sun.management.jmxremote.rmi.port \u7F16\u53F7\u65E0\u6548
-
-agent.err.file.not.set = \u672A\u6307\u5B9A\u6587\u4EF6
-agent.err.file.not.readable = \u6587\u4EF6\u4E0D\u53EF\u8BFB\u53D6
-agent.err.file.read.failed = \u672A\u80FD\u8BFB\u53D6\u6587\u4EF6
-agent.err.file.not.found = \u627E\u4E0D\u5230\u6587\u4EF6
-agent.err.file.access.not.restricted = \u5FC5\u987B\u9650\u5236\u6587\u4EF6\u8BFB\u53D6\u8BBF\u95EE\u6743\u9650
-
-agent.err.password.file.notset = \u672A\u6307\u5B9A\u53E3\u4EE4\u6587\u4EF6, \u4F46 com.sun.management.jmxremote.authenticate=true
-agent.err.password.file.not.readable = \u53E3\u4EE4\u6587\u4EF6\u4E0D\u53EF\u8BFB\u53D6
-agent.err.password.file.read.failed = \u8BFB\u53D6\u53E3\u4EE4\u6587\u4EF6\u5931\u8D25
-agent.err.password.file.notfound = \u627E\u4E0D\u5230\u53E3\u4EE4\u6587\u4EF6
-agent.err.password.file.access.notrestricted = \u5FC5\u987B\u9650\u5236\u53E3\u4EE4\u6587\u4EF6\u8BFB\u53D6\u8BBF\u95EE\u6743\u9650
-
-agent.err.access.file.notset = \u672A\u6307\u5B9A\u8BBF\u95EE\u6587\u4EF6, \u4F46 com.sun.management.jmxremote.authenticate=true
-agent.err.access.file.not.readable = \u8BBF\u95EE\u6587\u4EF6\u4E0D\u53EF\u8BFB\u53D6
-agent.err.access.file.read.failed = \u8BFB\u53D6\u8BBF\u95EE\u6587\u4EF6\u5931\u8D25
-agent.err.access.file.notfound = \u627E\u4E0D\u5230\u8BBF\u95EE\u6587\u4EF6
-
-agent.err.connector.server.io.error = JMX \u8FDE\u63A5\u5668\u670D\u52A1\u5668\u901A\u4FE1\u9519\u8BEF
-
-agent.err.invalid.option = \u6307\u5B9A\u7684\u9009\u9879\u65E0\u6548
-
-jmxremote.ConnectorBootstrap.starting = \u6B63\u5728\u542F\u52A8 JMX \u8FDE\u63A5\u5668\u670D\u52A1\u5668:
-jmxremote.ConnectorBootstrap.noAuthentication = \u65E0\u9A8C\u8BC1
-jmxremote.ConnectorBootstrap.ready = \u4F4D\u4E8E{0}\u7684 JMX \u8FDE\u63A5\u5668\u5DF2\u5C31\u7EEA
-jmxremote.ConnectorBootstrap.password.readonly = \u5FC5\u987B\u9650\u5236\u53E3\u4EE4\u6587\u4EF6\u8BFB\u53D6\u8BBF\u95EE\u6743\u9650: {0}
-jmxremote.ConnectorBootstrap.file.readonly = \u5FC5\u987B\u9650\u5236\u6587\u4EF6\u8BFB\u53D6\u8BBF\u95EE\u6743\u9650: {0}
--- a/jdk/src/java.management/share/classes/sun/management/resources/agent_zh_TW.properties Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-#
-# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-agent.err.error = \u932F\u8AA4
-agent.err.exception = \u4EE3\u7406\u7A0B\u5F0F\u767C\u751F\u7570\u5E38
-agent.err.warning = \u8B66\u544A
-
-agent.err.configfile.notfound = \u627E\u4E0D\u5230\u8A2D\u5B9A\u6A94\u6848
-agent.err.configfile.failed = \u7121\u6CD5\u8B80\u53D6\u8A2D\u5B9A\u6A94\u6848
-agent.err.configfile.closed.failed = \u7121\u6CD5\u95DC\u9589\u8A2D\u5B9A\u6A94\u6848
-agent.err.configfile.access.denied = \u5B58\u53D6\u8A2D\u5B9A\u6A94\u6848\u906D\u5230\u62D2\u7D55
-
-agent.err.exportaddress.failed = \u5C07 JMX \u9023\u63A5\u5668\u4F4D\u5740\u532F\u51FA\u81F3\u8A2D\u5099\u7DE9\u885D\u5340\u5931\u6557
-
-agent.err.agentclass.notfound = \u627E\u4E0D\u5230\u7BA1\u7406\u4EE3\u7406\u7A0B\u5F0F\u985E\u5225
-agent.err.agentclass.failed = \u7BA1\u7406\u4EE3\u7406\u7A0B\u5F0F\u985E\u5225\u5931\u6557
-agent.err.premain.notfound = \u4EE3\u7406\u7A0B\u5F0F\u985E\u5225\u4E2D\u4E0D\u5B58\u5728 premain(String)
-agent.err.agentclass.access.denied = \u5B58\u53D6 premain(String) \u906D\u5230\u62D2\u7D55
-agent.err.invalid.agentclass = com.sun.management.agent.class \u5C6C\u6027\u503C\u7121\u6548
-agent.err.invalid.state = \u7121\u6548\u7684\u4EE3\u7406\u7A0B\u5F0F\u72C0\u614B: {0}
-agent.err.invalid.jmxremote.port = com.sun.management.jmxremote.port \u865F\u78BC\u7121\u6548
-agent.err.invalid.jmxremote.rmi.port = com.sun.management.jmxremote.rmi.port \u865F\u78BC\u7121\u6548
-
-agent.err.file.not.set = \u672A\u6307\u5B9A\u6A94\u6848
-agent.err.file.not.readable = \u6A94\u6848\u7121\u6CD5\u8B80\u53D6
-agent.err.file.read.failed = \u7121\u6CD5\u8B80\u53D6\u6A94\u6848
-agent.err.file.not.found = \u627E\u4E0D\u5230\u6A94\u6848
-agent.err.file.access.not.restricted = \u5FC5\u9808\u9650\u5236\u6A94\u6848\u8B80\u53D6\u5B58\u53D6\u6B0A
-
-agent.err.password.file.notset = \u672A\u6307\u5B9A\u5BC6\u78BC\u6A94\u6848\uFF0C\u4F46 com.sun.management.jmxremote.authenticate=true
-agent.err.password.file.not.readable = \u5BC6\u78BC\u6A94\u6848\u7121\u6CD5\u8B80\u53D6
-agent.err.password.file.read.failed = \u7121\u6CD5\u8B80\u53D6\u5BC6\u78BC\u6A94\u6848
-agent.err.password.file.notfound = \u627E\u4E0D\u5230\u5BC6\u78BC\u6A94\u6848
-agent.err.password.file.access.notrestricted = \u5FC5\u9808\u9650\u5236\u5BC6\u78BC\u6A94\u6848\u8B80\u53D6\u5B58\u53D6
-
-agent.err.access.file.notset = \u672A\u6307\u5B9A\u5B58\u53D6\u6A94\u6848\uFF0C\u4F46 com.sun.management.jmxremote.authenticate=true
-agent.err.access.file.not.readable = \u5B58\u53D6\u6A94\u6848\u7121\u6CD5\u8B80\u53D6
-agent.err.access.file.read.failed = \u7121\u6CD5\u8B80\u53D6\u5B58\u53D6\u6A94\u6848
-agent.err.access.file.notfound = \u627E\u4E0D\u5230\u5B58\u53D6\u6A94\u6848
-
-agent.err.connector.server.io.error = JMX \u9023\u63A5\u5668\u4F3A\u670D\u5668\u901A\u8A0A\u932F\u8AA4
-
-agent.err.invalid.option = \u6307\u5B9A\u7684\u9078\u9805\u7121\u6548
-
-jmxremote.ConnectorBootstrap.starting = \u6B63\u5728\u555F\u52D5 JMX \u9023\u63A5\u5668\u4F3A\u670D\u5668:
-jmxremote.ConnectorBootstrap.noAuthentication = \u7121\u8A8D\u8B49
-jmxremote.ConnectorBootstrap.ready = JMX \u9023\u63A5\u5668\u5C31\u7DD2\uFF0C\u4F4D\u65BC: {0}
-jmxremote.ConnectorBootstrap.password.readonly = \u5FC5\u9808\u9650\u5236\u5BC6\u78BC\u6A94\u6848\u8B80\u53D6\u5B58\u53D6: {0}
-jmxremote.ConnectorBootstrap.file.readonly = \u5FC5\u9808\u9650\u5236\u6A94\u6848\u8B80\u53D6\u5B58\u53D6\u6B0A: {0}
--- a/jdk/src/java.management/share/classes/sun/management/spi/AgentProvider.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.management.spi;
-
-import java.util.Properties;
-
-/**
- * Service interface for management agent
- */
-public abstract class AgentProvider {
-
- /**
- * Instantiates a new AgentProvider.
- *
- * @throws SecurityException if the subclass (and calling code) does not
- * have
- * {@code RuntimePermission("sun.management.spi.AgentProvider.subclass")}
- */
- protected AgentProvider() {
- this(checkSubclassPermission());
- }
-
- private AgentProvider(Void unused) {
- }
-
- private static Void checkSubclassPermission() {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- sm.checkPermission(new RuntimePermission(AgentProvider.class.getName() + ".subclass"));
- }
- return null;
- }
-
- /**
- * Gets the name of the agent provider.
- *
- * @return name of agent provider
- */
- public abstract String getName();
-
- /**
- * Initializes and starts the agent.
- *
- * @throws IllegalStateException if this agent has already been started.
- */
- public abstract void startAgent();
-
- /**
- * Initializes and starts the agent at given port and with given properties
- *
- * @param props environment variables for agent
- *
- * @throws IllegalStateException if this agent has already been started.
- */
- public abstract void startAgent(Properties props);
-
- /**
- * Checks if agent is started and not terminated.
- *
- * @return true if agent is running, false otherwise.
- */
- public abstract boolean isActive();
-
- /**
- * Stops this agent.
- *
- * @throws IllegalStateException if this agent is not started.
- */
- public abstract void stopAgent();
-}
--- a/jdk/src/java.management/share/conf/jmxremote.access Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-######################################################################
-# Default Access Control File for Remote JMX(TM) Monitoring
-######################################################################
-#
-# Access control file for Remote JMX API access to monitoring.
-# This file defines the allowed access for different roles. The
-# password file (jmxremote.password by default) defines the roles and their
-# passwords. To be functional, a role must have an entry in
-# both the password and the access files.
-#
-# The default location of this file is $JRE/conf/management/jmxremote.access
-# You can specify an alternate location by specifying a property in
-# the management config file $JRE/conf/management/management.properties
-# (See that file for details)
-#
-# The file format for password and access files is syntactically the same
-# as the Properties file format. The syntax is described in the Javadoc
-# for java.util.Properties.load.
-# A typical access file has multiple lines, where each line is blank,
-# a comment (like this one), or an access control entry.
-#
-# An access control entry consists of a role name, and an
-# associated access level. The role name is any string that does not
-# itself contain spaces or tabs. It corresponds to an entry in the
-# password file (jmxremote.password). The access level is one of the
-# following:
-# "readonly" grants access to read attributes of MBeans.
-# For monitoring, this means that a remote client in this
-# role can read measurements but cannot perform any action
-# that changes the environment of the running program.
-# "readwrite" grants access to read and write attributes of MBeans,
-# to invoke operations on them, and optionally
-# to create or remove them. This access should be granted
-# only to trusted clients, since they can potentially
-# interfere with the smooth operation of a running program.
-#
-# The "readwrite" access level can optionally be followed by the "create" and/or
-# "unregister" keywords. The "unregister" keyword grants access to unregister
-# (delete) MBeans. The "create" keyword grants access to create MBeans of a
-# particular class or of any class matching a particular pattern. Access
-# should only be granted to create MBeans of known and trusted classes.
-#
-# For example, the following entry would grant readwrite access
-# to "controlRole", as well as access to create MBeans of the class
-# javax.management.monitor.CounterMonitor and to unregister any MBean:
-# controlRole readwrite \
-# create javax.management.monitor.CounterMonitorMBean \
-# unregister
-# or equivalently:
-# controlRole readwrite unregister create javax.management.monitor.CounterMBean
-#
-# The following entry would grant readwrite access as well as access to create
-# MBeans of any class in the packages javax.management.monitor and
-# javax.management.timer:
-# controlRole readwrite \
-# create javax.management.monitor.*,javax.management.timer.* \
-# unregister
-#
-# The \ character is defined in the Properties file syntax to allow continuation
-# lines as shown here. A * in a class pattern matches a sequence of characters
-# other than dot (.), so javax.management.monitor.* matches
-# javax.management.monitor.CounterMonitor but not
-# javax.management.monitor.foo.Bar.
-#
-# A given role should have at most one entry in this file. If a role
-# has no entry, it has no access.
-# If multiple entries are found for the same role name, then the last
-# access entry is used.
-#
-#
-# Default access control entries:
-# o The "monitorRole" role has readonly access.
-# o The "controlRole" role has readwrite access and can create the standard
-# Timer and Monitor MBeans defined by the JMX API.
-
-monitorRole readonly
-controlRole readwrite \
- create javax.management.monitor.*,javax.management.timer.* \
- unregister
--- a/jdk/src/java.management/share/conf/jmxremote.password.template Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-# ----------------------------------------------------------------------
-# Template for jmxremote.password
-#
-# o Copy this template to jmxremote.password
-# o Set the user/password entries in jmxremote.password
-# o Change the permission of jmxremote.password to read-only
-# by the owner.
-#
-# See below for the location of jmxremote.password file.
-# ----------------------------------------------------------------------
-
-##############################################################
-# Password File for Remote JMX Monitoring
-##############################################################
-#
-# Password file for Remote JMX API access to monitoring. This
-# file defines the different roles and their passwords. The access
-# control file (jmxremote.access by default) defines the allowed
-# access for each role. To be functional, a role must have an entry
-# in both the password and the access files.
-#
-# Default location of this file is $JRE/conf/management/jmxremote.password
-# You can specify an alternate location by specifying a property in
-# the management config file $JRE/conf/management/management.properties
-# or by specifying a system property (See that file for details).
-
-
-##############################################################
-# File permissions of the jmxremote.password file
-##############################################################
-# Since there are cleartext passwords stored in this file,
-# this file must be readable by ONLY the owner,
-# otherwise the program will exit with an error.
-#
-# The file format for password and access files is syntactically the same
-# as the Properties file format. The syntax is described in the Javadoc
-# for java.util.Properties.load.
-# Typical password file has multiple lines, where each line is blank,
-# a comment (like this one), or a password entry.
-#
-#
-# A password entry consists of a role name and an associated
-# password. The role name is any string that does not itself contain
-# spaces or tabs. The password is again any string that does not
-# contain spaces or tabs. Note that passwords appear in the clear in
-# this file, so it is a good idea not to use valuable passwords.
-#
-# A given role should have at most one entry in this file. If a role
-# has no entry, it has no access.
-# If multiple entries are found for the same role name, then the last one
-# is used.
-#
-# In a typical installation, this file can be read by anybody on the
-# local machine, and possibly by people on other machines.
-# For # security, you should either restrict the access to this file,
-# or specify another, less accessible file in the management config file
-# as described above.
-#
-# Following are two commented-out entries. The "measureRole" role has
-# password "QED". The "controlRole" role has password "R&D".
-#
-# monitorRole QED
-# controlRole R&D
-
--- a/jdk/src/java.management/share/conf/management.properties Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,331 +0,0 @@
-#####################################################################
-# Default Configuration File for Java Platform Management
-#####################################################################
-#
-# The Management Configuration file (in java.util.Properties format)
-# will be read if one of the following system properties is set:
-# -Dcom.sun.management.jmxremote.port=<port-number>
-# or -Dcom.sun.management.snmp.port=<port-number>
-# or -Dcom.sun.management.config.file=<this-file>
-#
-# The default Management Configuration file is:
-#
-# $JRE/conf/management/management.properties
-#
-# Another location for the Management Configuration File can be specified
-# by the following property on the Java command line:
-#
-# -Dcom.sun.management.config.file=<this-file>
-#
-# If -Dcom.sun.management.config.file=<this-file> is set, the port
-# number for the management agent can be specified in the config file
-# using the following lines:
-#
-# ################ Management Agent Port #########################
-#
-# For setting the JMX RMI agent port use the following line
-# com.sun.management.jmxremote.port=<port-number>
-#
-# For setting the SNMP agent port use the following line
-# com.sun.management.snmp.port=<port-number>
-
-#####################################################################
-# Optional Instrumentation
-#####################################################################
-#
-# By default only the basic instrumentation with low overhead is on.
-# The following properties allow to selectively turn on optional
-# instrumentation which are off by default and may have some
-# additional overhead.
-#
-# com.sun.management.enableThreadContentionMonitoring
-#
-# This option enables thread contention monitoring if the
-# Java virtual machine supports such instrumentation.
-# Refer to the specification for the java.lang.management.ThreadMBean
-# interface - see isThreadContentionMonitoringSupported() method.
-#
-
-# To enable thread contention monitoring, uncomment the following line
-# com.sun.management.enableThreadContentionMonitoring
-
-#####################################################################
-# SNMP Management Properties
-#####################################################################
-#
-# If the system property -Dcom.sun.management.snmp.port=<port-number>
-# is set then
-# - The SNMP agent (with the Java virtual machine MIB) is started
-# that listens on the specified port for incoming SNMP requests.
-# - the following properties for read for SNMP management.
-#
-# The configuration can be specified only at startup time.
-# Later changes to the above system property (e.g. via setProperty method), this
-# config file, or the ACL file has no effect to the running SNMP agent.
-#
-
-#
-# ##################### SNMP Trap Port #########################
-#
-# com.sun.management.snmp.trap=<trap-destination-port-number>
-# Specifies the remote port number at which managers are expected
-# to listen for trap. For each host defined in the ACL file,
-# the SNMP agent will send traps at <host>:<trap-destination-port-number>
-# Default for this property is 162.
-#
-
-# To set port for sending traps to a different port use the following line
-# com.sun.management.snmp.trap=<trap-destination-port-number>
-
-#
-# ################ SNMP listen interface #########################
-#
-# com.sun.management.snmp.interface=<InetAddress>
-# Specifies the local interface on which the SNMP agent will bind.
-# This is useful when running on machines which have several
-# interfaces defined. It makes it possible to listen to a specific
-# subnet accessible through that interface.
-# Default for this property is "localhost".
-#
-# The format of the value for that property is any string accepted
-# by java.net.InetAddress.getByName(String).
-#
-
-# For restricting the port on which SNMP agent listens use the following line
-# com.sun.management.snmp.interface=<InetAddress>
-
-#
-# #################### SNMP ACL file #########################
-#
-# com.sun.management.snmp.acl=true|false
-# Default for this property is true. (Case for true/false ignored)
-# If this property is specified as false then the ACL file
-# is not checked: all manager hosts are allowed all access.
-#
-
-# For SNMP without checking ACL file uncomment the following line
-# com.sun.management.snmp.acl=false
-
-#
-# com.sun.management.snmp.acl.file=filepath
-# Specifies location for ACL file
-# This is optional - default location is
-# $JRE/conf/management/snmp.acl
-#
-# If the property "com.sun.management.snmp.acl" is set to false,
-# then this property and the ACL file are ignored.
-# Otherwise the ACL file must exist and be in the valid format.
-# If the ACL file is empty or non existent then no access is allowed.
-#
-# The SNMP agent will read the ACL file at startup time.
-# Modification to the ACL file has no effect to any running SNMP
-# agents which read that ACL file at startup.
-#
-
-# For a non-default acl file location use the following line
-# com.sun.management.snmp.acl.file=filepath
-
-#####################################################################
-# RMI Management Properties
-#####################################################################
-#
-# If system property -Dcom.sun.management.jmxremote.port=<port-number>
-# is set then
-# - A MBean server is started
-# - JRE Platform MBeans are registered in the MBean server
-# - RMI connector is published in a private readonly registry at
-# specified port using a well known name, "jmxrmi"
-# - the following properties are read for JMX remote management.
-#
-# The configuration can be specified only at startup time.
-# Later changes to above system property (e.g. via setProperty method),
-# this config file, the password file, or the access file have no effect to the
-# running MBean server, the connector, or the registry.
-#
-
-#
-# ########## RMI connector settings for local management ##########
-#
-# com.sun.management.jmxremote.local.only=true|false
-# Default for this property is true. (Case for true/false ignored)
-# If this property is specified as true then the local JMX RMI connector
-# server will only accept connection requests from clients running on
-# the host where the out-of-the-box JMX management agent is running.
-# In order to ensure backwards compatibility this property could be
-# set to false. However, deploying the local management agent in this
-# way is discouraged because the local JMX RMI connector server will
-# accept connection requests from any client either local or remote.
-# For remote management the remote JMX RMI connector server should
-# be used instead with authentication and SSL/TLS encryption enabled.
-#
-
-# For allowing the local management agent accept local
-# and remote connection requests use the following line
-# com.sun.management.jmxremote.local.only=false
-
-#
-# ###################### RMI SSL #############################
-#
-# com.sun.management.jmxremote.ssl=true|false
-# Default for this property is true. (Case for true/false ignored)
-# If this property is specified as false then SSL is not used.
-#
-
-# For RMI monitoring without SSL use the following line
-# com.sun.management.jmxremote.ssl=false
-
-# com.sun.management.jmxremote.ssl.config.file=filepath
-# Specifies the location of the SSL configuration file. A properties
-# file can be used to supply the keystore and truststore location and
-# password settings thus avoiding to pass them as cleartext in the
-# command-line.
-#
-# The current implementation of the out-of-the-box management agent will
-# look up and use the properties specified below to configure the SSL
-# keystore and truststore, if present:
-# javax.net.ssl.keyStore=<keystore-location>
-# javax.net.ssl.keyStorePassword=<keystore-password>
-# javax.net.ssl.trustStore=<truststore-location>
-# javax.net.ssl.trustStorePassword=<truststore-password>
-# Any other properties in the file will be ignored. This will allow us
-# to extend the property set in the future if required by the default
-# SSL implementation.
-#
-# If the property "com.sun.management.jmxremote.ssl" is set to false,
-# then this property is ignored.
-#
-
-# For supplying the keystore settings in a file use the following line
-# com.sun.management.jmxremote.ssl.config.file=filepath
-
-# com.sun.management.jmxremote.ssl.enabled.cipher.suites=<cipher-suites>
-# The value of this property is a string that is a comma-separated list
-# of SSL/TLS cipher suites to enable. This property can be specified in
-# conjunction with the previous property "com.sun.management.jmxremote.ssl"
-# in order to control which particular SSL/TLS cipher suites are enabled
-# for use by accepted connections. If this property is not specified then
-# the SSL/TLS RMI Server Socket Factory uses the SSL/TLS cipher suites that
-# are enabled by default.
-#
-
-# com.sun.management.jmxremote.ssl.enabled.protocols=<protocol-versions>
-# The value of this property is a string that is a comma-separated list
-# of SSL/TLS protocol versions to enable. This property can be specified in
-# conjunction with the previous property "com.sun.management.jmxremote.ssl"
-# in order to control which particular SSL/TLS protocol versions are
-# enabled for use by accepted connections. If this property is not
-# specified then the SSL/TLS RMI Server Socket Factory uses the SSL/TLS
-# protocol versions that are enabled by default.
-#
-
-# com.sun.management.jmxremote.ssl.need.client.auth=true|false
-# Default for this property is false. (Case for true/false ignored)
-# If this property is specified as true in conjunction with the previous
-# property "com.sun.management.jmxremote.ssl" then the SSL/TLS RMI Server
-# Socket Factory will require client authentication.
-#
-
-# For RMI monitoring with SSL client authentication use the following line
-# com.sun.management.jmxremote.ssl.need.client.auth=true
-
-# com.sun.management.jmxremote.registry.ssl=true|false
-# Default for this property is false. (Case for true/false ignored)
-# If this property is specified as true then the RMI registry used
-# to bind the RMIServer remote object is protected with SSL/TLS
-# RMI Socket Factories that can be configured with the properties:
-# com.sun.management.jmxremote.ssl.config.file
-# com.sun.management.jmxremote.ssl.enabled.cipher.suites
-# com.sun.management.jmxremote.ssl.enabled.protocols
-# com.sun.management.jmxremote.ssl.need.client.auth
-# If the two properties below are true at the same time, i.e.
-# com.sun.management.jmxremote.ssl=true
-# com.sun.management.jmxremote.registry.ssl=true
-# then the RMIServer remote object and the RMI registry are
-# both exported with the same SSL/TLS RMI Socket Factories.
-#
-
-# For using an SSL/TLS protected RMI registry use the following line
-# com.sun.management.jmxremote.registry.ssl=true
-
-#
-# ################ RMI User authentication ################
-#
-# com.sun.management.jmxremote.authenticate=true|false
-# Default for this property is true. (Case for true/false ignored)
-# If this property is specified as false then no authentication is
-# performed and all users are allowed all access.
-#
-
-# For RMI monitoring without any checking use the following line
-# com.sun.management.jmxremote.authenticate=false
-
-#
-# ################ RMI Login configuration ###################
-#
-# com.sun.management.jmxremote.login.config=<config-name>
-# Specifies the name of a JAAS login configuration entry to use when
-# authenticating users of RMI monitoring.
-#
-# Setting this property is optional - the default login configuration
-# specifies a file-based authentication that uses the password file.
-#
-# When using this property to override the default login configuration
-# then the named configuration entry must be in a file that gets loaded
-# by JAAS. In addition, the login module(s) specified in the configuration
-# should use the name and/or password callbacks to acquire the user's
-# credentials. See the NameCallback and PasswordCallback classes in the
-# javax.security.auth.callback package for more details.
-#
-# If the property "com.sun.management.jmxremote.authenticate" is set to
-# false, then this property and the password & access files are ignored.
-#
-
-# For a non-default login configuration use the following line
-# com.sun.management.jmxremote.login.config=<config-name>
-
-#
-# ################ RMI Password file location ##################
-#
-# com.sun.management.jmxremote.password.file=filepath
-# Specifies location for password file
-# This is optional - default location is
-# $JRE/conf/management/jmxremote.password
-#
-# If the property "com.sun.management.jmxremote.authenticate" is set to
-# false, then this property and the password & access files are ignored.
-# Otherwise the password file must exist and be in the valid format.
-# If the password file is empty or non-existent then no access is allowed.
-#
-
-# For a non-default password file location use the following line
-# com.sun.management.jmxremote.password.file=filepath
-
-#
-# ################ RMI Access file location #####################
-#
-# com.sun.management.jmxremote.access.file=filepath
-# Specifies location for access file
-# This is optional - default location is
-# $JRE/conf/management/jmxremote.access
-#
-# If the property "com.sun.management.jmxremote.authenticate" is set to
-# false, then this property and the password & access files are ignored.
-# Otherwise, the access file must exist and be in the valid format.
-# If the access file is empty or non-existent then no access is allowed.
-#
-
-# For a non-default password file location use the following line
-# com.sun.management.jmxremote.access.file=filepath
-#
-
-# ################ Management agent listen interface #########################
-#
-# com.sun.management.jmxremote.host=<host-or-interface-name>
-# Specifies the local interface on which the JMX RMI agent will bind.
-# This is useful when running on machines which have several
-# interfaces defined. It makes it possible to listen to a specific
-# subnet accessible through that interface.
-#
-# The format of the value for that property is any string accepted
-# by java.net.InetAddress.getByName(String).
-#
--- a/jdk/src/java.management/share/conf/snmp.acl.template Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-# ----------------------------------------------------------------------
-# Template for SNMP Access Control List File
-#
-# o Copy this template to snmp.acl
-# o Set access control for SNMP support
-# o Change the permission of snmp.acl to be read-only
-# by the owner.
-#
-# See below for the location of snmp.acl file.
-# ----------------------------------------------------------------------
-
-############################################################
-# SNMP Access Control List File
-############################################################
-#
-# Default location of this file is $JRE/conf/management/snmp.acl.
-# You can specify an alternate location by specifying a property in
-# the management config file $JRE/conf/management/management.properties
-# or by specifying a system property (See that file for details).
-#
-
-
-##############################################################
-# File permissions of the snmp.acl file
-##############################################################
-#
-# Since there are cleartext community strings stored in this file,
-# this ACL file must be readable by ONLY the owner,
-# otherwise the program will exit with an error.
-#
-##############################################################
-# Format of the acl group
-##############################################################
-#
-# communities: a list of SNMP community strings to which the
-# access control applies separated by commas.
-#
-# access: either "read-only" or "read-write".
-#
-# managers: a list of hosts to be granted the access rights.
-# Each can be expressed as any one of the following:
-# - hostname: hubble
-# - ip v4 and v6 addresses: 123.456.789.12 , fe80::a00:20ff:fe9b:ea82
-# - ip v4 and v6 netmask prefix notation: 123.456.789.0/24,
-# fe80::a00:20ff:fe9b:ea82/64
-# see RFC 2373 (http://www.ietf.org/rfc/rfc2373.txt)
-#
-# An example of two community groups for multiple hosts:
-# acl = {
-# {
-# communities = public, private
-# access = read-only
-# managers = hubble, snowbell, nanak
-# }
-# {
-# communities = jerry
-# access = read-write
-# managers = hubble, telescope
-# }
-# }
-#
-##############################################################
-# Format of the trap group
-##############################################################
-#
-# trap-community: a single SNMP community string that will be included
-# in the traps sent to the hosts.
-#
-# hosts: a list of hosts to which the SNMP agent will send traps.
-#
-# An example of two trap community definitions for multiple hosts:
-# trap = {
-# {
-# trap-community = public
-# hosts = hubble, snowbell
-# }
-# {
-# trap-community = private
-# hosts = telescope
-# }
-# }
-#
-############################################################
-#
-# Update the community strings (public and private) below
-# before copying this template file
-#
-# Common SNMP ACL Example
-# ------------------------
-#
-# o Only localhost can connect, and access rights
-# are limited to read-only
-# o Traps are sent to localhost only
-#
-#
-# acl = {
-# {
-# communities = public, private
-# access = read-only
-# managers = localhost
-# }
-# }
-#
-#
-# trap = {
-# {
-# trap-community = public
-# hosts = localhost
-# }
-# }
--- a/jdk/src/java.management/unix/classes/sun/management/FileSystemImpl.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2004, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.management;
-
-import java.io.File;
-import java.io.IOException;
-
-/*
- * Solaris/Linux implementation of sun.management.FileSystem
- */
-public class FileSystemImpl extends FileSystem {
-
- public boolean supportsFileSecurity(File f) throws IOException {
- return true;
- }
-
- public boolean isAccessUserOnly(File f) throws IOException {
- return isAccessUserOnly0(f.getPath());
- }
-
- // Native methods
-
- static native boolean isAccessUserOnly0(String path) throws IOException;
-
- // Initialization
-
- static {
- java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction<Void>() {
- public Void run() {
- System.loadLibrary("management");
- return null;
- }
- });
- }
-}
--- a/jdk/src/java.management/unix/native/libmanagement/FileSystemImpl.c Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2004, 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. 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 <sys/types.h>
-#include <sys/stat.h>
-
-#include "jni.h"
-#include "jni_util.h"
-#include "sun_management_FileSystemImpl.h"
-
-#ifdef _ALLBSD_SOURCE
-#define stat64 stat
-#endif
-
-/*
- * Class: sun_management_FileSystemImpl
- * Method: isAccessUserOnly0
- * Signature: (Ljava/lang/String;)Z
- */
-JNIEXPORT jboolean JNICALL Java_sun_management_FileSystemImpl_isAccessUserOnly0
- (JNIEnv *env, jclass ignored, jstring str)
-{
- jboolean res = JNI_FALSE;
- jboolean isCopy;
- const char *path = JNU_GetStringPlatformChars(env, str, &isCopy);
- if (path != NULL) {
- struct stat64 sb;
- if (stat64(path, &sb) == 0) {
- res = ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) == 0) ? JNI_TRUE : JNI_FALSE;
- } else {
- JNU_ThrowIOExceptionWithLastError(env, "stat64 failed");
- }
- if (isCopy) {
- JNU_ReleaseStringPlatformChars(env, str, path);
- }
- }
- return res;
-}
--- a/jdk/src/java.management/windows/classes/sun/management/FileSystemImpl.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2004, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.management;
-
-import java.io.File;
-import java.io.IOException;
-
-/*
- * Windows implementation of sun.management.FileSystem
- */
-public class FileSystemImpl extends FileSystem {
-
- public boolean supportsFileSecurity(File f) throws IOException {
- return isSecuritySupported0(f.getAbsolutePath());
- }
-
- public boolean isAccessUserOnly(File f) throws IOException {
- String path = f.getAbsolutePath();
- if (!isSecuritySupported0(path)) {
- throw new UnsupportedOperationException("File system does not support file security");
- }
- return isAccessUserOnly0(path);
- }
-
- // Native methods
-
- static native void init0();
-
- static native boolean isSecuritySupported0(String path) throws IOException;
-
- static native boolean isAccessUserOnly0(String path) throws IOException;
-
- // Initialization
-
- static {
- java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction<Void>() {
- public Void run() {
- System.loadLibrary("management");
- return null;
- }
- });
- init0();
- }
-}
--- a/jdk/src/java.management/windows/native/libmanagement/FileSystemImpl.c Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,314 +0,0 @@
-/*
- * Copyright (c) 2004, 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.
- */
-
-#include <windows.h>
-#include <malloc.h>
-#include <string.h>
-
-#include "jni.h"
-#include "jni_util.h"
-#include "sun_management_FileSystemImpl.h"
-
-/*
- * Access mask to represent any file access
- */
-#define ANY_ACCESS (FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE)
-
-/*
- * Returns JNI_TRUE if the specified file is on a file system that supports
- * persistent ACLs (On NTFS file systems returns true, on FAT32 file systems
- * returns false).
- */
-static jboolean isSecuritySupported(JNIEnv* env, const char* path) {
- char* root;
- char* p;
- BOOL res;
- DWORD dwMaxComponentLength;
- DWORD dwFlags;
- char fsName[128];
- DWORD fsNameLength;
-
- /*
- * Get root directory. Assume that files are absolute paths. For UNCs
- * the slash after the share name is required.
- */
- root = strdup(path);
- if (*root == '\\') {
- /*
- * \\server\share\file ==> \\server\share\
- */
- int slashskip = 3;
- p = root;
- while ((*p == '\\') && (slashskip > 0)) {
- char* p2;
- p++;
- p2 = strchr(p, '\\');
- if ((p2 == NULL) || (*p2 != '\\')) {
- free(root);
- JNU_ThrowIOException(env, "Malformed UNC");
- return JNI_FALSE;
- }
- p = p2;
- slashskip--;
- }
- if (slashskip != 0) {
- free(root);
- JNU_ThrowIOException(env, "Malformed UNC");
- return JNI_FALSE;
- }
- p++;
- *p = '\0';
-
- } else {
- p = strchr(root, '\\');
- if (p == NULL) {
- free(root);
- JNU_ThrowIOException(env, "Absolute filename not specified");
- return JNI_FALSE;
- }
- p++;
- *p = '\0';
- }
-
-
- /*
- * Get the volume information - this gives us the file system file and
- * also tells us if the file system supports persistent ACLs.
- */
- fsNameLength = sizeof(fsName)-1;
- res = GetVolumeInformation(root,
- NULL, // address of name of the volume, can be NULL
- 0, // length of volume name
- NULL, // address of volume serial number, can be NULL
- &dwMaxComponentLength,
- &dwFlags,
- fsName,
- fsNameLength);
- if (res == 0) {
- free(root);
- JNU_ThrowIOExceptionWithLastError(env, "GetVolumeInformation failed");
- return JNI_FALSE;
- }
-
- free(root);
- return (dwFlags & FS_PERSISTENT_ACLS) ? JNI_TRUE : JNI_FALSE;
-}
-
-
-/*
- * Returns the security descriptor for a file.
- */
-static SECURITY_DESCRIPTOR* getFileSecurityDescriptor(JNIEnv* env, const char* path) {
- SECURITY_DESCRIPTOR* sd;
- DWORD len = 0;
- SECURITY_INFORMATION info =
- OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
-
- GetFileSecurityA(path, info , 0, 0, &len);
- if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
- JNU_ThrowIOExceptionWithLastError(env, "GetFileSecurity failed");
- return NULL;
- }
- sd = (SECURITY_DESCRIPTOR *)malloc(len);
- if (sd == NULL) {
- JNU_ThrowOutOfMemoryError(env, 0);
- } else {
- if (!(*GetFileSecurityA)(path, info, sd, len, &len)) {
- JNU_ThrowIOExceptionWithLastError(env, "GetFileSecurity failed");
- free(sd);
- return NULL;
- }
- }
- return sd;
-}
-
-/*
- * Returns pointer to the SID identifying the owner of the specified
- * file.
- */
-static SID* getFileOwner(JNIEnv* env, SECURITY_DESCRIPTOR* sd) {
- SID* owner;
- BOOL defaulted;
-
- if (!GetSecurityDescriptorOwner(sd, &owner, &defaulted)) {
- JNU_ThrowIOExceptionWithLastError(env, "GetSecurityDescriptorOwner failed");
- return NULL;
- }
- return owner;
-}
-
-/*
- * Returns pointer discretionary access-control list (ACL) from the security
- * descriptor of the specified file.
- */
-static ACL* getFileDACL(JNIEnv* env, SECURITY_DESCRIPTOR* sd) {
- ACL *acl;
- int defaulted, present;
-
- if (!GetSecurityDescriptorDacl(sd, &present, &acl, &defaulted)) {
- JNU_ThrowIOExceptionWithLastError(env, "GetSecurityDescriptorDacl failed");
- return NULL;
- }
- if (!present) {
- JNU_ThrowInternalError(env, "Security descriptor does not contain a DACL");
- return NULL;
- }
- return acl;
-}
-
-/*
- * Returns JNI_TRUE if the specified owner is the only SID will access
- * to the file.
- */
-static jboolean isAccessUserOnly(JNIEnv* env, SID* owner, ACL* acl) {
- ACL_SIZE_INFORMATION acl_size_info;
- DWORD i;
-
- /*
- * If there's no DACL then there's no access to the file
- */
- if (acl == NULL) {
- return JNI_TRUE;
- }
-
- /*
- * Get the ACE count
- */
- if (!GetAclInformation(acl, (void *) &acl_size_info, sizeof(acl_size_info),
- AclSizeInformation)) {
- JNU_ThrowIOExceptionWithLastError(env, "GetAclInformation failed");
- return JNI_FALSE;
- }
-
- /*
- * Iterate over the ACEs. For each "allow" type check that the SID
- * matches the owner, and check that the access is read only.
- */
- for (i = 0; i < acl_size_info.AceCount; i++) {
- void* ace;
- ACCESS_ALLOWED_ACE *access;
- SID* sid;
-
- if (!GetAce(acl, i, &ace)) {
- JNU_ThrowIOExceptionWithLastError(env, "GetAce failed");
- return -1;
- }
- if (((ACCESS_ALLOWED_ACE *)ace)->Header.AceType != ACCESS_ALLOWED_ACE_TYPE) {
- continue;
- }
- access = (ACCESS_ALLOWED_ACE *)ace;
- sid = (SID *) &access->SidStart;
- if (!EqualSid(owner, sid)) {
- /*
- * If the ACE allows any access then the file is not secure.
- */
- if (access->Mask & ANY_ACCESS) {
- return JNI_FALSE;
- }
- }
- }
- return JNI_TRUE;
-}
-
-
-/*
- * Class: sun_management_FileSystemImpl
- * Method: init0
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_sun_management_FileSystemImpl_init0
- (JNIEnv *env, jclass ignored)
-{
- /* nothing to do */
-}
-
-/*
- * Class: sun_management_FileSystemImpl
- * Method: isSecuritySupported0
- * Signature: (Ljava/lang/String;)Z
- */
-JNIEXPORT jboolean JNICALL Java_sun_management_FileSystemImpl_isSecuritySupported0
- (JNIEnv *env, jclass ignored, jstring str)
-{
- jboolean res;
- jboolean isCopy;
- const char* path;
-
- path = JNU_GetStringPlatformChars(env, str, &isCopy);
- if (path != NULL) {
- res = isSecuritySupported(env, path);
- if (isCopy) {
- JNU_ReleaseStringPlatformChars(env, str, path);
- }
- return res;
- } else {
- /* exception thrown - doesn't matter what we return */
- return JNI_TRUE;
- }
-}
-
-
-/*
- * Class: sun_management_FileSystemImpl
- * Method: isAccessUserOnly0
- * Signature: (Ljava/lang/String;)Z
- */
-JNIEXPORT jboolean JNICALL Java_sun_management_FileSystemImpl_isAccessUserOnly0
- (JNIEnv *env, jclass ignored, jstring str)
-{
- jboolean res = JNI_FALSE;
- jboolean isCopy;
- const char* path;
-
- path = JNU_GetStringPlatformChars(env, str, &isCopy);
- if (path != NULL) {
- /*
- * From the security descriptor get the file owner and
- * DACL. Then check if anybody but the owner has access
- * to the file.
- */
- SECURITY_DESCRIPTOR* sd = getFileSecurityDescriptor(env, path);
- if (sd != NULL) {
- SID *owner = getFileOwner(env, sd);
- if (owner != NULL) {
- ACL* acl = getFileDACL(env, sd);
- if (acl != NULL) {
- res = isAccessUserOnly(env, owner, acl);
- } else {
- /*
- * If acl is NULL it means that an exception was thrown
- * or there is "all acess" to the file.
- */
- res = JNI_FALSE;
- }
- }
- free(sd);
- }
- if (isCopy) {
- JNU_ReleaseStringPlatformChars(env, str, path);
- }
- }
- return res;
-}
--- a/jdk/src/java.rmi/share/classes/java/rmi/activation/ActivationInstantiator.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.rmi/share/classes/java/rmi/activation/ActivationInstantiator.java Thu Feb 09 23:15:52 2017 +0100
@@ -60,7 +60,20 @@
* initialization data, and
*
* <li> returning a MarshalledObject containing the stub for the
- * remote object it created </ul>
+ * remote object it created.</ul>
+ *
+ * <p>In order for activation to be successful, one of the following requirements
+ * must be met, otherwise {@link ActivationException} is thrown:
+ *
+ * <ul><li>The class to be activated and the special activation constructor are both public,
+ * and the class resides in a package that is
+ * {@linkplain java.lang.reflect.Module#isExported(String,java.lang.reflect.Module) exported}
+ * to at least the {@code java.rmi} module; or
+ *
+ * <li>The class to be activated resides in a package that is
+ * {@linkplain java.lang.reflect.Module#isOpen(String,java.lang.reflect.Module) open}
+ * to at least the {@code java.rmi} module.
+ * </ul>
*
* @param id the object's activation identifier
* @param desc the object's descriptor
--- a/jdk/src/java.rmi/share/classes/java/rmi/activation/Activator.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.rmi/share/classes/java/rmi/activation/Activator.java Thu Feb 09 23:15:52 2017 +0100
@@ -48,7 +48,7 @@
* The <code>Activator</code> works closely with
* <code>ActivationSystem</code>, which provides a means for registering
* groups and objects within those groups, and <code>ActivationMonitor</code>,
- * which recives information about active and inactive objects and inactive
+ * which receives information about active and inactive objects and inactive
* groups. <p>
*
* The activator is responsible for monitoring and detecting when
--- a/jdk/src/java.rmi/share/classes/java/rmi/server/UnicastRemoteObject.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.rmi/share/classes/java/rmi/server/UnicastRemoteObject.java Thu Feb 09 23:15:52 2017 +0100
@@ -107,8 +107,9 @@
* the binary name of the root class with the suffix {@code _Stub}.
*
* <li>The stub class is loaded by name using the class loader of the root
- * class. The stub class must extend {@link RemoteStub} and must have a
- * public constructor that has one parameter of type {@link RemoteRef}.
+ * class. The stub class must be public, it must extend {@link RemoteStub}, it must
+ * reside in a package that is exported to at least the {@code java.rmi} module, and it
+ * must have a public constructor that has one parameter of type {@link RemoteRef}.
*
* <li>Finally, an instance of the stub class is constructed with a
* {@link RemoteRef}.
@@ -124,12 +125,21 @@
*
* <ul>
*
- * <li>The proxy's class is defined by the class loader of the remote
- * object's class.
+ * <li>The proxy's class is defined according to the specifications for the
+ * <a href="{@docRoot}/java/lang/reflect/Proxy.html#membership">
+ * {@code Proxy}
+ * </a>
+ * class, using the class loader of the remote object's class.
*
* <li>The proxy implements all the remote interfaces implemented by the
* remote object's class.
*
+ * <li>Each remote interface must either be public and reside in a package that is
+ * {@linkplain java.lang.reflect.Module#isExported(String,java.lang.reflect.Module) exported}
+ * to at least the {@code java.rmi} module, or it must reside in a package that is
+ * {@linkplain java.lang.reflect.Module#isOpen(String,java.lang.reflect.Module) open}
+ * to at least the {@code java.rmi} module.
+ *
* <li>The proxy's invocation handler is a {@link
* RemoteObjectInvocationHandler} instance constructed with a
* {@link RemoteRef}.
--- a/jdk/src/java.rmi/share/classes/module-info.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.rmi/share/classes/module-info.java Thu Feb 09 23:15:52 2017 +0100
@@ -39,13 +39,14 @@
// accessible to the security manager at initialization time
exports com.sun.rmi.rmid to java.base;
exports sun.rmi.registry to
- java.management;
+ jdk.management.agent;
exports sun.rmi.server to
- java.management,
+ java.management.rmi,
+ jdk.management.agent,
jdk.jconsole;
exports sun.rmi.transport to
- java.management,
+ java.management.rmi,
+ jdk.management.agent,
jdk.jconsole;
uses java.rmi.server.RMIClassLoaderSpi;
}
-
--- a/jdk/src/java.se.ee/share/classes/module-info.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.se.ee/share/classes/module-info.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -36,10 +36,10 @@
// Upgradeable modules for Java EE technologies
requires transitive java.activation;
- requires transitive java.annotations.common;
requires transitive java.corba;
requires transitive java.transaction;
requires transitive java.xml.bind;
requires transitive java.xml.ws;
+ requires transitive java.xml.ws.annotation;
}
--- a/jdk/src/java.se/share/classes/module-info.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/java.se/share/classes/module-info.java Thu Feb 09 23:15:52 2017 +0100
@@ -36,6 +36,7 @@
requires transitive java.instrument;
requires transitive java.logging;
requires transitive java.management;
+ requires transitive java.management.rmi;
requires transitive java.naming;
requires transitive java.prefs;
requires transitive java.rmi;
@@ -47,4 +48,3 @@
requires transitive java.xml;
requires transitive java.xml.crypto;
}
-
--- a/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/WindowsTerminal.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/WindowsTerminal.java Thu Feb 09 23:15:52 2017 +0100
@@ -314,9 +314,9 @@
private static native void initIDs();
- private native int getConsoleMode();
+ protected native int getConsoleMode();
- private native void setConsoleMode(int mode);
+ protected native void setConsoleMode(int mode);
private byte[] readConsoleInput() {
KEY_EVENT_RECORD keyEvent = readKeyEvent();
--- a/jdk/src/jdk.internal.le/windows/native/lible/WindowsTerminal.cpp Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/jdk.internal.le/windows/native/lible/WindowsTerminal.cpp Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -77,7 +77,7 @@
INPUT_RECORD record;
DWORD n;
while (TRUE) {
- if (ReadConsoleInput(hStdIn, &record, 1, &n) == 0) {
+ if (ReadConsoleInputW(hStdIn, &record, 1, &n) == 0) {
return NULL;
}
if (record.EventType == KEY_EVENT) {
@@ -97,7 +97,7 @@
JNIEXPORT jint JNICALL Java_jdk_internal_jline_WindowsTerminal_getConsoleOutputCodepage
(JNIEnv *, jobject) {
- return GetConsoleCP();
+ return GetConsoleOutputCP();
}
JNIEXPORT jint JNICALL Java_jdk_internal_jline_WindowsTerminal_getWindowsTerminalWidth
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties Thu Feb 09 23:15:52 2017 +0100
@@ -36,7 +36,7 @@
error.bad.file.arg=\
Error parsing file arguments
error.bad.option=\
- One of options -{ctxu} must be specified.
+ One of options -{ctxuid} must be specified.
error.bad.cflag=\
'c' flag requires manifest or input files to be specified!
error.bad.uflag=\
@@ -202,7 +202,15 @@
\ jar --update --file foo.jar --main-class com.foo.Main --module-version 1.0\n\
\ -C foo/ module-info.class\n\
\ # Create a multi-release jar, placing some files in the META-INF/versions/9 directory:\n\
-\ jar --create --file mr.jar -C foo classes --release 9 -C foo9 classes
+\ jar --create --file mr.jar -C foo classes --release 9 -C foo9 classes\n\
+\n\
+To shorten or simplify the jar command, you can specify arguments in a separate\n\
+text file and pass it to the jar command with the at sign (@) as a prefix.\n\
+\n\
+\ Examples:\n\
+\ # Read additional options and list of class files from the file classes.list\n\
+\ jar --create --file my.jar @classes.list\
+\n
main.help.opt.main=\
\ Main operation mode:\n
main.help.opt.main.create=\
@@ -224,7 +232,8 @@
\ -C DIR Change to the specified directory and include the\n\
\ following file
main.help.opt.any.file=\
-\ -f, --file=FILE The archive file name\n\
+\ -f, --file=FILE The archive file name. When omitted, either stdin or\n\
+\ stdout is used based on the operation\n\
\ --release VERSION Places all following files in a versioned directory\n\
\ of the jar (i.e. META-INF/versions/VERSION/)
main.help.opt.any.verbose=\
@@ -264,7 +273,7 @@
main.help.opt.other=\
\ Other options:\n
main.help.opt.other.help=\
-\ -?, --help[:compat] Give this, or optionally the compatibility, help
+\ -h, --help[:compat] Give this, or optionally the compatibility, help
main.help.opt.other.help-extra=\
\ --help-extra Give help on extra options
main.help.opt.other.version=\
--- a/jdk/src/jdk.jconsole/share/classes/module-info.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/jdk.jconsole/share/classes/module-info.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,12 +26,12 @@
module jdk.jconsole {
requires transitive java.desktop;
requires transitive java.management;
- requires java.logging;
+ requires java.management.rmi;
requires java.rmi;
requires jdk.attach;
requires jdk.internal.jvmstat;
requires jdk.management;
+ requires jdk.management.agent;
exports com.sun.tools.jconsole;
uses com.sun.tools.jconsole.JConsolePlugin;
}
-
--- a/jdk/src/jdk.jconsole/share/classes/sun/tools/jconsole/JConsole.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/jdk.jconsole/share/classes/sun/tools/jconsole/JConsole.java Thu Feb 09 23:15:52 2017 +0100
@@ -949,23 +949,12 @@
}
}
- private static final boolean localAttachmentSupported;
- static {
- boolean supported;
- try {
- Class.forName("com.sun.tools.attach.VirtualMachine");
- Class.forName("sun.management.ConnectorAddressLink");
- supported = true;
- } catch (NoClassDefFoundError x) {
- supported = false;
- } catch (ClassNotFoundException x) {
- supported = false;
- }
- localAttachmentSupported = supported;
- }
-
+ /**
+ * local attach is supported in this implementation as jdk.jconsole
+ * requires jdk.attach and jdk.management.agent
+ */
public static boolean isLocalAttachAvailable() {
- return localAttachmentSupported;
+ return true;
}
--- a/jdk/src/jdk.jconsole/share/classes/sun/tools/jconsole/LocalVirtualMachine.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/jdk.jconsole/share/classes/sun/tools/jconsole/LocalVirtualMachine.java Thu Feb 09 23:15:52 2017 +0100
@@ -29,13 +29,11 @@
import java.io.IOException;
import java.io.File;
-// Sun specific
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;
import com.sun.tools.attach.AttachNotSupportedException;
-// Sun private
-import sun.management.ConnectorAddressLink;
+import jdk.internal.agent.ConnectorAddressLink;
import sun.jvmstat.monitor.HostIdentifier;
import sun.jvmstat.monitor.MonitoredHost;
import sun.jvmstat.monitor.MonitoredVm;
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModuleSorter.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModuleSorter.java Thu Feb 09 23:15:52 2017 +0100
@@ -25,10 +25,12 @@
package jdk.tools.jlink.internal;
import jdk.tools.jlink.plugin.PluginException;
+import jdk.tools.jlink.plugin.ResourcePoolEntry;
import jdk.tools.jlink.plugin.ResourcePoolModule;
import jdk.tools.jlink.plugin.ResourcePoolModuleView;
import java.lang.module.ModuleDescriptor;
+import java.nio.ByteBuffer;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
@@ -53,10 +55,19 @@
moduleView.modules().forEach(this::addModule);
}
+ private ModuleDescriptor readModuleDescriptor(ResourcePoolModule module) {
+ String p = "/" + module.name() + "/module-info.class";
+ ResourcePoolEntry content = module.findEntry(p).orElseThrow(() ->
+ new PluginException("module-info.class not found for " +
+ module.name() + " module")
+ );
+ ByteBuffer bb = ByteBuffer.wrap(content.contentBytes());
+ return ModuleDescriptor.read(bb);
+ }
+
private ModuleSorter addModule(ResourcePoolModule module) {
- ModuleDescriptor descriptor = module.descriptor();
addNode(module);
- descriptor.requires().stream()
+ readModuleDescriptor(module).requires().stream()
.forEach(req -> {
String dm = req.name();
ResourcePoolModule dep = moduleView.findModule(dm)
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java Thu Feb 09 23:15:52 2017 +0100
@@ -227,12 +227,6 @@
addOrderedPluginOptions(plugin, optionsSeen);
}
}
- mainOptions.add(new PluginOption(false,
- (task, opt, arg) -> {
- // This option is handled prior
- // to have the options parsed.
- },
- false, "--plugin-module-path"));
mainOptions.add(new PluginOption(true, (task, opt, arg) -> {
for (Plugin plugin : plugins) {
if (plugin.getName().equals(arg)) {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java Thu Feb 09 23:15:52 2017 +0100
@@ -29,7 +29,11 @@
import java.io.IOException;
import java.io.InputStream;
import java.lang.module.ModuleDescriptor;
-import java.lang.module.ModuleDescriptor.*;
+import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.ModuleDescriptor.Opens;
+import java.lang.module.ModuleDescriptor.Provides;
+import java.lang.module.ModuleDescriptor.Requires;
+import java.lang.module.ModuleDescriptor.Version;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
@@ -41,8 +45,6 @@
import java.util.TreeSet;
import java.util.function.IntSupplier;
-import jdk.internal.misc.JavaLangModuleAccess;
-import jdk.internal.misc.SharedSecrets;
import jdk.internal.module.Checks;
import jdk.internal.module.ModuleHashes;
import jdk.internal.module.ModuleInfo.Attributes;
@@ -55,6 +57,7 @@
import static jdk.internal.org.objectweb.asm.Opcodes.*;
+import jdk.tools.jlink.internal.ModuleSorter;
import jdk.tools.jlink.plugin.PluginException;
import jdk.tools.jlink.plugin.ResourcePool;
import jdk.tools.jlink.plugin.Plugin;
@@ -63,7 +66,7 @@
/**
* Jlink plugin to reconstitute module descriptors for system modules.
- * It will extend module-info.class with Packages attribute,
+ * It will extend module-info.class with ModulePackages attribute,
* if not present. It also determines the number of packages of
* the boot layer at link time.
*
@@ -73,16 +76,15 @@
* @see SystemModules
*/
public final class SystemModulesPlugin implements Plugin {
- private static final JavaLangModuleAccess JLMA =
- SharedSecrets.getJavaLangModuleAccess();
-
private static final String NAME = "system-modules";
private static final String DESCRIPTION =
PluginsResourceBundle.getDescription(NAME);
private boolean enabled;
+ private boolean retainModuleTarget;
public SystemModulesPlugin() {
this.enabled = true;
+ this.retainModuleTarget = false;
}
@Override
@@ -102,9 +104,19 @@
}
@Override
+ public boolean hasArguments() {
+ return true;
+ }
+
+ @Override
public void configure(Map<String, String> config) {
- if (config.containsKey(NAME)) {
- enabled = false;
+ String arg = config.get(NAME);
+ if (arg != null) {
+ if (arg.equals("retainModuleTarget")) {
+ retainModuleTarget = true;
+ } else {
+ throw new IllegalArgumentException(NAME + ": " + arg);
+ }
}
}
@@ -114,12 +126,15 @@
throw new PluginException(NAME + " was set");
}
- SystemModulesClassGenerator generator = new SystemModulesClassGenerator();
+ SystemModulesClassGenerator generator =
+ new SystemModulesClassGenerator(retainModuleTarget);
// generate the byte code to create ModuleDescriptors
- // skip parsing module-info.class and skip name check
- in.moduleView().modules().forEach(module -> {
+ // such that the modules linked in the image would skip parsing
+ // of module-info.class and also skip name check
+ // Sort modules in the topological order so that java.base is always first.
+ new ModuleSorter(in.moduleView()).sorted().forEach(module -> {
ResourcePoolEntry data = module.findEntry("module-info.class").orElseThrow(
// automatic module not supported yet
() -> new PluginException("module-info.class not found for " +
@@ -128,19 +143,10 @@
assert module.name().equals(data.moduleName());
try {
- ModuleInfo moduleInfo = new ModuleInfo(data.contentBytes(), module.packages());
- generator.addModule(moduleInfo);
+ // validate the module and add to system modules
+ data = generator.buildModuleInfo(data, module.packages());
- // link-time validation
- moduleInfo.validateNames();
- // check if any exported or open package is not present
- moduleInfo.validatePackages();
-
- // Packages attribute needs update
- if (moduleInfo.shouldAddPackagesAttribute()) {
- // replace with the overridden version
- data = data.copyWithContent(moduleInfo.getBytes());
- }
+ // add resource pool entry
out.add(data);
} catch (IOException e) {
throw new PluginException(e);
@@ -164,29 +170,55 @@
return out.build();
}
- class ModuleInfo {
- final ModuleDescriptor descriptor;
- final ModuleHashes recordedHashes;
- final ModuleResolution moduleResolution;
- final Set<String> packages;
- final ByteArrayInputStream bain;
+ static class ModuleInfo {
+ private final Attributes attrs;
+ private final Set<String> packages;
+ private final ByteArrayInputStream bain;
+ private final boolean dropModuleTarget;
+ private ModuleDescriptor descriptor; // may be different that the original one
- ModuleInfo(byte[] bytes, Set<String> packages) throws IOException {
+ ModuleInfo(byte[] bytes, Set<String> packages, boolean dropModuleTarget)
+ throws IOException
+ {
this.bain = new ByteArrayInputStream(bytes);
this.packages = packages;
- Attributes attrs = jdk.internal.module.ModuleInfo.read(bain, null);
+ this.attrs = jdk.internal.module.ModuleInfo.read(bain, null);
this.descriptor = attrs.descriptor();
- this.recordedHashes = attrs.recordedHashes();
- this.moduleResolution = attrs.moduleResolution();
-
if (descriptor.isAutomatic()) {
throw new InternalError("linking automatic module is not supported");
}
+
+ if (dropModuleTarget) {
+ // drop target attribute only if any OS property is present
+ this.dropModuleTarget =
+ descriptor.osName().isPresent() ||
+ descriptor.osArch().isPresent() ||
+ descriptor.osVersion().isPresent();
+ } else {
+ this.dropModuleTarget = false;
+ }
}
String moduleName() {
- return descriptor.name();
+ return attrs.descriptor().name();
+ }
+
+ ModuleDescriptor descriptor() {
+ return descriptor;
+ }
+
+
+ Set<String> packages() {
+ return packages;
+ }
+
+ ModuleHashes recordedHashes() {
+ return attrs.recordedHashes();
+ }
+
+ ModuleResolution moduleResolution() {
+ return attrs.moduleResolution();
}
/**
@@ -217,6 +249,9 @@
for (String pn : descriptor.packages()) {
Checks.requirePackageName(pn);
}
+ for (String pn : packages) {
+ Checks.requirePackageName(pn);
+ }
}
@@ -242,22 +277,47 @@
}
/**
- * Returns true if the PackagesAttribute should be written
+ * Returns true if module-info.class should be written
+ * 1. add ModulePackages attribute if not present; or
+ * 2. drop ModuleTarget attribute except java.base
*/
- boolean shouldAddPackagesAttribute() {
- return descriptor.packages().isEmpty() && packages.size() > 0;
+ boolean shouldRewrite() {
+ return shouldAddModulePackages() || shouldDropModuleTarget();
+ }
+
+ boolean shouldAddModulePackages() {
+ return (descriptor.packages().isEmpty() && packages.size() > 0);
+ }
+
+ boolean shouldDropModuleTarget() {
+ return dropModuleTarget &&
+ (descriptor.osName().isPresent() ||
+ descriptor.osArch().isPresent() ||
+ descriptor.osVersion().isPresent());
}
/**
- * Returns the bytes for the module-info.class with PackagesAttribute
+ * Returns the bytes for the module-info.class with ModulePackages
* if it contains at least one package
*/
byte[] getBytes() throws IOException {
bain.reset();
- // add Packages attribute if not exist
- if (shouldAddPackagesAttribute()) {
- return new ModuleInfoRewriter(bain, packages).getBytes();
+ // add ModulePackages attribute if not exist
+ if (shouldRewrite()) {
+ ModuleInfoRewriter rewriter = new ModuleInfoRewriter(bain);
+ if (shouldAddModulePackages()) {
+ rewriter.addModulePackages(packages);
+ }
+ if (shouldDropModuleTarget()) {
+ rewriter.dropModuleTarget();
+ }
+ // rewritten module descriptor
+ byte[] bytes = rewriter.getBytes();
+ try (ByteArrayInputStream bain = new ByteArrayInputStream(bytes)) {
+ this.descriptor = ModuleDescriptor.read(bain);
+ }
+ return bytes;
} else {
return bain.readAllBytes();
}
@@ -265,16 +325,23 @@
class ModuleInfoRewriter extends ByteArrayOutputStream {
final ModuleInfoExtender extender;
- ModuleInfoRewriter(InputStream in, Set<String> packages) throws IOException {
+ ModuleInfoRewriter(InputStream in) {
this.extender = ModuleInfoExtender.newExtender(in);
- // Add Packages attribute
- if (packages.size() > 0) {
- this.extender.packages(packages);
- }
- this.extender.write(this);
}
- byte[] getBytes() {
+ void addModulePackages(Set<String> packages) {
+ // Add ModulePackages attribute
+ if (packages.size() > 0) {
+ extender.packages(packages);
+ }
+ }
+
+ void dropModuleTarget() {
+ extender.targetPlatform("", "", "");
+ }
+
+ byte[] getBytes() throws IOException {
+ extender.write(this);
return buf;
}
}
@@ -316,6 +383,7 @@
private int nextLocalVar = 2; // index to next local variable
private final ClassWriter cw;
+ private boolean dropModuleTarget;
// Method visitor for generating the SystemModules::modules() method
private MethodVisitor mv;
@@ -329,9 +397,10 @@
private final DedupSetBuilder dedupSetBuilder
= new DedupSetBuilder(this::getNextLocalVar);
- public SystemModulesClassGenerator() {
+ public SystemModulesClassGenerator(boolean retainModuleTarget) {
this.cw = new ClassWriter(ClassWriter.COMPUTE_MAXS +
ClassWriter.COMPUTE_FRAMES);
+ this.dropModuleTarget = !retainModuleTarget;
}
private int getNextLocalVar() {
@@ -395,14 +464,52 @@
}
/*
- * Adds the given ModuleDescriptor to the system module list, and
- * prepares mapping from various Sets to SetBuilders to emit an
- * optimized number of sets during build.
+ * Adds the given ModuleDescriptor to the system module list.
+ * It performs link-time validation and prepares mapping from various
+ * Sets to SetBuilders to emit an optimized number of sets during build.
*/
- public void addModule(ModuleInfo moduleInfo) {
- ModuleDescriptor md = moduleInfo.descriptor;
+ public ResourcePoolEntry buildModuleInfo(ResourcePoolEntry entry,
+ Set<String> packages)
+ throws IOException
+ {
+ if (moduleInfos.isEmpty() && !entry.moduleName().equals("java.base")) {
+ throw new InternalError("java.base must be the first module to process");
+ }
+
+ ModuleInfo moduleInfo;
+ if (entry.moduleName().equals("java.base")) {
+ moduleInfo = new ModuleInfo(entry.contentBytes(), packages, false);
+ ModuleDescriptor md = moduleInfo.descriptor;
+ // drop Moduletarget attribute only if java.base has all OS properties
+ // otherwise, retain it
+ if (dropModuleTarget &&
+ md.osName().isPresent() && md.osArch().isPresent() &&
+ md.osVersion().isPresent()) {
+ dropModuleTarget = true;
+ } else {
+ dropModuleTarget = false;
+ }
+ } else {
+ moduleInfo = new ModuleInfo(entry.contentBytes(), packages, dropModuleTarget);
+ }
+
+ // link-time validation
+ moduleInfo.validateNames();
+ // check if any exported or open package is not present
+ moduleInfo.validatePackages();
+
+ // module-info.class may be overridden for optimization
+ // 1. update ModuleTarget attribute to drop osName, osArch, osVersion
+ // 2. add/update ModulePackages attribute
+ if (moduleInfo.shouldRewrite()) {
+ entry = entry.copyWithContent(moduleInfo.getBytes());
+ }
moduleInfos.add(moduleInfo);
+ dedups(moduleInfo.descriptor());
+ return entry;
+ }
+ private void dedups(ModuleDescriptor md) {
// exports
for (Exports e : md.exports()) {
dedupSetBuilder.stringSet(e.targets());
@@ -466,8 +573,8 @@
for (int index = 0; index < moduleInfos.size(); index++) {
ModuleInfo minfo = moduleInfos.get(index);
- new ModuleDescriptorBuilder(minfo.descriptor,
- minfo.packages,
+ new ModuleDescriptorBuilder(minfo.descriptor(),
+ minfo.packages(),
index).build();
}
mv.visitVarInsn(ALOAD, MD_VAR);
@@ -494,8 +601,8 @@
for (int index = 0; index < moduleInfos.size(); index++) {
ModuleInfo minfo = moduleInfos.get(index);
- if (minfo.recordedHashes != null) {
- new ModuleHashesBuilder(minfo.recordedHashes,
+ if (minfo.recordedHashes() != null) {
+ new ModuleHashesBuilder(minfo.recordedHashes(),
index,
hmv).build();
}
@@ -525,12 +632,12 @@
for (int index=0; index < moduleInfos.size(); index++) {
ModuleInfo minfo = moduleInfos.get(index);
- if (minfo.moduleResolution != null) {
+ if (minfo.moduleResolution() != null) {
mresmv.visitVarInsn(ALOAD, 0);
pushInt(mresmv, index);
mresmv.visitTypeInsn(NEW, MODULE_RESOLUTION_CLASSNAME);
mresmv.visitInsn(DUP);
- mresmv.visitLdcInsn(minfo.moduleResolution.value());
+ mresmv.visitLdcInsn(minfo.moduleResolution().value());
mresmv.visitMethodInsn(INVOKESPECIAL,
MODULE_RESOLUTION_CLASSNAME,
"<init>",
@@ -644,6 +751,11 @@
// main class
md.mainClass().ifPresent(this::mainClass);
+ // os name, arch, version
+ targetPlatform(md.osName().orElse(null),
+ md.osArch().orElse(null),
+ md.osVersion().orElse(null));
+
putModuleDescriptor();
}
@@ -937,6 +1049,33 @@
"version", STRING_SIG, false);
mv.visitInsn(POP);
}
+
+ /*
+ * Invoke Builder.osName(String name)
+ * Builder.osArch(String arch)
+ * Builder.osVersion(String version)
+ */
+ void targetPlatform(String osName, String osArch, String osVersion) {
+ if (osName != null) {
+ invokeBuilderMethod("osName", osName);
+ }
+
+ if (osArch != null) {
+ invokeBuilderMethod("osArch", osArch);
+ }
+
+ if (osVersion != null) {
+ invokeBuilderMethod("osVersion", osVersion);
+ }
+ }
+
+ void invokeBuilderMethod(String methodName, String value) {
+ mv.visitVarInsn(ALOAD, BUILDER_VAR);
+ mv.visitLdcInsn(value);
+ mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
+ methodName, STRING_SIG, false);
+ mv.visitInsn(POP);
+ }
}
class ModuleHashesBuilder {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties Thu Feb 09 23:15:52 2017 +0100
@@ -28,7 +28,7 @@
\<path> use --help for a list of possible options
main.usage=\
-Usage: {0} <options> --module-path <modulepath> --add-modules <mods> --output
+Usage: {0} <options> --module-path <modulepath> --add-modules <mods> --output\n\
\<path> Possible options include:
error.prefix=Error:
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties Thu Feb 09 23:15:52 2017 +0100
@@ -81,6 +81,8 @@
Takes a file hinting to jlink what java.lang.invoke classes to pre-generate. If\n\
this flag is not specified a default set of classes will be generated.
+system-modules.argument=retainModuleTarget
+
system-modules.description=Fast loading of module descriptors (always enabled)
onoff.argument=<on|off>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/jdk/internal/agent/Agent.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,729 @@
+/*
+ * Copyright (c) 2003, 2017, 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.internal.agent;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.management.ManagementFactory;
+import java.lang.reflect.Method;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.UnknownHostException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.MissingResourceException;
+import java.util.Properties;
+import java.util.ResourceBundle;
+import java.util.ServiceLoader;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXServiceURL;
+
+import static jdk.internal.agent.AgentConfigurationError.*;
+import jdk.internal.agent.spi.AgentProvider;
+import jdk.internal.vm.VMSupport;
+import sun.management.jdp.JdpController;
+import sun.management.jdp.JdpException;
+import sun.management.jmxremote.ConnectorBootstrap;
+
+/**
+ * This Agent is started by the VM when -Dcom.sun.management.snmp or
+ * -Dcom.sun.management.jmxremote is set. This class will be loaded by the
+ * system class loader. Also jmx framework could be started by jcmd
+ */
+public class Agent {
+ /**
+ * Agent status collector strategy class
+ */
+ private static abstract class StatusCollector {
+ protected static final Map<String, String> DEFAULT_PROPS = new HashMap<>();
+
+ static {
+ DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.PORT,
+ ConnectorBootstrap.DefaultValues.PORT);
+ DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.USE_LOCAL_ONLY,
+ ConnectorBootstrap.DefaultValues.USE_LOCAL_ONLY);
+ DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.USE_AUTHENTICATION,
+ ConnectorBootstrap.DefaultValues.USE_AUTHENTICATION);
+ DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.USE_SSL,
+ ConnectorBootstrap.DefaultValues.USE_SSL);
+ DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.USE_REGISTRY_SSL,
+ ConnectorBootstrap.DefaultValues.USE_REGISTRY_SSL);
+ DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.SSL_NEED_CLIENT_AUTH,
+ ConnectorBootstrap.DefaultValues.SSL_NEED_CLIENT_AUTH);
+ DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.CONFIG_FILE_NAME,
+ ConnectorBootstrap.DefaultValues.CONFIG_FILE_NAME);
+ DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.PASSWORD_FILE_NAME,
+ ConnectorBootstrap.DefaultValues.PASSWORD_FILE_NAME);
+ DEFAULT_PROPS.put(ConnectorBootstrap.PropertyNames.ACCESS_FILE_NAME,
+ ConnectorBootstrap.DefaultValues.ACCESS_FILE_NAME);
+
+ }
+
+ final protected StringBuilder sb = new StringBuilder();
+ final public String collect() {
+ Properties agentProps = VMSupport.getAgentProperties();
+ String localConnAddr = (String)agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP);
+ if (localConnAddr != null || jmxServer != null) {
+ addAgentStatus(true);
+ appendConnections(localConnAddr);
+ } else {
+ addAgentStatus(false);
+ }
+ return sb.toString();
+ }
+
+ private void appendConnections(String localConnAddr) {
+ appendConnectionsHeader();
+ if (localConnAddr != null) {
+ try {
+ JMXServiceURL u = new JMXServiceURL(localConnAddr);
+ addConnection(false, u);
+ } catch (MalformedURLException e) {
+ // will never happen
+ }
+
+ }
+ if (jmxServer != null) {
+ addConnection(true, jmxServer.getAddress());
+ }
+ appendConnectionsFooter();
+ }
+
+ private void addConnection(boolean remote, JMXServiceURL u) {
+ appendConnectionHeader(remote);
+ addConnectionDetails(u);
+ addConfigProperties();
+ appendConnectionFooter(remote);
+ }
+
+ private void addConfigProperties() {
+ appendConfigPropsHeader();
+
+ Properties remoteProps = configProps != null ?
+ configProps : getManagementProperties();
+ Map<Object, Object> props = new HashMap<>(DEFAULT_PROPS);
+
+ if (remoteProps == null) {
+ // local connector only
+ String loc_only = System.getProperty(
+ ConnectorBootstrap.PropertyNames.USE_LOCAL_ONLY
+ );
+
+ if (loc_only != null &&
+ !ConnectorBootstrap.DefaultValues.USE_LOCAL_ONLY.equals(loc_only)) {
+ props.put(
+ ConnectorBootstrap.PropertyNames.USE_LOCAL_ONLY,
+ loc_only
+ );
+ }
+ } else {
+ props.putAll(remoteProps);
+ }
+
+ props.entrySet().stream()
+ .filter(preprocess(Map.Entry::getKey, StatusCollector::isManagementProp))
+ .forEach(this::addConfigProp);
+
+ appendConfigPropsFooter();
+ }
+
+ private static boolean isManagementProp(Object pName) {
+ return pName != null && pName.toString().startsWith("com.sun.management.");
+ }
+
+ private static <T, V> Predicate<T> preprocess(Function<T, V> f, Predicate<V> p) {
+ return (T t) -> p.test(f.apply(t));
+ }
+
+ abstract protected void addAgentStatus(boolean enabled);
+ abstract protected void appendConnectionsHeader();
+ abstract protected void appendConnectionsFooter();
+ abstract protected void addConnectionDetails(JMXServiceURL u);
+ abstract protected void appendConnectionHeader(boolean remote);
+ abstract protected void appendConnectionFooter(boolean remote);
+ abstract protected void appendConfigPropsHeader();
+ abstract protected void appendConfigPropsFooter();
+ abstract protected void addConfigProp(Map.Entry<?, ?> prop);
+ }
+
+ /**
+ * Free-text status collector strategy implementation
+ */
+ final private static class TextStatusCollector extends StatusCollector {
+
+ @Override
+ protected void addAgentStatus(boolean enabled) {
+ sb.append("Agent: ").append(enabled ? "enabled" : "disabled").append('\n');
+ }
+
+ @Override
+ protected void appendConnectionsHeader() {
+ sb.append('\n');
+ }
+
+ @Override
+ protected void addConnectionDetails(JMXServiceURL u) {
+ sb.append("Protocol : ").append(u.getProtocol()).append('\n')
+ .append("Host : ").append(u.getHost()).append('\n')
+ .append("URL : ").append(u).append('\n');
+ }
+
+ @Override
+ protected void appendConnectionHeader(boolean remote) {
+ sb.append("Connection Type: ").append(remote ? "remote" : "local").append('\n');
+ }
+
+ @Override
+ protected void appendConfigPropsHeader() {
+ sb.append("Properties :\n");
+ }
+
+ @Override
+ protected void addConfigProp(Map.Entry<?, ?> prop) {
+ sb.append(" ").append(prop.getKey()).append(" = ")
+ .append(prop.getValue());
+ Object defVal = DEFAULT_PROPS.get(prop.getKey());
+ if (defVal != null && defVal.equals(prop.getValue())) {
+ sb.append(" [default]");
+ }
+ sb.append("\n");
+ }
+
+ @Override
+ protected void appendConnectionsFooter() {}
+
+ @Override
+ protected void appendConnectionFooter(boolean remote) {
+ sb.append('\n');
+ }
+
+ @Override
+ protected void appendConfigPropsFooter() {}
+ }
+
+ // management properties
+
+ private static Properties mgmtProps;
+ private static ResourceBundle messageRB;
+ private static final String CONFIG_FILE =
+ "com.sun.management.config.file";
+ private static final String SNMP_PORT =
+ "com.sun.management.snmp.port";
+ private static final String JMXREMOTE =
+ "com.sun.management.jmxremote";
+ private static final String JMXREMOTE_PORT =
+ "com.sun.management.jmxremote.port";
+ private static final String RMI_PORT =
+ "com.sun.management.jmxremote.rmi.port";
+ private static final String ENABLE_THREAD_CONTENTION_MONITORING =
+ "com.sun.management.enableThreadContentionMonitoring";
+ private static final String LOCAL_CONNECTOR_ADDRESS_PROP =
+ "com.sun.management.jmxremote.localConnectorAddress";
+ private static final String SNMP_AGENT_NAME =
+ "SnmpAgent";
+
+ private static final String JDP_DEFAULT_ADDRESS = "224.0.23.178";
+ private static final int JDP_DEFAULT_PORT = 7095;
+
+ // The only active agent allowed
+ private static JMXConnectorServer jmxServer = null;
+ // The properties used to configure the server
+ private static Properties configProps = null;
+
+ // Parse string com.sun.management.prop=xxx,com.sun.management.prop=yyyy
+ // and return property set if args is null or empty
+ // return empty property set
+ private static Properties parseString(String args) {
+ Properties argProps = new Properties();
+ if (args != null && !args.trim().equals("")) {
+ for (String option : args.split(",")) {
+ String s[] = option.split("=", 2);
+ String name = s[0].trim();
+ String value = (s.length > 1) ? s[1].trim() : "";
+
+ if (!name.startsWith("com.sun.management.")) {
+ error(INVALID_OPTION, name);
+ }
+
+ argProps.setProperty(name, value);
+ }
+ }
+
+ return argProps;
+ }
+
+ // invoked by -javaagent or -Dcom.sun.management.agent.class
+ public static void premain(String args) throws Exception {
+ agentmain(args);
+ }
+
+ // invoked by attach mechanism
+ public static void agentmain(String args) throws Exception {
+ if (args == null || args.length() == 0) {
+ args = JMXREMOTE; // default to local management
+ }
+
+ Properties arg_props = parseString(args);
+
+ // Read properties from the config file
+ Properties config_props = new Properties();
+ String fname = arg_props.getProperty(CONFIG_FILE);
+ readConfiguration(fname, config_props);
+
+ // Arguments override config file
+ config_props.putAll(arg_props);
+ startAgent(config_props);
+ }
+
+ // jcmd ManagementAgent.start_local entry point
+ // Also called due to command-line via startAgent()
+ private static synchronized void startLocalManagementAgent() {
+ Properties agentProps = VMSupport.getAgentProperties();
+
+ // start local connector if not started
+ if (agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP) == null) {
+ JMXConnectorServer cs = ConnectorBootstrap.startLocalConnectorServer();
+ String address = cs.getAddress().toString();
+ // Add the local connector address to the agent properties
+ agentProps.put(LOCAL_CONNECTOR_ADDRESS_PROP, address);
+
+ try {
+ // export the address to the instrumentation buffer
+ ConnectorAddressLink.export(address);
+ } catch (Exception x) {
+ // Connector server started but unable to export address
+ // to instrumentation buffer - non-fatal error.
+ warning(EXPORT_ADDRESS_FAILED, x.getMessage());
+ }
+ }
+ }
+
+ // jcmd ManagementAgent.start entry point
+ // This method starts the remote JMX agent and starts neither
+ // the local JMX agent nor the SNMP agent
+ // @see #startLocalManagementAgent and also @see #startAgent.
+ private static synchronized void startRemoteManagementAgent(String args) throws Exception {
+ if (jmxServer != null) {
+ throw new RuntimeException(getText(INVALID_STATE, "Agent already started"));
+ }
+
+ try {
+ Properties argProps = parseString(args);
+ configProps = new Properties();
+
+ // Load the management properties from the config file
+ // if config file is not specified readConfiguration implicitly
+ // reads <java.home>/conf/management/management.properties
+
+ String fname = System.getProperty(CONFIG_FILE);
+ readConfiguration(fname, configProps);
+
+ // management properties can be overridden by system properties
+ // which take precedence
+ Properties sysProps = System.getProperties();
+ synchronized (sysProps) {
+ configProps.putAll(sysProps);
+ }
+
+ // if user specifies config file into command line for either
+ // jcmd utilities or attach command it overrides properties set in
+ // command line at the time of VM start
+ String fnameUser = argProps.getProperty(CONFIG_FILE);
+ if (fnameUser != null) {
+ readConfiguration(fnameUser, configProps);
+ }
+
+ // arguments specified in command line of jcmd utilities
+ // override both system properties and one set by config file
+ // specified in jcmd command line
+ configProps.putAll(argProps);
+
+ // jcmd doesn't allow to change ThreadContentionMonitoring, but user
+ // can specify this property inside config file, so enable optional
+ // monitoring functionality if this property is set
+ final String enableThreadContentionMonitoring =
+ configProps.getProperty(ENABLE_THREAD_CONTENTION_MONITORING);
+
+ if (enableThreadContentionMonitoring != null) {
+ ManagementFactory.getThreadMXBean().
+ setThreadContentionMonitoringEnabled(true);
+ }
+
+ String jmxremotePort = configProps.getProperty(JMXREMOTE_PORT);
+ if (jmxremotePort != null) {
+ jmxServer = ConnectorBootstrap.
+ startRemoteConnectorServer(jmxremotePort, configProps);
+
+ startDiscoveryService(configProps);
+ } else {
+ throw new AgentConfigurationError(INVALID_JMXREMOTE_PORT, "No port specified");
+ }
+ } catch (JdpException e) {
+ error(e);
+ } catch (AgentConfigurationError err) {
+ error(err.getError(), err.getParams());
+ }
+ }
+
+ private static synchronized void stopRemoteManagementAgent() throws Exception {
+
+ JdpController.stopDiscoveryService();
+
+ if (jmxServer != null) {
+ ConnectorBootstrap.unexportRegistry();
+ ConnectorAddressLink.unexportRemote();
+
+ // Attempt to stop already stopped agent
+ // Don't cause any errors.
+ jmxServer.stop();
+ jmxServer = null;
+ configProps = null;
+ }
+ }
+
+ private static synchronized String getManagementAgentStatus() throws Exception {
+ return new TextStatusCollector().collect();
+ }
+
+ private static void startAgent(Properties props) throws Exception {
+ String snmpPort = props.getProperty(SNMP_PORT);
+ String jmxremote = props.getProperty(JMXREMOTE);
+ String jmxremotePort = props.getProperty(JMXREMOTE_PORT);
+
+ // Enable optional monitoring functionality if requested
+ final String enableThreadContentionMonitoring =
+ props.getProperty(ENABLE_THREAD_CONTENTION_MONITORING);
+ if (enableThreadContentionMonitoring != null) {
+ ManagementFactory.getThreadMXBean().
+ setThreadContentionMonitoringEnabled(true);
+ }
+
+ try {
+ if (snmpPort != null) {
+ loadSnmpAgent(props);
+ }
+
+ /*
+ * If the jmxremote.port property is set then we start the
+ * RMIConnectorServer for remote M&M.
+ *
+ * If the jmxremote or jmxremote.port properties are set then
+ * we start a RMIConnectorServer for local M&M. The address
+ * of this "local" server is exported as a counter to the jstat
+ * instrumentation buffer.
+ */
+ if (jmxremote != null || jmxremotePort != null) {
+ if (jmxremotePort != null) {
+ jmxServer = ConnectorBootstrap.
+ startRemoteConnectorServer(jmxremotePort, props);
+ startDiscoveryService(props);
+ }
+ startLocalManagementAgent();
+ }
+
+ } catch (AgentConfigurationError e) {
+ error(e.getError(), e.getParams());
+ } catch (Exception e) {
+ error(e);
+ }
+ }
+
+ private static void startDiscoveryService(Properties props)
+ throws IOException, JdpException {
+ // Start discovery service if requested
+ String discoveryPort = props.getProperty("com.sun.management.jdp.port");
+ String discoveryAddress = props.getProperty("com.sun.management.jdp.address");
+ String discoveryShouldStart = props.getProperty("com.sun.management.jmxremote.autodiscovery");
+
+ // Decide whether we should start autodicovery service.
+ // To start autodiscovery following conditions should be met:
+ // autodiscovery==true OR (autodicovery==null AND jdp.port != NULL)
+
+ boolean shouldStart = false;
+ if (discoveryShouldStart == null){
+ shouldStart = (discoveryPort != null);
+ }
+ else{
+ try{
+ shouldStart = Boolean.parseBoolean(discoveryShouldStart);
+ } catch (NumberFormatException e) {
+ throw new AgentConfigurationError(AGENT_EXCEPTION, "Couldn't parse autodiscovery argument");
+ }
+ }
+
+ if (shouldStart) {
+ // port and address are required arguments and have no default values
+ InetAddress address;
+ try {
+ address = (discoveryAddress == null) ?
+ InetAddress.getByName(JDP_DEFAULT_ADDRESS) : InetAddress.getByName(discoveryAddress);
+ } catch (UnknownHostException e) {
+ throw new AgentConfigurationError(AGENT_EXCEPTION, e, "Unable to broadcast to requested address");
+ }
+
+ int port = JDP_DEFAULT_PORT;
+ if (discoveryPort != null) {
+ try {
+ port = Integer.parseInt(discoveryPort);
+ } catch (NumberFormatException e) {
+ throw new AgentConfigurationError(AGENT_EXCEPTION, "Couldn't parse JDP port argument");
+ }
+ }
+
+ // Get service URL to broadcast it
+ Map<String,String> remoteProps = ConnectorAddressLink.importRemoteFrom(0);
+ String jmxUrlStr = remoteProps.get("sun.management.JMXConnectorServer.0.remoteAddress");
+
+ String instanceName = props.getProperty("com.sun.management.jdp.name");
+
+ JdpController.startDiscoveryService(address, port, instanceName, jmxUrlStr);
+ }
+ }
+
+ public static Properties loadManagementProperties() {
+ Properties props = new Properties();
+
+ // Load the management properties from the config file
+
+ String fname = System.getProperty(CONFIG_FILE);
+ readConfiguration(fname, props);
+
+ // management properties can be overridden by system properties
+ // which take precedence
+ Properties sysProps = System.getProperties();
+ synchronized (sysProps) {
+ props.putAll(sysProps);
+ }
+
+ return props;
+ }
+
+ public static synchronized Properties getManagementProperties() {
+ if (mgmtProps == null) {
+ String configFile = System.getProperty(CONFIG_FILE);
+ String snmpPort = System.getProperty(SNMP_PORT);
+ String jmxremote = System.getProperty(JMXREMOTE);
+ String jmxremotePort = System.getProperty(JMXREMOTE_PORT);
+
+ if (configFile == null && snmpPort == null
+ && jmxremote == null && jmxremotePort == null) {
+ // return if out-of-the-management option is not specified
+ return null;
+ }
+ mgmtProps = loadManagementProperties();
+ }
+ return mgmtProps;
+ }
+
+ private static void loadSnmpAgent(Properties props) {
+ /*
+ * Load the jdk.snmp service
+ */
+ AgentProvider provider = AccessController.doPrivileged(
+ (PrivilegedAction<AgentProvider>) () -> {
+ for (AgentProvider aProvider : ServiceLoader.loadInstalled(AgentProvider.class)) {
+ if (aProvider.getName().equals(SNMP_AGENT_NAME))
+ return aProvider;
+ }
+ return null;
+ }, null
+ );
+
+ if (provider != null) {
+ provider.startAgent(props);
+ } else { // snmp runtime doesn't exist - initialization fails
+ throw new UnsupportedOperationException("Unsupported management property: " + SNMP_PORT);
+ }
+ }
+
+ // read config file and initialize the properties
+ private static void readConfiguration(String fname, Properties p) {
+ if (fname == null) {
+ String home = System.getProperty("java.home");
+ if (home == null) {
+ throw new Error("Can't find java.home ??");
+ }
+ StringBuilder defaultFileName = new StringBuilder(home);
+ defaultFileName.append(File.separator).append("conf");
+ defaultFileName.append(File.separator).append("management");
+ defaultFileName.append(File.separator).append("management.properties");
+ // Set file name
+ fname = defaultFileName.toString();
+ }
+ final File configFile = new File(fname);
+ if (!configFile.exists()) {
+ error(CONFIG_FILE_NOT_FOUND, fname);
+ }
+
+ InputStream in = null;
+ try {
+ in = new FileInputStream(configFile);
+ BufferedInputStream bin = new BufferedInputStream(in);
+ p.load(bin);
+ } catch (FileNotFoundException e) {
+ error(CONFIG_FILE_OPEN_FAILED, e.getMessage());
+ } catch (IOException e) {
+ error(CONFIG_FILE_OPEN_FAILED, e.getMessage());
+ } catch (SecurityException e) {
+ error(CONFIG_FILE_ACCESS_DENIED, fname);
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ error(CONFIG_FILE_CLOSE_FAILED, fname);
+ }
+ }
+ }
+ }
+
+ public static void startAgent() throws Exception {
+ String prop = System.getProperty("com.sun.management.agent.class");
+
+ // -Dcom.sun.management.agent.class not set so read management
+ // properties and start agent
+ if (prop == null) {
+ // initialize management properties
+ Properties props = getManagementProperties();
+ if (props != null) {
+ startAgent(props);
+ }
+ return;
+ }
+
+ // -Dcom.sun.management.agent.class=<agent classname>:<agent args>
+ String[] values = prop.split(":");
+ if (values.length < 1 || values.length > 2) {
+ error(AGENT_CLASS_INVALID, "\"" + prop + "\"");
+ }
+ String cname = values[0];
+ String args = (values.length == 2 ? values[1] : null);
+
+ if (cname == null || cname.length() == 0) {
+ error(AGENT_CLASS_INVALID, "\"" + prop + "\"");
+ }
+
+ if (cname != null) {
+ try {
+ // Instantiate the named class.
+ // invoke the premain(String args) method
+ Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(cname);
+ Method premain = clz.getMethod("premain",
+ new Class<?>[]{String.class});
+ premain.invoke(null, /* static */
+ new Object[]{args});
+ } catch (ClassNotFoundException ex) {
+ error(AGENT_CLASS_NOT_FOUND, "\"" + cname + "\"");
+ } catch (NoSuchMethodException ex) {
+ error(AGENT_CLASS_PREMAIN_NOT_FOUND, "\"" + cname + "\"");
+ } catch (SecurityException ex) {
+ error(AGENT_CLASS_ACCESS_DENIED);
+ } catch (Exception ex) {
+ String msg = (ex.getCause() == null
+ ? ex.getMessage()
+ : ex.getCause().getMessage());
+ error(AGENT_CLASS_FAILED, msg);
+ }
+ }
+ }
+
+ public static void error(String key) {
+ String keyText = getText(key);
+ System.err.print(getText("agent.err.error") + ": " + keyText);
+ throw new RuntimeException(keyText);
+ }
+
+ public static void error(String key, String[] params) {
+ if (params == null || params.length == 0) {
+ error(key);
+ } else {
+ StringBuilder message = new StringBuilder(params[0]);
+ for (int i = 1; i < params.length; i++) {
+ message.append(' ').append(params[i]);
+ }
+ error(key, message.toString());
+ }
+ }
+
+ public static void error(String key, String message) {
+ String keyText = getText(key);
+ System.err.print(getText("agent.err.error") + ": " + keyText);
+ System.err.println(": " + message);
+ throw new RuntimeException(keyText + ": " + message);
+ }
+
+ public static void error(Exception e) {
+ e.printStackTrace();
+ System.err.println(getText(AGENT_EXCEPTION) + ": " + e.toString());
+ throw new RuntimeException(e);
+ }
+
+ public static void warning(String key, String message) {
+ System.err.print(getText("agent.err.warning") + ": " + getText(key));
+ System.err.println(": " + message);
+ }
+
+ private static void initResource() {
+ try {
+ messageRB =
+ ResourceBundle.getBundle("jdk.internal.agent.resources.agent");
+ } catch (MissingResourceException e) {
+ throw new Error("Fatal: Resource for management agent is missing");
+ }
+ }
+
+ public static String getText(String key) {
+ if (messageRB == null) {
+ initResource();
+ }
+ try {
+ return messageRB.getString(key);
+ } catch (MissingResourceException e) {
+ return "Missing management agent resource bundle: key = \"" + key + "\"";
+ }
+ }
+
+ public static String getText(String key, String... args) {
+ if (messageRB == null) {
+ initResource();
+ }
+ String format = messageRB.getString(key);
+ if (format == null) {
+ format = "missing resource key: key = \"" + key + "\", "
+ + "arguments = \"{0}\", \"{1}\", \"{2}\"";
+ }
+ return MessageFormat.format(format, (Object[]) args);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/jdk/internal/agent/AgentConfigurationError.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2004, 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.
+ */
+
+package jdk.internal.agent;
+
+/**
+ * Configuration Error thrown by a management agent.
+ */
+public class AgentConfigurationError extends Error {
+ public static final String AGENT_EXCEPTION =
+ "agent.err.exception";
+ public static final String CONFIG_FILE_NOT_FOUND =
+ "agent.err.configfile.notfound";
+ public static final String CONFIG_FILE_OPEN_FAILED =
+ "agent.err.configfile.failed";
+ public static final String CONFIG_FILE_CLOSE_FAILED =
+ "agent.err.configfile.closed.failed";
+ public static final String CONFIG_FILE_ACCESS_DENIED =
+ "agent.err.configfile.access.denied";
+ public static final String EXPORT_ADDRESS_FAILED =
+ "agent.err.exportaddress.failed";
+ public static final String AGENT_CLASS_NOT_FOUND =
+ "agent.err.agentclass.notfound";
+ public static final String AGENT_CLASS_FAILED =
+ "agent.err.agentclass.failed";
+ public static final String AGENT_CLASS_PREMAIN_NOT_FOUND =
+ "agent.err.premain.notfound";
+ public static final String AGENT_CLASS_ACCESS_DENIED =
+ "agent.err.agentclass.access.denied";
+ public static final String AGENT_CLASS_INVALID =
+ "agent.err.invalid.agentclass";
+ public static final String INVALID_JMXREMOTE_PORT =
+ "agent.err.invalid.jmxremote.port";
+ public static final String INVALID_JMXREMOTE_RMI_PORT =
+ "agent.err.invalid.jmxremote.rmi.port";
+ public static final String PASSWORD_FILE_NOT_SET =
+ "agent.err.password.file.notset";
+ public static final String PASSWORD_FILE_NOT_READABLE =
+ "agent.err.password.file.not.readable";
+ public static final String PASSWORD_FILE_READ_FAILED =
+ "agent.err.password.file.read.failed";
+ public static final String PASSWORD_FILE_NOT_FOUND =
+ "agent.err.password.file.notfound";
+ public static final String ACCESS_FILE_NOT_SET =
+ "agent.err.access.file.notset";
+ public static final String ACCESS_FILE_NOT_READABLE =
+ "agent.err.access.file.not.readable";
+ public static final String ACCESS_FILE_READ_FAILED =
+ "agent.err.access.file.read.failed";
+ public static final String ACCESS_FILE_NOT_FOUND =
+ "agent.err.access.file.notfound";
+ public static final String PASSWORD_FILE_ACCESS_NOT_RESTRICTED =
+ "agent.err.password.file.access.notrestricted";
+ public static final String FILE_ACCESS_NOT_RESTRICTED =
+ "agent.err.file.access.not.restricted";
+ public static final String FILE_NOT_FOUND =
+ "agent.err.file.not.found";
+ public static final String FILE_NOT_READABLE =
+ "agent.err.file.not.readable";
+ public static final String FILE_NOT_SET =
+ "agent.err.file.not.set";
+ public static final String FILE_READ_FAILED =
+ "agent.err.file.read.failed";
+ public static final String CONNECTOR_SERVER_IO_ERROR =
+ "agent.err.connector.server.io.error";
+ public static final String INVALID_OPTION =
+ "agent.err.invalid.option";
+ public static final String INVALID_STATE =
+ "agent.err.invalid.state";
+
+ private final String error;
+ private final String[] params;
+
+ public AgentConfigurationError(String error) {
+ super();
+ this.error = error;
+ this.params = null;
+ }
+
+ public AgentConfigurationError(String error, Throwable cause) {
+ super(cause);
+ this.error = error;
+ this.params = null;
+ }
+
+ public AgentConfigurationError(String error, String... params) {
+ super();
+ this.error = error;
+ this.params = params.clone();
+ }
+
+ public AgentConfigurationError(String error, Throwable cause, String... params) {
+ super(cause);
+ this.error = error;
+ this.params = params.clone();
+ }
+
+ public String getError() {
+ return error;
+ }
+
+ public String[] getParams() {
+ return params.clone();
+ }
+
+ private static final long serialVersionUID = 1211605593516195475L;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/jdk/internal/agent/ConnectorAddressLink.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2004, 2015, 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.internal.agent;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import jdk.internal.perf.Perf;
+import sun.management.counter.Units;
+import sun.management.counter.Counter;
+import sun.management.counter.perf.PerfInstrumentation;
+
+/**
+ * A utility class to support the exporting and importing of the address
+ * of a connector server using the instrumentation buffer.
+ *
+ * @since 1.5
+ */
+public class ConnectorAddressLink {
+ /**
+ * A simple wrapper for the perf-counter backing {@linkplain ByteBuffer}
+ */
+ private static final class PerfHandle {
+ private ByteBuffer bb;
+
+ private PerfHandle(ByteBuffer bb) {
+ this.bb = bb.order(ByteOrder.nativeOrder());
+ }
+
+ private void putLong(long l) {
+ this.bb = bb.clear();
+ this.bb.asLongBuffer().put(l);
+ }
+ }
+
+ private static final String CONNECTOR_ADDRESS_COUNTER =
+ "sun.management.JMXConnectorServer.address";
+ private static final String REMOTE_CONNECTOR_STATE_COUNTER =
+ "sun.management.JMXConnectorServer.remote.enabled";
+
+ /*
+ * The format of the jvmstat counters representing the properties of
+ * a given out-of-the-box JMX remote connector will be as follows:
+ *
+ * sun.management.JMXConnectorServer.<counter>.<key>=<value>
+ *
+ * where:
+ *
+ * counter = index computed by this class which uniquely identifies
+ * an out-of-the-box JMX remote connector running in this
+ * Java virtual machine.
+ * key/value = a given key/value pair in the map supplied to the
+ * exportRemote() method.
+ *
+ * For example,
+ *
+ * sun.management.JMXConnectorServer.0.remoteAddress=service:jmx:rmi:///jndi/rmi://myhost:5000/jmxrmi
+ * sun.management.JMXConnectorServer.0.authenticate=false
+ * sun.management.JMXConnectorServer.0.ssl=false
+ * sun.management.JMXConnectorServer.0.sslRegistry=false
+ * sun.management.JMXConnectorServer.0.sslNeedClientAuth=false
+ */
+ private static final String REMOTE_CONNECTOR_COUNTER_PREFIX =
+ "sun.management.JMXConnectorServer.";
+
+ /*
+ * JMX remote connector counter (it will be incremented every
+ * time a new out-of-the-box JMX remote connector is created).
+ */
+ private static final AtomicInteger counter = new AtomicInteger();
+
+ private static PerfHandle remotePerfHandle = null;
+
+ /**
+ * Exports the specified connector address to the instrumentation buffer
+ * so that it can be read by this or other Java virtual machines running
+ * on the same system.
+ *
+ * @param address The connector address.
+ */
+ public static void export(String address) {
+ if (address == null || address.length() == 0) {
+ throw new IllegalArgumentException("address not specified");
+ }
+ Perf perf = Perf.getPerf();
+ perf.createString(
+ CONNECTOR_ADDRESS_COUNTER, 1, Units.STRING.intValue(), address);
+ }
+
+ public static void unexportRemote() {
+ unexport(remotePerfHandle);
+ }
+
+ private static void unexport(PerfHandle ph) {
+ if (ph != null) {
+ ph.putLong(-1L);
+ }
+ }
+
+ /**
+ * Imports the connector address from the instrument buffer
+ * of the specified Java virtual machine.
+ *
+ * @param vmid an identifier that uniquely identifies a local Java virtual
+ * machine, or <code>0</code> to indicate the current Java virtual machine.
+ *
+ * @return the value of the connector address, or <code>null</code> if the
+ * target VM has not exported a connector address.
+ *
+ * @throws IOException An I/O error occurred while trying to acquire the
+ * instrumentation buffer.
+ */
+ public static String importFrom(int vmid) throws IOException {
+ Perf perf = Perf.getPerf();
+ ByteBuffer bb;
+ try {
+ bb = perf.attach(vmid, "r");
+ } catch (IllegalArgumentException iae) {
+ throw new IOException(iae.getMessage());
+ }
+ List<Counter> counters =
+ new PerfInstrumentation(bb).findByPattern(CONNECTOR_ADDRESS_COUNTER);
+ Iterator<Counter> i = counters.iterator();
+ if (i.hasNext()) {
+ Counter c = i.next();
+ return (String) c.getValue();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Exports the specified remote connector address and associated
+ * configuration properties to the instrumentation buffer so that
+ * it can be read by this or other Java virtual machines running
+ * on the same system.
+ *
+ * @param properties The remote connector address properties.
+ */
+ public static void exportRemote(Map<String, String> properties) {
+ final int index = counter.getAndIncrement();
+ Perf perf = Perf.getPerf();
+ for (Map.Entry<String, String> entry : properties.entrySet()) {
+ perf.createString(REMOTE_CONNECTOR_COUNTER_PREFIX + index + "." +
+ entry.getKey(), 1, Units.STRING.intValue(), entry.getValue());
+ }
+ if (remotePerfHandle != null) {
+ remotePerfHandle.putLong(index);
+ } else {
+ remotePerfHandle = new PerfHandle(
+ perf.createLong(REMOTE_CONNECTOR_STATE_COUNTER, 1, Units.NONE.intValue(), (long)index)
+ );
+ }
+ }
+
+ /**
+ * Imports the remote connector address and associated
+ * configuration properties from the instrument buffer
+ * of the specified Java virtual machine.
+ *
+ * @param vmid an identifier that uniquely identifies a local Java virtual
+ * machine, or <code>0</code> to indicate the current Java virtual machine.
+ *
+ * @return a map containing the remote connector's properties, or an empty
+ * map if the target VM has not exported the remote connector's properties.
+ *
+ * @throws IOException An I/O error occurred while trying to acquire the
+ * instrumentation buffer.
+ */
+ public static Map<String, String> importRemoteFrom(int vmid) throws IOException {
+ Perf perf = Perf.getPerf();
+ ByteBuffer bb;
+ try {
+ bb = perf.attach(vmid, "r");
+ } catch (IllegalArgumentException iae) {
+ throw new IOException(iae.getMessage());
+ }
+ List<Counter> counters = new PerfInstrumentation(bb).getAllCounters();
+ Map<String, String> properties = new HashMap<>();
+ for (Counter c : counters) {
+ String name = c.getName();
+ if (name.startsWith(REMOTE_CONNECTOR_COUNTER_PREFIX) &&
+ !name.equals(CONNECTOR_ADDRESS_COUNTER)) {
+ properties.put(name, c.getValue().toString());
+ }
+ }
+ return properties;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/jdk/internal/agent/FileSystem.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2004, 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.internal.agent;
+
+import java.io.File;
+import java.io.IOException;
+
+/*
+ * Utility class to support file system operations
+ *
+ * @since 1.5
+ */
+public abstract class FileSystem {
+
+ private static final Object lock = new Object();
+ private static FileSystem fs;
+
+ protected FileSystem() { }
+
+ /**
+ * Opens the file system
+ */
+ public static FileSystem open() {
+ synchronized (lock) {
+ if (fs == null) {
+ fs = new FileSystemImpl();
+ }
+ return fs;
+ }
+ }
+
+ /**
+ * Tells whether or not the specified file is located on a
+ * file system that supports file security or not.
+ *
+ * @throws IOException if an I/O error occurs.
+ */
+ public abstract boolean supportsFileSecurity(File f) throws IOException;
+
+ /**
+ * Tell whether or not the specified file is accessible
+ * by anything other than the file owner.
+ *
+ * @throws IOException if an I/O error occurs.
+ *
+ * @throws UnsupportedOperationException
+ * If file is located on a file system that doesn't support
+ * file security.
+ */
+ public abstract boolean isAccessUserOnly(File f) throws IOException;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/jdk/internal/agent/resources/agent.properties Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,71 @@
+#
+# Copyright (c) 2004, 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. 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.
+#
+
+agent.err.error = Error
+agent.err.exception = Exception thrown by the agent
+agent.err.warning = Warning
+
+agent.err.configfile.notfound = Config file not found
+agent.err.configfile.failed = Failed in reading the config file
+agent.err.configfile.closed.failed = Failed in closing the config file
+agent.err.configfile.access.denied = Access to the config file is denied
+
+agent.err.exportaddress.failed = Export of JMX connector address to instrumentation buffer failed
+
+agent.err.agentclass.notfound = Management agent class not found
+agent.err.agentclass.failed = Management agent class failed
+agent.err.premain.notfound = premain(String) does not exist in agent class
+agent.err.agentclass.access.denied = Access to premain(String) is denied
+agent.err.invalid.agentclass = Invalid com.sun.management.agent.class property value
+agent.err.invalid.state = Invalid agent state: {0}
+agent.err.invalid.jmxremote.port = Invalid com.sun.management.jmxremote.port number
+agent.err.invalid.jmxremote.rmi.port = Invalid com.sun.management.jmxremote.rmi.port number
+
+agent.err.file.not.set = File not specified
+agent.err.file.not.readable = File not readable
+agent.err.file.read.failed = Failed in reading the file
+agent.err.file.not.found = File not found
+agent.err.file.access.not.restricted = File read access must be restricted
+
+agent.err.password.file.notset = Password file is not specified but com.sun.management.jmxremote.authenticate=true
+agent.err.password.file.not.readable = Password file not readable
+agent.err.password.file.read.failed = Failed in reading the password file
+agent.err.password.file.notfound = Password file not found
+agent.err.password.file.access.notrestricted = Password file read access must be restricted
+
+agent.err.access.file.notset = Access file is not specified but com.sun.management.jmxremote.authenticate=true
+agent.err.access.file.not.readable = Access file not readable
+agent.err.access.file.read.failed = Failed in reading the access file
+agent.err.access.file.notfound = Access file not found
+
+agent.err.connector.server.io.error = JMX connector server communication error
+
+agent.err.invalid.option = Invalid option specified
+
+jmxremote.ConnectorBootstrap.starting = Starting JMX Connector Server:
+jmxremote.ConnectorBootstrap.noAuthentication = No Authentication
+jmxremote.ConnectorBootstrap.ready = JMX Connector ready at: {0}
+jmxremote.ConnectorBootstrap.password.readonly = Password file read access must be restricted: {0}
+jmxremote.ConnectorBootstrap.file.readonly = File read access must be restricted: {0}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/jdk/internal/agent/resources/agent_de.properties Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,71 @@
+#
+# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+agent.err.error = Fehler
+agent.err.exception = Ausnahme von Agent ausgel\u00F6st
+agent.err.warning = Warnung
+
+agent.err.configfile.notfound = Konfigurationsdatei wurde nicht gefunden
+agent.err.configfile.failed = Konfigurationsdatei konnte nicht gelesen werden
+agent.err.configfile.closed.failed = Konfigurationsdatei konnte nicht geschlossen werden
+agent.err.configfile.access.denied = Zugriff auf Konfigurationsdatei wurde abgelehnt
+
+agent.err.exportaddress.failed = Export der JMX-Connector-Adresse in Instrumentierungspuffer nicht erfolgreich
+
+agent.err.agentclass.notfound = Management Agent-Klasse nicht gefunden
+agent.err.agentclass.failed = Management Agent-Klasse nicht erfolgreich
+agent.err.premain.notfound = premain(String) ist in Agent-Klasse nicht vorhanden
+agent.err.agentclass.access.denied = Zugriff auf premain(String) wurde abgelehnt
+agent.err.invalid.agentclass = Ung\u00FCltiger Eigenschaftswert f\u00FCr com.sun.management.agent.class
+agent.err.invalid.state = Ung\u00FCltiger Agent-Zustand: {0}
+agent.err.invalid.jmxremote.port = Ung\u00FCltige Nummer f\u00FCr com.sun.management.jmxremote.port
+agent.err.invalid.jmxremote.rmi.port = Ung\u00FCltige Nummer f\u00FCr com.sun.management.jmxremote.rmi.port
+
+agent.err.file.not.set = Datei nicht angegeben
+agent.err.file.not.readable = Datei nicht lesbar
+agent.err.file.read.failed = Datei konnte nicht gelesen werden
+agent.err.file.not.found = Datei wurde nicht gefunden
+agent.err.file.access.not.restricted = Lesezugriff auf Datei muss eingeschr\u00E4nkt werden
+
+agent.err.password.file.notset = Es wurde keine Kennwortdatei angegeben, obwohl com.sun.management.jmxremote.authenticate auf "true" gesetzt ist
+agent.err.password.file.not.readable = Kennwortdatei nicht lesbar
+agent.err.password.file.read.failed = Kennwortdatei konnte nicht gelesen werden
+agent.err.password.file.notfound = Kennwortdatei nicht gefunden
+agent.err.password.file.access.notrestricted = Lesezugriff auf Kennwortdatei muss eingeschr\u00E4nkt werden
+
+agent.err.access.file.notset = Es wurde keine Zugriffsdatei angegeben, obwohl com.sun.management.jmxremote.authenticate auf "true" gesetzt ist
+agent.err.access.file.not.readable = Zugriffsdatei kann nicht gelesen werden
+agent.err.access.file.read.failed = Zugriffsdatei konnte nicht gelesen werden
+agent.err.access.file.notfound = Zugriffsdatei nicht gefunden
+
+agent.err.connector.server.io.error = Fehler bei JMX-Connector-Serverkommunikation
+
+agent.err.invalid.option = Ung\u00FCltige Option angegeben
+
+jmxremote.ConnectorBootstrap.starting = JMX-Connector-Server starten:
+jmxremote.ConnectorBootstrap.noAuthentication = Keine Authentifizierung
+jmxremote.ConnectorBootstrap.ready = JMX-Connector bereit unter: {0}
+jmxremote.ConnectorBootstrap.password.readonly = Lesezugriff auf Kennwortdatei muss eingeschr\u00E4nkt werden: {0}
+jmxremote.ConnectorBootstrap.file.readonly = Lesezugriff auf Datei muss eingeschr\u00E4nkt werden: {0}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/jdk/internal/agent/resources/agent_es.properties Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,71 @@
+#
+# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+agent.err.error = Error
+agent.err.exception = Excepci\u00F3n devuelta por el agente
+agent.err.warning = Advertencia
+
+agent.err.configfile.notfound = No se ha encontrado el archivo de configuraci\u00F3n
+agent.err.configfile.failed = Fallo al leer el archivo de configuraci\u00F3n
+agent.err.configfile.closed.failed = Fallo al cerrar el archivo de configuraci\u00F3n
+agent.err.configfile.access.denied = Acceso denegado al archivo de configuraci\u00F3n
+
+agent.err.exportaddress.failed = Fallo al exportar la direcci\u00F3n del conector JMX al buffer de instrumentaci\u00F3n
+
+agent.err.agentclass.notfound = Clase de agente de gesti\u00F3n no encontrada
+agent.err.agentclass.failed = Fallo de clase de agente de gesti\u00F3n
+agent.err.premain.notfound = premain(String) no existe en la clase del agente
+agent.err.agentclass.access.denied = Acceso denegado a premain(String)
+agent.err.invalid.agentclass = Valor de propiedad com.sun.management.agent.class no v\u00E1lido
+agent.err.invalid.state = Estado de agente no v\u00E1lido: {0}
+agent.err.invalid.jmxremote.port = N\u00FAmero com.sun.management.jmxremote.port no v\u00E1lido
+agent.err.invalid.jmxremote.rmi.port = N\u00FAmero com.sun.management.jmxremote.rmi.port no v\u00E1lido
+
+agent.err.file.not.set = Archivo no especificado
+agent.err.file.not.readable = Archivo ilegible
+agent.err.file.read.failed = Fallo al leer el archivo
+agent.err.file.not.found = Archivo no encontrado
+agent.err.file.access.not.restricted = El acceso de lectura al archivo debe ser restringido
+
+agent.err.password.file.notset = El archivo de contrase\u00F1as no se ha especificado, pero com.sun.management.jmxremote.authenticate=true
+agent.err.password.file.not.readable = No se puede leer el archivo de contrase\u00F1as
+agent.err.password.file.read.failed = Fallo al leer el archivo de contrase\u00F1as
+agent.err.password.file.notfound = Archivo de contrase\u00F1as no encontrado
+agent.err.password.file.access.notrestricted = Se debe restringir el acceso de lectura al archivo de contrase\u00F1as
+
+agent.err.access.file.notset = El archivo de acceso no se ha especificado, pero com.sun.management.jmxremote.authenticate=true
+agent.err.access.file.not.readable = No se puede leer el archivo de acceso
+agent.err.access.file.read.failed = Fallo al leer el archivo de acceso
+agent.err.access.file.notfound = Archivo de acceso no encontrado
+
+agent.err.connector.server.io.error = Error de comunicaci\u00F3n con el servidor de conector JMX
+
+agent.err.invalid.option = Opci\u00F3n especificada no v\u00E1lida
+
+jmxremote.ConnectorBootstrap.starting = Iniciando servidor de conector JMX:
+jmxremote.ConnectorBootstrap.noAuthentication = Sin autenticaci\u00F3n
+jmxremote.ConnectorBootstrap.ready = Conector JMX listo en: {0}
+jmxremote.ConnectorBootstrap.password.readonly = Se debe restringir el acceso de lectura al archivo de contrase\u00F1as: {0}
+jmxremote.ConnectorBootstrap.file.readonly = El acceso de lectura al archivo debe ser restringido: {0}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/jdk/internal/agent/resources/agent_fr.properties Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,71 @@
+#
+# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+agent.err.error = Erreur
+agent.err.exception = Exception envoy\u00E9e par l'agent
+agent.err.warning = Avertissement
+
+agent.err.configfile.notfound = Fichier de configuration introuvable
+agent.err.configfile.failed = Impossible de lire le fichier de configuration
+agent.err.configfile.closed.failed = Impossible de fermer le fichier de configuration
+agent.err.configfile.access.denied = Acc\u00E8s refus\u00E9 au fichier de configuration
+
+agent.err.exportaddress.failed = Impossible d'exporter l'adresse du connecteur JMX dans le tampon d'instrumentation
+
+agent.err.agentclass.notfound = Classe d'agents de gestion introuvable
+agent.err.agentclass.failed = Echec de la classe d'agents de gestion
+agent.err.premain.notfound = premain(String) n'existe pas dans la classe d'agents
+agent.err.agentclass.access.denied = Acc\u00E8s \u00E0 premain(String) refus\u00E9
+agent.err.invalid.agentclass = Valeur de propri\u00E9t\u00E9 com.sun.management.agent.class incorrecte
+agent.err.invalid.state = Etat de l''agent non valide : {0}
+agent.err.invalid.jmxremote.port = Num\u00E9ro com.sun.management.jmxremote.port incorrect
+agent.err.invalid.jmxremote.rmi.port = Num\u00E9ro com.sun.management.jmxremote.rmi.port non valide
+
+agent.err.file.not.set = Fichier non sp\u00E9cifi\u00E9
+agent.err.file.not.readable = Fichier illisible
+agent.err.file.read.failed = Impossible de lire le fichier
+agent.err.file.not.found = Fichier introuvable
+agent.err.file.access.not.restricted = L'acc\u00E8s en lecture au fichier doit \u00EAtre limit\u00E9
+
+agent.err.password.file.notset = Le fichier de mots de passe n'est pas sp\u00E9cifi\u00E9 mais com.sun.management.jmxremote.authenticate=true
+agent.err.password.file.not.readable = Fichier de mots de passe illisible
+agent.err.password.file.read.failed = Impossible de lire le fichier de mots de passe
+agent.err.password.file.notfound = Fichier de mots de passe introuvable
+agent.err.password.file.access.notrestricted = L'acc\u00E8s en lecture au fichier de mots de passe doit \u00EAtre limit\u00E9
+
+agent.err.access.file.notset = Le fichier d'acc\u00E8s n'est pas sp\u00E9cifi\u00E9 mais com.sun.management.jmxremote.authenticate=true
+agent.err.access.file.not.readable = Fichier d'acc\u00E8s illisible
+agent.err.access.file.read.failed = Impossible de lire le fichier d'acc\u00E8s
+agent.err.access.file.notfound = Fichier d'acc\u00E8s introuvable
+
+agent.err.connector.server.io.error = Erreur de communication avec le serveur du connecteur JMX
+
+agent.err.invalid.option = Option sp\u00E9cifi\u00E9e non valide
+
+jmxremote.ConnectorBootstrap.starting = D\u00E9marrage du serveur du connecteur JMX :
+jmxremote.ConnectorBootstrap.noAuthentication = Pas d'authentification
+jmxremote.ConnectorBootstrap.ready = Connecteur JMX pr\u00EAt \u00E0 : {0}
+jmxremote.ConnectorBootstrap.password.readonly = L''acc\u00E8s en lecture au fichier de mots de passe doit \u00EAtre limit\u00E9 : {0}
+jmxremote.ConnectorBootstrap.file.readonly = L''acc\u00E8s en lecture au fichier doit \u00EAtre limit\u00E9 : {0}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/jdk/internal/agent/resources/agent_it.properties Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,71 @@
+#
+# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+agent.err.error = Errore
+agent.err.exception = Eccezione dell'agente
+agent.err.warning = Avvertenza
+
+agent.err.configfile.notfound = File di configurazione non trovato
+agent.err.configfile.failed = Errore di lettura file di configurazione
+agent.err.configfile.closed.failed = Errore di chiusura file di configurazione
+agent.err.configfile.access.denied = Accesso negato al file di configurazione
+
+agent.err.exportaddress.failed = Errore di esportazione dell'indirizzo connettore JMX nel buffer strumenti
+
+agent.err.agentclass.notfound = Classe agente gestione non trovata
+agent.err.agentclass.failed = Errore classe agente gestione
+agent.err.premain.notfound = premain(String) non esiste nella classe agente
+agent.err.agentclass.access.denied = Accesso negato a premain(String)
+agent.err.invalid.agentclass = Valore propriet\u00E0 com.sun.management.agent.class non valido
+agent.err.invalid.state = Stato agente non valido: {0}
+agent.err.invalid.jmxremote.port = Numero com.sun.management.jmxremote.port non valido
+agent.err.invalid.jmxremote.rmi.port = Numero com.sun.management.jmxremote.rmi.port non valido
+
+agent.err.file.not.set = File non specificato
+agent.err.file.not.readable = File non leggibile
+agent.err.file.read.failed = Errore di lettura file
+agent.err.file.not.found = File non trovato
+agent.err.file.access.not.restricted = Limitare l'accesso in lettura al file
+
+agent.err.password.file.notset = Il password file non \u00E8 specificato ma com.sun.management.jmxremote.authenticate=true
+agent.err.password.file.not.readable = Password file non leggibile
+agent.err.password.file.read.failed = Errore di lettura password file
+agent.err.password.file.notfound = Password file non trovato
+agent.err.password.file.access.notrestricted = Limitare l'accesso in lettura al password file
+
+agent.err.access.file.notset = Il file di accesso non \u00E8 specificato ma com.sun.management.jmxremote.authenticate=true
+agent.err.access.file.not.readable = File di accesso non leggibile
+agent.err.access.file.read.failed = Errore di lettura file di accesso
+agent.err.access.file.notfound = File di accesso non trovato
+
+agent.err.connector.server.io.error = Errore di comunicazione server del connettore JMX
+
+agent.err.invalid.option = Specificata opzione non valida
+
+jmxremote.ConnectorBootstrap.starting = Avvio del server connettore JMX:
+jmxremote.ConnectorBootstrap.noAuthentication = Nessuna autenticazione
+jmxremote.ConnectorBootstrap.ready = Connettore JMX pronto in: {0}
+jmxremote.ConnectorBootstrap.password.readonly = Limitare l''accesso in lettura al password file: {0}
+jmxremote.ConnectorBootstrap.file.readonly = Limitare l''accesso in lettura al file: {0}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/jdk/internal/agent/resources/agent_ja.properties Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,71 @@
+#
+# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+agent.err.error = \u30A8\u30E9\u30FC
+agent.err.exception = \u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u304C\u4F8B\u5916\u3092\u30B9\u30ED\u30FC\u3057\u307E\u3057\u305F
+agent.err.warning = \u8B66\u544A
+
+agent.err.configfile.notfound = \u69CB\u6210\u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
+agent.err.configfile.failed = \u69CB\u6210\u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u53D6\u308A\u306B\u5931\u6557\u3057\u307E\u3057\u305F
+agent.err.configfile.closed.failed = \u69CB\u6210\u30D5\u30A1\u30A4\u30EB\u3092\u9589\u3058\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F
+agent.err.configfile.access.denied = \u69CB\u6210\u30D5\u30A1\u30A4\u30EB\u3078\u306E\u30A2\u30AF\u30BB\u30B9\u304C\u62D2\u5426\u3055\u308C\u307E\u3057\u305F
+
+agent.err.exportaddress.failed = JMX\u30B3\u30CD\u30AF\u30BF\u30FB\u30A2\u30C9\u30EC\u30B9\u306E\u8A08\u6E2C\u30D0\u30C3\u30D5\u30A1\u3078\u306E\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u304C\u5931\u6557\u3057\u307E\u3057\u305F
+
+agent.err.agentclass.notfound = \u7BA1\u7406\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u30FB\u30AF\u30E9\u30B9\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
+agent.err.agentclass.failed = \u7BA1\u7406\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u30FB\u30AF\u30E9\u30B9\u304C\u5931\u6557\u3057\u307E\u3057\u305F
+agent.err.premain.notfound = premain(String)\u304C\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u30FB\u30AF\u30E9\u30B9\u306B\u5B58\u5728\u3057\u307E\u305B\u3093
+agent.err.agentclass.access.denied = premain(String)\u3078\u306E\u30A2\u30AF\u30BB\u30B9\u304C\u62D2\u5426\u3055\u308C\u307E\u3057\u305F
+agent.err.invalid.agentclass = com.sun.management.agent.class\u30D7\u30ED\u30D1\u30C6\u30A3\u306E\u5024\u304C\u7121\u52B9\u3067\u3059
+agent.err.invalid.state = \u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u306E\u72B6\u614B\u304C\u7121\u52B9\u3067\u3059: {0}
+agent.err.invalid.jmxremote.port = com.sun.management.jmxremote.port\u306E\u756A\u53F7\u304C\u7121\u52B9\u3067\u3059
+agent.err.invalid.jmxremote.rmi.port = com.sun.management.jmxremote.rmi.port\u306E\u756A\u53F7\u304C\u7121\u52B9\u3067\u3059
+
+agent.err.file.not.set = \u30D5\u30A1\u30A4\u30EB\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093
+agent.err.file.not.readable = \u30D5\u30A1\u30A4\u30EB\u3092\u8AAD\u307F\u53D6\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u305B\u3093
+agent.err.file.read.failed = \u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u53D6\u308A\u306B\u5931\u6557\u3057\u307E\u3057\u305F
+agent.err.file.not.found = \u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F
+agent.err.file.access.not.restricted = \u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u53D6\u308A\u30A2\u30AF\u30BB\u30B9\u306F\u5236\u9650\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059
+
+agent.err.password.file.notset = \u30D1\u30B9\u30EF\u30FC\u30C9\u30FB\u30D5\u30A1\u30A4\u30EB\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u304C\u3001com.sun.management.jmxremote.authenticate=true\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u3059
+agent.err.password.file.not.readable = \u30D1\u30B9\u30EF\u30FC\u30C9\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u8AAD\u307F\u53D6\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u305B\u3093
+agent.err.password.file.read.failed = \u30D1\u30B9\u30EF\u30FC\u30C9\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u53D6\u308A\u306B\u5931\u6557\u3057\u307E\u3057\u305F
+agent.err.password.file.notfound = \u30D1\u30B9\u30EF\u30FC\u30C9\u30FB\u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
+agent.err.password.file.access.notrestricted = \u30D1\u30B9\u30EF\u30FC\u30C9\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u53D6\u308A\u30A2\u30AF\u30BB\u30B9\u306F\u5236\u9650\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059
+
+agent.err.access.file.notset = \u30A2\u30AF\u30BB\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u304C\u3001com.sun.management.jmxremote.authenticate=true\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u3059
+agent.err.access.file.not.readable = \u30A2\u30AF\u30BB\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u8AAD\u307F\u53D6\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u305B\u3093
+agent.err.access.file.read.failed = \u30A2\u30AF\u30BB\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u53D6\u308A\u306B\u5931\u6557\u3057\u307E\u3057\u305F
+agent.err.access.file.notfound = \u30A2\u30AF\u30BB\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
+
+agent.err.connector.server.io.error = JMX\u30B3\u30CD\u30AF\u30BF\u30FB\u30B5\u30FC\u30D0\u30FC\u306E\u901A\u4FE1\u30A8\u30E9\u30FC
+
+agent.err.invalid.option = \u7121\u52B9\u306A\u30AA\u30D7\u30B7\u30E7\u30F3\u304C\u6307\u5B9A\u3055\u308C\u307E\u3057\u305F
+
+jmxremote.ConnectorBootstrap.starting = JMX\u30B3\u30CD\u30AF\u30BF\u30FB\u30B5\u30FC\u30D0\u30FC\u3092\u8D77\u52D5\u3057\u3066\u3044\u307E\u3059:
+jmxremote.ConnectorBootstrap.noAuthentication = \u8A8D\u8A3C\u306A\u3057
+jmxremote.ConnectorBootstrap.ready = JMX\u30B3\u30CD\u30AF\u30BF\u306E\u6E96\u5099\u304C\u3067\u304D\u307E\u3057\u305F: {0}
+jmxremote.ConnectorBootstrap.password.readonly = \u30D1\u30B9\u30EF\u30FC\u30C9\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u53D6\u308A\u30A2\u30AF\u30BB\u30B9\u306F\u5236\u9650\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059: {0}
+jmxremote.ConnectorBootstrap.file.readonly = \u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u53D6\u308A\u30A2\u30AF\u30BB\u30B9\u306F\u5236\u9650\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059: {0}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/jdk/internal/agent/resources/agent_ko.properties Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,71 @@
+#
+# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+agent.err.error = \uC624\uB958
+agent.err.exception = \uC5D0\uC774\uC804\uD2B8\uC5D0 \uC608\uC678\uC0AC\uD56D\uC774 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.
+agent.err.warning = \uACBD\uACE0
+
+agent.err.configfile.notfound = \uAD6C\uC131 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
+agent.err.configfile.failed = \uAD6C\uC131 \uD30C\uC77C \uC77D\uAE30\uB97C \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.
+agent.err.configfile.closed.failed = \uAD6C\uC131 \uD30C\uC77C \uB2EB\uAE30\uB97C \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.
+agent.err.configfile.access.denied = \uAD6C\uC131 \uD30C\uC77C\uC5D0 \uB300\uD55C \uC561\uC138\uC2A4\uAC00 \uAC70\uBD80\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
+
+agent.err.exportaddress.failed = \uAE30\uAE30 \uBC84\uD37C\uB85C JMX \uCEE4\uB125\uD130 \uC8FC\uC18C \uC775\uC2A4\uD3EC\uD2B8\uB97C \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.
+
+agent.err.agentclass.notfound = \uAD00\uB9AC \uC5D0\uC774\uC804\uD2B8 \uD074\uB798\uC2A4\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
+agent.err.agentclass.failed = \uAD00\uB9AC \uC5D0\uC774\uC804\uD2B8 \uD074\uB798\uC2A4\uB97C \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.
+agent.err.premain.notfound = \uC5D0\uC774\uC804\uD2B8 \uD074\uB798\uC2A4\uC5D0 premain(\uBB38\uC790\uC5F4)\uC774 \uC874\uC7AC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
+agent.err.agentclass.access.denied = premain(\uBB38\uC790\uC5F4)\uC5D0 \uB300\uD55C \uC561\uC138\uC2A4\uAC00 \uAC70\uBD80\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
+agent.err.invalid.agentclass = com.sun.management.agent.class \uC18D\uC131 \uAC12\uC774 \uBD80\uC801\uD569\uD569\uB2C8\uB2E4.
+agent.err.invalid.state = \uBD80\uC801\uD569\uD55C \uC5D0\uC774\uC804\uD2B8 \uC0C1\uD0DC: {0}
+agent.err.invalid.jmxremote.port = com.sun.management.jmxremote.port \uBC88\uD638\uAC00 \uBD80\uC801\uD569\uD569\uB2C8\uB2E4.
+agent.err.invalid.jmxremote.rmi.port = \uBD80\uC801\uD569\uD55C com.sun.management.jmxremote.rmi.port \uBC88\uD638
+
+agent.err.file.not.set = \uD30C\uC77C\uC774 \uC9C0\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.
+agent.err.file.not.readable = \uD30C\uC77C\uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
+agent.err.file.read.failed = \uD30C\uC77C \uC77D\uAE30\uB97C \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.
+agent.err.file.not.found = \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
+agent.err.file.access.not.restricted = \uD30C\uC77C \uC77D\uAE30 \uC561\uC138\uC2A4\uB294 \uC81C\uD55C\uB418\uC5B4\uC57C \uD569\uB2C8\uB2E4.
+
+agent.err.password.file.notset = \uBE44\uBC00\uBC88\uD638 \uD30C\uC77C\uC774 \uC9C0\uC815\uB418\uC9C0 \uC54A\uC558\uC9C0\uB9CC com.sun.management.jmxremote.authenticate=true\uC785\uB2C8\uB2E4.
+agent.err.password.file.not.readable = \uBE44\uBC00\uBC88\uD638 \uD30C\uC77C\uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
+agent.err.password.file.read.failed = \uBE44\uBC00\uBC88\uD638 \uD30C\uC77C \uC77D\uAE30\uB97C \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.
+agent.err.password.file.notfound = \uBE44\uBC00\uBC88\uD638 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
+agent.err.password.file.access.notrestricted = \uBE44\uBC00\uBC88\uD638 \uD30C\uC77C \uC77D\uAE30 \uC561\uC138\uC2A4\uB294 \uC81C\uD55C\uB418\uC5B4\uC57C \uD569\uB2C8\uB2E4.
+
+agent.err.access.file.notset = \uC561\uC138\uC2A4 \uD30C\uC77C\uC774 \uC9C0\uC815\uB418\uC9C0 \uC54A\uC558\uC9C0\uB9CC com.sun.management.jmxremote.authenticate=true\uC785\uB2C8\uB2E4.
+agent.err.access.file.not.readable = \uC561\uC138\uC2A4 \uD30C\uC77C\uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
+agent.err.access.file.read.failed = \uC561\uC138\uC2A4 \uD30C\uC77C \uC77D\uAE30\uB97C \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.
+agent.err.access.file.notfound = \uC561\uC138\uC2A4 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
+
+agent.err.connector.server.io.error = JMX \uCEE4\uB125\uD130 \uC11C\uBC84 \uD1B5\uC2E0 \uC624\uB958
+
+agent.err.invalid.option = \uBD80\uC801\uD569\uD55C \uC635\uC158\uC774 \uC9C0\uC815\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
+
+jmxremote.ConnectorBootstrap.starting = JMX \uCEE4\uB125\uD130 \uC11C\uBC84\uB97C \uC2DC\uC791\uD558\uB294 \uC911:
+jmxremote.ConnectorBootstrap.noAuthentication = \uC778\uC99D \uC5C6\uC74C
+jmxremote.ConnectorBootstrap.ready = {0}\uC5D0\uC11C JMX \uCEE4\uB125\uD130\uAC00 \uC900\uBE44\uB418\uC5C8\uC2B5\uB2C8\uB2E4.
+jmxremote.ConnectorBootstrap.password.readonly = \uBE44\uBC00\uBC88\uD638 \uD30C\uC77C \uC77D\uAE30 \uC561\uC138\uC2A4\uB294 \uC81C\uD55C\uB418\uC5B4\uC57C \uD568: {0}
+jmxremote.ConnectorBootstrap.file.readonly = \uD30C\uC77C \uC77D\uAE30 \uC561\uC138\uC2A4\uB294 \uC81C\uD55C\uB418\uC5B4\uC57C \uD568: {0}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/jdk/internal/agent/resources/agent_pt_BR.properties Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,71 @@
+#
+# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+agent.err.error = Erro
+agent.err.exception = Exce\u00E7\u00E3o gerada pelo agente
+agent.err.warning = Advert\u00EAncia
+
+agent.err.configfile.notfound = Arquivo de configura\u00E7\u00E3o n\u00E3o encontrado
+agent.err.configfile.failed = Falha ao ler o arquivo de configura\u00E7\u00E3o
+agent.err.configfile.closed.failed = Falha ao fechar o arquivo de configura\u00E7\u00E3o
+agent.err.configfile.access.denied = Acesso negado ao arquivo de configura\u00E7\u00E3o
+
+agent.err.exportaddress.failed = Falha na exporta\u00E7\u00E3o do endere\u00E7o do conector JMX para o buffer de instrumenta\u00E7\u00E3o
+
+agent.err.agentclass.notfound = Classe do agente de gerenciamento n\u00E3o encontrada
+agent.err.agentclass.failed = Falha na classe do agente de gerenciamento
+agent.err.premain.notfound = premain(String) n\u00E3o existe na classe do agente
+agent.err.agentclass.access.denied = Acesso negado a premain(String)
+agent.err.invalid.agentclass = Valor inv\u00E1lido da propriedade com.sun.management.agent.class
+agent.err.invalid.state = Estado inv\u00E1lido do agente: {0}
+agent.err.invalid.jmxremote.port = N\u00FAmero inv\u00E1lido de com.sun.management.jmxremote.port
+agent.err.invalid.jmxremote.rmi.port = N\u00FAmero inv\u00E1lido do com.sun.management.jmxremote.rmi.port
+
+agent.err.file.not.set = Arquivo n\u00E3o especificado
+agent.err.file.not.readable = Arquivo ileg\u00EDvel
+agent.err.file.read.failed = Falha ao ler o arquivo
+agent.err.file.not.found = Arquivo n\u00E3o encontrado
+agent.err.file.access.not.restricted = O acesso de leitura do arquivo deve ser limitado
+
+agent.err.password.file.notset = O arquivo de senha n\u00E3o est\u00E1 especificado, mas com.sun.management.jmxremote.authenticate=true
+agent.err.password.file.not.readable = Arquivo de senha ileg\u00EDvel
+agent.err.password.file.read.failed = Falha ao ler o arquivo de senha
+agent.err.password.file.notfound = Arquivo de senha n\u00E3o encontrado
+agent.err.password.file.access.notrestricted = O acesso de leitura do arquivo de senha deve ser limitado
+
+agent.err.access.file.notset = O arquivo de acesso n\u00E3o est\u00E1 especificado, mas com.sun.management.jmxremote.authenticate=true
+agent.err.access.file.not.readable = Arquivo de acesso ileg\u00EDvel
+agent.err.access.file.read.failed = Falha ao ler o arquivo de acesso
+agent.err.access.file.notfound = Arquivo de acesso n\u00E3o encontrado
+
+agent.err.connector.server.io.error = Erro de comunica\u00E7\u00E3o do servidor do conector JMX
+
+agent.err.invalid.option = Op\u00E7\u00E3o especificada inv\u00E1lida
+
+jmxremote.ConnectorBootstrap.starting = Iniciando o Servidor do Conector JMX:
+jmxremote.ConnectorBootstrap.noAuthentication = Sem autentica\u00E7\u00E3o
+jmxremote.ConnectorBootstrap.ready = Conector JMX pronto em: {0}
+jmxremote.ConnectorBootstrap.password.readonly = O acesso de leitura do arquivo de senha deve ser limitado: {0}
+jmxremote.ConnectorBootstrap.file.readonly = O acesso de leitura do arquivo deve ser limitado: {0}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/jdk/internal/agent/resources/agent_sv.properties Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,71 @@
+#
+# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+agent.err.error = Fel
+agent.err.exception = Agenten orsakade ett undantag
+agent.err.warning = Varning
+
+agent.err.configfile.notfound = Konfigurationsfilen hittades inte
+agent.err.configfile.failed = Kunde inte l\u00E4sa konfigurationsfilen
+agent.err.configfile.closed.failed = Kunde inte st\u00E4nga konfigurationsfilen
+agent.err.configfile.access.denied = \u00C5tkomst till konfigurationsfilen nekad
+
+agent.err.exportaddress.failed = Kunde inte exportera JMX-anslutningsadressen till instrumentbufferten
+
+agent.err.agentclass.notfound = Administrationsagentklassen hittades inte
+agent.err.agentclass.failed = Administrationsagentklassen utf\u00F6rdes inte
+agent.err.premain.notfound = premain(String) finns inte i agentklassen
+agent.err.agentclass.access.denied = \u00C5tkomst till premain(String) nekad
+agent.err.invalid.agentclass = Ogiltigt egenskapsv\u00E4rde f\u00F6r com.sun.management.agent.class
+agent.err.invalid.state = Ogiltig agentstatus: {0}
+agent.err.invalid.jmxremote.port = Ogiltigt com.sun.management.jmxremote.port-nummer
+agent.err.invalid.jmxremote.rmi.port = Ogiltigt com.sun.management.jmxremote.rmi.port-nummer
+
+agent.err.file.not.set = Filen \u00E4r inte angiven
+agent.err.file.not.readable = Filen \u00E4r inte l\u00E4sbar
+agent.err.file.read.failed = Kunde inte l\u00E4sa filen
+agent.err.file.not.found = Filen hittades inte
+agent.err.file.access.not.restricted = Fill\u00E4snings\u00E5tkomst m\u00E5ste begr\u00E4nsas
+
+agent.err.password.file.notset = L\u00F6senordsfilen har inte angetts men com.sun.management.jmxremote.authenticate=true
+agent.err.password.file.not.readable = L\u00F6senordsfilen \u00E4r inte l\u00E4sbar
+agent.err.password.file.read.failed = Kunde inte l\u00E4sa l\u00F6senordsfilen
+agent.err.password.file.notfound = Hittar inte l\u00F6senordsfilen
+agent.err.password.file.access.notrestricted = L\u00E4sbeh\u00F6righeten f\u00F6r filen m\u00E5ste begr\u00E4nsas
+
+agent.err.access.file.notset = \u00C5tkomstfilen har inte angetts men com.sun.management.jmxremote.authenticate=true
+agent.err.access.file.not.readable = Access-filen \u00E4r inte l\u00E4sbar
+agent.err.access.file.read.failed = Kunde inte l\u00E4sa \u00E5tkomstfilen
+agent.err.access.file.notfound = Access-filen hittades inte
+
+agent.err.connector.server.io.error = Serverkommunikationsfel f\u00F6r JMX-anslutning
+
+agent.err.invalid.option = Det angivna alternativet \u00E4r ogiltigt
+
+jmxremote.ConnectorBootstrap.starting = Startar server f\u00F6r JMX-anslutning:
+jmxremote.ConnectorBootstrap.noAuthentication = Ingen autentisering
+jmxremote.ConnectorBootstrap.ready = JMX-anslutning redo p\u00E5: {0}
+jmxremote.ConnectorBootstrap.password.readonly = L\u00E4sbeh\u00F6righeten f\u00F6r l\u00F6senordsfilen m\u00E5ste begr\u00E4nsas: {0}
+jmxremote.ConnectorBootstrap.file.readonly = Fill\u00E4snings\u00E5tkomst m\u00E5ste begr\u00E4nsas {0}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/jdk/internal/agent/resources/agent_zh_CN.properties Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,71 @@
+#
+# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+agent.err.error = \u9519\u8BEF
+agent.err.exception = \u4EE3\u7406\u629B\u51FA\u5F02\u5E38\u9519\u8BEF
+agent.err.warning = \u8B66\u544A
+
+agent.err.configfile.notfound = \u627E\u4E0D\u5230\u914D\u7F6E\u6587\u4EF6
+agent.err.configfile.failed = \u672A\u80FD\u8BFB\u53D6\u914D\u7F6E\u6587\u4EF6
+agent.err.configfile.closed.failed = \u672A\u80FD\u5173\u95ED\u914D\u7F6E\u6587\u4EF6
+agent.err.configfile.access.denied = \u62D2\u7EDD\u8BBF\u95EE\u914D\u7F6E\u6587\u4EF6
+
+agent.err.exportaddress.failed = \u672A\u80FD\u5C06 JMX \u8FDE\u63A5\u5668\u5730\u5740\u5BFC\u51FA\u5230\u68C0\u6D4B\u7F13\u51B2\u533A
+
+agent.err.agentclass.notfound = \u627E\u4E0D\u5230\u7BA1\u7406\u4EE3\u7406\u7C7B
+agent.err.agentclass.failed = \u7BA1\u7406\u4EE3\u7406\u7C7B\u5931\u8D25
+agent.err.premain.notfound = \u4EE3\u7406\u7C7B\u4E2D\u4E0D\u5B58\u5728 premain(String)
+agent.err.agentclass.access.denied = \u62D2\u7EDD\u8BBF\u95EE premain(String)
+agent.err.invalid.agentclass = com.sun.management.agent.class \u5C5E\u6027\u503C\u65E0\u6548
+agent.err.invalid.state = \u65E0\u6548\u7684\u4EE3\u7406\u72B6\u6001: {0}
+agent.err.invalid.jmxremote.port = com.sun.management.jmxremote.port \u7F16\u53F7\u65E0\u6548
+agent.err.invalid.jmxremote.rmi.port = com.sun.management.jmxremote.rmi.port \u7F16\u53F7\u65E0\u6548
+
+agent.err.file.not.set = \u672A\u6307\u5B9A\u6587\u4EF6
+agent.err.file.not.readable = \u6587\u4EF6\u4E0D\u53EF\u8BFB\u53D6
+agent.err.file.read.failed = \u672A\u80FD\u8BFB\u53D6\u6587\u4EF6
+agent.err.file.not.found = \u627E\u4E0D\u5230\u6587\u4EF6
+agent.err.file.access.not.restricted = \u5FC5\u987B\u9650\u5236\u6587\u4EF6\u8BFB\u53D6\u8BBF\u95EE\u6743\u9650
+
+agent.err.password.file.notset = \u672A\u6307\u5B9A\u53E3\u4EE4\u6587\u4EF6, \u4F46 com.sun.management.jmxremote.authenticate=true
+agent.err.password.file.not.readable = \u53E3\u4EE4\u6587\u4EF6\u4E0D\u53EF\u8BFB\u53D6
+agent.err.password.file.read.failed = \u8BFB\u53D6\u53E3\u4EE4\u6587\u4EF6\u5931\u8D25
+agent.err.password.file.notfound = \u627E\u4E0D\u5230\u53E3\u4EE4\u6587\u4EF6
+agent.err.password.file.access.notrestricted = \u5FC5\u987B\u9650\u5236\u53E3\u4EE4\u6587\u4EF6\u8BFB\u53D6\u8BBF\u95EE\u6743\u9650
+
+agent.err.access.file.notset = \u672A\u6307\u5B9A\u8BBF\u95EE\u6587\u4EF6, \u4F46 com.sun.management.jmxremote.authenticate=true
+agent.err.access.file.not.readable = \u8BBF\u95EE\u6587\u4EF6\u4E0D\u53EF\u8BFB\u53D6
+agent.err.access.file.read.failed = \u8BFB\u53D6\u8BBF\u95EE\u6587\u4EF6\u5931\u8D25
+agent.err.access.file.notfound = \u627E\u4E0D\u5230\u8BBF\u95EE\u6587\u4EF6
+
+agent.err.connector.server.io.error = JMX \u8FDE\u63A5\u5668\u670D\u52A1\u5668\u901A\u4FE1\u9519\u8BEF
+
+agent.err.invalid.option = \u6307\u5B9A\u7684\u9009\u9879\u65E0\u6548
+
+jmxremote.ConnectorBootstrap.starting = \u6B63\u5728\u542F\u52A8 JMX \u8FDE\u63A5\u5668\u670D\u52A1\u5668:
+jmxremote.ConnectorBootstrap.noAuthentication = \u65E0\u9A8C\u8BC1
+jmxremote.ConnectorBootstrap.ready = \u4F4D\u4E8E{0}\u7684 JMX \u8FDE\u63A5\u5668\u5DF2\u5C31\u7EEA
+jmxremote.ConnectorBootstrap.password.readonly = \u5FC5\u987B\u9650\u5236\u53E3\u4EE4\u6587\u4EF6\u8BFB\u53D6\u8BBF\u95EE\u6743\u9650: {0}
+jmxremote.ConnectorBootstrap.file.readonly = \u5FC5\u987B\u9650\u5236\u6587\u4EF6\u8BFB\u53D6\u8BBF\u95EE\u6743\u9650: {0}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/jdk/internal/agent/resources/agent_zh_TW.properties Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,71 @@
+#
+# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+agent.err.error = \u932F\u8AA4
+agent.err.exception = \u4EE3\u7406\u7A0B\u5F0F\u767C\u751F\u7570\u5E38
+agent.err.warning = \u8B66\u544A
+
+agent.err.configfile.notfound = \u627E\u4E0D\u5230\u8A2D\u5B9A\u6A94\u6848
+agent.err.configfile.failed = \u7121\u6CD5\u8B80\u53D6\u8A2D\u5B9A\u6A94\u6848
+agent.err.configfile.closed.failed = \u7121\u6CD5\u95DC\u9589\u8A2D\u5B9A\u6A94\u6848
+agent.err.configfile.access.denied = \u5B58\u53D6\u8A2D\u5B9A\u6A94\u6848\u906D\u5230\u62D2\u7D55
+
+agent.err.exportaddress.failed = \u5C07 JMX \u9023\u63A5\u5668\u4F4D\u5740\u532F\u51FA\u81F3\u8A2D\u5099\u7DE9\u885D\u5340\u5931\u6557
+
+agent.err.agentclass.notfound = \u627E\u4E0D\u5230\u7BA1\u7406\u4EE3\u7406\u7A0B\u5F0F\u985E\u5225
+agent.err.agentclass.failed = \u7BA1\u7406\u4EE3\u7406\u7A0B\u5F0F\u985E\u5225\u5931\u6557
+agent.err.premain.notfound = \u4EE3\u7406\u7A0B\u5F0F\u985E\u5225\u4E2D\u4E0D\u5B58\u5728 premain(String)
+agent.err.agentclass.access.denied = \u5B58\u53D6 premain(String) \u906D\u5230\u62D2\u7D55
+agent.err.invalid.agentclass = com.sun.management.agent.class \u5C6C\u6027\u503C\u7121\u6548
+agent.err.invalid.state = \u7121\u6548\u7684\u4EE3\u7406\u7A0B\u5F0F\u72C0\u614B: {0}
+agent.err.invalid.jmxremote.port = com.sun.management.jmxremote.port \u865F\u78BC\u7121\u6548
+agent.err.invalid.jmxremote.rmi.port = com.sun.management.jmxremote.rmi.port \u865F\u78BC\u7121\u6548
+
+agent.err.file.not.set = \u672A\u6307\u5B9A\u6A94\u6848
+agent.err.file.not.readable = \u6A94\u6848\u7121\u6CD5\u8B80\u53D6
+agent.err.file.read.failed = \u7121\u6CD5\u8B80\u53D6\u6A94\u6848
+agent.err.file.not.found = \u627E\u4E0D\u5230\u6A94\u6848
+agent.err.file.access.not.restricted = \u5FC5\u9808\u9650\u5236\u6A94\u6848\u8B80\u53D6\u5B58\u53D6\u6B0A
+
+agent.err.password.file.notset = \u672A\u6307\u5B9A\u5BC6\u78BC\u6A94\u6848\uFF0C\u4F46 com.sun.management.jmxremote.authenticate=true
+agent.err.password.file.not.readable = \u5BC6\u78BC\u6A94\u6848\u7121\u6CD5\u8B80\u53D6
+agent.err.password.file.read.failed = \u7121\u6CD5\u8B80\u53D6\u5BC6\u78BC\u6A94\u6848
+agent.err.password.file.notfound = \u627E\u4E0D\u5230\u5BC6\u78BC\u6A94\u6848
+agent.err.password.file.access.notrestricted = \u5FC5\u9808\u9650\u5236\u5BC6\u78BC\u6A94\u6848\u8B80\u53D6\u5B58\u53D6
+
+agent.err.access.file.notset = \u672A\u6307\u5B9A\u5B58\u53D6\u6A94\u6848\uFF0C\u4F46 com.sun.management.jmxremote.authenticate=true
+agent.err.access.file.not.readable = \u5B58\u53D6\u6A94\u6848\u7121\u6CD5\u8B80\u53D6
+agent.err.access.file.read.failed = \u7121\u6CD5\u8B80\u53D6\u5B58\u53D6\u6A94\u6848
+agent.err.access.file.notfound = \u627E\u4E0D\u5230\u5B58\u53D6\u6A94\u6848
+
+agent.err.connector.server.io.error = JMX \u9023\u63A5\u5668\u4F3A\u670D\u5668\u901A\u8A0A\u932F\u8AA4
+
+agent.err.invalid.option = \u6307\u5B9A\u7684\u9078\u9805\u7121\u6548
+
+jmxremote.ConnectorBootstrap.starting = \u6B63\u5728\u555F\u52D5 JMX \u9023\u63A5\u5668\u4F3A\u670D\u5668:
+jmxremote.ConnectorBootstrap.noAuthentication = \u7121\u8A8D\u8B49
+jmxremote.ConnectorBootstrap.ready = JMX \u9023\u63A5\u5668\u5C31\u7DD2\uFF0C\u4F4D\u65BC: {0}
+jmxremote.ConnectorBootstrap.password.readonly = \u5FC5\u9808\u9650\u5236\u5BC6\u78BC\u6A94\u6848\u8B80\u53D6\u5B58\u53D6: {0}
+jmxremote.ConnectorBootstrap.file.readonly = \u5FC5\u9808\u9650\u5236\u6A94\u6848\u8B80\u53D6\u5B58\u53D6\u6B0A: {0}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/jdk/internal/agent/spi/AgentProvider.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.agent.spi;
+
+import java.util.Properties;
+
+/**
+ * Service interface for management agent
+ */
+public abstract class AgentProvider {
+
+ /**
+ * Instantiates a new AgentProvider.
+ *
+ * @throws SecurityException if the subclass (and calling code) does not
+ * have
+ * {@code RuntimePermission("sun.management.spi.AgentProvider.subclass")}
+ */
+ protected AgentProvider() {
+ this(checkSubclassPermission());
+ }
+
+ private AgentProvider(Void unused) {
+ }
+
+ private static Void checkSubclassPermission() {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new RuntimePermission(AgentProvider.class.getName() + ".subclass"));
+ }
+ return null;
+ }
+
+ /**
+ * Gets the name of the agent provider.
+ *
+ * @return name of agent provider
+ */
+ public abstract String getName();
+
+ /**
+ * Initializes and starts the agent.
+ *
+ * @throws IllegalStateException if this agent has already been started.
+ */
+ public abstract void startAgent();
+
+ /**
+ * Initializes and starts the agent at given port and with given properties
+ *
+ * @param props environment variables for agent
+ *
+ * @throws IllegalStateException if this agent has already been started.
+ */
+ public abstract void startAgent(Properties props);
+
+ /**
+ * Checks if agent is started and not terminated.
+ *
+ * @return true if agent is running, false otherwise.
+ */
+ public abstract boolean isActive();
+
+ /**
+ * Stops this agent.
+ *
+ * @throws IllegalStateException if this agent is not started.
+ */
+ public abstract void stopAgent();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/module-info.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+module jdk.management.agent {
+ requires java.management;
+ requires java.management.rmi;
+
+ exports jdk.internal.agent to jdk.jconsole;
+
+ uses jdk.internal.agent.spi.AgentProvider;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/sun/management/jdp/JdpBroadcaster.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 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.
+ */
+package sun.management.jdp;
+
+import java.io.IOException;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.NetworkInterface;
+import java.net.ProtocolFamily;
+import java.net.StandardProtocolFamily;
+import java.net.StandardSocketOptions;
+import java.nio.ByteBuffer;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.UnsupportedAddressTypeException;
+import java.util.Enumeration;
+
+/**
+ * JdpBroadcaster is responsible for sending pre-built JDP packet across a Net
+ *
+ * <p> Multicast group address, port number and ttl have to be chosen on upper
+ * level and passed to broadcaster constructor. Also it's possible to specify
+ * source address to broadcast from. </p>
+ *
+ * <p>JdpBradcaster doesn't perform any validation on a supplied {@code port} and {@code ttl} because
+ * the allowed values depend on an operating system setup</p>
+ *
+ */
+public final class JdpBroadcaster {
+
+ private final InetAddress addr;
+ private final int port;
+ private final DatagramChannel channel;
+
+ /**
+ * Create a new broadcaster
+ *
+ * @param address - multicast group address
+ * @param srcAddress - address of interface we should use to broadcast.
+ * @param port - udp port to use
+ * @param ttl - packet ttl
+ * @throws IOException
+ */
+ public JdpBroadcaster(InetAddress address, InetAddress srcAddress, int port, int ttl)
+ throws IOException, JdpException {
+ this.addr = address;
+ this.port = port;
+
+ ProtocolFamily family = (address instanceof Inet6Address)
+ ? StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
+
+ channel = DatagramChannel.open(family);
+ channel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
+ channel.setOption(StandardSocketOptions.IP_MULTICAST_TTL, ttl);
+
+ // with srcAddress equal to null, this constructor do exactly the same as
+ // if srcAddress is not passed
+ if (srcAddress != null) {
+ // User requests particular interface to bind to
+ NetworkInterface interf = NetworkInterface.getByInetAddress(srcAddress);
+
+ if (interf == null) {
+ throw new JdpException("Unable to get network interface for " + srcAddress.toString());
+ }
+
+ if (!interf.isUp()) {
+ throw new JdpException(interf.getName() + " is not up.");
+ }
+
+ if (!interf.supportsMulticast()) {
+ throw new JdpException(interf.getName() + " does not support multicast.");
+ }
+
+ try {
+ channel.bind(new InetSocketAddress(srcAddress, 0));
+ } catch (UnsupportedAddressTypeException ex) {
+ throw new JdpException("Unable to bind to source address");
+ }
+ channel.setOption(StandardSocketOptions.IP_MULTICAST_IF, interf);
+ }
+ }
+
+ /**
+ * Create a new broadcaster
+ *
+ * @param address - multicast group address
+ * @param port - udp port to use
+ * @param ttl - packet ttl
+ * @throws IOException
+ */
+ public JdpBroadcaster(InetAddress address, int port, int ttl)
+ throws IOException, JdpException {
+ this(address, null, port, ttl);
+ }
+
+ /**
+ * Broadcast pre-built packet
+ *
+ * @param packet - instance of JdpPacket
+ * @throws IOException
+ */
+ public void sendPacket(JdpPacket packet)
+ throws IOException {
+ byte[] data = packet.getPacketData();
+ // Unlike allocate/put wrap don't need a flip afterward
+ ByteBuffer b = ByteBuffer.wrap(data);
+ channel.send(b, new InetSocketAddress(addr, port));
+ }
+
+ /**
+ * Shutdown broadcaster and close underlying socket channel
+ *
+ * @throws IOException
+ */
+ public void shutdown() throws IOException {
+ channel.close();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/sun/management/jdp/JdpController.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 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.
+ */
+package sun.management.jdp;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.UUID;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import sun.management.VMManagement;
+
+/**
+ * JdpController is responsible to create and manage a broadcast loop.
+ *
+ * <p> Other part of code has no access to broadcast loop and have to use
+ * provided static methods
+ * {@link #startDiscoveryService(InetAddress,int,String,String) startDiscoveryService}
+ * and {@link #stopDiscoveryService() stopDiscoveryService}
+ * <p>{@link #startDiscoveryService(InetAddress,int,String,String) startDiscoveryService} could be called multiple
+ * times as it stops the running service if it is necessary.
+ * Call to {@link #stopDiscoveryService() stopDiscoveryService}
+ * ignored if service isn't run.
+ *
+ *
+ * <p> System properties below could be used to control broadcast loop behavior.
+ * Property below have to be set explicitly in command line. It's not possible to
+ * set it in management.config file. Careless changes of these properties could
+ * lead to security or network issues.
+ * <ul>
+ * <li>com.sun.management.jdp.ttl - set ttl for broadcast packet</li>
+ * <li>com.sun.management.jdp.pause - set broadcast interval in seconds</li>
+ * <li>com.sun.management.jdp.source_addr - an address of interface to use for broadcast</li>
+ * </ul>
+ *
+ * <p>null parameters values are filtered out on {@link JdpPacketWriter} level and
+ * corresponding keys are not placed to packet.
+ */
+public final class JdpController {
+
+ private static class JDPControllerRunner implements Runnable {
+
+ private final JdpJmxPacket packet;
+ private final JdpBroadcaster bcast;
+ private final int pause;
+ private volatile boolean shutdown = false;
+
+ private JDPControllerRunner(JdpBroadcaster bcast, JdpJmxPacket packet, int pause) {
+ this.bcast = bcast;
+ this.packet = packet;
+ this.pause = pause;
+ }
+
+ @Override
+ public void run() {
+ try {
+ while (!shutdown) {
+ bcast.sendPacket(packet);
+ try {
+ Thread.sleep(this.pause);
+ } catch (InterruptedException e) {
+ // pass
+ }
+ }
+
+ } catch (IOException e) {
+ // pass;
+ }
+
+ // It's not possible to re-use controller,
+ // nevertheless reset shutdown variable
+ try {
+ stop();
+ bcast.shutdown();
+ } catch (IOException ex) {
+ // pass - ignore IOException during shutdown
+ }
+ }
+
+ public void stop() {
+ shutdown = true;
+ }
+ }
+ private static JDPControllerRunner controller = null;
+
+ private JdpController(){
+ // Don't allow to instantiate this class.
+ }
+
+ // Utility to handle optional system properties
+ // Parse an integer from string or return default if provided string is null
+ private static int getInteger(String val, int dflt, String msg) throws JdpException {
+ try {
+ return (val == null) ? dflt : Integer.parseInt(val);
+ } catch (NumberFormatException ex) {
+ throw new JdpException(msg);
+ }
+ }
+
+ // Parse an inet address from string or return default if provided string is null
+ private static InetAddress getInetAddress(String val, InetAddress dflt, String msg) throws JdpException {
+ try {
+ return (val == null) ? dflt : InetAddress.getByName(val);
+ } catch (UnknownHostException ex) {
+ throw new JdpException(msg);
+ }
+ }
+
+ // Get the process id of the current running Java process
+ private static Integer getProcessId() {
+ try {
+ // Get the current process id using a reflection hack
+ RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
+ Field jvm = runtime.getClass().getDeclaredField("jvm");
+ jvm.setAccessible(true);
+
+ VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime);
+ Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId");
+ pid_method.setAccessible(true);
+ Integer pid = (Integer) pid_method.invoke(mgmt);
+ return pid;
+ } catch(Exception ex) {
+ return null;
+ }
+ }
+
+
+ /**
+ * Starts discovery service
+ *
+ * @param address - multicast group address
+ * @param port - udp port to use
+ * @param instanceName - name of running JVM instance
+ * @param url - JMX service url
+ * @throws IOException
+ */
+ public static synchronized void startDiscoveryService(InetAddress address, int port, String instanceName, String url)
+ throws IOException, JdpException {
+
+ // Limit packet to local subnet by default
+ int ttl = getInteger(
+ System.getProperty("com.sun.management.jdp.ttl"), 1,
+ "Invalid jdp packet ttl");
+
+ // Broadcast once a 5 seconds by default
+ int pause = getInteger(
+ System.getProperty("com.sun.management.jdp.pause"), 5,
+ "Invalid jdp pause");
+
+ // Converting seconds to milliseconds
+ pause = pause * 1000;
+
+ // Allow OS to choose broadcast source
+ InetAddress sourceAddress = getInetAddress(
+ System.getProperty("com.sun.management.jdp.source_addr"), null,
+ "Invalid source address provided");
+
+ // Generate session id
+ UUID id = UUID.randomUUID();
+
+ JdpJmxPacket packet = new JdpJmxPacket(id, url);
+
+ // Don't broadcast whole command line for security reason.
+ // Strip everything after first space
+ String javaCommand = System.getProperty("sun.java.command");
+ if (javaCommand != null) {
+ String[] arr = javaCommand.split(" ", 2);
+ packet.setMainClass(arr[0]);
+ }
+
+ // Put optional explicit java instance name to packet, if user doesn't specify
+ // it the key is skipped. PacketWriter is responsible to skip keys having null value.
+ packet.setInstanceName(instanceName);
+
+ // Set rmi server hostname if it explicitly specified by user with
+ // java.rmi.server.hostname
+ String rmiHostname = System.getProperty("java.rmi.server.hostname");
+ packet.setRmiHostname(rmiHostname);
+
+ // Set broadcast interval
+ packet.setBroadcastInterval(Integer.toString(pause));
+
+ // Set process id
+ Integer pid = getProcessId();
+ if (pid != null) {
+ packet.setProcessId(pid.toString());
+ }
+
+ JdpBroadcaster bcast = new JdpBroadcaster(address, sourceAddress, port, ttl);
+
+ // Stop discovery service if it's already running
+ stopDiscoveryService();
+
+ controller = new JDPControllerRunner(bcast, packet, pause);
+
+ Thread t = new Thread(null, controller, "JDP broadcaster", 0, false);
+ t.setDaemon(true);
+ t.start();
+ }
+
+ /**
+ * Stop running discovery service,
+ * it's safe to attempt to stop not started service
+ */
+ public static synchronized void stopDiscoveryService() {
+ if ( controller != null ){
+ controller.stop();
+ controller = null;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/sun/management/jdp/JdpException.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 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.
+ */
+package sun.management.jdp;
+
+/**
+ * An Exception thrown if a JDP implementation encounters a problem.
+ */
+public final class JdpException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Construct a new JDP exception with a meaningful message
+ *
+ * @param msg - message
+ */
+ public JdpException(String msg) {
+ super(msg);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/sun/management/jdp/JdpGenericPacket.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 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.
+ */
+package sun.management.jdp;
+
+/**
+ * JdpGenericPacket responsible to provide fields
+ * common for all Jdp packets
+ */
+public abstract class JdpGenericPacket implements JdpPacket {
+
+ /**
+ * JDP protocol magic. Magic allows a reader to quickly select
+ * JDP packets from a bunch of broadcast packets addressed to the same port
+ * and broadcast group. Any packet intended to be parsed by JDP client
+ * has to start from this magic.
+ */
+ private static final int MAGIC = 0xC0FFEE42;
+
+ /**
+ * Current version of protocol. Any implementation of this protocol has to
+ * conform with the packet structure and the flow described in JEP-168
+ */
+ private static final short PROTOCOL_VERSION = 1;
+
+ /**
+ * Default do-nothing constructor
+ */
+ protected JdpGenericPacket(){
+ // do nothing
+ }
+
+
+ /**
+ * Validate protocol header magic field
+ *
+ * @param magic - value to validate
+ * @throws JdpException
+ */
+ public static void checkMagic(int magic)
+ throws JdpException {
+ if (magic != MAGIC) {
+ throw new JdpException("Invalid JDP magic header: " + magic);
+ }
+ }
+
+ /**
+ * Validate protocol header version field
+ *
+ * @param version - value to validate
+ * @throws JdpException
+ */
+ public static void checkVersion(short version)
+ throws JdpException {
+
+ if (version > PROTOCOL_VERSION) {
+ throw new JdpException("Unsupported protocol version: " + version);
+ }
+ }
+
+ /**
+ *
+ * @return protocol magic
+ */
+ public static int getMagic() {
+ return MAGIC;
+ }
+
+ /**
+ *
+ * @return current protocol version
+ */
+ public static short getVersion() {
+ return PROTOCOL_VERSION;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/sun/management/jdp/JdpJmxPacket.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 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.
+ */
+package sun.management.jdp;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.UUID;
+
+/**
+ * A packet to broadcasts JMX URL
+ *
+ * Fields:
+ *
+ * <ul>
+ * <li>UUID - broadcast session ID, changed every time when we start/stop
+ * discovery service</li>
+ * <li>JMX_URL - URL to connect to JMX service</li>
+ * <li>MAIN_CLASS - optional name of main class, filled from sun.java.command stripped for
+ * security reason to first space</li>
+ * <li>INSTANCE_NAME - optional custom name of particular instance as provided by customer</li>
+ * </ul>
+ */
+public final class JdpJmxPacket
+ extends JdpGenericPacket
+ implements JdpPacket {
+
+ /**
+ * Session ID
+ */
+ public final static String UUID_KEY = "DISCOVERABLE_SESSION_UUID";
+ /**
+ * Name of main class
+ */
+ public final static String MAIN_CLASS_KEY = "MAIN_CLASS";
+ /**
+ * JMX service URL
+ */
+ public final static String JMX_SERVICE_URL_KEY = "JMX_SERVICE_URL";
+ /**
+ * Name of Java instance
+ */
+ public final static String INSTANCE_NAME_KEY = "INSTANCE_NAME";
+ /**
+ * PID of java process, optional presented if it could be obtained
+ */
+ public final static String PROCESS_ID_KEY = "PROCESS_ID";
+ /**
+ * Hostname of rmi server, optional presented if user overrides rmi server
+ * hostname by java.rmi.server.hostname property
+ */
+ public final static String RMI_HOSTNAME_KEY = "RMI_HOSTNAME";
+ /**
+ * Configured broadcast interval, optional
+ */
+ public final static String BROADCAST_INTERVAL_KEY = "BROADCAST_INTERVAL";
+
+ private UUID id;
+ private String mainClass;
+ private String jmxServiceUrl;
+ private String instanceName;
+ private String processId;
+ private String rmiHostname;
+ private String broadcastInterval;
+
+ /**
+ * Create new instance from user provided data. Set mandatory fields
+ *
+ * @param id - java instance id
+ * @param jmxServiceUrl - JMX service url
+ */
+ public JdpJmxPacket(UUID id, String jmxServiceUrl) {
+ this.id = id;
+ this.jmxServiceUrl = jmxServiceUrl;
+ }
+
+ /**
+ * Create new instance from network data Parse packet and set fields.
+ *
+ * @param data - raw packet data as it came from a Net
+ * @throws JdpException
+ */
+ public JdpJmxPacket(byte[] data)
+ throws JdpException {
+ JdpPacketReader reader;
+
+ reader = new JdpPacketReader(data);
+ Map<String, String> p = reader.getDiscoveryDataAsMap();
+
+ String sId = p.get(UUID_KEY);
+ this.id = (sId == null) ? null : UUID.fromString(sId);
+ this.jmxServiceUrl = p.get(JMX_SERVICE_URL_KEY);
+ this.mainClass = p.get(MAIN_CLASS_KEY);
+ this.instanceName = p.get(INSTANCE_NAME_KEY);
+ this.processId = p.get(PROCESS_ID_KEY);
+ this.rmiHostname = p.get(RMI_HOSTNAME_KEY);
+ this.broadcastInterval = p.get(BROADCAST_INTERVAL_KEY);
+ }
+
+ /**
+ * Set main class field
+ *
+ * @param mainClass - main class of running app
+ */
+ public void setMainClass(String mainClass) {
+ this.mainClass = mainClass;
+ }
+
+ /**
+ * Set instance name field
+ *
+ * @param instanceName - name of instance as provided by customer
+ */
+ public void setInstanceName(String instanceName) {
+ this.instanceName = instanceName;
+ }
+
+ /**
+ * @return id of discovery session
+ */
+ public UUID getId() {
+ return id;
+ }
+
+ /**
+ *
+ * @return main class field
+ */
+ public String getMainClass() {
+ return mainClass;
+ }
+
+ /**
+ *
+ * @return JMX service URL
+ */
+ public String getJmxServiceUrl() {
+ return jmxServiceUrl;
+ }
+
+ /**
+ *
+ * @return instance name
+ */
+ public String getInstanceName() {
+ return instanceName;
+ }
+
+ public String getProcessId() {
+ return processId;
+ }
+
+ public void setProcessId(String processId) {
+ this.processId = processId;
+ }
+
+ public String getRmiHostname() {
+ return rmiHostname;
+ }
+
+ public void setRmiHostname(String rmiHostname) {
+ this.rmiHostname = rmiHostname;
+ }
+
+ public String getBroadcastInterval() {
+ return broadcastInterval;
+ }
+
+ public void setBroadcastInterval(String broadcastInterval) {
+ this.broadcastInterval = broadcastInterval;
+ }
+
+ /**
+ *
+ * @return assembled packet ready to be sent across a Net
+ * @throws IOException
+ */
+ @Override
+ public byte[] getPacketData() throws IOException {
+ // Assemble packet from fields to byte array
+ JdpPacketWriter writer;
+ writer = new JdpPacketWriter();
+ writer.addEntry(UUID_KEY, (id == null) ? null : id.toString());
+ writer.addEntry(MAIN_CLASS_KEY, mainClass);
+ writer.addEntry(JMX_SERVICE_URL_KEY, jmxServiceUrl);
+ writer.addEntry(INSTANCE_NAME_KEY, instanceName);
+ writer.addEntry(PROCESS_ID_KEY, processId);
+ writer.addEntry(RMI_HOSTNAME_KEY, rmiHostname);
+ writer.addEntry(BROADCAST_INTERVAL_KEY, broadcastInterval);
+
+ return writer.getPacketBytes();
+ }
+
+ /**
+ *
+ * @return packet hash code
+ */
+ @Override
+ public int hashCode() {
+ int hash = 1;
+ hash = hash * 31 + id.hashCode();
+ hash = hash * 31 + jmxServiceUrl.hashCode();
+ return hash;
+ }
+
+ /**
+ * Compare two packets
+ *
+ * @param o - packet to compare
+ * @return either packet equals or not
+ */
+ @Override
+ public boolean equals(Object o) {
+
+ if (o == null || ! (o instanceof JdpJmxPacket) ){
+ return false;
+ }
+
+ JdpJmxPacket p = (JdpJmxPacket) o;
+ return Objects.equals(id, p.getId()) && Objects.equals(jmxServiceUrl, p.getJmxServiceUrl());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/sun/management/jdp/JdpPacket.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 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.
+ */
+package sun.management.jdp;
+
+import java.io.IOException;
+
+/**
+ * Packet to broadcast
+ *
+ * <p>Each packet have to contain MAGIC and PROTOCOL_VERSION in order to be
+ * recognized as a valid JDP packet.</p>
+ *
+ * <p>Default implementation build packet as a set of UTF-8 encoded Key/Value pairs
+ * are stored as an ordered list of values, and are sent to the server
+ * in that order.</p>
+ *
+ * <p>
+ * Packet structure:
+ *
+ * 4 bytes JDP magic (0xC0FFE42)
+ * 2 bytes JDP protocol version (01)
+ *
+ * 2 bytes size of key
+ * x bytes key (UTF-8 encoded)
+ * 2 bytes size of value
+ * x bytes value (UTF-8 encoded)
+ *
+ * repeat as many times as necessary ...
+ * </p>
+ */
+public interface JdpPacket {
+
+ /**
+ * This method responsible to assemble packet and return a byte array
+ * ready to be sent across a Net.
+ *
+ * @return assembled packet as an array of bytes
+ * @throws IOException
+ */
+ public byte[] getPacketData() throws IOException;
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/sun/management/jdp/JdpPacketReader.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 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.
+ */
+package sun.management.jdp;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * JdpPacketReader responsible for reading a packet <p>This class gets a byte
+ * array as it came from a Net, validates it and breaks a part </p>
+ */
+public final class JdpPacketReader {
+
+ private final DataInputStream pkt;
+ private Map<String, String> pmap = null;
+
+ /**
+ * Create packet reader, extract and check magic and version
+ *
+ * @param packet - packet received from a Net
+ * @throws JdpException
+ */
+ public JdpPacketReader(byte[] packet)
+ throws JdpException {
+ ByteArrayInputStream bais = new ByteArrayInputStream(packet);
+ pkt = new DataInputStream(bais);
+
+ try {
+ int magic = pkt.readInt();
+ JdpGenericPacket.checkMagic(magic);
+ } catch (IOException e) {
+ throw new JdpException("Invalid JDP packet received, bad magic");
+ }
+
+ try {
+ short version = pkt.readShort();
+ JdpGenericPacket.checkVersion(version);
+ } catch (IOException e) {
+ throw new JdpException("Invalid JDP packet received, bad protocol version");
+ }
+ }
+
+ /**
+ * Get next entry from packet
+ *
+ * @return the entry
+ * @throws EOFException
+ * @throws JdpException
+ */
+ public String getEntry()
+ throws EOFException, JdpException {
+
+ try {
+ short len = pkt.readShort();
+ // Artificial setting the "len" field to Short.MAX_VALUE may cause a reader to allocate
+ // to much memory. Prevent this possible DOS attack.
+ if (len < 1 && len > pkt.available()) {
+ throw new JdpException("Broken JDP packet. Invalid entry length field.");
+ }
+
+ byte[] b = new byte[len];
+ if (pkt.read(b) != len) {
+ throw new JdpException("Broken JDP packet. Unable to read entry.");
+ }
+ return new String(b, "UTF-8");
+
+ } catch (EOFException e) {
+ throw e;
+ } catch (UnsupportedEncodingException ex) {
+ throw new JdpException("Broken JDP packet. Unable to decode entry.");
+ } catch (IOException e) {
+ throw new JdpException("Broken JDP packet. Unable to read entry.");
+ }
+
+
+ }
+
+ /**
+ * return packet content as a key/value map
+ *
+ * @return map containing packet entries pair of entries treated as
+ * key,value
+ * @throws IOException
+ * @throws JdpException
+ */
+ public Map<String, String> getDiscoveryDataAsMap()
+ throws JdpException {
+ // return cached map if possible
+ if (pmap != null) {
+ return pmap;
+ }
+
+ String key = null, value = null;
+
+ final Map<String, String> tmpMap = new HashMap<>();
+ try {
+ while (true) {
+ key = getEntry();
+ value = getEntry();
+ tmpMap.put(key, value);
+ }
+ } catch (EOFException e) {
+ // EOF reached on reading value, report broken packet
+ // otherwise ignore it.
+ if (value == null) {
+ throw new JdpException("Broken JDP packet. Key without value." + key);
+ }
+ }
+
+ pmap = Collections.unmodifiableMap(tmpMap);
+ return pmap;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/sun/management/jdp/JdpPacketWriter.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 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.
+ */
+package sun.management.jdp;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * JdpPacketWriter responsible for writing a packet
+ * <p>This class assembles a set of key/value pairs to valid JDP packet,
+ * ready to be sent across a Net</p>
+ */
+public final class JdpPacketWriter {
+
+ private final ByteArrayOutputStream baos;
+ private final DataOutputStream pkt;
+
+ /**
+ * Create a JDP packet, add mandatory magic and version headers
+ *
+ * @throws IOException
+ */
+ public JdpPacketWriter()
+ throws IOException {
+ baos = new ByteArrayOutputStream();
+ pkt = new DataOutputStream(baos);
+
+ pkt.writeInt(JdpGenericPacket.getMagic());
+ pkt.writeShort(JdpGenericPacket.getVersion());
+ }
+
+ /**
+ * Put string entry to packet
+ *
+ * @param entry - string to put (utf-8 encoded)
+ * @throws IOException
+ */
+ public void addEntry(String entry)
+ throws IOException {
+ /* DataOutputStream.writeUTF() do essentially
+ * the same as:
+ * pkt.writeShort(entry.getBytes("UTF-8").length);
+ * pkt.write(entry.getBytes("UTF-8"));
+ */
+ pkt.writeUTF(entry);
+ }
+
+ /**
+ * Put key/value pair to packet
+ *
+ * @param key - key to put (utf-8 encoded)
+ * @param val - value to put (utf-8 encoded)
+ * @throws IOException
+ */
+ public void addEntry(String key, String val)
+ throws IOException {
+ /* Silently skip key if value is null.
+ * We don't need to distinguish between key missing
+ * and key has no value cases
+ */
+ if (val != null) {
+ addEntry(key);
+ addEntry(val);
+ }
+ }
+
+ /**
+ * Return assembled packet as a byte array
+ *
+ * @return packet bytes
+ */
+ public byte[] getPacketBytes() {
+ return baos.toByteArray();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/sun/management/jdp/package-info.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 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.
+ */
+/**
+ * Summary
+ * -------
+ *
+ * Define a lightweight network protocol for discovering running and
+ * manageable Java processes within a network subnet.
+ *
+ *
+ * Description
+ * -----------
+ *
+ * The protocol is lightweight multicast based, and works like a beacon,
+ * broadcasting the JMXService URL needed to connect to the external JMX
+ * agent if an application is started with appropriate parameters.
+ *
+ * The payload is structured like this:
+ *
+ * 4 bytes JDP magic (0xC0FFEE42)
+ * 2 bytes JDP protocol version (1)
+ * 2 bytes size of the next entry
+ * x bytes next entry (UTF-8 encoded)
+ * 2 bytes size of next entry
+ * ... Rinse and repeat...
+ *
+ * The payload will be parsed as even entries being keys, odd entries being
+ * values.
+ *
+ * The standard JDP packet contains four entries:
+ *
+ * - `DISCOVERABLE_SESSION_UUID` -- Unique id of the instance; this id changes every time
+ * the discovery protocol starts and stops
+ *
+ * - `MAIN_CLASS` -- The value of the `sun.java.command` property
+ *
+ * - `JMX_SERVICE_URL` -- The URL to connect to the JMX agent
+ *
+ * - `INSTANCE_NAME` -- The user-provided name of the running instance
+ *
+ * The protocol sends packets to 224.0.23.178:7095 by default.
+ *
+ * The protocol uses system properties to control it's behaviour:
+ * - `com.sun.management.jdp.port` -- override default port
+ *
+ * - `com.sun.management.jdp.address` -- override default address
+ *
+ * - `com.sun.management.jmxremote.autodiscovery` -- whether we should start autodiscovery or
+ * not. Autodiscovery starts if and only if following conditions are met: (autodiscovery is
+ * true OR (autodiscovery is not set AND jdp.port is set))
+ *
+ * - `com.sun.management.jdp.ttl` -- set ttl for broadcast packet, default is 1
+ * - `com.sun.management.jdp.pause` -- set broadcast interval in seconds default is 5
+ * - `com.sun.management.jdp.source_addr` -- an address of interface to use for broadcast
+ */
+
+package sun.management.jdp;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/sun/management/jmxremote/ConnectorBootstrap.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,1027 @@
+/*
+ * Copyright (c) 2003, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.management.jmxremote;
+
+import java.lang.System.Logger;
+import java.lang.System.Logger.Level;
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.lang.management.ManagementFactory;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.Socket;
+import java.net.ServerSocket;
+import java.net.UnknownHostException;
+import java.rmi.NoSuchObjectException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.registry.Registry;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+import java.rmi.server.RMISocketFactory;
+import java.rmi.server.RemoteObject;
+import java.rmi.server.UnicastRemoteObject;
+import java.security.KeyStore;
+import java.security.Principal;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import javax.management.MBeanServer;
+import javax.management.remote.JMXAuthenticator;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.rmi.RMIConnectorServer;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManagerFactory;
+import javax.rmi.ssl.SslRMIClientSocketFactory;
+import javax.rmi.ssl.SslRMIServerSocketFactory;
+import javax.security.auth.Subject;
+
+import com.sun.jmx.remote.internal.rmi.RMIExporter;
+import com.sun.jmx.remote.security.JMXPluggableAuthenticator;
+
+import jdk.internal.agent.Agent;
+import jdk.internal.agent.AgentConfigurationError;
+import static jdk.internal.agent.AgentConfigurationError.*;
+import jdk.internal.agent.ConnectorAddressLink;
+import jdk.internal.agent.FileSystem;
+import sun.rmi.server.UnicastRef;
+import sun.rmi.server.UnicastServerRef;
+import sun.rmi.server.UnicastServerRef2;
+
+/**
+ * This class initializes and starts the RMIConnectorServer for JSR 163
+ * JMX Monitoring.
+ **/
+public final class ConnectorBootstrap {
+
+ /**
+ * Default values for JMX configuration properties.
+ **/
+ public static interface DefaultValues {
+
+ public static final String PORT = "0";
+ public static final String CONFIG_FILE_NAME = "management.properties";
+ public static final String USE_SSL = "true";
+ public static final String USE_LOCAL_ONLY = "true";
+ public static final String USE_REGISTRY_SSL = "false";
+ public static final String USE_AUTHENTICATION = "true";
+ public static final String PASSWORD_FILE_NAME = "jmxremote.password";
+ public static final String ACCESS_FILE_NAME = "jmxremote.access";
+ public static final String SSL_NEED_CLIENT_AUTH = "false";
+ }
+
+ /**
+ * Names of JMX configuration properties.
+ **/
+ public static interface PropertyNames {
+
+ public static final String PORT =
+ "com.sun.management.jmxremote.port";
+ public static final String HOST =
+ "com.sun.management.jmxremote.host";
+ public static final String RMI_PORT =
+ "com.sun.management.jmxremote.rmi.port";
+ public static final String CONFIG_FILE_NAME =
+ "com.sun.management.config.file";
+ public static final String USE_LOCAL_ONLY =
+ "com.sun.management.jmxremote.local.only";
+ public static final String USE_SSL =
+ "com.sun.management.jmxremote.ssl";
+ public static final String USE_REGISTRY_SSL =
+ "com.sun.management.jmxremote.registry.ssl";
+ public static final String USE_AUTHENTICATION =
+ "com.sun.management.jmxremote.authenticate";
+ public static final String PASSWORD_FILE_NAME =
+ "com.sun.management.jmxremote.password.file";
+ public static final String ACCESS_FILE_NAME =
+ "com.sun.management.jmxremote.access.file";
+ public static final String LOGIN_CONFIG_NAME =
+ "com.sun.management.jmxremote.login.config";
+ public static final String SSL_ENABLED_CIPHER_SUITES =
+ "com.sun.management.jmxremote.ssl.enabled.cipher.suites";
+ public static final String SSL_ENABLED_PROTOCOLS =
+ "com.sun.management.jmxremote.ssl.enabled.protocols";
+ public static final String SSL_NEED_CLIENT_AUTH =
+ "com.sun.management.jmxremote.ssl.need.client.auth";
+ public static final String SSL_CONFIG_FILE_NAME =
+ "com.sun.management.jmxremote.ssl.config.file";
+ }
+
+ /**
+ * JMXConnectorServer associated data.
+ */
+ private static class JMXConnectorServerData {
+
+ public JMXConnectorServerData(
+ JMXConnectorServer jmxConnectorServer,
+ JMXServiceURL jmxRemoteURL) {
+ this.jmxConnectorServer = jmxConnectorServer;
+ this.jmxRemoteURL = jmxRemoteURL;
+ }
+ JMXConnectorServer jmxConnectorServer;
+ JMXServiceURL jmxRemoteURL;
+ }
+
+ /**
+ * <p>Prevents our RMI server objects from keeping the JVM alive.</p>
+ *
+ * <p>We use a private interface in Sun's JMX Remote API implementation
+ * that allows us to specify how to export RMI objects. We do so using
+ * UnicastServerRef, a class in Sun's RMI implementation. This is all
+ * non-portable, of course, so this is only valid because we are inside
+ * Sun's JRE.</p>
+ *
+ * <p>Objects are exported using {@link
+ * UnicastServerRef#exportObject(Remote, Object, boolean)}. The
+ * boolean parameter is called <code>permanent</code> and means
+ * both that the object is not eligible for Distributed Garbage
+ * Collection, and that its continued existence will not prevent
+ * the JVM from exiting. It is the latter semantics we want (we
+ * already have the former because of the way the JMX Remote API
+ * works). Hence the somewhat misleading name of this class.</p>
+ */
+ private static class PermanentExporter implements RMIExporter {
+
+ public Remote exportObject(Remote obj,
+ int port,
+ RMIClientSocketFactory csf,
+ RMIServerSocketFactory ssf)
+ throws RemoteException {
+
+ synchronized (this) {
+ if (firstExported == null) {
+ firstExported = obj;
+ }
+ }
+
+ final UnicastServerRef ref;
+ if (csf == null && ssf == null) {
+ ref = new UnicastServerRef(port);
+ } else {
+ ref = new UnicastServerRef2(port, csf, ssf);
+ }
+ return ref.exportObject(obj, null, true);
+ }
+
+ // Nothing special to be done for this case
+ public boolean unexportObject(Remote obj, boolean force)
+ throws NoSuchObjectException {
+ return UnicastRemoteObject.unexportObject(obj, force);
+ }
+ Remote firstExported;
+ }
+
+ /**
+ * This JMXAuthenticator wraps the JMXPluggableAuthenticator and verifies
+ * that at least one of the principal names contained in the authenticated
+ * Subject is present in the access file.
+ */
+ private static class AccessFileCheckerAuthenticator
+ implements JMXAuthenticator {
+
+ public AccessFileCheckerAuthenticator(Map<String, Object> env) throws IOException {
+ environment = env;
+ accessFile = (String) env.get("jmx.remote.x.access.file");
+ properties = propertiesFromFile(accessFile);
+ }
+
+ public Subject authenticate(Object credentials) {
+ final JMXAuthenticator authenticator =
+ new JMXPluggableAuthenticator(environment);
+ final Subject subject = authenticator.authenticate(credentials);
+ checkAccessFileEntries(subject);
+ return subject;
+ }
+
+ private void checkAccessFileEntries(Subject subject) {
+ if (subject == null) {
+ throw new SecurityException(
+ "Access denied! No matching entries found in " +
+ "the access file [" + accessFile + "] as the " +
+ "authenticated Subject is null");
+ }
+ final Set<Principal> principals = subject.getPrincipals();
+ for (Principal p1: principals) {
+ if (properties.containsKey(p1.getName())) {
+ return;
+ }
+ }
+
+ final Set<String> principalsStr = new HashSet<>();
+ for (Principal p2: principals) {
+ principalsStr.add(p2.getName());
+ }
+ throw new SecurityException(
+ "Access denied! No entries found in the access file [" +
+ accessFile + "] for any of the authenticated identities " +
+ principalsStr);
+ }
+
+ private static Properties propertiesFromFile(String fname)
+ throws IOException {
+ Properties p = new Properties();
+ if (fname == null) {
+ return p;
+ }
+ try (FileInputStream fin = new FileInputStream(fname)) {
+ p.load(fin);
+ }
+ return p;
+ }
+ private final Map<String, Object> environment;
+ private final Properties properties;
+ private final String accessFile;
+ }
+
+ // The variable below is here to support stop functionality
+ // It would be overriten if you call startRemoteCommectionServer second
+ // time. It's OK for now as logic in Agent.java forbids mutiple agents
+ private static Registry registry = null;
+
+ public static void unexportRegistry() {
+ // Remove the entry from registry
+ try {
+ if (registry != null) {
+ UnicastRemoteObject.unexportObject(registry, true);
+ registry = null;
+ }
+ } catch(NoSuchObjectException ex) {
+ // This exception can appears only if we attempt
+ // to unexportRegistry second time. So it's safe
+ // to ignore it without additional messages.
+ }
+ }
+
+ /**
+ * Initializes and starts the JMX Connector Server.
+ * If the com.sun.management.jmxremote.port property is not defined,
+ * simply return. Otherwise, attempts to load the config file, and
+ * then calls {@link #startRemoteConnectorServer
+ * (java.lang.String, java.util.Properties)}.
+ *
+ * This method is used by some jtreg tests.
+ **/
+ public static synchronized JMXConnectorServer initialize() {
+
+ // Load a new management properties
+ final Properties props = Agent.loadManagementProperties();
+ if (props == null) {
+ return null;
+ }
+
+ final String portStr = props.getProperty(PropertyNames.PORT);
+ return startRemoteConnectorServer(portStr, props);
+ }
+
+ /**
+ * This method is used by some jtreg tests.
+ *
+ * @see #startRemoteConnectorServer
+ * (String portStr, Properties props)
+ */
+ public static synchronized JMXConnectorServer initialize(String portStr, Properties props) {
+ return startRemoteConnectorServer(portStr, props);
+ }
+
+ /**
+ * Initializes and starts a JMX Connector Server for remote
+ * monitoring and management.
+ **/
+ public static synchronized JMXConnectorServer startRemoteConnectorServer(String portStr, Properties props) {
+
+ // Get port number
+ final int port;
+ try {
+ port = Integer.parseInt(portStr);
+ } catch (NumberFormatException x) {
+ throw new AgentConfigurationError(INVALID_JMXREMOTE_PORT, x, portStr);
+ }
+ if (port < 0) {
+ throw new AgentConfigurationError(INVALID_JMXREMOTE_PORT, portStr);
+ }
+
+ // User can specify a port to be used to export rmi object,
+ // in order to simplify firewall rules
+ // if port is not specified random one will be allocated.
+ int rmiPort = 0;
+ String rmiPortStr = props.getProperty(PropertyNames.RMI_PORT);
+ try {
+ if (rmiPortStr != null) {
+ rmiPort = Integer.parseInt(rmiPortStr);
+ }
+ } catch (NumberFormatException x) {
+ throw new AgentConfigurationError(INVALID_JMXREMOTE_RMI_PORT, x, rmiPortStr);
+ }
+ if (rmiPort < 0) {
+ throw new AgentConfigurationError(INVALID_JMXREMOTE_RMI_PORT, rmiPortStr);
+ }
+
+ // Do we use authentication?
+ final String useAuthenticationStr =
+ props.getProperty(PropertyNames.USE_AUTHENTICATION,
+ DefaultValues.USE_AUTHENTICATION);
+ final boolean useAuthentication =
+ Boolean.valueOf(useAuthenticationStr).booleanValue();
+
+ // Do we use SSL?
+ final String useSslStr =
+ props.getProperty(PropertyNames.USE_SSL,
+ DefaultValues.USE_SSL);
+ final boolean useSsl =
+ Boolean.valueOf(useSslStr).booleanValue();
+
+ // Do we use RMI Registry SSL?
+ final String useRegistrySslStr =
+ props.getProperty(PropertyNames.USE_REGISTRY_SSL,
+ DefaultValues.USE_REGISTRY_SSL);
+ final boolean useRegistrySsl =
+ Boolean.valueOf(useRegistrySslStr).booleanValue();
+
+ final String enabledCipherSuites =
+ props.getProperty(PropertyNames.SSL_ENABLED_CIPHER_SUITES);
+ String enabledCipherSuitesList[] = null;
+ if (enabledCipherSuites != null) {
+ StringTokenizer st = new StringTokenizer(enabledCipherSuites, ",");
+ int tokens = st.countTokens();
+ enabledCipherSuitesList = new String[tokens];
+ for (int i = 0; i < tokens; i++) {
+ enabledCipherSuitesList[i] = st.nextToken();
+ }
+ }
+
+ final String enabledProtocols =
+ props.getProperty(PropertyNames.SSL_ENABLED_PROTOCOLS);
+ String enabledProtocolsList[] = null;
+ if (enabledProtocols != null) {
+ StringTokenizer st = new StringTokenizer(enabledProtocols, ",");
+ int tokens = st.countTokens();
+ enabledProtocolsList = new String[tokens];
+ for (int i = 0; i < tokens; i++) {
+ enabledProtocolsList[i] = st.nextToken();
+ }
+ }
+
+ final String sslNeedClientAuthStr =
+ props.getProperty(PropertyNames.SSL_NEED_CLIENT_AUTH,
+ DefaultValues.SSL_NEED_CLIENT_AUTH);
+ final boolean sslNeedClientAuth =
+ Boolean.valueOf(sslNeedClientAuthStr).booleanValue();
+
+ // Read SSL config file name
+ final String sslConfigFileName =
+ props.getProperty(PropertyNames.SSL_CONFIG_FILE_NAME);
+
+ String loginConfigName = null;
+ String passwordFileName = null;
+ String accessFileName = null;
+
+ // Initialize settings when authentication is active
+ if (useAuthentication) {
+
+ // Get non-default login configuration
+ loginConfigName =
+ props.getProperty(PropertyNames.LOGIN_CONFIG_NAME);
+
+ if (loginConfigName == null) {
+ // Get password file
+ passwordFileName =
+ props.getProperty(PropertyNames.PASSWORD_FILE_NAME,
+ getDefaultFileName(DefaultValues.PASSWORD_FILE_NAME));
+ checkPasswordFile(passwordFileName);
+ }
+
+ // Get access file
+ accessFileName = props.getProperty(PropertyNames.ACCESS_FILE_NAME,
+ getDefaultFileName(DefaultValues.ACCESS_FILE_NAME));
+ checkAccessFile(accessFileName);
+ }
+
+ final String bindAddress =
+ props.getProperty(PropertyNames.HOST);
+
+ if (logger.isLoggable(Level.DEBUG)) {
+ logger.log(Level.DEBUG, "startRemoteConnectorServer",
+ Agent.getText("jmxremote.ConnectorBootstrap.starting") +
+ "\n\t" + PropertyNames.PORT + "=" + port +
+ (bindAddress == null ? "" : "\n\t" + PropertyNames.HOST + "=" + bindAddress) +
+ "\n\t" + PropertyNames.RMI_PORT + "=" + rmiPort +
+ "\n\t" + PropertyNames.USE_SSL + "=" + useSsl +
+ "\n\t" + PropertyNames.USE_REGISTRY_SSL + "=" + useRegistrySsl +
+ "\n\t" + PropertyNames.SSL_CONFIG_FILE_NAME + "=" + sslConfigFileName +
+ "\n\t" + PropertyNames.SSL_ENABLED_CIPHER_SUITES + "=" +
+ enabledCipherSuites +
+ "\n\t" + PropertyNames.SSL_ENABLED_PROTOCOLS + "=" +
+ enabledProtocols +
+ "\n\t" + PropertyNames.SSL_NEED_CLIENT_AUTH + "=" +
+ sslNeedClientAuth +
+ "\n\t" + PropertyNames.USE_AUTHENTICATION + "=" +
+ useAuthentication +
+ (useAuthentication ? (loginConfigName == null ? ("\n\t" + PropertyNames.PASSWORD_FILE_NAME + "=" +
+ passwordFileName) : ("\n\t" + PropertyNames.LOGIN_CONFIG_NAME + "=" +
+ loginConfigName)) : "\n\t" +
+ Agent.getText("jmxremote.ConnectorBootstrap.noAuthentication")) +
+ (useAuthentication ? ("\n\t" + PropertyNames.ACCESS_FILE_NAME + "=" +
+ accessFileName) : "") +
+ "");
+ }
+
+ final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ JMXConnectorServer cs = null;
+ JMXServiceURL url = null;
+ try {
+ final JMXConnectorServerData data = exportMBeanServer(
+ mbs, port, rmiPort, useSsl, useRegistrySsl,
+ sslConfigFileName, enabledCipherSuitesList,
+ enabledProtocolsList, sslNeedClientAuth,
+ useAuthentication, loginConfigName,
+ passwordFileName, accessFileName, bindAddress);
+ cs = data.jmxConnectorServer;
+ url = data.jmxRemoteURL;
+ config("startRemoteConnectorServer",
+ Agent.getText("jmxremote.ConnectorBootstrap.ready",
+ url.toString()));
+ } catch (Exception e) {
+ throw new AgentConfigurationError(AGENT_EXCEPTION, e, e.toString());
+ }
+ try {
+ // Export remote connector address and associated configuration
+ // properties to the instrumentation buffer.
+ Map<String, String> properties = new HashMap<>();
+ properties.put("remoteAddress", url.toString());
+ properties.put("authenticate", useAuthenticationStr);
+ properties.put("ssl", useSslStr);
+ properties.put("sslRegistry", useRegistrySslStr);
+ properties.put("sslNeedClientAuth", sslNeedClientAuthStr);
+ ConnectorAddressLink.exportRemote(properties);
+ } catch (Exception e) {
+ // Remote connector server started but unable to export remote
+ // connector address and associated configuration properties to
+ // the instrumentation buffer - non-fatal error.
+ config("startRemoteConnectorServer", e);
+ }
+ return cs;
+ }
+
+ /*
+ * Creates and starts a RMI Connector Server for "local" monitoring
+ * and management.
+ */
+ public static JMXConnectorServer startLocalConnectorServer() {
+ // Ensure cryptographically strong random number generater used
+ // to choose the object number - see java.rmi.server.ObjID
+ System.setProperty("java.rmi.server.randomIDs", "true");
+
+ // This RMI server should not keep the VM alive
+ Map<String, Object> env = new HashMap<>();
+ env.put(RMIExporter.EXPORTER_ATTRIBUTE, new PermanentExporter());
+ env.put(RMIConnectorServer.CREDENTIAL_TYPES, new String[]{
+ String[].class.getName(), String.class.getName()
+ });
+
+ // The local connector server need only be available via the
+ // loopback connection.
+ String localhost = "localhost";
+ InetAddress lh = null;
+ try {
+ lh = InetAddress.getByName(localhost);
+ localhost = lh.getHostAddress();
+ } catch (UnknownHostException x) {
+ }
+
+ // localhost unknown or (somehow) didn't resolve to
+ // a loopback address.
+ if (lh == null || !lh.isLoopbackAddress()) {
+ localhost = "127.0.0.1";
+ }
+
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ try {
+ JMXServiceURL url = new JMXServiceURL("rmi", localhost, 0);
+ // Do we accept connections from local interfaces only?
+ Properties props = Agent.getManagementProperties();
+ if (props == null) {
+ props = new Properties();
+ }
+ String useLocalOnlyStr = props.getProperty(
+ PropertyNames.USE_LOCAL_ONLY, DefaultValues.USE_LOCAL_ONLY);
+ boolean useLocalOnly = Boolean.valueOf(useLocalOnlyStr).booleanValue();
+ if (useLocalOnly) {
+ env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE,
+ new LocalRMIServerSocketFactory());
+ }
+ JMXConnectorServer server =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
+ server.start();
+ return server;
+ } catch (Exception e) {
+ throw new AgentConfigurationError(AGENT_EXCEPTION, e, e.toString());
+ }
+ }
+
+ private static void checkPasswordFile(String passwordFileName) {
+ if (passwordFileName == null || passwordFileName.length() == 0) {
+ throw new AgentConfigurationError(PASSWORD_FILE_NOT_SET);
+ }
+ File file = new File(passwordFileName);
+ if (!file.exists()) {
+ throw new AgentConfigurationError(PASSWORD_FILE_NOT_FOUND, passwordFileName);
+ }
+
+ if (!file.canRead()) {
+ throw new AgentConfigurationError(PASSWORD_FILE_NOT_READABLE, passwordFileName);
+ }
+
+ FileSystem fs = FileSystem.open();
+ try {
+ if (fs.supportsFileSecurity(file)) {
+ if (!fs.isAccessUserOnly(file)) {
+ final String msg = Agent.getText("jmxremote.ConnectorBootstrap.password.readonly",
+ passwordFileName);
+ config("startRemoteConnectorServer", msg);
+ throw new AgentConfigurationError(PASSWORD_FILE_ACCESS_NOT_RESTRICTED,
+ passwordFileName);
+ }
+ }
+ } catch (IOException e) {
+ throw new AgentConfigurationError(PASSWORD_FILE_READ_FAILED,
+ e, passwordFileName);
+ }
+ }
+
+ private static void checkAccessFile(String accessFileName) {
+ if (accessFileName == null || accessFileName.length() == 0) {
+ throw new AgentConfigurationError(ACCESS_FILE_NOT_SET);
+ }
+ File file = new File(accessFileName);
+ if (!file.exists()) {
+ throw new AgentConfigurationError(ACCESS_FILE_NOT_FOUND, accessFileName);
+ }
+
+ if (!file.canRead()) {
+ throw new AgentConfigurationError(ACCESS_FILE_NOT_READABLE, accessFileName);
+ }
+ }
+
+ private static void checkRestrictedFile(String restrictedFileName) {
+ if (restrictedFileName == null || restrictedFileName.length() == 0) {
+ throw new AgentConfigurationError(FILE_NOT_SET);
+ }
+ File file = new File(restrictedFileName);
+ if (!file.exists()) {
+ throw new AgentConfigurationError(FILE_NOT_FOUND, restrictedFileName);
+ }
+ if (!file.canRead()) {
+ throw new AgentConfigurationError(FILE_NOT_READABLE, restrictedFileName);
+ }
+ FileSystem fs = FileSystem.open();
+ try {
+ if (fs.supportsFileSecurity(file)) {
+ if (!fs.isAccessUserOnly(file)) {
+ final String msg = Agent.getText(
+ "jmxremote.ConnectorBootstrap.file.readonly",
+ restrictedFileName);
+ config("startRemoteConnectorServer", msg);
+ throw new AgentConfigurationError(
+ FILE_ACCESS_NOT_RESTRICTED, restrictedFileName);
+ }
+ }
+ } catch (IOException e) {
+ throw new AgentConfigurationError(
+ FILE_READ_FAILED, e, restrictedFileName);
+ }
+ }
+
+ /**
+ * Compute the full path name for a default file.
+ * @param basename basename (with extension) of the default file.
+ * @return ${JRE}/conf/management/${basename}
+ **/
+ private static String getDefaultFileName(String basename) {
+ final String fileSeparator = File.separator;
+ return System.getProperty("java.home") + fileSeparator + "conf" +
+ fileSeparator + "management" + fileSeparator +
+ basename;
+ }
+
+ private static SslRMIServerSocketFactory createSslRMIServerSocketFactory(
+ String sslConfigFileName,
+ String[] enabledCipherSuites,
+ String[] enabledProtocols,
+ boolean sslNeedClientAuth,
+ String bindAddress) {
+ if (sslConfigFileName == null) {
+ return new HostAwareSslSocketFactory(
+ enabledCipherSuites,
+ enabledProtocols,
+ sslNeedClientAuth, bindAddress);
+ } else {
+ checkRestrictedFile(sslConfigFileName);
+ try {
+ // Load the SSL keystore properties from the config file
+ Properties p = new Properties();
+ try (InputStream in = new FileInputStream(sslConfigFileName)) {
+ BufferedInputStream bin = new BufferedInputStream(in);
+ p.load(bin);
+ }
+ String keyStore =
+ p.getProperty("javax.net.ssl.keyStore");
+ String keyStorePassword =
+ p.getProperty("javax.net.ssl.keyStorePassword", "");
+ String trustStore =
+ p.getProperty("javax.net.ssl.trustStore");
+ String trustStorePassword =
+ p.getProperty("javax.net.ssl.trustStorePassword", "");
+
+ char[] keyStorePasswd = null;
+ if (keyStorePassword.length() != 0) {
+ keyStorePasswd = keyStorePassword.toCharArray();
+ }
+
+ char[] trustStorePasswd = null;
+ if (trustStorePassword.length() != 0) {
+ trustStorePasswd = trustStorePassword.toCharArray();
+ }
+
+ KeyStore ks = null;
+ if (keyStore != null) {
+ ks = KeyStore.getInstance(KeyStore.getDefaultType());
+ try (FileInputStream ksfis = new FileInputStream(keyStore)) {
+ ks.load(ksfis, keyStorePasswd);
+ }
+ }
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(
+ KeyManagerFactory.getDefaultAlgorithm());
+ kmf.init(ks, keyStorePasswd);
+
+ KeyStore ts = null;
+ if (trustStore != null) {
+ ts = KeyStore.getInstance(KeyStore.getDefaultType());
+ try (FileInputStream tsfis = new FileInputStream(trustStore)) {
+ ts.load(tsfis, trustStorePasswd);
+ }
+ }
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(
+ TrustManagerFactory.getDefaultAlgorithm());
+ tmf.init(ts);
+
+ SSLContext ctx = SSLContext.getInstance("SSL");
+ ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+
+ return new HostAwareSslSocketFactory(
+ ctx,
+ enabledCipherSuites,
+ enabledProtocols,
+ sslNeedClientAuth, bindAddress);
+ } catch (Exception e) {
+ throw new AgentConfigurationError(AGENT_EXCEPTION, e, e.toString());
+ }
+ }
+ }
+
+ private static JMXConnectorServerData exportMBeanServer(
+ MBeanServer mbs,
+ int port,
+ int rmiPort,
+ boolean useSsl,
+ boolean useRegistrySsl,
+ String sslConfigFileName,
+ String[] enabledCipherSuites,
+ String[] enabledProtocols,
+ boolean sslNeedClientAuth,
+ boolean useAuthentication,
+ String loginConfigName,
+ String passwordFileName,
+ String accessFileName,
+ String bindAddress)
+ throws IOException, MalformedURLException {
+
+ /* Make sure we use non-guessable RMI object IDs. Otherwise
+ * attackers could hijack open connections by guessing their
+ * IDs. */
+ System.setProperty("java.rmi.server.randomIDs", "true");
+
+ JMXServiceURL url = new JMXServiceURL("rmi", bindAddress, rmiPort);
+
+ Map<String, Object> env = new HashMap<>();
+
+ PermanentExporter exporter = new PermanentExporter();
+
+ env.put(RMIExporter.EXPORTER_ATTRIBUTE, exporter);
+ env.put(RMIConnectorServer.CREDENTIAL_TYPES, new String[]{
+ String[].class.getName(), String.class.getName()
+ });
+
+ boolean useSocketFactory = bindAddress != null && !useSsl;
+
+ if (useAuthentication) {
+ if (loginConfigName != null) {
+ env.put("jmx.remote.x.login.config", loginConfigName);
+ }
+ if (passwordFileName != null) {
+ env.put("jmx.remote.x.password.file", passwordFileName);
+ }
+
+ env.put("jmx.remote.x.access.file", accessFileName);
+
+ if (env.get("jmx.remote.x.password.file") != null ||
+ env.get("jmx.remote.x.login.config") != null) {
+ env.put(JMXConnectorServer.AUTHENTICATOR,
+ new AccessFileCheckerAuthenticator(env));
+ }
+ }
+
+ RMIClientSocketFactory csf = null;
+ RMIServerSocketFactory ssf = null;
+
+ if (useSsl || useRegistrySsl) {
+ csf = new SslRMIClientSocketFactory();
+ ssf = createSslRMIServerSocketFactory(
+ sslConfigFileName, enabledCipherSuites,
+ enabledProtocols, sslNeedClientAuth, bindAddress);
+ }
+
+ if (useSsl) {
+ env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE,
+ csf);
+ env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE,
+ ssf);
+ }
+
+ if (useSocketFactory) {
+ ssf = new HostAwareSocketFactory(bindAddress);
+ env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE,
+ ssf);
+ }
+
+ JMXConnectorServer connServer = null;
+ try {
+ connServer =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
+ connServer.start();
+ } catch (IOException e) {
+ if (connServer == null || connServer.getAddress() == null) {
+ throw new AgentConfigurationError(CONNECTOR_SERVER_IO_ERROR,
+ e, url.toString());
+ } else {
+ throw new AgentConfigurationError(CONNECTOR_SERVER_IO_ERROR,
+ e, connServer.getAddress().toString());
+ }
+ }
+
+ if (useRegistrySsl) {
+ registry =
+ new SingleEntryRegistry(port, csf, ssf,
+ "jmxrmi", exporter.firstExported);
+ } else if (useSocketFactory) {
+ registry =
+ new SingleEntryRegistry(port, csf, ssf,
+ "jmxrmi", exporter.firstExported);
+ } else {
+ registry =
+ new SingleEntryRegistry(port,
+ "jmxrmi", exporter.firstExported);
+ }
+
+
+ int registryPort =
+ ((UnicastRef) ((RemoteObject) registry).getRef()).getLiveRef().getPort();
+ String jmxUrlStr = String.format("service:jmx:rmi:///jndi/rmi://%s:%d/jmxrmi",
+ url.getHost(), registryPort);
+ JMXServiceURL remoteURL = new JMXServiceURL(jmxUrlStr);
+
+ /* Our exporter remembers the first object it was asked to
+ export, which will be an RMIServerImpl appropriate for
+ publication in our special registry. We could
+ alternatively have constructed the RMIServerImpl explicitly
+ and then constructed an RMIConnectorServer passing it as a
+ parameter, but that's quite a bit more verbose and pulls in
+ lots of knowledge of the RMI connector. */
+
+ return new JMXConnectorServerData(connServer, remoteURL);
+ }
+
+ /**
+ * This class cannot be instantiated.
+ **/
+ private ConnectorBootstrap() {
+ }
+
+ private static final Logger logger =
+ System.getLogger(ConnectorBootstrap.class.getPackageName());
+ private static void config(String func, String msg) {
+ logger.log(Level.DEBUG, msg);
+ }
+
+ private static void config(String func, Throwable t) {
+ logger.log(Level.DEBUG, "ConnectorBootstrap::" + func, t);
+ }
+
+ private static void config(String func, String msg, Throwable t) {
+ logger.log(Level.DEBUG, msg, t);
+ }
+
+ private static class HostAwareSocketFactory implements RMIServerSocketFactory {
+
+ private final String bindAddress;
+
+ private HostAwareSocketFactory(String bindAddress) {
+ this.bindAddress = bindAddress;
+ }
+
+ @Override
+ public ServerSocket createServerSocket(int port) throws IOException {
+ if (bindAddress == null) {
+ return new ServerSocket(port);
+ } else {
+ try {
+ InetAddress addr = InetAddress.getByName(bindAddress);
+ return new ServerSocket(port, 0, addr);
+ } catch (UnknownHostException e) {
+ return new ServerSocket(port);
+ }
+ }
+ }
+ }
+
+ private static class HostAwareSslSocketFactory extends SslRMIServerSocketFactory {
+
+ private final String bindAddress;
+ private final String[] enabledCipherSuites;
+ private final String[] enabledProtocols;
+ private final boolean needClientAuth;
+ private final SSLContext context;
+
+ private HostAwareSslSocketFactory(String[] enabledCipherSuites,
+ String[] enabledProtocols,
+ boolean sslNeedClientAuth,
+ String bindAddress) throws IllegalArgumentException {
+ this(null, enabledCipherSuites, enabledProtocols, sslNeedClientAuth, bindAddress);
+ }
+
+ private HostAwareSslSocketFactory(SSLContext ctx,
+ String[] enabledCipherSuites,
+ String[] enabledProtocols,
+ boolean sslNeedClientAuth,
+ String bindAddress) throws IllegalArgumentException {
+ this.context = ctx;
+ this.bindAddress = bindAddress;
+ this.enabledProtocols = enabledProtocols;
+ this.enabledCipherSuites = enabledCipherSuites;
+ this.needClientAuth = sslNeedClientAuth;
+ checkValues(ctx, enabledCipherSuites, enabledProtocols);
+ }
+
+ @Override
+ public ServerSocket createServerSocket(int port) throws IOException {
+ if (bindAddress != null) {
+ try {
+ InetAddress addr = InetAddress.getByName(bindAddress);
+ return new SslServerSocket(port, 0, addr, context,
+ enabledCipherSuites, enabledProtocols, needClientAuth);
+ } catch (UnknownHostException e) {
+ return new SslServerSocket(port, context,
+ enabledCipherSuites, enabledProtocols, needClientAuth);
+ }
+ } else {
+ return new SslServerSocket(port, context,
+ enabledCipherSuites, enabledProtocols, needClientAuth);
+ }
+ }
+
+ private static void checkValues(SSLContext context,
+ String[] enabledCipherSuites,
+ String[] enabledProtocols) throws IllegalArgumentException {
+ // Force the initialization of the default at construction time,
+ // rather than delaying it to the first time createServerSocket()
+ // is called.
+ //
+ final SSLSocketFactory sslSocketFactory =
+ context == null ?
+ (SSLSocketFactory)SSLSocketFactory.getDefault() : context.getSocketFactory();
+ SSLSocket sslSocket = null;
+ if (enabledCipherSuites != null || enabledProtocols != null) {
+ try {
+ sslSocket = (SSLSocket) sslSocketFactory.createSocket();
+ } catch (Exception e) {
+ final String msg = "Unable to check if the cipher suites " +
+ "and protocols to enable are supported";
+ throw (IllegalArgumentException)
+ new IllegalArgumentException(msg).initCause(e);
+ }
+ }
+
+ // Check if all the cipher suites and protocol versions to enable
+ // are supported by the underlying SSL/TLS implementation and if
+ // true create lists from arrays.
+ //
+ if (enabledCipherSuites != null) {
+ sslSocket.setEnabledCipherSuites(enabledCipherSuites);
+ }
+ if (enabledProtocols != null) {
+ sslSocket.setEnabledProtocols(enabledProtocols);
+ }
+ }
+ }
+
+ private static class SslServerSocket extends ServerSocket {
+
+ private static SSLSocketFactory defaultSSLSocketFactory;
+ private final String[] enabledCipherSuites;
+ private final String[] enabledProtocols;
+ private final boolean needClientAuth;
+ private final SSLContext context;
+
+ private SslServerSocket(int port,
+ SSLContext ctx,
+ String[] enabledCipherSuites,
+ String[] enabledProtocols,
+ boolean needClientAuth) throws IOException {
+ super(port);
+ this.enabledProtocols = enabledProtocols;
+ this.enabledCipherSuites = enabledCipherSuites;
+ this.needClientAuth = needClientAuth;
+ this.context = ctx;
+ }
+
+ private SslServerSocket(int port,
+ int backlog,
+ InetAddress bindAddr,
+ SSLContext ctx,
+ String[] enabledCipherSuites,
+ String[] enabledProtocols,
+ boolean needClientAuth) throws IOException {
+ super(port, backlog, bindAddr);
+ this.enabledProtocols = enabledProtocols;
+ this.enabledCipherSuites = enabledCipherSuites;
+ this.needClientAuth = needClientAuth;
+ this.context = ctx;
+ }
+
+ @Override
+ public Socket accept() throws IOException {
+ final SSLSocketFactory sslSocketFactory =
+ context == null ?
+ getDefaultSSLSocketFactory() : context.getSocketFactory();
+ Socket socket = super.accept();
+ SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(
+ socket, socket.getInetAddress().getHostName(),
+ socket.getPort(), true);
+ sslSocket.setUseClientMode(false);
+ if (enabledCipherSuites != null) {
+ sslSocket.setEnabledCipherSuites(enabledCipherSuites);
+ }
+ if (enabledProtocols != null) {
+ sslSocket.setEnabledProtocols(enabledProtocols);
+ }
+ sslSocket.setNeedClientAuth(needClientAuth);
+ return sslSocket;
+ }
+
+ private static synchronized SSLSocketFactory getDefaultSSLSocketFactory() {
+ if (defaultSSLSocketFactory == null) {
+ defaultSSLSocketFactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
+ return defaultSSLSocketFactory;
+ } else {
+ return defaultSSLSocketFactory;
+ }
+ }
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/sun/management/jmxremote/LocalRMIServerSocketFactory.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.management.jmxremote;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.rmi.server.RMIServerSocketFactory;
+import java.util.Enumeration;
+
+/**
+ * This RMI server socket factory creates server sockets that
+ * will only accept connection requests from clients running
+ * on the host where the RMI remote objects have been exported.
+ */
+public final class LocalRMIServerSocketFactory implements RMIServerSocketFactory {
+ /**
+ * Creates a server socket that only accepts connection requests from
+ * clients running on the host where the RMI remote objects have been
+ * exported.
+ */
+ public ServerSocket createServerSocket(int port) throws IOException {
+ return new ServerSocket(port) {
+ @Override
+ public Socket accept() throws IOException {
+ final Socket socket = super.accept();
+ final InetAddress remoteAddr = socket.getInetAddress();
+ final String msg = "The server sockets created using the " +
+ "LocalRMIServerSocketFactory only accept connections " +
+ "from clients running on the host where the RMI " +
+ "remote objects have been exported.";
+
+ if (remoteAddr == null) {
+ // Though unlikeky, the socket could be already
+ // closed... Send a more detailed message in
+ // this case. Also avoid throwing NullPointerExceptiion
+ //
+ String details = "";
+ if (socket.isClosed()) {
+ details = " Socket is closed.";
+ } else if (!socket.isConnected()) {
+ details = " Socket is not connected";
+ }
+ try {
+ socket.close();
+ } catch (Exception ok) {
+ // ok - this is just cleanup before throwing detailed
+ // exception.
+ }
+ throw new IOException(msg +
+ " Couldn't determine client address." +
+ details);
+ } else if (remoteAddr.isLoopbackAddress()) {
+ // local address: accept the connection.
+ return socket;
+ }
+ // Retrieve all the network interfaces on this host.
+ Enumeration<NetworkInterface> nis;
+ try {
+ nis = NetworkInterface.getNetworkInterfaces();
+ } catch (SocketException e) {
+ try {
+ socket.close();
+ } catch (IOException ioe) {
+ // Ignore...
+ }
+ throw new IOException(msg, e);
+ }
+ // Walk through the network interfaces to see
+ // if any of them matches the client's address.
+ // If true, then the client's address is local.
+ while (nis.hasMoreElements()) {
+ NetworkInterface ni = nis.nextElement();
+ Enumeration<InetAddress> addrs = ni.getInetAddresses();
+ while (addrs.hasMoreElements()) {
+ InetAddress localAddr = addrs.nextElement();
+ if (localAddr.equals(remoteAddr)) {
+ return socket;
+ }
+ }
+ }
+ // The client's address is remote so refuse the connection.
+ try {
+ socket.close();
+ } catch (IOException ioe) {
+ // Ignore...
+ }
+ throw new IOException(msg);
+ }
+ };
+ }
+
+ /**
+ * Two LocalRMIServerSocketFactory objects
+ * are equal if they are of the same type.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ return (obj instanceof LocalRMIServerSocketFactory);
+ }
+
+ /**
+ * Returns a hash code value for this LocalRMIServerSocketFactory.
+ */
+ @Override
+ public int hashCode() {
+ return getClass().hashCode();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/sun/management/jmxremote/SingleEntryRegistry.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2003, 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.
+ */
+
+/*
+ * @author Sun Microsystems, Inc.
+ * @build @BUILD_TAG_PLACEHOLDER@
+ *
+ * @COPYRIGHT_MINI_LEGAL_NOTICE_PLACEHOLDER@
+ */
+
+package sun.management.jmxremote;
+
+import java.rmi.AccessException;
+import java.rmi.NotBoundException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMIServerSocketFactory;
+
+import sun.rmi.registry.RegistryImpl;
+
+/** A Registry that consists of a single entry that never changes. */
+public class SingleEntryRegistry extends RegistryImpl {
+ SingleEntryRegistry(int port, String name, Remote object)
+ throws RemoteException {
+ super(port);
+ this.name = name;
+ this.object = object;
+ }
+
+ SingleEntryRegistry(int port,
+ RMIClientSocketFactory csf,
+ RMIServerSocketFactory ssf,
+ String name,
+ Remote object)
+ throws RemoteException {
+ super(port, csf, ssf);
+ this.name = name;
+ this.object = object;
+ }
+
+ public String[] list() {
+ return new String[] {name};
+ }
+
+ public Remote lookup(String name) throws NotBoundException {
+ if (name.equals(this.name))
+ return object;
+ throw new NotBoundException("Not bound: \"" + name + "\" (only " +
+ "bound name is \"" + this.name + "\")");
+ }
+
+ public void bind(String name, Remote obj) throws AccessException {
+ throw new AccessException("Cannot modify this registry");
+ }
+
+ public void rebind(String name, Remote obj) throws AccessException {
+ throw new AccessException("Cannot modify this registry");
+ }
+
+ public void unbind(String name) throws AccessException {
+ throw new AccessException("Cannot modify this registry");
+ }
+
+ private final String name;
+ private final Remote object;
+
+ private static final long serialVersionUID = -4897238949499730950L;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/classes/sun/management/jmxremote/package.html Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+
+ Copyright (c) 2003, 2007, 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.
+
+-->
+
+</head>
+<body bgcolor="white">
+
+Provides classes that make it possible to create a JMX RMI Connector Server
+at bootstrap for the JSR 163 instrumentation.
+
+@since 1.5
+</body>
+</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/conf/jmxremote.access Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,79 @@
+######################################################################
+# Default Access Control File for Remote JMX(TM) Monitoring
+######################################################################
+#
+# Access control file for Remote JMX API access to monitoring.
+# This file defines the allowed access for different roles. The
+# password file (jmxremote.password by default) defines the roles and their
+# passwords. To be functional, a role must have an entry in
+# both the password and the access files.
+#
+# The default location of this file is $JRE/conf/management/jmxremote.access
+# You can specify an alternate location by specifying a property in
+# the management config file $JRE/conf/management/management.properties
+# (See that file for details)
+#
+# The file format for password and access files is syntactically the same
+# as the Properties file format. The syntax is described in the Javadoc
+# for java.util.Properties.load.
+# A typical access file has multiple lines, where each line is blank,
+# a comment (like this one), or an access control entry.
+#
+# An access control entry consists of a role name, and an
+# associated access level. The role name is any string that does not
+# itself contain spaces or tabs. It corresponds to an entry in the
+# password file (jmxremote.password). The access level is one of the
+# following:
+# "readonly" grants access to read attributes of MBeans.
+# For monitoring, this means that a remote client in this
+# role can read measurements but cannot perform any action
+# that changes the environment of the running program.
+# "readwrite" grants access to read and write attributes of MBeans,
+# to invoke operations on them, and optionally
+# to create or remove them. This access should be granted
+# only to trusted clients, since they can potentially
+# interfere with the smooth operation of a running program.
+#
+# The "readwrite" access level can optionally be followed by the "create" and/or
+# "unregister" keywords. The "unregister" keyword grants access to unregister
+# (delete) MBeans. The "create" keyword grants access to create MBeans of a
+# particular class or of any class matching a particular pattern. Access
+# should only be granted to create MBeans of known and trusted classes.
+#
+# For example, the following entry would grant readwrite access
+# to "controlRole", as well as access to create MBeans of the class
+# javax.management.monitor.CounterMonitor and to unregister any MBean:
+# controlRole readwrite \
+# create javax.management.monitor.CounterMonitorMBean \
+# unregister
+# or equivalently:
+# controlRole readwrite unregister create javax.management.monitor.CounterMBean
+#
+# The following entry would grant readwrite access as well as access to create
+# MBeans of any class in the packages javax.management.monitor and
+# javax.management.timer:
+# controlRole readwrite \
+# create javax.management.monitor.*,javax.management.timer.* \
+# unregister
+#
+# The \ character is defined in the Properties file syntax to allow continuation
+# lines as shown here. A * in a class pattern matches a sequence of characters
+# other than dot (.), so javax.management.monitor.* matches
+# javax.management.monitor.CounterMonitor but not
+# javax.management.monitor.foo.Bar.
+#
+# A given role should have at most one entry in this file. If a role
+# has no entry, it has no access.
+# If multiple entries are found for the same role name, then the last
+# access entry is used.
+#
+#
+# Default access control entries:
+# o The "monitorRole" role has readonly access.
+# o The "controlRole" role has readwrite access and can create the standard
+# Timer and Monitor MBeans defined by the JMX API.
+
+monitorRole readonly
+controlRole readwrite \
+ create javax.management.monitor.*,javax.management.timer.* \
+ unregister
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/conf/jmxremote.password.template Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,64 @@
+# ----------------------------------------------------------------------
+# Template for jmxremote.password
+#
+# o Copy this template to jmxremote.password
+# o Set the user/password entries in jmxremote.password
+# o Change the permission of jmxremote.password to read-only
+# by the owner.
+#
+# See below for the location of jmxremote.password file.
+# ----------------------------------------------------------------------
+
+##############################################################
+# Password File for Remote JMX Monitoring
+##############################################################
+#
+# Password file for Remote JMX API access to monitoring. This
+# file defines the different roles and their passwords. The access
+# control file (jmxremote.access by default) defines the allowed
+# access for each role. To be functional, a role must have an entry
+# in both the password and the access files.
+#
+# Default location of this file is $JRE/conf/management/jmxremote.password
+# You can specify an alternate location by specifying a property in
+# the management config file $JRE/conf/management/management.properties
+# or by specifying a system property (See that file for details).
+
+
+##############################################################
+# File permissions of the jmxremote.password file
+##############################################################
+# Since there are cleartext passwords stored in this file,
+# this file must be readable by ONLY the owner,
+# otherwise the program will exit with an error.
+#
+# The file format for password and access files is syntactically the same
+# as the Properties file format. The syntax is described in the Javadoc
+# for java.util.Properties.load.
+# Typical password file has multiple lines, where each line is blank,
+# a comment (like this one), or a password entry.
+#
+#
+# A password entry consists of a role name and an associated
+# password. The role name is any string that does not itself contain
+# spaces or tabs. The password is again any string that does not
+# contain spaces or tabs. Note that passwords appear in the clear in
+# this file, so it is a good idea not to use valuable passwords.
+#
+# A given role should have at most one entry in this file. If a role
+# has no entry, it has no access.
+# If multiple entries are found for the same role name, then the last one
+# is used.
+#
+# In a typical installation, this file can be read by anybody on the
+# local machine, and possibly by people on other machines.
+# For # security, you should either restrict the access to this file,
+# or specify another, less accessible file in the management config file
+# as described above.
+#
+# Following are two commented-out entries. The "measureRole" role has
+# password "QED". The "controlRole" role has password "R&D".
+#
+# monitorRole QED
+# controlRole R&D
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/share/conf/management.properties Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,331 @@
+#####################################################################
+# Default Configuration File for Java Platform Management
+#####################################################################
+#
+# The Management Configuration file (in java.util.Properties format)
+# will be read if one of the following system properties is set:
+# -Dcom.sun.management.jmxremote.port=<port-number>
+# or -Dcom.sun.management.snmp.port=<port-number>
+# or -Dcom.sun.management.config.file=<this-file>
+#
+# The default Management Configuration file is:
+#
+# $JRE/conf/management/management.properties
+#
+# Another location for the Management Configuration File can be specified
+# by the following property on the Java command line:
+#
+# -Dcom.sun.management.config.file=<this-file>
+#
+# If -Dcom.sun.management.config.file=<this-file> is set, the port
+# number for the management agent can be specified in the config file
+# using the following lines:
+#
+# ################ Management Agent Port #########################
+#
+# For setting the JMX RMI agent port use the following line
+# com.sun.management.jmxremote.port=<port-number>
+#
+# For setting the SNMP agent port use the following line
+# com.sun.management.snmp.port=<port-number>
+
+#####################################################################
+# Optional Instrumentation
+#####################################################################
+#
+# By default only the basic instrumentation with low overhead is on.
+# The following properties allow to selectively turn on optional
+# instrumentation which are off by default and may have some
+# additional overhead.
+#
+# com.sun.management.enableThreadContentionMonitoring
+#
+# This option enables thread contention monitoring if the
+# Java virtual machine supports such instrumentation.
+# Refer to the specification for the java.lang.management.ThreadMBean
+# interface - see isThreadContentionMonitoringSupported() method.
+#
+
+# To enable thread contention monitoring, uncomment the following line
+# com.sun.management.enableThreadContentionMonitoring
+
+#####################################################################
+# SNMP Management Properties
+#####################################################################
+#
+# If the system property -Dcom.sun.management.snmp.port=<port-number>
+# is set then
+# - The SNMP agent (with the Java virtual machine MIB) is started
+# that listens on the specified port for incoming SNMP requests.
+# - the following properties for read for SNMP management.
+#
+# The configuration can be specified only at startup time.
+# Later changes to the above system property (e.g. via setProperty method), this
+# config file, or the ACL file has no effect to the running SNMP agent.
+#
+
+#
+# ##################### SNMP Trap Port #########################
+#
+# com.sun.management.snmp.trap=<trap-destination-port-number>
+# Specifies the remote port number at which managers are expected
+# to listen for trap. For each host defined in the ACL file,
+# the SNMP agent will send traps at <host>:<trap-destination-port-number>
+# Default for this property is 162.
+#
+
+# To set port for sending traps to a different port use the following line
+# com.sun.management.snmp.trap=<trap-destination-port-number>
+
+#
+# ################ SNMP listen interface #########################
+#
+# com.sun.management.snmp.interface=<InetAddress>
+# Specifies the local interface on which the SNMP agent will bind.
+# This is useful when running on machines which have several
+# interfaces defined. It makes it possible to listen to a specific
+# subnet accessible through that interface.
+# Default for this property is "localhost".
+#
+# The format of the value for that property is any string accepted
+# by java.net.InetAddress.getByName(String).
+#
+
+# For restricting the port on which SNMP agent listens use the following line
+# com.sun.management.snmp.interface=<InetAddress>
+
+#
+# #################### SNMP ACL file #########################
+#
+# com.sun.management.snmp.acl=true|false
+# Default for this property is true. (Case for true/false ignored)
+# If this property is specified as false then the ACL file
+# is not checked: all manager hosts are allowed all access.
+#
+
+# For SNMP without checking ACL file uncomment the following line
+# com.sun.management.snmp.acl=false
+
+#
+# com.sun.management.snmp.acl.file=filepath
+# Specifies location for ACL file
+# This is optional - default location is
+# $JRE/conf/management/snmp.acl
+#
+# If the property "com.sun.management.snmp.acl" is set to false,
+# then this property and the ACL file are ignored.
+# Otherwise the ACL file must exist and be in the valid format.
+# If the ACL file is empty or non existent then no access is allowed.
+#
+# The SNMP agent will read the ACL file at startup time.
+# Modification to the ACL file has no effect to any running SNMP
+# agents which read that ACL file at startup.
+#
+
+# For a non-default acl file location use the following line
+# com.sun.management.snmp.acl.file=filepath
+
+#####################################################################
+# RMI Management Properties
+#####################################################################
+#
+# If system property -Dcom.sun.management.jmxremote.port=<port-number>
+# is set then
+# - A MBean server is started
+# - JRE Platform MBeans are registered in the MBean server
+# - RMI connector is published in a private readonly registry at
+# specified port using a well known name, "jmxrmi"
+# - the following properties are read for JMX remote management.
+#
+# The configuration can be specified only at startup time.
+# Later changes to above system property (e.g. via setProperty method),
+# this config file, the password file, or the access file have no effect to the
+# running MBean server, the connector, or the registry.
+#
+
+#
+# ########## RMI connector settings for local management ##########
+#
+# com.sun.management.jmxremote.local.only=true|false
+# Default for this property is true. (Case for true/false ignored)
+# If this property is specified as true then the local JMX RMI connector
+# server will only accept connection requests from clients running on
+# the host where the out-of-the-box JMX management agent is running.
+# In order to ensure backwards compatibility this property could be
+# set to false. However, deploying the local management agent in this
+# way is discouraged because the local JMX RMI connector server will
+# accept connection requests from any client either local or remote.
+# For remote management the remote JMX RMI connector server should
+# be used instead with authentication and SSL/TLS encryption enabled.
+#
+
+# For allowing the local management agent accept local
+# and remote connection requests use the following line
+# com.sun.management.jmxremote.local.only=false
+
+#
+# ###################### RMI SSL #############################
+#
+# com.sun.management.jmxremote.ssl=true|false
+# Default for this property is true. (Case for true/false ignored)
+# If this property is specified as false then SSL is not used.
+#
+
+# For RMI monitoring without SSL use the following line
+# com.sun.management.jmxremote.ssl=false
+
+# com.sun.management.jmxremote.ssl.config.file=filepath
+# Specifies the location of the SSL configuration file. A properties
+# file can be used to supply the keystore and truststore location and
+# password settings thus avoiding to pass them as cleartext in the
+# command-line.
+#
+# The current implementation of the out-of-the-box management agent will
+# look up and use the properties specified below to configure the SSL
+# keystore and truststore, if present:
+# javax.net.ssl.keyStore=<keystore-location>
+# javax.net.ssl.keyStorePassword=<keystore-password>
+# javax.net.ssl.trustStore=<truststore-location>
+# javax.net.ssl.trustStorePassword=<truststore-password>
+# Any other properties in the file will be ignored. This will allow us
+# to extend the property set in the future if required by the default
+# SSL implementation.
+#
+# If the property "com.sun.management.jmxremote.ssl" is set to false,
+# then this property is ignored.
+#
+
+# For supplying the keystore settings in a file use the following line
+# com.sun.management.jmxremote.ssl.config.file=filepath
+
+# com.sun.management.jmxremote.ssl.enabled.cipher.suites=<cipher-suites>
+# The value of this property is a string that is a comma-separated list
+# of SSL/TLS cipher suites to enable. This property can be specified in
+# conjunction with the previous property "com.sun.management.jmxremote.ssl"
+# in order to control which particular SSL/TLS cipher suites are enabled
+# for use by accepted connections. If this property is not specified then
+# the SSL/TLS RMI Server Socket Factory uses the SSL/TLS cipher suites that
+# are enabled by default.
+#
+
+# com.sun.management.jmxremote.ssl.enabled.protocols=<protocol-versions>
+# The value of this property is a string that is a comma-separated list
+# of SSL/TLS protocol versions to enable. This property can be specified in
+# conjunction with the previous property "com.sun.management.jmxremote.ssl"
+# in order to control which particular SSL/TLS protocol versions are
+# enabled for use by accepted connections. If this property is not
+# specified then the SSL/TLS RMI Server Socket Factory uses the SSL/TLS
+# protocol versions that are enabled by default.
+#
+
+# com.sun.management.jmxremote.ssl.need.client.auth=true|false
+# Default for this property is false. (Case for true/false ignored)
+# If this property is specified as true in conjunction with the previous
+# property "com.sun.management.jmxremote.ssl" then the SSL/TLS RMI Server
+# Socket Factory will require client authentication.
+#
+
+# For RMI monitoring with SSL client authentication use the following line
+# com.sun.management.jmxremote.ssl.need.client.auth=true
+
+# com.sun.management.jmxremote.registry.ssl=true|false
+# Default for this property is false. (Case for true/false ignored)
+# If this property is specified as true then the RMI registry used
+# to bind the RMIServer remote object is protected with SSL/TLS
+# RMI Socket Factories that can be configured with the properties:
+# com.sun.management.jmxremote.ssl.config.file
+# com.sun.management.jmxremote.ssl.enabled.cipher.suites
+# com.sun.management.jmxremote.ssl.enabled.protocols
+# com.sun.management.jmxremote.ssl.need.client.auth
+# If the two properties below are true at the same time, i.e.
+# com.sun.management.jmxremote.ssl=true
+# com.sun.management.jmxremote.registry.ssl=true
+# then the RMIServer remote object and the RMI registry are
+# both exported with the same SSL/TLS RMI Socket Factories.
+#
+
+# For using an SSL/TLS protected RMI registry use the following line
+# com.sun.management.jmxremote.registry.ssl=true
+
+#
+# ################ RMI User authentication ################
+#
+# com.sun.management.jmxremote.authenticate=true|false
+# Default for this property is true. (Case for true/false ignored)
+# If this property is specified as false then no authentication is
+# performed and all users are allowed all access.
+#
+
+# For RMI monitoring without any checking use the following line
+# com.sun.management.jmxremote.authenticate=false
+
+#
+# ################ RMI Login configuration ###################
+#
+# com.sun.management.jmxremote.login.config=<config-name>
+# Specifies the name of a JAAS login configuration entry to use when
+# authenticating users of RMI monitoring.
+#
+# Setting this property is optional - the default login configuration
+# specifies a file-based authentication that uses the password file.
+#
+# When using this property to override the default login configuration
+# then the named configuration entry must be in a file that gets loaded
+# by JAAS. In addition, the login module(s) specified in the configuration
+# should use the name and/or password callbacks to acquire the user's
+# credentials. See the NameCallback and PasswordCallback classes in the
+# javax.security.auth.callback package for more details.
+#
+# If the property "com.sun.management.jmxremote.authenticate" is set to
+# false, then this property and the password & access files are ignored.
+#
+
+# For a non-default login configuration use the following line
+# com.sun.management.jmxremote.login.config=<config-name>
+
+#
+# ################ RMI Password file location ##################
+#
+# com.sun.management.jmxremote.password.file=filepath
+# Specifies location for password file
+# This is optional - default location is
+# $JRE/conf/management/jmxremote.password
+#
+# If the property "com.sun.management.jmxremote.authenticate" is set to
+# false, then this property and the password & access files are ignored.
+# Otherwise the password file must exist and be in the valid format.
+# If the password file is empty or non-existent then no access is allowed.
+#
+
+# For a non-default password file location use the following line
+# com.sun.management.jmxremote.password.file=filepath
+
+#
+# ################ RMI Access file location #####################
+#
+# com.sun.management.jmxremote.access.file=filepath
+# Specifies location for access file
+# This is optional - default location is
+# $JRE/conf/management/jmxremote.access
+#
+# If the property "com.sun.management.jmxremote.authenticate" is set to
+# false, then this property and the password & access files are ignored.
+# Otherwise, the access file must exist and be in the valid format.
+# If the access file is empty or non-existent then no access is allowed.
+#
+
+# For a non-default password file location use the following line
+# com.sun.management.jmxremote.access.file=filepath
+#
+
+# ################ Management agent listen interface #########################
+#
+# com.sun.management.jmxremote.host=<host-or-interface-name>
+# Specifies the local interface on which the JMX RMI agent will bind.
+# This is useful when running on machines which have several
+# interfaces defined. It makes it possible to listen to a specific
+# subnet accessible through that interface.
+#
+# The format of the value for that property is any string accepted
+# by java.net.InetAddress.getByName(String).
+#
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/unix/classes/jdk/internal/agent/FileSystemImpl.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2004, 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. 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.internal.agent;
+
+import java.io.File;
+import java.io.IOException;
+
+/*
+ * Solaris/Linux implementation of jdk.internal.agent.FileSystem
+ */
+public class FileSystemImpl extends FileSystem {
+
+ public boolean supportsFileSecurity(File f) throws IOException {
+ return true;
+ }
+
+ public boolean isAccessUserOnly(File f) throws IOException {
+ return isAccessUserOnly0(f.getPath());
+ }
+
+ // Native methods
+
+ static native boolean isAccessUserOnly0(String path) throws IOException;
+
+ // Initialization
+
+ static {
+ java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction<Void>() {
+ public Void run() {
+ System.loadLibrary("management_agent");
+ return null;
+ }
+ });
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/unix/native/libmanagement_agent/FileSystemImpl.c Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2004, 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. 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 <sys/types.h>
+#include <sys/stat.h>
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jdk_internal_agent_FileSystemImpl.h"
+
+#ifdef _ALLBSD_SOURCE
+#define stat64 stat
+#endif
+
+/*
+ * JNI_OnLoad
+ */
+JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
+{
+ JNIEnv* env;
+
+ if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_2) != JNI_OK) {
+ return JNI_EVERSION; /* JNI version not supported */
+ }
+
+ return JNI_VERSION_9;
+}
+
+/*
+ * Class: jdk_internal_agent_FileSystemImpl
+ * Method: isAccessUserOnly0
+ * Signature: (Ljava/lang/String;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jdk_internal_agent_FileSystemImpl_isAccessUserOnly0
+ (JNIEnv *env, jclass ignored, jstring str)
+{
+ jboolean res = JNI_FALSE;
+ jboolean isCopy;
+ const char *path = JNU_GetStringPlatformChars(env, str, &isCopy);
+ if (path != NULL) {
+ struct stat64 sb;
+ if (stat64(path, &sb) == 0) {
+ res = ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) == 0) ? JNI_TRUE : JNI_FALSE;
+ } else {
+ JNU_ThrowIOExceptionWithLastError(env, "stat64 failed");
+ }
+ if (isCopy) {
+ JNU_ReleaseStringPlatformChars(env, str, path);
+ }
+ }
+ return res;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/windows/classes/jdk/internal/agent/FileSystemImpl.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2004, 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. 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.internal.agent;
+
+import java.io.File;
+import java.io.IOException;
+
+/*
+ * Windows implementation of sun.management.FileSystem
+ */
+public class FileSystemImpl extends FileSystem {
+
+ public boolean supportsFileSecurity(File f) throws IOException {
+ return isSecuritySupported0(f.getAbsolutePath());
+ }
+
+ public boolean isAccessUserOnly(File f) throws IOException {
+ String path = f.getAbsolutePath();
+ if (!isSecuritySupported0(path)) {
+ throw new UnsupportedOperationException("File system does not support file security");
+ }
+ return isAccessUserOnly0(path);
+ }
+
+ // Native methods
+
+ static native void init0();
+
+ static native boolean isSecuritySupported0(String path) throws IOException;
+
+ static native boolean isAccessUserOnly0(String path) throws IOException;
+
+ // Initialization
+
+ static {
+ java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction<Void>() {
+ public Void run() {
+ System.loadLibrary("management_agent");
+ return null;
+ }
+ });
+ init0();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.management.agent/windows/native/libmanagement_agent/FileSystemImpl.c Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2004, 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.
+ */
+
+#include <windows.h>
+#include <malloc.h>
+#include <string.h>
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jdk_internal_agent_FileSystemImpl.h"
+
+JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
+{
+ JNIEnv* env;
+
+ if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_2) != JNI_OK) {
+ return JNI_EVERSION; /* JNI version not supported */
+ }
+
+ return JNI_VERSION_9;
+}
+
+
+/*
+ * Access mask to represent any file access
+ */
+#define ANY_ACCESS (FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE)
+
+/*
+ * Returns JNI_TRUE if the specified file is on a file system that supports
+ * persistent ACLs (On NTFS file systems returns true, on FAT32 file systems
+ * returns false).
+ */
+static jboolean isSecuritySupported(JNIEnv* env, const char* path) {
+ char* root;
+ char* p;
+ BOOL res;
+ DWORD dwMaxComponentLength;
+ DWORD dwFlags;
+ char fsName[128];
+ DWORD fsNameLength;
+
+ /*
+ * Get root directory. Assume that files are absolute paths. For UNCs
+ * the slash after the share name is required.
+ */
+ root = strdup(path);
+ if (*root == '\\') {
+ /*
+ * \\server\share\file ==> \\server\share\
+ */
+ int slashskip = 3;
+ p = root;
+ while ((*p == '\\') && (slashskip > 0)) {
+ char* p2;
+ p++;
+ p2 = strchr(p, '\\');
+ if ((p2 == NULL) || (*p2 != '\\')) {
+ free(root);
+ JNU_ThrowIOException(env, "Malformed UNC");
+ return JNI_FALSE;
+ }
+ p = p2;
+ slashskip--;
+ }
+ if (slashskip != 0) {
+ free(root);
+ JNU_ThrowIOException(env, "Malformed UNC");
+ return JNI_FALSE;
+ }
+ p++;
+ *p = '\0';
+
+ } else {
+ p = strchr(root, '\\');
+ if (p == NULL) {
+ free(root);
+ JNU_ThrowIOException(env, "Absolute filename not specified");
+ return JNI_FALSE;
+ }
+ p++;
+ *p = '\0';
+ }
+
+
+ /*
+ * Get the volume information - this gives us the file system file and
+ * also tells us if the file system supports persistent ACLs.
+ */
+ fsNameLength = sizeof(fsName)-1;
+ res = GetVolumeInformation(root,
+ NULL, // address of name of the volume, can be NULL
+ 0, // length of volume name
+ NULL, // address of volume serial number, can be NULL
+ &dwMaxComponentLength,
+ &dwFlags,
+ fsName,
+ fsNameLength);
+ if (res == 0) {
+ free(root);
+ JNU_ThrowIOExceptionWithLastError(env, "GetVolumeInformation failed");
+ return JNI_FALSE;
+ }
+
+ free(root);
+ return (dwFlags & FS_PERSISTENT_ACLS) ? JNI_TRUE : JNI_FALSE;
+}
+
+
+/*
+ * Returns the security descriptor for a file.
+ */
+static SECURITY_DESCRIPTOR* getFileSecurityDescriptor(JNIEnv* env, const char* path) {
+ SECURITY_DESCRIPTOR* sd;
+ DWORD len = 0;
+ SECURITY_INFORMATION info =
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
+
+ GetFileSecurityA(path, info , 0, 0, &len);
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+ JNU_ThrowIOExceptionWithLastError(env, "GetFileSecurity failed");
+ return NULL;
+ }
+ sd = (SECURITY_DESCRIPTOR *)malloc(len);
+ if (sd == NULL) {
+ JNU_ThrowOutOfMemoryError(env, 0);
+ } else {
+ if (!(*GetFileSecurityA)(path, info, sd, len, &len)) {
+ JNU_ThrowIOExceptionWithLastError(env, "GetFileSecurity failed");
+ free(sd);
+ return NULL;
+ }
+ }
+ return sd;
+}
+
+/*
+ * Returns pointer to the SID identifying the owner of the specified
+ * file.
+ */
+static SID* getFileOwner(JNIEnv* env, SECURITY_DESCRIPTOR* sd) {
+ SID* owner;
+ BOOL defaulted;
+
+ if (!GetSecurityDescriptorOwner(sd, &owner, &defaulted)) {
+ JNU_ThrowIOExceptionWithLastError(env, "GetSecurityDescriptorOwner failed");
+ return NULL;
+ }
+ return owner;
+}
+
+/*
+ * Returns pointer discretionary access-control list (ACL) from the security
+ * descriptor of the specified file.
+ */
+static ACL* getFileDACL(JNIEnv* env, SECURITY_DESCRIPTOR* sd) {
+ ACL *acl;
+ int defaulted, present;
+
+ if (!GetSecurityDescriptorDacl(sd, &present, &acl, &defaulted)) {
+ JNU_ThrowIOExceptionWithLastError(env, "GetSecurityDescriptorDacl failed");
+ return NULL;
+ }
+ if (!present) {
+ JNU_ThrowInternalError(env, "Security descriptor does not contain a DACL");
+ return NULL;
+ }
+ return acl;
+}
+
+/*
+ * Returns JNI_TRUE if the specified owner is the only SID will access
+ * to the file.
+ */
+static jboolean isAccessUserOnly(JNIEnv* env, SID* owner, ACL* acl) {
+ ACL_SIZE_INFORMATION acl_size_info;
+ DWORD i;
+
+ /*
+ * If there's no DACL then there's no access to the file
+ */
+ if (acl == NULL) {
+ return JNI_TRUE;
+ }
+
+ /*
+ * Get the ACE count
+ */
+ if (!GetAclInformation(acl, (void *) &acl_size_info, sizeof(acl_size_info),
+ AclSizeInformation)) {
+ JNU_ThrowIOExceptionWithLastError(env, "GetAclInformation failed");
+ return JNI_FALSE;
+ }
+
+ /*
+ * Iterate over the ACEs. For each "allow" type check that the SID
+ * matches the owner, and check that the access is read only.
+ */
+ for (i = 0; i < acl_size_info.AceCount; i++) {
+ void* ace;
+ ACCESS_ALLOWED_ACE *access;
+ SID* sid;
+
+ if (!GetAce(acl, i, &ace)) {
+ JNU_ThrowIOExceptionWithLastError(env, "GetAce failed");
+ return -1;
+ }
+ if (((ACCESS_ALLOWED_ACE *)ace)->Header.AceType != ACCESS_ALLOWED_ACE_TYPE) {
+ continue;
+ }
+ access = (ACCESS_ALLOWED_ACE *)ace;
+ sid = (SID *) &access->SidStart;
+ if (!EqualSid(owner, sid)) {
+ /*
+ * If the ACE allows any access then the file is not secure.
+ */
+ if (access->Mask & ANY_ACCESS) {
+ return JNI_FALSE;
+ }
+ }
+ }
+ return JNI_TRUE;
+}
+
+
+/*
+ * Class: jdk_internal_agent_FileSystemImpl
+ * Method: init0
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_jdk_internal_agent_FileSystemImpl_init0
+ (JNIEnv *env, jclass ignored)
+{
+ /* nothing to do */
+}
+
+/*
+ * Class: jdk_internal_agent_FileSystemImpl
+ * Method: isSecuritySupported0
+ * Signature: (Ljava/lang/String;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jdk_internal_agent_FileSystemImpl_isSecuritySupported0
+ (JNIEnv *env, jclass ignored, jstring str)
+{
+ jboolean res;
+ jboolean isCopy;
+ const char* path;
+
+ path = JNU_GetStringPlatformChars(env, str, &isCopy);
+ if (path != NULL) {
+ res = isSecuritySupported(env, path);
+ if (isCopy) {
+ JNU_ReleaseStringPlatformChars(env, str, path);
+ }
+ return res;
+ } else {
+ /* exception thrown - doesn't matter what we return */
+ return JNI_TRUE;
+ }
+}
+
+
+/*
+ * Class: jdk_internal_agent_FileSystemImpl
+ * Method: isAccessUserOnly0
+ * Signature: (Ljava/lang/String;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jdk_internal_agent_FileSystemImpl_isAccessUserOnly0
+ (JNIEnv *env, jclass ignored, jstring str)
+{
+ jboolean res = JNI_FALSE;
+ jboolean isCopy;
+ const char* path;
+
+ path = JNU_GetStringPlatformChars(env, str, &isCopy);
+ if (path != NULL) {
+ /*
+ * From the security descriptor get the file owner and
+ * DACL. Then check if anybody but the owner has access
+ * to the file.
+ */
+ SECURITY_DESCRIPTOR* sd = getFileSecurityDescriptor(env, path);
+ if (sd != NULL) {
+ SID *owner = getFileOwner(env, sd);
+ if (owner != NULL) {
+ ACL* acl = getFileDACL(env, sd);
+ if (acl != NULL) {
+ res = isAccessUserOnly(env, owner, acl);
+ } else {
+ /*
+ * If acl is NULL it means that an exception was thrown
+ * or there is "all acess" to the file.
+ */
+ res = JNI_FALSE;
+ }
+ }
+ free(sd);
+ }
+ if (isCopy) {
+ JNU_ReleaseStringPlatformChars(env, str, path);
+ }
+ }
+ return res;
+}
--- a/jdk/test/com/sun/tools/attach/StartManagementAgent.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/com/sun/tools/attach/StartManagementAgent.java Thu Feb 09 23:15:52 2017 +0100
@@ -41,7 +41,7 @@
* @summary Test for VirtualMachine.startManagementAgent and VirtualMachine.startLocalManagementAgent
* @modules jdk.jartool/sun.tools.jar
* @library /lib/testlibrary
- * @modules java.management
+ * @modules jdk.management.agent
* jdk.attach
* jdk.jartool/sun.tools.jar
* @run build Application SimpleProvider jdk.testlibrary.*
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/print/PrinterJob/PrintCrashTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017, 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 8163889
+ * @summary Printing crashes on OSX.
+ * @run main PrintCrashTest
+ */
+
+import javax.print.attribute.HashPrintRequestAttributeSet;
+import javax.print.attribute.standard.Destination;
+
+import java.awt.GraphicsEnvironment;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.Transparency;
+import java.awt.image.BufferedImage;
+import java.awt.print.Printable;
+import java.awt.print.PrinterJob;
+
+import java.io.File;
+
+public class PrintCrashTest {
+ public static void main(String[] args) throws Exception {
+ PrinterJob printerJob = PrinterJob.getPrinterJob();
+ printerJob.setPrintable((graphics, pageFormat, pageIndex) -> {
+ if (pageIndex != 0) {
+ return Printable.NO_SUCH_PAGE;
+ } else {
+ Shape shape = new Rectangle(110, 110, 10, 10);
+ Rectangle rect = shape.getBounds();
+
+ BufferedImage image = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()
+ .getDefaultConfiguration().createCompatibleImage(rect.width, rect.height, Transparency.BITMASK);
+ graphics.drawImage(image, rect.x, rect.y, rect.width, rect.height, null);
+
+ return Printable.PAGE_EXISTS;
+ }
+ });
+
+ File file = null;
+ try {
+ HashPrintRequestAttributeSet hashPrintRequestAttributeSet = new HashPrintRequestAttributeSet();
+ file = File.createTempFile("out", "ps");
+ file.deleteOnExit();
+ Destination destination = new Destination(file.toURI());
+ hashPrintRequestAttributeSet.add(destination);
+ printerJob.print(hashPrintRequestAttributeSet);
+ } finally {
+ if (file != null) {
+ file.delete();
+ }
+ }
+ }
+}
+
--- a/jdk/test/java/lang/StackWalker/Basic.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/lang/StackWalker/Basic.java Thu Feb 09 23:15:52 2017 +0100
@@ -23,18 +23,21 @@
/*
* @test
- * @bug 8140450
+ * @bug 8140450 8173898
* @summary Basic test for the StackWalker::walk method
* @run testng Basic
*/
import java.lang.StackWalker.StackFrame;
import java.util.List;
+import java.util.Objects;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import static java.lang.StackWalker.Option.*;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
+import static org.testng.Assert.*;
public class Basic {
private static boolean verbose = false;
@@ -60,6 +63,17 @@
}
}
+ @Test
+ public static void testWalkFromConstructor() throws Exception {
+ System.out.println("testWalkFromConstructor:");
+ List<String> found = ((ConstructorNewInstance)ConstructorNewInstance.class.getMethod("create")
+ .invoke(null)).collectedFrames();
+ assertEquals(List.of(ConstructorNewInstance.class.getName()+"::<init>",
+ ConstructorNewInstance.class.getName()+"::create",
+ Basic.class.getName()+"::testWalkFromConstructor"),
+ found);
+ }
+
private final int depth;
Basic(int depth) {
this.depth = depth;
@@ -77,6 +91,47 @@
assertEquals(limit, frames.size());
}
+ static class ConstructorNewInstance {
+ static final StackWalker walker =
+ StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
+ List<String> testFramesOrReflectionFrames;
+ public ConstructorNewInstance() {
+ testFramesOrReflectionFrames = walker.walk(this::parse);
+ }
+ public List<String> collectedFrames() {
+ return testFramesOrReflectionFrames;
+ }
+ public boolean accept(StackFrame f) {
+ // Frames whose class names don't contain "."
+ // are our own test frames. These are the ones
+ // we expect.
+ // Frames whose class names contain ".reflect."
+ // are reflection frames. None should be present,
+ // since they are supposed to be filtered by
+ // by StackWalker. If we find any, we want to fail.
+ if (!f.getClassName().contains(".")
+ || f.getClassName().contains(".reflect.")) {
+ System.out.println(" " + f);
+ return true;
+ }
+ // Filter out all other frames (in particular
+ // those from the test framework) in order to
+ // have predictable results.
+ return false;
+ }
+ public String frame(StackFrame f) {
+ return f.getClassName() + "::" + f.getMethodName();
+ }
+ List<String> parse(Stream<StackFrame> s) {
+ return s.filter(this::accept)
+ .map(this::frame)
+ .collect(Collectors.toList());
+ }
+ public static ConstructorNewInstance create() throws Exception {
+ return ConstructorNewInstance.class.getConstructor().newInstance();
+ }
+ }
+
class StackBuilder {
private final int stackDepth;
private final int limit;
@@ -131,9 +186,4 @@
}
}
- static void assertEquals(int x, int y) {
- if (x != y) {
- throw new RuntimeException(x + " != " + y);
- }
- }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/StackWalker/ReflectionFrames.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,842 @@
+/*
+ * Copyright (c) 2017, 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 8173898
+ * @summary Basic test for checking filtering of reflection frames
+ * @run testng ReflectionFrames
+ */
+
+import java.lang.StackWalker.StackFrame;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import static java.lang.StackWalker.Option.*;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+public class ReflectionFrames {
+ final static boolean verbose = false;
+
+ /**
+ * This test invokes new StackInspector() directly from
+ * the caller StackInspector.Caller.create method.
+ * It checks that the caller is StackInspector.Caller.
+ * It also checks the expected frames collected
+ * by walking the stack from the default StackInspector()
+ * constructor.
+ * This is done twice, once using a default StackWalker
+ * that hides reflection frames, once using a StackWalker
+ * configured to show reflection frames.
+ */
+ @Test
+ public static void testNewStackInspector() throws Exception {
+ // Sets the default walker which hides reflection
+ // frames.
+ StackInspector.walker.set(StackInspector.walkerHide);
+
+ // Calls the StackInspector.create method through reflection
+ // and check the frames collected in the StackInspector
+ // default constructor.
+ // The create method invokes new StackInspector() directly.
+ // No reflection frame should appear.
+ System.out.println("testNewStackInspector: create");
+
+ StackInspector obj = ((StackInspector)StackInspector.Caller.class
+ .getMethod("create", How.class)
+ .invoke(null, How.NEW));
+ assertEquals(obj.collectedFrames,
+ List.of(StackInspector.class.getName()
+ +"::<init>",
+ StackInspector.Caller.class.getName()
+ +"::create",
+ ReflectionFrames.class.getName()
+ +"::testNewStackInspector"));
+ assertEquals(obj.cls, StackInspector.Caller.class);
+ assertEquals(obj.filtered, 0);
+
+ // Calls the StackInspector.reflect method through reflection
+ // and check the frames collected in the StackInspector
+ // default constructor.
+ // The reflect method invokes the create method through
+ // reflection.
+ // The create method invokes new StackInspector() directly.
+ // No reflection frame should appear.
+ System.out.println("testNewStackInspector: reflect");
+
+ obj = ((StackInspector)StackInspector.Caller.class
+ .getMethod("reflect", How.class)
+ .invoke(null, How.NEW));
+ assertEquals(obj.collectedFrames,
+ List.of(StackInspector.class.getName()
+ +"::<init>",
+ StackInspector.Caller.class.getName()
+ +"::create",
+ StackInspector.Caller.class.getName()
+ +"::reflect",
+ ReflectionFrames.class.getName()
+ +"::testNewStackInspector"));
+ assertEquals(obj.cls, StackInspector.Caller.class);
+ assertEquals(obj.filtered, 0);
+
+ // Calls the StackInspector.handle method through reflection
+ // and check the frames collected in the StackInspector
+ // default constructor.
+ // The handle method invokes the create method using
+ // a MethodHandle.
+ // The create method invokes new StackInspector() directly.
+ // No reflection frame should appear.
+ System.out.println("testNewStackInspector: handle");
+
+ obj = ((StackInspector)StackInspector.Caller.class
+ .getMethod("handle", How.class)
+ .invoke(null, How.NEW));
+ assertEquals(obj.collectedFrames,
+ List.of(StackInspector.class.getName()
+ +"::<init>",
+ StackInspector.Caller.class.getName()
+ +"::create",
+ StackInspector.Caller.class.getName()
+ +"::handle",
+ ReflectionFrames.class.getName()
+ +"::testNewStackInspector"));
+ assertEquals(obj.cls, StackInspector.Caller.class);
+ assertEquals(obj.filtered, 0);
+
+ // Sets a non-default walker configured to show
+ // reflection frames
+ StackInspector.walker.set(StackInspector.walkerShow);
+
+ // Calls the StackInspector.create method through reflection
+ // and check the frames collected in the StackInspector
+ // default constructor.
+ // The create method invokes new StackInspector() directly.
+ // We should see all reflection frames, except the
+ // jdk.internal.reflect frames which we are filtering
+ // out in StackInspector::filter.
+ System.out.println("testNewStackInspector: create: show reflect");
+
+ obj = ((StackInspector)StackInspector.Caller.class
+ .getMethod("create", How.class)
+ .invoke(null, How.NEW));
+ assertEquals(obj.collectedFrames,
+ List.of(StackInspector.class.getName()
+ +"::<init>",
+ StackInspector.Caller.class.getName()
+ +"::create",
+ Method.class.getName()
+ +"::invoke",
+ ReflectionFrames.class.getName()
+ +"::testNewStackInspector"));
+ assertEquals(obj.cls, StackInspector.Caller.class);
+ assertNotEquals(obj.filtered, 0);
+
+ // Calls the StackInspector.reflect method through reflection
+ // and check the frames collected in the StackInspector
+ // default constructor.
+ // The reflect method invokes the create method through
+ // reflection.
+ // The create method invokes new StackInspector() directly.
+ // We should see all reflection frames, except the
+ // jdk.internal.reflect frames which we are filtering
+ // out in StackInspector::filter.
+ System.out.println("testNewStackInspector: reflect: show reflect");
+
+ obj = ((StackInspector)StackInspector.Caller.class
+ .getMethod("reflect", How.class)
+ .invoke(null, How.NEW));
+ assertEquals(obj.collectedFrames,
+ List.of(StackInspector.class.getName()
+ +"::<init>",
+ StackInspector.Caller.class.getName()
+ +"::create",
+ Method.class.getName()
+ +"::invoke",
+ StackInspector.Caller.class.getName()
+ +"::reflect",
+ Method.class.getName()
+ +"::invoke",
+ ReflectionFrames.class.getName()
+ +"::testNewStackInspector"));
+ assertEquals(obj.cls, StackInspector.Caller.class);
+ assertNotEquals(obj.filtered, 0);
+
+ // Calls the StackInspector.handle method through reflection
+ // and check the frames collected in the StackInspector
+ // default constructor.
+ // The handle method invokes the create method using
+ // MethodHandle.
+ // The create method invokes new StackInspector() directly.
+ // We should see all reflection frames, except the
+ // jdk.internal.reflect frames which we are filtering
+ // out in StackInspector::filter.
+ System.out.println("testNewStackInspector: handle: show reflect");
+
+ obj = ((StackInspector)StackInspector.Caller.class
+ .getMethod("handle", How.class)
+ .invoke(null, How.NEW));
+ assertEquals(obj.collectedFrames,
+ List.of(StackInspector.class.getName()
+ +"::<init>",
+ StackInspector.Caller.class.getName()
+ +"::create",
+ // MethodHandle::invoke remains hidden
+ StackInspector.Caller.class.getName()
+ +"::handle",
+ Method.class.getName()
+ +"::invoke",
+ ReflectionFrames.class.getName()
+ +"::testNewStackInspector"));
+ assertEquals(obj.cls, StackInspector.Caller.class);
+ assertNotEquals(obj.filtered, 0);
+ }
+
+ /**
+ * This test invokes Constructor.newInstance() from
+ * the caller StackInspector.Caller.create method.
+ * It checks that the caller is StackInspector.Caller.
+ * It also checks the expected frames collected
+ * by walking the stack from the default StackInspector()
+ * constructor.
+ * This is done twice, once using a default StackWalker
+ * that hides reflection frames, once using a StackWalker
+ * configured to show reflection frames.
+ */
+ @Test
+ public static void testConstructor() throws Exception {
+ // Sets the default walker which hides reflection
+ // frames.
+ StackInspector.walker.set(StackInspector.walkerHide);
+
+ // Calls the StackInspector.create method through reflection
+ // and check the frames collected in the StackInspector
+ // default constructor.
+ // The create method invokes Constructor.newInstance().
+ // No reflection frame should appear.
+ System.out.println("testConstructor: create");
+
+ StackInspector obj = ((StackInspector)StackInspector.Caller.class
+ .getMethod("create", How.class)
+ .invoke(null, How.CONSTRUCTOR));
+ assertEquals(obj.collectedFrames,
+ List.of(StackInspector.class.getName()
+ +"::<init>",
+ StackInspector.Caller.class.getName()
+ +"::create",
+ ReflectionFrames.class.getName()
+ +"::testConstructor"));
+ assertEquals(obj.cls, StackInspector.Caller.class);
+ assertEquals(obj.filtered, 0);
+
+ // Calls the StackInspector.reflect method through reflection
+ // and check the frames collected in the StackInspector
+ // default constructor.
+ // The reflect method invokes the create method through
+ // reflection.
+ // The create method invokes Constructor.newInstance().
+ // No reflection frame should appear.
+ System.out.println("testConstructor: reflect");
+
+ obj = ((StackInspector)StackInspector.Caller.class
+ .getMethod("reflect", How.class)
+ .invoke(null, How.CONSTRUCTOR));
+ assertEquals(obj.collectedFrames,
+ List.of(StackInspector.class.getName()
+ +"::<init>",
+ StackInspector.Caller.class.getName()
+ +"::create",
+ StackInspector.Caller.class.getName()
+ +"::reflect",
+ ReflectionFrames.class.getName()
+ +"::testConstructor"));
+ assertEquals(obj.cls, StackInspector.Caller.class);
+ assertEquals(obj.filtered, 0);
+
+ // Calls the StackInspector.handle method through reflection
+ // and check the frames collected in the StackInspector
+ // default constructor.
+ // The handle method invokes the create method using
+ // MethodHandle.
+ // The create method invokes Constructor.newInstance().
+ // No reflection frame should appear.
+ System.out.println("testConstructor: handle");
+
+ obj = ((StackInspector)StackInspector.Caller.class
+ .getMethod("handle", How.class)
+ .invoke(null, How.CONSTRUCTOR));
+ assertEquals(obj.collectedFrames,
+ List.of(StackInspector.class.getName()
+ +"::<init>",
+ StackInspector.Caller.class.getName()
+ +"::create",
+ StackInspector.Caller.class.getName()
+ +"::handle",
+ ReflectionFrames.class.getName()
+ +"::testConstructor"));
+ assertEquals(obj.cls, StackInspector.Caller.class);
+ assertEquals(obj.filtered, 0);
+
+ // Sets a non-default walker configured to show
+ // reflection frames
+ StackInspector.walker.set(StackInspector.walkerShow);
+
+ // Calls the StackInspector.create method through reflection
+ // and check the frames collected in the StackInspector
+ // default constructor.
+ // The create method invokes Constructor.newInstance().
+ // We should see all reflection frames, except the
+ // jdk.internal.reflect frames which we are filtering
+ // out in StackInspector::filter.
+ System.out.println("testConstructor: create: show reflect");
+
+ obj = ((StackInspector)StackInspector.Caller.class
+ .getMethod("create", How.class)
+ .invoke(null, How.CONSTRUCTOR));
+ assertEquals(obj.collectedFrames,
+ List.of(StackInspector.class.getName()
+ +"::<init>",
+ Constructor.class.getName()
+ +"::newInstance",
+ StackInspector.Caller.class.getName()
+ +"::create",
+ Method.class.getName()
+ +"::invoke",
+ ReflectionFrames.class.getName()
+ +"::testConstructor"));
+ assertEquals(obj.cls, StackInspector.Caller.class);
+ assertNotEquals(obj.filtered, 0);
+
+ // Calls the StackInspector.reflect method through reflection
+ // and check the frames collected in the StackInspector
+ // default constructor.
+ // The reflect method invokes the create method through
+ // reflection.
+ // The create method invokes Constructor.newInstance().
+ // We should see all reflection frames, except the
+ // jdk.internal.reflect frames which we are filtering
+ // out in StackInspector::filter.
+ System.out.println("testConstructor: reflect: show reflect");
+
+ obj = ((StackInspector)StackInspector.Caller.class
+ .getMethod("reflect", How.class)
+ .invoke(null, How.CONSTRUCTOR));
+ assertEquals(obj.collectedFrames,
+ List.of(StackInspector.class.getName()
+ +"::<init>",
+ Constructor.class.getName()
+ +"::newInstance",
+ StackInspector.Caller.class.getName()
+ +"::create",
+ Method.class.getName()
+ +"::invoke",
+ StackInspector.Caller.class.getName()
+ +"::reflect",
+ Method.class.getName()
+ +"::invoke",
+ ReflectionFrames.class.getName()
+ +"::testConstructor"));
+ assertEquals(obj.cls, StackInspector.Caller.class);
+ assertNotEquals(obj.filtered, 0);
+
+ // Calls the StackInspector.handle method through reflection
+ // and check the frames collected in the StackInspector
+ // default constructor.
+ // The handle method invokes the create method using
+ // MethodHandle.
+ // The create method invokes Constructor.newInstance().
+ // We should see all reflection frames, except the
+ // jdk.internal.reflect frames which we are filtering
+ // out in StackInspector::filter.
+ System.out.println("testConstructor: handle: show reflect");
+
+ obj = ((StackInspector)StackInspector.Caller.class
+ .getMethod("handle", How.class)
+ .invoke(null, How.CONSTRUCTOR));
+ assertEquals(obj.collectedFrames,
+ List.of(StackInspector.class.getName()
+ +"::<init>",
+ Constructor.class.getName()
+ +"::newInstance",
+ StackInspector.Caller.class.getName()
+ +"::create",
+ // MethodHandle::invoke remains hidden
+ StackInspector.Caller.class.getName()
+ +"::handle",
+ Method.class.getName()
+ +"::invoke",
+ ReflectionFrames.class.getName()
+ +"::testConstructor"));
+ assertEquals(obj.cls, StackInspector.Caller.class);
+ assertNotEquals(obj.filtered, 0);
+ }
+
+ /**
+ * This test invokes StackInspector.class.newInstance() from
+ * the caller StackInspector.Caller.create method. Because
+ * Class.newInstance() is not considered as a
+ * reflection frame, the the caller returned by
+ * getCallerClass() should appear to be java.lang.Class
+ * and not StackInspector.Caller.
+ * It also checks the expected frames collected
+ * by walking the stack from the default StackInspector()
+ * constructor.
+ * This is done twice, once using a default StackWalker
+ * that hides reflection frames, once using a StackWalker
+ * configured to show reflection frames.
+ */
+ @Test
+ public static void testNewInstance() throws Exception {
+ // Sets the default walker which hides reflection
+ // frames.
+ StackInspector.walker.set(StackInspector.walkerHide);
+
+ // Calls the StackInspector.create method through reflection
+ // and check the frames collected in the StackInspector
+ // default constructor.
+ // The create method invokes StackInspector.class.newInstance().
+ // No reflection frame should appear, except
+ // Class::newInstance which is not considered as
+ // a reflection frame.
+ System.out.println("testNewInstance: create");
+
+ StackInspector obj = ((StackInspector)StackInspector.Caller.class
+ .getMethod("create", How.class)
+ .invoke(null, How.CLASS));
+ assertEquals(obj.collectedFrames,
+ List.of(StackInspector.class.getName()
+ +"::<init>",
+ Class.class.getName()
+ +"::newInstance",
+ StackInspector.Caller.class.getName()
+ +"::create",
+ ReflectionFrames.class.getName()
+ +"::testNewInstance"));
+ // Because Class.newInstance is not filtered, then the
+ // caller is Class.class
+ assertEquals(obj.cls, Class.class);
+ assertEquals(obj.filtered, 0);
+
+ // Calls the StackInspector.reflect method through reflection
+ // and check the frames collected in the StackInspector
+ // default constructor.
+ // The reflect method invokes the create method through
+ // reflection.
+ // The create method invokes StackInspector.class.newInstance().
+ // No reflection frame should appear, except
+ // Class::newInstance which is not considered as
+ // a reflection frame.
+ System.out.println("testNewInstance: reflect");
+
+ obj = ((StackInspector)StackInspector.Caller.class
+ .getMethod("reflect", How.class)
+ .invoke(null, How.CLASS));
+ assertEquals(obj.collectedFrames,
+ List.of(StackInspector.class.getName()
+ +"::<init>",
+ Class.class.getName()
+ +"::newInstance",
+ StackInspector.Caller.class.getName()
+ +"::create",
+ StackInspector.Caller.class.getName()
+ +"::reflect",
+ ReflectionFrames.class.getName()
+ +"::testNewInstance"));
+
+ // Because Class.newInstance is not filtered, then the
+ // caller is Class.class
+ assertEquals(obj.cls, Class.class);
+ assertEquals(obj.filtered, 0);
+
+ // Calls the StackInspector.handle method through reflection
+ // and check the frames collected in the StackInspector
+ // default constructor.
+ // The handle method invokes the create method using
+ // reflection.
+ // The create method invokes StackInspector.class.newInstance().
+ // No reflection frame should appear, except
+ // Class::newInstance which is not considered as
+ // a reflection frame.
+ System.out.println("testNewInstance: handle");
+
+ obj = ((StackInspector)StackInspector.Caller.class
+ .getMethod("handle", How.class)
+ .invoke(null, How.CLASS));
+ assertEquals(obj.collectedFrames,
+ List.of(StackInspector.class.getName()
+ +"::<init>",
+ Class.class.getName()
+ +"::newInstance",
+ StackInspector.Caller.class.getName()
+ +"::create",
+ StackInspector.Caller.class.getName()
+ +"::handle",
+ ReflectionFrames.class.getName()
+ +"::testNewInstance"));
+
+ // Because Class.newInstance is not filtered, then the
+ // caller is Class.class
+ assertEquals(obj.cls, Class.class);
+ assertEquals(obj.filtered, 0);
+
+ // Sets a non-default walker configured to show
+ // reflection frames
+ StackInspector.walker.set(StackInspector.walkerShow);
+
+ // Calls the StackInspector.create method through reflection
+ // and check the frames collected in the StackInspector
+ // default constructor.
+ // The create method invokes StackInspector.class.newInstance().
+ // We should see all reflection frames, except the
+ // jdk.internal.reflect frames which we are filtering
+ // out in StackInspector::filter.
+ System.out.println("testNewInstance: create: show reflect");
+
+ obj = ((StackInspector)StackInspector.Caller.class
+ .getMethod("create", How.class)
+ .invoke(null, How.CLASS));
+ assertEquals(obj.collectedFrames,
+ List.of(StackInspector.class.getName()
+ +"::<init>",
+ Constructor.class.getName()
+ +"::newInstance",
+ Class.class.getName()
+ +"::newInstance",
+ StackInspector.Caller.class.getName()
+ +"::create",
+ Method.class.getName()
+ +"::invoke",
+ ReflectionFrames.class.getName()
+ +"::testNewInstance"));
+ // Because Class.newInstance is not filtered, then the
+ // caller is Class.class
+ assertEquals(obj.cls, Class.class);
+ assertNotEquals(obj.filtered, 0);
+
+ // Calls the StackInspector.reflect method through reflection
+ // and check the frames collected in the StackInspector
+ // default constructor.
+ // The reflect method invokes the create method through
+ // reflection.
+ // The create method invokes StackInspector.class.newInstance().
+ // We should see all reflection frames, except the
+ // jdk.internal.reflect frames which we are filtering
+ // out in StackInspector::filter.
+ System.out.println("testNewInstance: reflect: show reflect");
+
+ obj = ((StackInspector)StackInspector.Caller.class
+ .getMethod("reflect", How.class)
+ .invoke(null, How.CLASS));
+ assertEquals(obj.collectedFrames,
+ List.of(StackInspector.class.getName()
+ +"::<init>",
+ Constructor.class.getName()
+ +"::newInstance",
+ Class.class.getName()
+ +"::newInstance",
+ StackInspector.Caller.class.getName()
+ +"::create",
+ Method.class.getName()
+ +"::invoke",
+ StackInspector.Caller.class.getName()
+ +"::reflect",
+ Method.class.getName()
+ +"::invoke",
+ ReflectionFrames.class.getName()
+ +"::testNewInstance"));
+
+ // Because Class.newInstance is not filtered, then the
+ // caller is Class.class
+ assertEquals(obj.cls, Class.class);
+ assertNotEquals(obj.filtered, 0);
+
+ // Calls the StackInspector.handle method through reflection
+ // and check the frames collected in the StackInspector
+ // default constructor.
+ // The handle method invokes the create method using
+ // MethodHandle.
+ // The create method invokes StackInspector.class.newInstance().
+ // We should see all reflection frames, except the
+ // jdk.internal.reflect frames which we are filtering
+ // out in StackInspector::filter.
+ System.out.println("testNewInstance: handle: show reflect");
+
+ obj = ((StackInspector)StackInspector.Caller.class
+ .getMethod("handle", How.class)
+ .invoke(null, How.CLASS));
+ assertEquals(obj.collectedFrames,
+ List.of(StackInspector.class.getName()
+ +"::<init>",
+ Constructor.class.getName()
+ +"::newInstance",
+ Class.class.getName()
+ +"::newInstance",
+ StackInspector.Caller.class.getName()
+ +"::create",
+ // MethodHandle::invoke remains hidden
+ StackInspector.Caller.class.getName()
+ +"::handle",
+ Method.class.getName()
+ +"::invoke",
+ ReflectionFrames.class.getName()
+ +"::testNewInstance"));
+
+ // Because Class.newInstance is not filtered, then the
+ // caller is Class.class
+ assertEquals(obj.cls, Class.class);
+ assertNotEquals(obj.filtered, 0);
+ }
+
+ @Test
+ public static void testGetCaller() throws Exception {
+ // Sets the default walker which hides reflection
+ // frames.
+ StackInspector.walker.set(StackInspector.walkerHide);
+
+ assertEquals(StackInspector.getCaller(), ReflectionFrames.class);
+ assertEquals(StackInspector.class.getMethod("getCaller").invoke(null),
+ ReflectionFrames.class);
+
+ // Sets a non-default walker configured to show
+ // reflection frames
+ StackInspector.walker.set(StackInspector.walkerShow);
+
+ assertEquals(StackInspector.getCaller(), ReflectionFrames.class);
+ assertEquals(StackInspector.class.getMethod("getCaller").invoke(null),
+ ReflectionFrames.class);
+ }
+
+ @Test
+ public static void testReflectCaller() throws Exception {
+ // Sets the default walker which hides reflection
+ // frames.
+ StackInspector.walker.set(StackInspector.walkerHide);
+
+ assertEquals(StackInspector.reflectCaller(), ReflectionFrames.class);
+ assertEquals(StackInspector.class.getMethod("reflectCaller").invoke(null),
+ ReflectionFrames.class);
+
+ // Sets a non-default walker configured to show
+ // reflection frames
+ StackInspector.walker.set(StackInspector.walkerShow);
+
+ assertEquals(StackInspector.reflectCaller(), ReflectionFrames.class);
+ assertEquals(StackInspector.class.getMethod("reflectCaller").invoke(null),
+ ReflectionFrames.class);
+ }
+
+ @Test
+ public static void testSupplyCaller() throws Exception {
+ // Sets the default walker which hides reflection
+ // frames.
+ StackInspector.walker.set(StackInspector.walkerHide);
+
+ assertEquals(StackInspector.supplyCaller(), ReflectionFrames.class);
+ assertEquals(StackInspector.class.getMethod("supplyCaller").invoke(null),
+ ReflectionFrames.class);
+
+ // Sets a non-default walker configured to show
+ // reflection frames
+ StackInspector.walker.set(StackInspector.walkerShow);
+
+ assertEquals(StackInspector.supplyCaller(), ReflectionFrames.class);
+ assertEquals(StackInspector.class.getMethod("supplyCaller").invoke(null),
+ ReflectionFrames.class);
+ }
+
+ @Test
+ public static void testHandleCaller() throws Exception {
+ // Sets the default walker which hides reflection
+ // frames.
+ StackInspector.walker.set(StackInspector.walkerHide);
+
+ assertEquals(StackInspector.handleCaller(), ReflectionFrames.class);
+ assertEquals(StackInspector.class.getMethod("handleCaller").invoke(null),
+ ReflectionFrames.class);
+
+ // Sets a non-default walker configured to show
+ // reflection frames
+ StackInspector.walker.set(StackInspector.walkerShow);
+
+ assertEquals(StackInspector.handleCaller(), ReflectionFrames.class);
+ assertEquals(StackInspector.class.getMethod("handleCaller").invoke(null),
+ ReflectionFrames.class);
+ }
+
+ static enum How { NEW, CONSTRUCTOR, CLASS};
+
+ /**
+ * An object that collect stack frames by walking the stack
+ * (and calling getCallerClass()) from within its constructor.
+ * For the purpose of this test, StackInspector objects are
+ * always created from the nested StackInspector.Caller class,
+ * which should therefore appear as the caller of the
+ * StackInspector constructor.
+ */
+ static class StackInspector {
+ static final StackWalker walkerHide =
+ StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
+ static final StackWalker walkerShow =
+ StackWalker.getInstance(EnumSet.of(
+ StackWalker.Option.RETAIN_CLASS_REFERENCE,
+ StackWalker.Option.SHOW_REFLECT_FRAMES));
+ final static ThreadLocal<StackWalker> walker = new ThreadLocal<>() {
+ protected StackWalker initialValue() {
+ return walkerHide;
+ }
+ };
+
+ List<String> collectedFrames;
+ Class<?> cls = null;
+ boolean stop;
+ int filtered;
+ final boolean filterImplFrames;
+
+ public StackInspector() {
+ stop = false;
+ // if reflection frames are not hidden, we want to
+ // filter implementation frames before collecting
+ // to avoid depending on internal details.
+ filterImplFrames = walker.get() == walkerShow;
+ collectedFrames = walker.get().walk(this::parse);
+ cls = walker.get().getCallerClass();
+ }
+
+ public List<String> collectedFrames() {
+ return collectedFrames;
+ }
+
+ // The takeWhile method arrange for stopping frame collection
+ // as soon as a frame from ReflectionFrames.class is reached.
+ // The first such frame encountered is still included in the
+ // collected frames, but collection stops right after.
+ // This makes it possible to filter out anything above the
+ // the test method frame, such as frames from the test
+ // framework.
+ public boolean takeWhile(StackFrame f) {
+ if (stop) return false;
+ if (verbose) System.out.println(" " + f);
+ stop = stop || f.getDeclaringClass() == ReflectionFrames.class;
+ return true;
+ }
+
+ // filter out implementation frames to avoid depending
+ // on implementation details. If present, Class::newInstance,
+ // Method::invoke and Constructor::newInstance will
+ // still appear in the collected frames, which is
+ // sufficient for the purpose of the test.
+ // In the case where the StackWalker itself is supposed to
+ // filter the reflection frames, then this filter will always
+ // return true. This way, if such a reflection frame appears when
+ // it sjould have been filtered by StackWalker, it will make the
+ // test fail.
+ public boolean filter(StackFrame f) {
+ if (filterImplFrames &&
+ f.getClassName().startsWith("jdk.internal.reflect.")) {
+ filtered++;
+ return false;
+ }
+ if (!verbose) System.out.println(" " + f);
+ return true;
+ }
+
+ public String frame(StackFrame f) {
+ return f.getClassName() + "::" + f.getMethodName();
+ }
+
+ List<String> parse(Stream<StackFrame> s) {
+ return s.takeWhile(this::takeWhile)
+ .filter(this::filter)
+ .map(this::frame)
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * The Caller class is used to create instances of
+ * StackInspector, either direcltly, or throug reflection.
+ */
+ public static class Caller {
+ public static StackInspector create(How how) throws Exception {
+ switch(how) {
+ case NEW: return new StackInspector();
+ case CONSTRUCTOR: return StackInspector.class
+ .getConstructor().newInstance();
+ case CLASS: return StackInspector.class.newInstance();
+ default: throw new AssertionError(String.valueOf(how));
+ }
+ }
+ public static StackInspector reflect(How how) throws Exception {
+ return (StackInspector) Caller.class.getMethod("create", How.class)
+ .invoke(null, how);
+ }
+ public static StackInspector handle(How how) throws Exception {
+ Lookup lookup = MethodHandles.lookup();
+ MethodHandle mh = lookup.findStatic(Caller.class, "create",
+ MethodType.methodType(StackInspector.class, How.class));
+ try {
+ return (StackInspector) mh.invoke(how);
+ } catch (Error | Exception x) {
+ throw x;
+ } catch(Throwable t) {
+ throw new AssertionError(t);
+ }
+ }
+ }
+
+ public static Class<?> getCaller() throws Exception {
+ return walker.get().getCallerClass();
+ }
+
+ public static Class<?> reflectCaller() throws Exception {
+ return (Class<?>)StackWalker.class.getMethod("getCallerClass")
+ .invoke(walker.get());
+ }
+
+ public static Class<?> supplyCaller() throws Exception {
+ return ((Supplier<Class<?>>)StackInspector.walker.get()::getCallerClass).get();
+ }
+
+ public static Class<?> handleCaller() throws Exception {
+ Lookup lookup = MethodHandles.lookup();
+ MethodHandle mh = lookup.findVirtual(StackWalker.class, "getCallerClass",
+ MethodType.methodType(Class.class));
+ try {
+ return (Class<?>) mh.invoke(walker.get());
+ } catch (Error | Exception x) {
+ throw x;
+ } catch(Throwable t) {
+ throw new AssertionError(t);
+ }
+ }
+ }
+}
--- a/jdk/test/java/lang/annotation/AnnotationWithLambda.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/lang/annotation/AnnotationWithLambda.java Thu Feb 09 23:15:52 2017 +0100
@@ -43,7 +43,7 @@
public class AnnotationWithLambda {
@Test
- void testAnnotationWithLambda() {
+ public void testAnnotationWithLambda() {
Method[] methods = AnnotationWithLambda.MethodsWithAnnotations.class.getDeclaredMethods();
for (Method method : methods) {
assertTrue((method.isAnnotationPresent(LambdaWithParameter.class)) &&
--- a/jdk/test/java/lang/reflect/Proxy/ProxyForMethodHandle.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/lang/reflect/Proxy/ProxyForMethodHandle.java Thu Feb 09 23:15:52 2017 +0100
@@ -46,7 +46,7 @@
* to a dynamic module
*/
@Test
- static void testRunnableMethodHandle() throws Exception {
+ public static void testRunnableMethodHandle() throws Exception {
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodType mt = MethodType.methodType(void.class);
MethodHandle mh = lookup.findStatic(ProxyForMethodHandle.class, "runForRunnable", mt);
--- a/jdk/test/java/net/HttpURLConnection/SetAuthenticator/HTTPSetAuthenticatorTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/net/HttpURLConnection/SetAuthenticator/HTTPSetAuthenticatorTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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,11 +32,12 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;
-/**
+/*
* @test
* @bug 8169415
* @library /lib/testlibrary/
- * @modules java.base/sun.net.www
+ * @modules java.logging
+ * java.base/sun.net.www
* java.base/sun.net.www.protocol.http
* jdk.httpserver/sun.net.httpserver
* @build jdk.testlibrary.SimpleSSLContext HTTPTest HTTPTestServer HTTPTestClient HTTPSetAuthenticatorTest
--- a/jdk/test/java/net/HttpURLConnection/SetAuthenticator/HTTPTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/net/HttpURLConnection/SetAuthenticator/HTTPTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -43,11 +43,12 @@
import javax.net.ssl.SSLSession;
import jdk.testlibrary.SimpleSSLContext;
-/**
+/*
* @test
* @bug 8169415
* @library /lib/testlibrary/
- * @modules java.base/sun.net.www
+ * @modules java.logging
+ * java.base/sun.net.www
* jdk.httpserver/sun.net.httpserver
* @build jdk.testlibrary.SimpleSSLContext HTTPTest HTTPTestServer HTTPTestClient
* @summary A simple HTTP test that starts an echo server supporting Digest
--- a/jdk/test/java/net/HttpURLConnection/SetAuthenticator/HTTPTestServer.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/net/HttpURLConnection/SetAuthenticator/HTTPTestServer.java Thu Feb 09 23:15:52 2017 +0100
@@ -50,11 +50,13 @@
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.Objects;
import java.util.Random;
+import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
import javax.net.ssl.SSLContext;
import sun.net.www.HeaderParser;
@@ -145,10 +147,63 @@
}
}
+ /**
+ * The HttpServerFactory ensures that the local port used by an HttpServer
+ * previously created by the current test/VM will not get reused by
+ * a subsequent test in the same VM. This is to avoid having the
+ * AuthCache reuse credentials from previous tests - which would
+ * invalidate the assumptions made by the current test on when
+ * the default authenticator should be called.
+ */
+ private static final class HttpServerFactory {
+ private static final int MAX = 10;
+ private static final CopyOnWriteArrayList<String> addresses =
+ new CopyOnWriteArrayList<>();
+ private static HttpServer newHttpServer(HttpProtocolType protocol)
+ throws IOException {
+ switch (protocol) {
+ case HTTP: return HttpServer.create();
+ case HTTPS: return HttpsServer.create();
+ default: throw new InternalError("Unsupported protocol " + protocol);
+ }
+ }
+ static <T extends HttpServer> T create(HttpProtocolType protocol)
+ throws IOException {
+ final int max = addresses.size() + MAX;
+ final List<HttpServer> toClose = new ArrayList<>();
+ try {
+ for (int i = 1; i <= max; i++) {
+ HttpServer server = newHttpServer(protocol);
+ server.bind(new InetSocketAddress("127.0.0.1", 0), 0);
+ InetSocketAddress address = server.getAddress();
+ String key = address.toString();
+ if (addresses.addIfAbsent(key)) {
+ System.out.println("Server bound to: " + key
+ + " after " + i + " attempt(s)");
+ return (T) server;
+ }
+ System.out.println("warning: address " + key
+ + " already used. Retrying bind.");
+ // keep the port bound until we get a port that we haven't
+ // used already
+ toClose.add(server);
+ }
+ } finally {
+ // if we had to retry, then close the servers we're not
+ // going to use.
+ for (HttpServer s : toClose) {
+ try { s.stop(1); } catch (Exception x) { /* ignore */ }
+ }
+ }
+ throw new IOException("Couldn't bind servers after " + max + " attempts: "
+ + "addresses used before: " + addresses);
+ }
+ }
+
static HttpServer createHttpServer(HttpProtocolType protocol) throws IOException {
switch (protocol) {
- case HTTP: return HttpServer.create();
- case HTTPS: return configure(HttpsServer.create());
+ case HTTP: return HttpServerFactory.create(protocol);
+ case HTTPS: return configure(HttpServerFactory.create(protocol));
default: throw new InternalError("Unsupported protocol " + protocol);
}
}
@@ -193,7 +248,6 @@
final HttpHandler hh = server.createHandler(schemeType, auth, authType);
HttpContext ctxt = impl.createContext(path, hh);
server.configureAuthentication(ctxt, schemeType, auth, authType);
- impl.bind(new InetSocketAddress("127.0.0.1", 0), 0);
impl.start();
return server;
}
@@ -215,8 +269,6 @@
final HttpHandler hh = server.createHandler(schemeType, auth, authType);
HttpContext ctxt = impl.createContext(path, hh);
server.configureAuthentication(ctxt, schemeType, auth, authType);
-
- impl.bind(new InetSocketAddress("127.0.0.1", 0), 0);
impl.start();
return server;
@@ -253,7 +305,6 @@
final HttpHandler hh = redirectingServer.create300Handler(locationURL,
HttpAuthType.SERVER, code300);
impl.createContext("/", hh);
- impl.bind(new InetSocketAddress("127.0.0.1", 0), 0);
impl.start();
return redirectingServer;
}
--- a/jdk/test/java/net/ProxySelector/SystemProxies.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/net/ProxySelector/SystemProxies.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,9 +22,13 @@
*/
/*
- * This is a manual test to determine the proxies set on the system for various
- * protocols. See bug 6912868.
+ * @test
+ * @bug 6912868 8170868
+ * @summary Basic test to provide some coverage of system proxy code. Will
+ * always pass. Should be run manually for specific systems to inspect output.
+ * @run main/othervm -Djava.net.useSystemProxies=true SystemProxies
*/
+
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.URI;
--- a/jdk/test/java/nio/file/FileSystem/Basic.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/nio/file/FileSystem/Basic.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2017, 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,11 +30,18 @@
*/
import java.io.File;
-import java.nio.file.*;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.FileStore;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.ProviderNotFoundException;
import java.util.HashMap;
+import java.util.concurrent.TimeUnit;
import jdk.testlibrary.FileUtils;
/**
@@ -47,6 +54,44 @@
throw new RuntimeException(msg);
}
+ static void checkFileStores(String os, FileSystem fs) throws IOException {
+ boolean checkFileStores = true;
+ if (!os.equals("Windows")) {
+ // try to check whether 'df' hangs
+ System.out.println("\n--- Begin df output ---");
+ System.out.flush();
+ Process proc = new ProcessBuilder("df").inheritIO().start();
+ try {
+ proc.waitFor(90, TimeUnit.SECONDS);
+ } catch (InterruptedException ignored) {
+ }
+ System.out.println("--- End df output ---\n");
+ System.out.flush();
+ try {
+ int exitValue = proc.exitValue();
+ if (exitValue != 0) {
+ System.err.printf("df process exited with %d != 0%n",
+ exitValue);
+ checkFileStores = false;
+ }
+ } catch (IllegalThreadStateException ignored) {
+ System.err.println("df command apparently hung");
+ checkFileStores = false;
+ }
+ }
+
+ // sanity check method
+ if (checkFileStores) {
+ System.out.println("\n--- Begin FileStores ---");
+ for (FileStore store: fs.getFileStores()) {
+ System.out.println(store);
+ }
+ System.out.println("--- EndFileStores ---\n");
+ } else {
+ System.err.println("Skipping FileStore check due to df failure");
+ }
+ }
+
static void checkSupported(FileSystem fs, String... views) {
for (String view: views) {
check(fs.supportedFileAttributeViews().contains(view),
@@ -70,7 +115,9 @@
}
}
- public static void main(String[] args) throws IOException, URISyntaxException {
+ public static void main(String[] args)
+ throws IOException, URISyntaxException {
+ String os = System.getProperty("os.name");
FileSystem fs = FileSystems.getDefault();
// close should throw UOE
@@ -85,15 +132,11 @@
check(fs.provider().getScheme().equals("file"),
"should use 'file' scheme");
- // santity check method - need to re-visit this in future as I/O errors
- // are possible
- for (FileStore store: fs.getFileStores()) {
- System.out.println(store);
- }
+ // sanity check FileStores
+ checkFileStores(os, fs);
// sanity check supportedFileAttributeViews
checkSupported(fs, "basic");
- String os = System.getProperty("os.name");
if (os.equals("SunOS"))
checkSupported(fs, "posix", "unix", "owner", "acl", "user");
if (os.equals("Linux"))
--- a/jdk/test/java/time/TEST.properties Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/time/TEST.properties Thu Feb 09 23:15:52 2017 +0100
@@ -1,6 +1,5 @@
-# Threeten test uses TestNG
+# java.time tests use TestNG
TestNG.dirs = .
othervm.dirs = tck/java/time/chrono test/java/time/chrono test/java/time/format
lib.dirs = ../../lib/testlibrary
lib.build = jdk.testlibrary.RandomFactory
-modules = java.base/java.time:open java.base/java.time.chrono:open java.base/java.time.zone:open
--- a/jdk/test/java/time/tck/java/time/AbstractTCKTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/time/tck/java/time/AbstractTCKTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -69,14 +69,35 @@
import java.io.ObjectOutputStream;
import java.io.ObjectStreamConstants;
import java.io.Serializable;
-import java.lang.reflect.Field;
import java.util.Formatter;
+import java.util.Map;
/**
* Base test class.
*/
public abstract class AbstractTCKTest {
+ /**
+ * Map from package name to the serialVersionUID of the .Ser class for the package.
+ */
+ private static Map<String, Long> serialVersionUIDs = Map.of(
+ "java.time", -7683839454370182990L,
+ "java.time.chrono", -6103370247208168577L,
+ "java.time.zone", -8885321777449118786L
+ );
+
+ /**
+ * Returns the serialVersionUID for the class.
+ * The SUIDs are defined by the specification for each class.
+ * @param serClass the class to return the SUID of
+ * @return returns the serialVersionUID for the class
+ */
+ public final static long getSUID(Class<?> serClass) {
+ String pkgName = serClass.getPackageName();
+ return serialVersionUIDs.get(pkgName);
+ }
+
+
protected static boolean isIsoLeap(long year) {
if (year % 4 != 0) {
return false;
@@ -111,10 +132,8 @@
protected static void assertSerializedBySer(Object object, byte[] expectedBytes, byte[]... matches) throws Exception {
String serClass = object.getClass().getPackage().getName() + ".Ser";
- Class<?> serCls = Class.forName(serClass);
- Field field = serCls.getDeclaredField("serialVersionUID");
- field.setAccessible(true);
- long serVer = (Long) field.get(null);
+ long serVer = getSUID(object.getClass());
+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (ObjectOutputStream oos = new ObjectOutputStream(baos) ) {
oos.writeObject(object);
@@ -172,9 +191,8 @@
* @throws Exception if an unexpected condition occurs
*/
protected static void assertNotSerializable(Class<?> serClass) throws Exception {
- Field field = serClass.getDeclaredField("serialVersionUID");
- field.setAccessible(true);
- long serVer = (Long) field.get(null);
+ long serVer = getSUID(serClass);
+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (DataOutputStream out = new DataOutputStream(baos)) {
out.writeShort(ObjectStreamConstants.STREAM_MAGIC);
@@ -201,7 +219,6 @@
fail("Class should not be deserializable " + serClass.getName());
}
-
/**
* Utility method to dump a byte array in a java syntax.
* @param bytes and array of bytes
--- a/jdk/test/java/time/tck/java/time/TCKOffsetDateTime.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/time/tck/java/time/TCKOffsetDateTime.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -104,8 +104,6 @@
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
import java.time.Clock;
import java.time.DateTimeException;
import java.time.Duration;
@@ -470,24 +468,12 @@
//-----------------------------------------------------------------------
@Test(expectedExceptions=NullPointerException.class)
public void constructor_nullTime() throws Throwable {
- Constructor<OffsetDateTime> con = OffsetDateTime.class.getDeclaredConstructor(LocalDateTime.class, ZoneOffset.class);
- con.setAccessible(true);
- try {
- con.newInstance(null, OFFSET_PONE);
- } catch (InvocationTargetException ex) {
- throw ex.getCause();
- }
+ OffsetDateTime.of(null, OFFSET_PONE);
}
@Test(expectedExceptions=NullPointerException.class)
public void constructor_nullOffset() throws Throwable {
- Constructor<OffsetDateTime> con = OffsetDateTime.class.getDeclaredConstructor(LocalDateTime.class, ZoneOffset.class);
- con.setAccessible(true);
- try {
- con.newInstance(LocalDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30)), null);
- } catch (InvocationTargetException ex) {
- throw ex.getCause();
- }
+ OffsetDateTime.of(LocalDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30)), null);
}
//-----------------------------------------------------------------------
--- a/jdk/test/java/time/tck/java/time/TCKOffsetTime.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/time/tck/java/time/TCKOffsetTime.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -89,8 +89,6 @@
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
import java.time.Clock;
import java.time.DateTimeException;
import java.time.Instant;
@@ -465,28 +463,16 @@
}
//-----------------------------------------------------------------------
- // constructor
+ // constructor via factory
//-----------------------------------------------------------------------
@Test(expectedExceptions=NullPointerException.class)
public void constructor_nullTime() throws Throwable {
- Constructor<OffsetTime> con = OffsetTime.class.getDeclaredConstructor(LocalTime.class, ZoneOffset.class);
- con.setAccessible(true);
- try {
- con.newInstance(null, OFFSET_PONE);
- } catch (InvocationTargetException ex) {
- throw ex.getCause();
- }
+ OffsetTime.of(null, OFFSET_PONE);
}
@Test(expectedExceptions=NullPointerException.class)
public void constructor_nullOffset() throws Throwable {
- Constructor<OffsetTime> con = OffsetTime.class.getDeclaredConstructor(LocalTime.class, ZoneOffset.class);
- con.setAccessible(true);
- try {
- con.newInstance(LocalTime.of(11, 30, 0, 0), null);
- } catch (InvocationTargetException ex) {
- throw ex.getCause();
- }
+ OffsetTime.of(LocalTime.of(11, 30, 0, 0), null);
}
//-----------------------------------------------------------------------
--- a/jdk/test/java/time/tck/java/time/serial/TCKZoneIdSerialization.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/time/tck/java/time/serial/TCKZoneIdSerialization.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -63,8 +63,11 @@
import org.testng.annotations.Test;
import tck.java.time.AbstractTCKTest;
-import java.io.*;
-import java.lang.reflect.Field;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamConstants;
import java.time.DateTimeException;
import java.time.ZoneId;
import java.time.zone.ZoneRulesException;
@@ -153,10 +156,8 @@
private ZoneId deserialize(String id) throws Exception {
String serClass = ZoneId.class.getPackage().getName() + ".Ser";
- Class<?> serCls = Class.forName(serClass);
- Field field = serCls.getDeclaredField("serialVersionUID");
- field.setAccessible(true);
- long serVer = (Long) field.get(null);
+ long serVer = getSUID(ZoneId.class);
+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (DataOutputStream dos = new DataOutputStream(baos)) {
dos.writeShort(ObjectStreamConstants.STREAM_MAGIC);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/time/test/java/time/TEST.properties Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,2 @@
+# java.time test system clock
+modules = java.base/java.time:open
--- a/jdk/test/java/util/AbstractList/CheckForComodification.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/AbstractList/CheckForComodification.java Thu Feb 09 23:15:52 2017 +0100
@@ -35,7 +35,7 @@
public class CheckForComodification {
private static final int LENGTH = 10;
public static void main(String[] args) throws Exception {
- List<Integer> list = new ArrayList<Integer>();
+ List<Integer> list = new ArrayList<>();
for (int i = 0; i < LENGTH; i++)
list.add(i);
try {
--- a/jdk/test/java/util/ArrayList/Bug6533203.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/ArrayList/Bug6533203.java Thu Feb 09 23:15:52 2017 +0100
@@ -32,7 +32,7 @@
@SuppressWarnings({"serial","unchecked"})
public class Bug6533203 {
void test(String[] args) throws Throwable {
- final List<Integer> superstitious = new ArrayList<Integer>() {
+ final List<Integer> superstitious = new ArrayList<>() {
public void add(int index, Integer i) {
if (i == 13) throw new Error("unlucky");
else super.add(index, i); }};
--- a/jdk/test/java/util/ArrayList/IteratorMicroBenchmark.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/ArrayList/IteratorMicroBenchmark.java Thu Feb 09 23:15:52 2017 +0100
@@ -209,8 +209,8 @@
// iterations, size, warmupSeconds, filter);
final ConcurrentSkipListMap<Integer,Integer> m
- = new ConcurrentSkipListMap<Integer,Integer>();
- final ArrayList<Integer> al = new ArrayList<Integer>(size);
+ = new ConcurrentSkipListMap<>();
+ final ArrayList<Integer> al = new ArrayList<>(size);
// Populate collections with random data
final ThreadLocalRandom rnd = ThreadLocalRandom.current();
@@ -218,16 +218,16 @@
m.put(rnd.nextInt(size), rnd.nextInt(size));
al.add(rnd.nextInt(size));
}
- final Vector<Integer> v = new Vector<Integer>(al);
- final ArrayDeque<Integer> ad = new ArrayDeque<Integer>(al);
+ final Vector<Integer> v = new Vector<>(al);
+ final ArrayDeque<Integer> ad = new ArrayDeque<>(al);
// shuffle ArrayDeque elements so they wrap
for (int i = 0, n = rnd.nextInt(size); i < n; i++)
ad.addLast(ad.removeFirst());
// Also test "short" collections
final int shortSize = 5;
- final Vector<Integer> sv = new Vector<Integer>(v.subList(0, shortSize));
- final ArrayList<Integer> sal = new ArrayList<Integer>(sv);
+ final Vector<Integer> sv = new Vector<>(v.subList(0, shortSize));
+ final ArrayList<Integer> sal = new ArrayList<>(sv);
// Checks for correctness *and* prevents loop optimizations
class Check {
@@ -613,8 +613,7 @@
public void work() throws Throwable {
for (int i = 0; i < iterations; i++) {
int sum = 0;
- List<Iterator<Integer>> its
- = new ArrayList<Iterator<Integer>>(2);
+ List<Iterator<Integer>> its = new ArrayList<>(2);
its.add(v.iterator());
its.add(al.iterator());
for (int k = 0; its.get(k).hasNext(); k = (k == 0) ? 1 : 0)
--- a/jdk/test/java/util/ArrayList/RangeCheckMicroBenchmark.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/ArrayList/RangeCheckMicroBenchmark.java Thu Feb 09 23:15:52 2017 +0100
@@ -159,7 +159,7 @@
final int size = intArg(args, "size", 1000);
final Pattern filter = patternArg(args, "filter");
- final ArrayList<Integer> list = new ArrayList<Integer>();
+ final ArrayList<Integer> list = new ArrayList<>();
final Random rnd = new Random();
for (int i = 0; i < size; i++)
list.add(rnd.nextInt());
--- a/jdk/test/java/util/Calendar/SupplementalJapaneseEraTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/Calendar/SupplementalJapaneseEraTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,10 @@
*/
import java.text.SimpleDateFormat;
+import java.time.chrono.JapaneseChronology;
import java.time.chrono.JapaneseDate;
import java.time.chrono.JapaneseEra;
+import java.time.format.DateTimeFormatterBuilder;
import java.time.format.TextStyle;
import java.util.Calendar;
import java.util.Date;
@@ -122,7 +124,7 @@
got = sdf.format(firstDayOfEra);
expected = NEW_ERA_ABBR+" 1-02-11";
if (!expected.equals(got)) {
- System.err.printf("GGGG y-MM-dd: got=\"%s\", expected=\"%s\"%n", got, expected);
+ System.err.printf("G y-MM-dd: got=\"%s\", expected=\"%s\"%n", got, expected);
errors++;
}
@@ -163,6 +165,20 @@
System.err.printf("JapaneseEra (NARROW_STANDALONE): got=\"%s\", expected=\"%s\"%n", got, NEW_ERA_ABBR);
errors++;
}
+
+ // test long/abbreviated names with java.time.format
+ got = new DateTimeFormatterBuilder()
+ .appendPattern("GGGG")
+ .appendLiteral(" ")
+ .appendPattern("G")
+ .toFormatter(Locale.US)
+ .withChronology(JapaneseChronology.INSTANCE)
+ .format(jdate);
+ expected = NEW_ERA_NAME + " " + NEW_ERA_ABBR;
+ if (!expected.equals(got)) {
+ System.err.printf("java.time formatter long/abbr names: got=\"%s\", expected=\"%s\"%n", got, expected);
+ errors++;
+ }
}
private static void testValidation(String eraName) {
--- a/jdk/test/java/util/Calendar/SupplementalJapaneseEraTest.sh Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/Calendar/SupplementalJapaneseEraTest.sh Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -22,7 +22,7 @@
#
# @test
-# @bug 8048123 8054214
+# @bug 8048123 8054214 8173423
# @summary Test for jdk.calendar.japanese.supplemental.era support
# @build SupplementalJapaneseEraTest
# @run shell SupplementalJapaneseEraTest.sh
--- a/jdk/test/java/util/Collection/IteratorMicroBenchmark.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/Collection/IteratorMicroBenchmark.java Thu Feb 09 23:15:52 2017 +0100
@@ -255,7 +255,7 @@
// "iterations=%d size=%d, warmup=%1g, filter=\"%s\"%n",
// iterations, size, warmupSeconds, filter);
- final ArrayList<Integer> al = new ArrayList<Integer>(size);
+ final ArrayList<Integer> al = new ArrayList<>(size);
// Populate collections with random data
final ThreadLocalRandom rnd = ThreadLocalRandom.current();
@@ -307,14 +307,14 @@
for (Integer n : x)
sum += n;
check.sum(sum);}}},
- new Job(klazz + " .iterator().forEachRemaining()") {
+ new Job(klazz + " iterator().forEachRemaining()") {
public void work() throws Throwable {
int[] sum = new int[1];
for (int i = 0; i < iterations; i++) {
sum[0] = 0;
x.iterator().forEachRemaining(n -> sum[0] += n);
check.sum(sum[0]);}}},
- new Job(klazz + " .spliterator().tryAdvance()") {
+ new Job(klazz + " spliterator().tryAdvance()") {
public void work() throws Throwable {
int[] sum = new int[1];
for (int i = 0; i < iterations; i++) {
@@ -322,28 +322,49 @@
Spliterator<Integer> spliterator = x.spliterator();
do {} while (spliterator.tryAdvance(n -> sum[0] += n));
check.sum(sum[0]);}}},
- new Job(klazz + " .spliterator().forEachRemaining()") {
+ new Job(klazz + " spliterator().forEachRemaining()") {
public void work() throws Throwable {
int[] sum = new int[1];
for (int i = 0; i < iterations; i++) {
sum[0] = 0;
x.spliterator().forEachRemaining(n -> sum[0] += n);
check.sum(sum[0]);}}},
- new Job(klazz + " .removeIf") {
+ new Job(klazz + " removeIf") {
public void work() throws Throwable {
int[] sum = new int[1];
for (int i = 0; i < iterations; i++) {
sum[0] = 0;
- x.removeIf(n -> { sum[0] += n; return false; });
+ if (x.removeIf(n -> { sum[0] += n; return false; }))
+ throw new AssertionError();
check.sum(sum[0]);}}},
- new Job(klazz + " .forEach") {
+ new Job(klazz + " contains") {
+ public void work() throws Throwable {
+ int[] sum = new int[1];
+ Object y = new Object() {
+ public boolean equals(Object z) {
+ sum[0] += (int) z; return false; }};
+ for (int i = 0; i < iterations; i++) {
+ sum[0] = 0;
+ if (x.contains(y)) throw new AssertionError();
+ check.sum(sum[0]);}}},
+ new Job(klazz + " remove(Object)") {
+ public void work() throws Throwable {
+ int[] sum = new int[1];
+ Object y = new Object() {
+ public boolean equals(Object z) {
+ sum[0] += (int) z; return false; }};
+ for (int i = 0; i < iterations; i++) {
+ sum[0] = 0;
+ if (x.remove(y)) throw new AssertionError();
+ check.sum(sum[0]);}}},
+ new Job(klazz + " forEach") {
public void work() throws Throwable {
int[] sum = new int[1];
for (int i = 0; i < iterations; i++) {
sum[0] = 0;
x.forEach(n -> sum[0] += n);
check.sum(sum[0]);}}},
- new Job(klazz + " .toArray()") {
+ new Job(klazz + " toArray()") {
public void work() throws Throwable {
int[] sum = new int[1];
for (int i = 0; i < iterations; i++) {
@@ -351,7 +372,7 @@
for (Object o : x.toArray())
sum[0] += (Integer) o;
check.sum(sum[0]);}}},
- new Job(klazz + " .toArray(a)") {
+ new Job(klazz + " toArray(a)") {
public void work() throws Throwable {
Integer[] a = new Integer[x.size()];
int[] sum = new int[1];
@@ -361,7 +382,7 @@
for (Object o : a)
sum[0] += (Integer) o;
check.sum(sum[0]);}}},
- new Job(klazz + " .toArray(empty)") {
+ new Job(klazz + " toArray(empty)") {
public void work() throws Throwable {
Integer[] empty = new Integer[0];
int[] sum = new int[1];
@@ -370,12 +391,12 @@
for (Integer o : x.toArray(empty))
sum[0] += o;
check.sum(sum[0]);}}},
- new Job(klazz + " .stream().collect") {
+ new Job(klazz + " stream().collect") {
public void work() throws Throwable {
for (int i = 0; i < iterations; i++) {
check.sum(x.stream()
.collect(summingInt(e -> e)));}}},
- new Job(klazz + " .parallelStream().collect") {
+ new Job(klazz + " parallelStream().collect") {
public void work() throws Throwable {
for (int i = 0; i < iterations; i++) {
check.sum(x.parallelStream()
@@ -385,7 +406,7 @@
List<Job> dequeJobs(Deque<Integer> x) {
String klazz = x.getClass().getSimpleName();
return List.of(
- new Job(klazz + " .descendingIterator() loop") {
+ new Job(klazz + " descendingIterator() loop") {
public void work() throws Throwable {
for (int i = 0; i < iterations; i++) {
int sum = 0;
@@ -393,7 +414,7 @@
while (it.hasNext())
sum += it.next();
check.sum(sum);}}},
- new Job(klazz + " .descendingIterator().forEachRemaining()") {
+ new Job(klazz + " descendingIterator().forEachRemaining()") {
public void work() throws Throwable {
int[] sum = new int[1];
for (int i = 0; i < iterations; i++) {
--- a/jdk/test/java/util/Collection/MOAT.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/Collection/MOAT.java Thu Feb 09 23:15:52 2017 +0100
@@ -678,7 +678,7 @@
private static void testQueueAddRemove(final Queue<Integer> q,
final Integer e) {
- final List<Integer> originalContents = new ArrayList<Integer>(q);
+ final List<Integer> originalContents = new ArrayList<>(q);
final boolean isEmpty = q.isEmpty();
final boolean isList = (q instanceof List);
final List asList = isList ? (List) q : null;
@@ -1207,8 +1207,7 @@
private static void throwsConsistently(Class<? extends Throwable> k,
Iterable<Fun> fs) {
- List<Class<? extends Throwable>> threw
- = new ArrayList<Class<? extends Throwable>>();
+ List<Class<? extends Throwable>> threw = new ArrayList<>();
for (Fun f : fs)
try { f.f(); threw.add(null); }
catch (Throwable t) {
@@ -1224,7 +1223,7 @@
final ConcurrentMap<T,Integer> cm = (m instanceof ConcurrentMap)
? (ConcurrentMap<T,Integer>) m
: null;
- List<Fun> fs = new ArrayList<Fun>();
+ List<Fun> fs = new ArrayList<>();
fs.add(() -> check(! m.containsKey(null)));
fs.add(() -> equal(m.remove(null), null));
fs.add(() -> equal(m.get(null), null));
--- a/jdk/test/java/util/Collection/RemoveMicroBenchmark.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/Collection/RemoveMicroBenchmark.java Thu Feb 09 23:15:52 2017 +0100
@@ -254,7 +254,7 @@
// "iterations=%d size=%d, warmup=%1g, filter=\"%s\"%n",
// iterations, size, warmupSeconds, filter);
- final ArrayList<Integer> al = new ArrayList<Integer>(size);
+ final ArrayList<Integer> al = new ArrayList<>(size);
// Populate collections with random data
final ThreadLocalRandom rnd = ThreadLocalRandom.current();
@@ -333,7 +333,7 @@
Supplier<Collection<Integer>> supplier,
ArrayList<Integer> al) {
return List.of(
- new Job(description + " .removeIf") {
+ new Job(description + " removeIf") {
public void work() throws Throwable {
Collection<Integer> x = supplier.get();
int[] sum = new int[1];
@@ -342,7 +342,21 @@
x.addAll(al);
x.removeIf(n -> { sum[0] += n; return true; });
check.sum(sum[0]);}}},
- new Job(description + " .removeAll") {
+ new Job(description + " removeIf rnd-two-pass") {
+ public void work() throws Throwable {
+ ThreadLocalRandom rnd = ThreadLocalRandom.current();
+ Collection<Integer> x = supplier.get();
+ int[] sum = new int[1];
+ for (int i = 0; i < iterations; i++) {
+ sum[0] = 0;
+ x.addAll(al);
+ x.removeIf(n -> {
+ boolean b = rnd.nextBoolean();
+ if (b) sum[0] += n;
+ return b; });
+ x.removeIf(n -> { sum[0] += n; return true; });
+ check.sum(sum[0]);}}},
+ new Job(description + " removeAll") {
public void work() throws Throwable {
Collection<Integer> x = supplier.get();
int[] sum = new int[1];
@@ -352,7 +366,7 @@
x.addAll(al);
x.removeAll(universe);
check.sum(sum[0]);}}},
- new Job(description + " .retainAll") {
+ new Job(description + " retainAll") {
public void work() throws Throwable {
Collection<Integer> x = supplier.get();
int[] sum = new int[1];
@@ -375,6 +389,28 @@
it.remove();
}
check.sum(sum[0]);}}},
+ new Job(description + " Iterator.remove-rnd-two-pass") {
+ public void work() throws Throwable {
+ ThreadLocalRandom rnd = ThreadLocalRandom.current();
+ Collection<Integer> x = supplier.get();
+ int[] sum = new int[1];
+ for (int i = 0; i < iterations; i++) {
+ sum[0] = 0;
+ x.addAll(al);
+ for (Iterator<Integer> it = x.iterator();
+ it.hasNext(); ) {
+ Integer e = it.next();
+ if (rnd.nextBoolean()) {
+ sum[0] += e;
+ it.remove();
+ }
+ }
+ for (Iterator<Integer> it = x.iterator();
+ it.hasNext(); ) {
+ sum[0] += it.next();
+ it.remove();
+ }
+ check.sum(sum[0]);}}},
new Job(description + " clear") {
public void work() throws Throwable {
Collection<Integer> x = supplier.get();
--- a/jdk/test/java/util/Collections/BigBinarySearch.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/Collections/BigBinarySearch.java Thu Feb 09 23:15:52 2017 +0100
@@ -38,7 +38,7 @@
extends AbstractList<Integer>
implements RandomAccess
{
- private Map<Integer,Integer> m = new HashMap<Integer,Integer>();
+ private Map<Integer,Integer> m = new HashMap<>();
public Integer get(int i) {
if (i < 0) throw new IndexOutOfBoundsException(""+i);
--- a/jdk/test/java/util/Collections/Disjoint.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/Collections/Disjoint.java Thu Feb 09 23:15:52 2017 +0100
@@ -42,7 +42,7 @@
int x = 0;
for (int i = 0; i < N; i++) {
int size = rnd.nextInt(10) + 2;
- List<Integer> list = new ArrayList<Integer>(size);
+ List<Integer> list = new ArrayList<>(size);
for (int j = 1; j < size; j++)
list.add(x++);
list.add(x);
--- a/jdk/test/java/util/Collections/RacingCollections.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/Collections/RacingCollections.java Thu Feb 09 23:15:52 2017 +0100
@@ -184,8 +184,7 @@
}
private static List<Map<Integer, Boolean>> newConcurrentMaps() {
- List<Map<Integer, Boolean>> list =
- new ArrayList<Map<Integer, Boolean>>();
+ List<Map<Integer, Boolean>> list = new ArrayList<>();
list.add(new ConcurrentHashMap<Integer, Boolean>());
list.add(new ConcurrentSkipListMap<Integer, Boolean>());
return list;
@@ -196,7 +195,7 @@
list.add(new Hashtable<Integer, Boolean>());
list.add(new HashMap<Integer, Boolean>());
list.add(new TreeMap<Integer, Boolean>());
- Comparator<Integer> cmp = new Comparator<Integer>() {
+ Comparator<Integer> cmp = new Comparator<>() {
public int compare(Integer x, Integer y) {
return x - y;
}};
@@ -205,7 +204,7 @@
}
private static List<Set<Integer>> newConcurrentSets() {
- List<Set<Integer>> list = new ArrayList<Set<Integer>>();
+ List<Set<Integer>> list = new ArrayList<>();
list.add(new ConcurrentSkipListSet<Integer>());
list.add(new CopyOnWriteArraySet<Integer>());
return list;
@@ -220,7 +219,7 @@
}
private static List<List<Integer>> newConcurrentLists() {
- List<List<Integer>> list = new ArrayList<List<Integer>>();
+ List<List<Integer>> list = new ArrayList<>();
list.add(new CopyOnWriteArrayList<Integer>());
return list;
}
@@ -233,8 +232,7 @@
}
private static List<Queue<Integer>> newConcurrentQueues() {
- List<Queue<Integer>> list =
- new ArrayList<Queue<Integer>>(newConcurrentDeques());
+ List<Queue<Integer>> list = new ArrayList<>(newConcurrentDeques());
list.add(new ArrayBlockingQueue<Integer>(10));
list.add(new LinkedBlockingQueue<Integer>(10));
list.add(new LinkedTransferQueue<Integer>());
@@ -243,14 +241,13 @@
}
private static List<Queue<Integer>> newQueues() {
- List<Queue<Integer>> list =
- new ArrayList<Queue<Integer>>(newDeques());
+ List<Queue<Integer>> list = new ArrayList<>(newDeques());
list.add(new LinkedBlockingQueue<Integer>(10));
return list;
}
private static List<Deque<Integer>> newConcurrentDeques() {
- List<Deque<Integer>> list = new ArrayList<Deque<Integer>>();
+ List<Deque<Integer>> list = new ArrayList<>();
list.add(new LinkedBlockingDeque<Integer>(10));
list.add(new ConcurrentLinkedDeque<Integer>());
return list;
--- a/jdk/test/java/util/Collections/ReverseOrder2.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/Collections/ReverseOrder2.java Thu Feb 09 23:15:52 2017 +0100
@@ -67,7 +67,7 @@
equal(list, golden);
}
- private static Comparator<String> cmp = new Comparator<String> () {
+ private static Comparator<String> cmp = new Comparator<>() {
public int compare(String s1, String s2) {
int i1 = Integer.parseInt(s1);
int i2 = Integer.parseInt(s2);
@@ -75,7 +75,7 @@
}
};
- private static final List<String> golden = new ArrayList<String>(N);
+ private static final List<String> golden = new ArrayList<>(N);
static {
for (int i = N-1; i >= 0; i--)
golden.add(String.valueOf(i));
@@ -89,7 +89,7 @@
equal(list, golden2);
}
- private static final List<Integer> golden2 = new ArrayList<Integer>(N);
+ private static final List<Integer> golden2 = new ArrayList<>(N);
static {
for (int i = N-1; i >= 0; i--)
golden2.add(i);
--- a/jdk/test/java/util/Collections/SetFromMap.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/Collections/SetFromMap.java Thu Feb 09 23:15:52 2017 +0100
@@ -49,7 +49,7 @@
private static void realMain() throws Throwable {
try {
- Map<String,Boolean> m = new IdentityHashMap<String,Boolean>();
+ Map<String,Boolean> m = new IdentityHashMap<>();
Set<String> s = Collections.newSetFromMap(m);
String foo1 = new String("foo");
String foo2 = new String("foo");
--- a/jdk/test/java/util/Deque/ChorusLine.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/Deque/ChorusLine.java Thu Feb 09 23:15:52 2017 +0100
@@ -131,7 +131,7 @@
}}};
private static void realMain(String[] args) throws Throwable {
- Collection<Deque<Integer>> deqs = new ArrayDeque<Deque<Integer>>(3);
+ Collection<Deque<Integer>> deqs = new ArrayDeque<>(3);
deqs.add(new ArrayDeque<Integer>());
deqs.add(new LinkedList<Integer>());
deqs.add(new LinkedBlockingDeque<Integer>());
@@ -157,12 +157,12 @@
prev = deq;
}
- Deque<Iterator<Integer>> its = new ArrayDeque<Iterator<Integer>>();
+ Deque<Iterator<Integer>> its = new ArrayDeque<>();
for (Deque<Integer> deq : deqs)
its.addLast(deq.iterator());
equal(its);
- Deque<Iterator<Integer>> dits = new ArrayDeque<Iterator<Integer>>();
+ Deque<Iterator<Integer>> dits = new ArrayDeque<>();
for (Deque<Integer> deq : deqs)
dits.addLast(deq.descendingIterator());
equal(dits);
--- a/jdk/test/java/util/IdentityHashMap/ToArray.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/IdentityHashMap/ToArray.java Thu Feb 09 23:15:52 2017 +0100
@@ -36,11 +36,10 @@
// new ArrayList(IdentityHashMap.entrySet())
// used to return bogus entries.
//----------------------------------------------------------------
- Map<String,String> mm = new IdentityHashMap<String,String>();
+ Map<String,String> mm = new IdentityHashMap<>();
mm.put("foo", "bar");
mm.put("baz", "quux");
- List<Map.Entry<String,String>> lm
- = new ArrayList<Map.Entry<String,String>>(mm.entrySet());
+ List<Map.Entry<String,String>> lm = new ArrayList<>(mm.entrySet());
String s = lm.toString();
if (! (s.equals("[foo=bar, baz=quux]") ||
s.equals("[baz=quux, foo=bar]")))
@@ -65,8 +64,7 @@
// IdentityHashMap.entrySet().toArray(T[] a) used to simply
// return toArray() !
//----------------------------------------------------------------
- IdentityHashMap<Integer,Integer> map
- = new IdentityHashMap<Integer,Integer>();
+ IdentityHashMap<Integer,Integer> map = new IdentityHashMap<>();
Set<Map.Entry<Integer,Integer>> es = map.entrySet();
if (es.toArray().length != 0)
throw new Error("non-empty");
--- a/jdk/test/java/util/IdentityHashMap/ToString.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/IdentityHashMap/ToString.java Thu Feb 09 23:15:52 2017 +0100
@@ -32,7 +32,7 @@
public class ToString {
public static void main(String[] args) {
- Map<String, String> m = new IdentityHashMap<String, String>();
+ Map<String, String> m = new IdentityHashMap<>();
Set<Map.Entry<String, String>> es = m.entrySet();
m.put("beer", "good");
Iterator<Map.Entry<String, String>> i = es.iterator();
--- a/jdk/test/java/util/NavigableMap/LockStep.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/NavigableMap/LockStep.java Thu Feb 09 23:15:52 2017 +0100
@@ -753,7 +753,7 @@
List<NavigableMap> maps = Arrays.asList(m1, m2);
for (NavigableMap m : maps) testEmptyMap(m);
- final Set<Integer> ints = new HashSet<Integer>();
+ final Set<Integer> ints = new HashSet<>();
while (ints.size() < size)
ints.add(rnd.nextInt(1024));
final Integer[] elts = ints.toArray(new Integer[size]);
@@ -795,7 +795,7 @@
List<NavigableSet> sets = Arrays.asList(s1, s2);
for (NavigableSet s : sets) testEmptySet(s);
- final Set<Integer> ints = new HashSet<Integer>();
+ final Set<Integer> ints = new HashSet<>();
while (ints.size() < size)
ints.add(rnd.nextInt(1024));
final Integer[] elts = ints.toArray(new Integer[size]);
--- a/jdk/test/java/util/PriorityQueue/ForgetMeNot.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/PriorityQueue/ForgetMeNot.java Thu Feb 09 23:15:52 2017 +0100
@@ -61,7 +61,7 @@
}
private static void realMain(String[] args) throws Throwable {
- final PriorityQueue<Integer> q = new PriorityQueue<Integer>();
+ final PriorityQueue<Integer> q = new PriorityQueue<>();
Iterator<Integer> it;
//----------------------------------------------------------------
--- a/jdk/test/java/util/PriorityQueue/NoNulls.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/PriorityQueue/NoNulls.java Thu Feb 09 23:15:52 2017 +0100
@@ -51,7 +51,7 @@
public class NoNulls {
void test(String[] args) throws Throwable {
final Comparator<String> nullTolerantComparator
- = new Comparator<String>() {
+ = new Comparator<>() {
public int compare(String x, String y) {
return (x == null ? -1 :
y == null ? 1 :
@@ -63,7 +63,7 @@
nullSortedSet.add(null);
final PriorityQueue<String> nullPriorityQueue
- = new PriorityQueue<String>() {
+ = new PriorityQueue<>() {
public Object[] toArray() { return new Object[] { null };}};
final Collection<String> nullCollection = new ArrayList<>();
--- a/jdk/test/java/util/PriorityQueue/PriorityQueueSort.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/PriorityQueue/PriorityQueueSort.java Thu Feb 09 23:15:52 2017 +0100
@@ -62,31 +62,31 @@
if (args.length > 0)
n = Integer.parseInt(args[0]);
- List<Integer> sorted = new ArrayList<Integer>(n);
+ List<Integer> sorted = new ArrayList<>(n);
for (int i = 0; i < n; i++)
sorted.add(new Integer(i));
- List<Integer> shuffled = new ArrayList<Integer>(sorted);
+ List<Integer> shuffled = new ArrayList<>(sorted);
Collections.shuffle(shuffled);
- Queue<Integer> pq = new PriorityQueue<Integer>(n, new MyComparator());
+ Queue<Integer> pq = new PriorityQueue<>(n, new MyComparator());
for (Iterator<Integer> i = shuffled.iterator(); i.hasNext(); )
pq.add(i.next());
- List<Integer> recons = new ArrayList<Integer>();
+ List<Integer> recons = new ArrayList<>();
while (!pq.isEmpty())
recons.add(pq.remove());
if (!recons.equals(sorted))
throw new RuntimeException("Sort test failed");
recons.clear();
- pq = new PriorityQueue<Integer>(shuffled);
+ pq = new PriorityQueue<>(shuffled);
while (!pq.isEmpty())
recons.add(pq.remove());
if (!recons.equals(sorted))
throw new RuntimeException("Sort test failed");
// Remove all odd elements from queue
- pq = new PriorityQueue<Integer>(shuffled);
+ pq = new PriorityQueue<>(shuffled);
for (Iterator<Integer> i = pq.iterator(); i.hasNext(); )
if ((i.next().intValue() & 1) == 1)
i.remove();
--- a/jdk/test/java/util/PriorityQueue/RemoveContains.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/PriorityQueue/RemoveContains.java Thu Feb 09 23:15:52 2017 +0100
@@ -69,7 +69,7 @@
}
public static void main(String[] args) {
- final Comparator<String> firstChar = new Comparator<String>() {
+ final Comparator<String> firstChar = new Comparator<>() {
public int compare(String x, String y) {
return x.charAt(0) - y.charAt(0); }};
--- a/jdk/test/java/util/Random/DistinctSeeds.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/Random/DistinctSeeds.java Thu Feb 09 23:15:52 2017 +0100
@@ -61,7 +61,7 @@
}
final int threadCount = 2;
List<RandomCollector> collectors = new ArrayList<>();
- List<Thread> threads = new ArrayList<Thread>();
+ List<Thread> threads = new ArrayList<>();
for (int i = 0; i < threadCount; i++) {
RandomCollector r = new RandomCollector();
collectors.add(r);
@@ -72,7 +72,7 @@
for (Thread thread : threads)
thread.join();
int collisions = 0;
- HashSet<Long> s = new HashSet<Long>();
+ HashSet<Long> s = new HashSet<>();
for (RandomCollector r : collectors) {
for (long x : r.randoms) {
if (s.contains(x))
--- a/jdk/test/java/util/TreeMap/NullAtEnd.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/TreeMap/NullAtEnd.java Thu Feb 09 23:15:52 2017 +0100
@@ -64,7 +64,7 @@
}
private static final Comparator<String> NULL_AT_END
- = new Comparator<String>() {
+ = new Comparator<>() {
/**
* Allows for nulls. Null is greater than anything non-null.
*/
@@ -78,14 +78,13 @@
public static void main(String[] args) {
try {
- SortedMap<String,String> m1
- = new TreeMap<String,String>(NULL_AT_END);
+ SortedMap<String,String> m1 = new TreeMap<>(NULL_AT_END);
check(eq(m1.put("a", "a"), null));
check(eq(m1.put("b", "b"), null));
check(eq(m1.put("c", "c"), null));
check(eq(m1.put(null, "d"), null));
- SortedMap<String,String> m2 = new TreeMap<String,String>(m1);
+ SortedMap<String,String> m2 = new TreeMap<>(m1);
check(eq(m1.lastKey(), null));
check(eq(m1.get(m1.lastKey()), "d"));
--- a/jdk/test/java/util/Vector/CopyInto.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/Vector/CopyInto.java Thu Feb 09 23:15:52 2017 +0100
@@ -36,7 +36,7 @@
public class CopyInto {
private static void realMain(String[] args) throws Throwable {
try {
- Vector<String> v = new Vector<String>();
+ Vector<String> v = new Vector<>();
v.add("foo");
v.copyInto(new Integer[3]);
fail("Expected ArrayStoreException");
--- a/jdk/test/java/util/concurrent/ArrayBlockingQueue/IteratorConsistency.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/ArrayBlockingQueue/IteratorConsistency.java Thu Feb 09 23:15:52 2017 +0100
@@ -86,26 +86,24 @@
}
Object itrs(ArrayBlockingQueue q) {
- try {
- return itrsField.get(q);
- } catch (Throwable t) { throw new Error(); }
+ try { return itrsField.get(q); }
+ catch (Throwable ex) { throw new AssertionError(ex); }
}
int takeIndex(ArrayBlockingQueue q) {
- try {
- return takeIndexField.getInt(q);
- } catch (Throwable t) { throw new Error(); }
+ try { return takeIndexField.getInt(q); }
+ catch (Throwable ex) { throw new AssertionError(ex); }
}
List<Iterator> trackedIterators(Object itrs) {
try {
- List<Iterator> its = new ArrayList<Iterator>();
+ List<Iterator> its = new ArrayList<>();
if (itrs != null)
for (Object p = headField.get(itrs); p != null; p = nextField.get(p))
its.add(((WeakReference<Iterator>)(p)).get());
Collections.reverse(its);
return its;
- } catch (Throwable t) { throw new Error(); }
+ } catch (Throwable ex) { throw new AssertionError(ex); }
}
List<Iterator> trackedIterators(ArrayBlockingQueue q) {
@@ -114,7 +112,7 @@
List<Iterator> attachedIterators(Object itrs) {
try {
- List<Iterator> its = new ArrayList<Iterator>();
+ List<Iterator> its = new ArrayList<>();
if (itrs != null)
for (Object p = headField.get(itrs); p != null; p = nextField.get(p)) {
Iterator it = ((WeakReference<Iterator>)(p)).get();
@@ -123,7 +121,7 @@
}
Collections.reverse(its);
return its;
- } catch (Throwable t) { unexpected(t); return null; }
+ } catch (Throwable ex) { unexpected(ex); return null; }
}
List<Iterator> attachedIterators(ArrayBlockingQueue q) {
@@ -131,9 +129,8 @@
}
Object[] internalArray(ArrayBlockingQueue q) {
- try {
- return (Object[]) itemsField.get(q);
- } catch (Throwable t) { throw new Error(t); }
+ try { return (Object[]) itemsField.get(q); }
+ catch (Throwable ex) { throw new AssertionError(ex); }
}
void printInternalArray(ArrayBlockingQueue q) {
@@ -242,7 +239,7 @@
//----------------------------------------------------------------
try {
ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
- List<Iterator> its = new ArrayList<Iterator>();
+ List<Iterator> its = new ArrayList<>();
for (int i = 0; i < capacity; i++)
check(q.add(i));
check(itrs(q) == null);
@@ -268,7 +265,7 @@
//----------------------------------------------------------------
try {
ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
- List<Iterator> its = new ArrayList<Iterator>();
+ List<Iterator> its = new ArrayList<>();
for (int i = 0; i < capacity; i++)
q.add(i);
check(itrs(q) == null);
@@ -295,7 +292,7 @@
//----------------------------------------------------------------
try {
ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
- List<Iterator> its = new ArrayList<Iterator>();
+ List<Iterator> its = new ArrayList<>();
for (int i = 0; i < capacity; i++)
q.add(i);
check(itrs(q) == null);
@@ -366,7 +363,7 @@
//----------------------------------------------------------------
try {
ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
- List<Iterator> its = new ArrayList<Iterator>();
+ List<Iterator> its = new ArrayList<>();
for (int i = 0; i < capacity; i++)
q.add(i);
for (int i = 0; i < capacity; i++) {
@@ -404,7 +401,7 @@
//----------------------------------------------------------------
try {
ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
- List<Iterator> its = new ArrayList<Iterator>();
+ List<Iterator> its = new ArrayList<>();
// Move takeIndex to middle
for (int i = 0; i < capacity/2; i++) {
check(q.add(i));
@@ -444,7 +441,7 @@
}
equal(attachedIterators(q), its);
break;
- default: throw new Error();
+ default: throw new AssertionError();
}
for (int i = 0; i < capacity; i++) {
@@ -478,7 +475,7 @@
//----------------------------------------------------------------
try {
ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
- List<Iterator> its = new ArrayList<Iterator>();
+ List<Iterator> its = new ArrayList<>();
for (int i = 0; i < capacity; i++)
q.add(i);
for (int i = 0; i < capacity; i++) {
@@ -501,8 +498,8 @@
//----------------------------------------------------------------
try {
ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
- List<Iterator> its = new ArrayList<Iterator>();
- List<Iterator> retained = new ArrayList<Iterator>();
+ List<Iterator> its = new ArrayList<>();
+ List<Iterator> retained = new ArrayList<>();
final int size = 1 + rnd.nextInt(capacity);
for (int i = 0; i < size; i++)
q.add(i);
@@ -537,7 +534,7 @@
// Expect around 8 sweeps per PROBE_HOP
final int SWEEPS_PER_PROBE_HOP = 8;
ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
- List<Iterator> its = new ArrayList<Iterator>();
+ List<Iterator> its = new ArrayList<>();
for (int i = 0; i < capacity; i++)
q.add(i);
for (int i = 0; i < PROBE_HOP_COUNT * PROBE_HOP; i++) {
@@ -568,7 +565,7 @@
//----------------------------------------------------------------
try {
ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
- List<Iterator> its = new ArrayList<Iterator>();
+ List<Iterator> its = new ArrayList<>();
for (int i = 0; i < capacity/2; i++) {
q.add(i);
q.remove();
@@ -621,7 +618,7 @@
check(!q.contains(i));
equal(q.size(), size - 1);
break;
- default: throw new Error();
+ default: throw new AssertionError();
}
checkRemoveThrowsISE(it);
check(isDetached(it));
@@ -638,11 +635,9 @@
//----------------------------------------------------------------
try {
ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
- Queue<Iterator> its0
- = new ArrayDeque<Iterator>();
- Queue<Iterator> itsMid
- = new ArrayDeque<Iterator>();
- List<Iterator> its = new ArrayList<Iterator>();
+ Queue<Iterator> its0 = new ArrayDeque<>();
+ Queue<Iterator> itsMid = new ArrayDeque<>();
+ List<Iterator> its = new ArrayList<>();
for (int i = 0; i < capacity; i++)
q.add(i);
for (int i = 0; i < 2 * capacity + 1; i++) {
--- a/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java Thu Feb 09 23:15:52 2017 +0100
@@ -42,7 +42,6 @@
import java.util.ArrayList;
import java.util.List;
-import java.util.SplittableRandom;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
@@ -55,6 +54,7 @@
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import jdk.testlibrary.Utils;
@@ -89,7 +89,6 @@
final CountDownLatch consumersInterrupted;
final LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer();
final CyclicBarrier barrier;
- final SplittableRandom rnd = new SplittableRandom();
volatile boolean done = false;
CancelledProducerConsumerLoops(int npairs, BlockingQueue<Integer> queue) {
@@ -109,7 +108,7 @@
cons[i] = pool.submit(new Consumer());
}
barrier.await();
- Thread.sleep(rnd.nextInt(5));
+ Thread.sleep(ThreadLocalRandom.current().nextInt(5));
for (int i = 1; i < npairs; i++) {
if (!prods[i].cancel(true) ||
--- a/jdk/test/java/util/concurrent/BlockingQueue/DrainToFails.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/BlockingQueue/DrainToFails.java Thu Feb 09 23:15:52 2017 +0100
@@ -148,7 +148,7 @@
System.err.println(q.getClass().getSimpleName());
for (int i = 0; i < CAPACITY; i++)
q.add(i);
- List<Thread> putters = new ArrayList<Thread>();
+ List<Thread> putters = new ArrayList<>();
for (int i = 0; i < 4; i++) {
Thread putter = new Thread(putter(q, 42 + i));
putters.add(putter);
--- a/jdk/test/java/util/concurrent/BlockingQueue/Interrupt.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/BlockingQueue/Interrupt.java Thu Feb 09 23:15:52 2017 +0100
@@ -82,7 +82,7 @@
(q instanceof BlockingDeque<?>) ?
(BlockingDeque<Object>) q : null;
q.clear();
- List<Fun> fs = new ArrayList<Fun>();
+ List<Fun> fs = new ArrayList<>();
fs.add(() -> q.take());
fs.add(() -> q.poll(LONG_DELAY_MS, MILLISECONDS));
if (deq != null) {
--- a/jdk/test/java/util/concurrent/BlockingQueue/PollMemoryLeak.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/BlockingQueue/PollMemoryLeak.java Thu Feb 09 23:15:52 2017 +0100
@@ -105,13 +105,13 @@
}
ConcurrentHashMap<Class<?>, Collection<Field>> classFields
- = new ConcurrentHashMap<Class<?>, Collection<Field>>();
+ = new ConcurrentHashMap<>();
Collection<Field> referenceFieldsOf(Class<?> k) {
Collection<Field> fields = classFields.get(k);
if (fields == null) {
fields = new ArrayDeque<Field>();
- ArrayDeque<Field> allFields = new ArrayDeque<Field>();
+ ArrayDeque<Field> allFields = new ArrayDeque<>();
for (Class<?> c = k; c != null; c = c.getSuperclass())
for (Field field : c.getDeclaredFields())
if (!Modifier.isStatic(field.getModifiers())
@@ -130,7 +130,7 @@
}
Set<Object> retainedObjects(Object x) {
- ArrayDeque<Object> todo = new ArrayDeque<Object>() {
+ ArrayDeque<Object> todo = new ArrayDeque<>() {
public void push(Object x) { if (x != null) super.push(x); }};
Set<Object> uniqueObjects = Collections.newSetFromMap(
new IdentityHashMap<Object, Boolean>());
--- a/jdk/test/java/util/concurrent/ConcurrentHashMap/MapCheck.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/ConcurrentHashMap/MapCheck.java Thu Feb 09 23:15:52 2017 +0100
@@ -51,7 +51,7 @@
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
-import java.util.SplittableRandom;
+import java.util.concurrent.ThreadLocalRandom;
public class MapCheck {
@@ -612,7 +612,7 @@
}
static void shuffle(Object[] keys) {
- SplittableRandom rnd = new SplittableRandom();
+ ThreadLocalRandom rnd = ThreadLocalRandom.current();
int size = keys.length;
for (int i=size; i>1; i--) {
int r = rnd.nextInt(i);
--- a/jdk/test/java/util/concurrent/ConcurrentHashMap/MapLoops.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/ConcurrentHashMap/MapLoops.java Thu Feb 09 23:15:52 2017 +0100
@@ -68,8 +68,7 @@
static final ExecutorService pool = Executors.newCachedThreadPool();
- static final List<Throwable> throwables
- = new CopyOnWriteArrayList<Throwable>();
+ static final List<Throwable> throwables = new CopyOnWriteArrayList<>();
public static void main(String[] args) throws Exception {
--- a/jdk/test/java/util/concurrent/ConcurrentLinkedQueue/RemoveLeak.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/ConcurrentLinkedQueue/RemoveLeak.java Thu Feb 09 23:15:52 2017 +0100
@@ -101,13 +101,13 @@
}
ConcurrentHashMap<Class<?>, Collection<Field>> classFields
- = new ConcurrentHashMap<Class<?>, Collection<Field>>();
+ = new ConcurrentHashMap<>();
Collection<Field> referenceFieldsOf(Class<?> k) {
Collection<Field> fields = classFields.get(k);
if (fields == null) {
fields = new ArrayDeque<Field>();
- ArrayDeque<Field> allFields = new ArrayDeque<Field>();
+ ArrayDeque<Field> allFields = new ArrayDeque<>();
for (Class<?> c = k; c != null; c = c.getSuperclass())
for (Field field : c.getDeclaredFields())
if (!Modifier.isStatic(field.getModifiers())
@@ -126,7 +126,7 @@
}
Set<Object> retainedObjects(Object x) {
- ArrayDeque<Object> todo = new ArrayDeque<Object>() {
+ ArrayDeque<Object> todo = new ArrayDeque<>() {
public void push(Object x) { if (x != null) super.push(x); }};
Set<Object> uniqueObjects = Collections.newSetFromMap(
new IdentityHashMap<Object, Boolean>());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/ConcurrentLinkedQueue/WhiteBox.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,355 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Martin Buchholz with assistance from members of JCP
+ * JSR-166 Expert Group and released to the public domain, as
+ * explained at http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/*
+ * @test
+ * @modules java.base/java.util.concurrent:open
+ * @run testng WhiteBox
+ * @summary White box tests of implementation details
+ */
+
+import static org.testng.Assert.*;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.ThreadLocalRandom;
+import static java.util.stream.Collectors.toList;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+@Test
+public class WhiteBox {
+ final ThreadLocalRandom rnd = ThreadLocalRandom.current();
+ final VarHandle HEAD, TAIL, ITEM, NEXT;
+
+ WhiteBox() throws ReflectiveOperationException {
+ Class<?> qClass = ConcurrentLinkedQueue.class;
+ Class<?> nodeClass = Class.forName(qClass.getName() + "$Node");
+ MethodHandles.Lookup lookup
+ = MethodHandles.privateLookupIn(qClass, MethodHandles.lookup());
+ HEAD = lookup.findVarHandle(qClass, "head", nodeClass);
+ TAIL = lookup.findVarHandle(qClass, "tail", nodeClass);
+ NEXT = lookup.findVarHandle(nodeClass, "next", nodeClass);
+ ITEM = lookup.findVarHandle(nodeClass, "item", Object.class);
+ }
+
+ Object head(ConcurrentLinkedQueue q) { return HEAD.getVolatile(q); }
+ Object tail(ConcurrentLinkedQueue q) { return TAIL.getVolatile(q); }
+ Object item(Object node) { return ITEM.getVolatile(node); }
+ Object next(Object node) { return NEXT.getVolatile(node); }
+
+ int nodeCount(ConcurrentLinkedQueue q) {
+ int i = 0;
+ for (Object p = head(q); p != null; ) {
+ i++;
+ if (p == (p = next(p))) p = head(q);
+ }
+ return i;
+ }
+
+ void assertIsSelfLinked(Object node) {
+ assertSame(next(node), node);
+ assertNull(item(node));
+ }
+
+ void assertIsNotSelfLinked(Object node) {
+ assertNotSame(node, next(node));
+ }
+
+ @Test
+ public void addRemove() {
+ ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
+ assertInvariants(q);
+ assertNull(item(head(q)));
+ assertEquals(nodeCount(q), 1);
+ q.add(1);
+ assertEquals(nodeCount(q), 2);
+ assertInvariants(q);
+ q.remove(1);
+ assertEquals(nodeCount(q), 1);
+ assertInvariants(q);
+ }
+
+ /**
+ * Traversal actions that visit every node and do nothing, but
+ * have side effect of squeezing out dead nodes.
+ */
+ @DataProvider
+ public Object[][] traversalActions() {
+ return List.<Consumer<ConcurrentLinkedQueue>>of(
+ q -> q.forEach(e -> {}),
+ q -> assertFalse(q.contains(new Object())),
+ q -> assertFalse(q.remove(new Object())),
+ q -> q.spliterator().forEachRemaining(e -> {}),
+ q -> q.stream().collect(toList()),
+ q -> assertFalse(q.removeIf(e -> false)),
+ q -> assertFalse(q.removeAll(List.of())))
+ .stream().map(x -> new Object[]{ x }).toArray(Object[][]::new);
+ }
+
+ @Test(dataProvider = "traversalActions")
+ public void traversalOperationsCollapseNodes(
+ Consumer<ConcurrentLinkedQueue> traversalAction) {
+ ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
+ Object oldHead;
+ int n = 1 + rnd.nextInt(5);
+ for (int i = 0; i < n; i++) q.add(i);
+ assertInvariants(q);
+ assertEquals(nodeCount(q), n + 1);
+ oldHead = head(q);
+ traversalAction.accept(q); // collapses head node
+ assertIsSelfLinked(oldHead);
+ assertInvariants(q);
+ assertEquals(nodeCount(q), n);
+ // Iterator.remove does not currently try to collapse dead nodes
+ for (Iterator it = q.iterator(); it.hasNext(); ) {
+ it.next();
+ it.remove();
+ }
+ assertEquals(nodeCount(q), n);
+ assertInvariants(q);
+ oldHead = head(q);
+ traversalAction.accept(q); // collapses all nodes
+ if (n > 1) assertIsSelfLinked(oldHead);
+ assertEquals(nodeCount(q), 1);
+ assertInvariants(q);
+
+ for (int i = 0; i < n + 1; i++) q.add(i);
+ assertEquals(nodeCount(q), n + 2);
+ oldHead = head(q);
+ assertEquals(0, q.poll()); // 2 leading nodes collapsed
+ assertIsSelfLinked(oldHead);
+ assertEquals(nodeCount(q), n);
+ assertTrue(q.remove(n));
+ assertEquals(nodeCount(q), n);
+ traversalAction.accept(q); // trailing node is never collapsed
+ }
+
+ @Test(dataProvider = "traversalActions")
+ public void traversalOperationsCollapseLeadingNodes(
+ Consumer<ConcurrentLinkedQueue> traversalAction) {
+ ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
+ Object oldHead;
+ int n = 1 + rnd.nextInt(5);
+ for (int i = 0; i < n; i++) q.add(i);
+ assertEquals(nodeCount(q), n + 1);
+ oldHead = head(q);
+ traversalAction.accept(q);
+ assertInvariants(q);
+ assertEquals(nodeCount(q), n);
+ assertIsSelfLinked(oldHead);
+ }
+
+ @Test(dataProvider = "traversalActions")
+ public void traversalOperationsDoNotSelfLinkInteriorNodes(
+ Consumer<ConcurrentLinkedQueue> traversalAction) {
+ ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
+ int c;
+ int n = 3 + rnd.nextInt(3);
+ for (int i = 0; i < n; i++) q.add(i);
+ Object oneNode;
+ for (oneNode = head(q);
+ ! (item(oneNode) != null && item(oneNode).equals(1));
+ oneNode = next(oneNode))
+ ;
+ Object next = next(oneNode);
+ c = nodeCount(q);
+ for (Iterator it = q.iterator(); it.hasNext(); )
+ if (it.next().equals(1)) it.remove();
+ assertEquals(nodeCount(q), c - 1); // iterator detached head!
+ assertNull(item(oneNode));
+ assertSame(next, next(oneNode));
+ assertInvariants(q);
+ c = nodeCount(q);
+ traversalAction.accept(q);
+ assertEquals(nodeCount(q), c - 1);
+ assertSame(next, next(oneNode)); // un-linked, but not self-linked
+ }
+
+ /**
+ * Checks that traversal operations collapse a random pattern of
+ * dead nodes as could normally only occur with a race.
+ */
+ @Test(dataProvider = "traversalActions")
+ public void traversalOperationsCollapseRandomNodes(
+ Consumer<ConcurrentLinkedQueue> traversalAction) {
+ ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
+ int n = rnd.nextInt(6);
+ for (int i = 0; i < n; i++) q.add(i);
+ ArrayList nulledOut = new ArrayList();
+ for (Object p = head(q); p != null; p = next(p))
+ if (item(p) != null && rnd.nextBoolean()) {
+ nulledOut.add(item(p));
+ ITEM.setVolatile(p, null);
+ }
+ traversalAction.accept(q);
+ int c = nodeCount(q);
+ assertEquals(q.size(), c - (q.contains(n - 1) ? 0 : 1));
+ for (int i = 0; i < n; i++)
+ assertTrue(nulledOut.contains(i) ^ q.contains(i));
+ }
+
+ /**
+ * Traversal actions that remove every element, and are also
+ * expected to squeeze out dead nodes.
+ */
+ @DataProvider
+ public Object[][] bulkRemovalActions() {
+ return List.<Consumer<ConcurrentLinkedQueue>>of(
+ q -> q.clear(),
+ q -> assertTrue(q.removeIf(e -> true)),
+ q -> assertTrue(q.retainAll(List.of())))
+ .stream().map(x -> new Object[]{ x }).toArray(Object[][]::new);
+ }
+
+ @Test(dataProvider = "bulkRemovalActions")
+ public void bulkRemovalOperationsCollapseNodes(
+ Consumer<ConcurrentLinkedQueue> bulkRemovalAction) {
+ ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
+ int n = 1 + rnd.nextInt(5);
+ for (int i = 0; i < n; i++) q.add(i);
+ bulkRemovalAction.accept(q);
+ assertEquals(nodeCount(q), 1);
+ assertInvariants(q);
+ }
+
+ /**
+ * Actions that remove the first element, and are expected to
+ * leave at most one slack dead node at head.
+ */
+ @DataProvider
+ public Object[][] pollActions() {
+ return List.<Consumer<ConcurrentLinkedQueue>>of(
+ q -> assertNotNull(q.poll()),
+ q -> assertNotNull(q.remove()))
+ .stream().map(x -> new Object[]{ x }).toArray(Object[][]::new);
+ }
+
+ @Test(dataProvider = "pollActions")
+ public void pollActionsOneNodeSlack(
+ Consumer<ConcurrentLinkedQueue> pollAction) {
+ ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
+ int n = 1 + rnd.nextInt(5);
+ for (int i = 0; i < n; i++) q.add(i);
+ assertEquals(nodeCount(q), n + 1);
+ for (int i = 0; i < n; i++) {
+ int c = nodeCount(q);
+ boolean slack = item(head(q)) == null;
+ if (slack) assertNotNull(item(next(head(q))));
+ pollAction.accept(q);
+ assertEquals(nodeCount(q), q.isEmpty() ? 1 : c - (slack ? 2 : 0));
+ }
+ assertInvariants(q);
+ }
+
+ /**
+ * Actions that append an element, and are expected to
+ * leave at most one slack node at tail.
+ */
+ @DataProvider
+ public Object[][] addActions() {
+ return List.<Consumer<ConcurrentLinkedQueue>>of(
+ q -> q.add(1),
+ q -> q.offer(1))
+ .stream().map(x -> new Object[]{ x }).toArray(Object[][]::new);
+ }
+
+ @Test(dataProvider = "addActions")
+ public void addActionsOneNodeSlack(
+ Consumer<ConcurrentLinkedQueue> addAction) {
+ ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
+ int n = 1 + rnd.nextInt(5);
+ for (int i = 0; i < n; i++) {
+ boolean slack = next(tail(q)) != null;
+ addAction.accept(q);
+ if (slack)
+ assertNull(next(tail(q)));
+ else {
+ assertNotNull(next(tail(q)));
+ assertNull(next(next(tail(q))));
+ }
+ assertInvariants(q);
+ }
+ }
+
+ byte[] serialBytes(Object o) {
+ try {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(bos);
+ oos.writeObject(o);
+ oos.flush();
+ oos.close();
+ return bos.toByteArray();
+ } catch (Exception fail) {
+ throw new AssertionError(fail);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ <T> T serialClone(T o) {
+ try {
+ ObjectInputStream ois = new ObjectInputStream
+ (new ByteArrayInputStream(serialBytes(o)));
+ T clone = (T) ois.readObject();
+ assertNotSame(o, clone);
+ assertSame(o.getClass(), clone.getClass());
+ return clone;
+ } catch (Exception fail) {
+ throw new AssertionError(fail);
+ }
+ }
+
+ public void testSerialization() {
+ ConcurrentLinkedQueue q = serialClone(new ConcurrentLinkedQueue());
+ assertInvariants(q);
+ }
+
+ /** Checks conditions which should always be true. */
+ void assertInvariants(ConcurrentLinkedQueue q) {
+ assertNotNull(head(q));
+ assertNotNull(tail(q));
+ // head is never self-linked (but tail may!)
+ for (Object h; next(h = head(q)) == h; )
+ assertNotSame(h, head(q)); // must be update race
+ }
+}
--- a/jdk/test/java/util/concurrent/ConcurrentMap/ConcurrentRemoveIf.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/ConcurrentMap/ConcurrentRemoveIf.java Thu Feb 09 23:15:52 2017 +0100
@@ -28,7 +28,7 @@
* @summary Test removeIf on views of concurrent maps
*/
-import org.testng.Assert;
+import static org.testng.Assert.assertEquals;
import org.testng.annotations.AfterClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@@ -54,8 +54,8 @@
static final int SIZE = 1000;
static final int HALF_SIZE = SIZE / 2;
- @DataProvider(name = "String,Supplier<ConcurrentMap>,Runnable")
- public static Object[][] spliteratorDataProvider() {
+ @DataProvider()
+ public static Object[][] concurrentMapViewRemoveIfActions() {
List<Object[]> rows = new ArrayList<>();
// ConcurrentMap classes to test
@@ -95,24 +95,17 @@
dm.values().removeIf(v -> v == 0);
});
- for (Map.Entry<String, Supplier<ConcurrentMap<Integer, Integer>>> mapSupplier : maps.entrySet()) {
- Supplier<ConcurrentMap<Integer, Integer>> sm = mapSupplier.getValue();
- for (Map.Entry<String, Consumer<ConcurrentMap<Integer, Integer>>> action : actions.entrySet()) {
- rows.add(new Object[]{
- mapSupplier.getKey() + action.getKey(),
- sm,
- action.getValue()});
- }
+ maps.forEach((mapDescription, sm) -> {
+ actions.forEach((actionDescription, action) -> {
+ rows.add(new Object[] {mapDescription + actionDescription, sm, action});
+ });
if (sm.get() instanceof ConcurrentNavigableMap) {
- for (Map.Entry<String, Consumer<ConcurrentNavigableMap<Integer, Integer>>> action : navActions.entrySet()) {
- rows.add(new Object[]{
- mapSupplier.getKey() + action.getKey(),
- sm,
- action.getValue()});
- }
+ navActions.forEach((actionDescription, action) -> {
+ rows.add(new Object[] {mapDescription + actionDescription, sm, action});
+ });
}
- }
+ });
return rows.toArray(new Object[0][]);
}
@@ -124,7 +117,7 @@
executorService.shutdown();
}
- @Test(dataProvider = "String,Supplier<ConcurrentMap>,Runnable")
+ @Test(dataProvider = "concurrentMapViewRemoveIfActions")
public void testMap(String desc, Supplier<ConcurrentMap<Integer, Integer>> ms, Consumer<ConcurrentMap<Integer, Integer>> action)
throws InterruptedException {
for (int i = 0; i < K; i++) {
@@ -140,7 +133,7 @@
// To start working simultaneously
CyclicBarrier threadStarted = new CyclicBarrier(2);
- // This task put 1's into map
+ // This task puts 1's into map
CompletableFuture<Void> putter = CompletableFuture.runAsync(
awaitOn(threadStarted, () -> fillMap(map, 1)),
executorService);
@@ -153,7 +146,8 @@
// Wait for both tasks to complete
CompletableFuture.allOf(putter, remover).join();
- Assert.assertEquals(map.size(), SIZE, "Map size incorrect");
+ assertEquals(map.size(), SIZE, "Map size incorrect");
+ map.forEach((k, v) -> assertEquals(v, (Integer)1));
}
static void fillMap(ConcurrentMap<Integer, Integer> map, int value) {
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java Thu Feb 09 23:15:52 2017 +0100
@@ -73,7 +73,7 @@
int items = 1024 * 1024;
Collection<Queue<Integer>> concurrentQueues() {
- List<Queue<Integer>> queues = new ArrayList<Queue<Integer>>();
+ List<Queue<Integer>> queues = new ArrayList<>();
queues.add(new ConcurrentLinkedDeque<Integer>());
queues.add(new ConcurrentLinkedQueue<Integer>());
queues.add(new ArrayBlockingQueue<Integer>(items, false));
@@ -166,7 +166,7 @@
LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer();
CyclicBarrier barrier = new CyclicBarrier(n + 1, timer);
totalItems = new AtomicInteger(n * items);
- ArrayList<Future<Integer>> results = new ArrayList<Future<Integer>>(n);
+ ArrayList<Future<Integer>> results = new ArrayList<>(n);
for (int i = 0; i < n; ++i)
results.add(pool.submit(new Stage(q, barrier, items)));
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java Thu Feb 09 23:15:52 2017 +0100
@@ -82,10 +82,10 @@
throw new AssertionError("failed to do a \"full\" gc");
}
- final Map<String,String> results = new ConcurrentHashMap<String,String>();
+ final Map<String,String> results = new ConcurrentHashMap<>();
Collection<Queue<Boolean>> queues() {
- List<Queue<Boolean>> queues = new ArrayList<Queue<Boolean>>();
+ List<Queue<Boolean>> queues = new ArrayList<>();
queues.add(new ConcurrentLinkedDeque<Boolean>());
queues.add(new ConcurrentLinkedQueue<Boolean>());
queues.add(new ArrayBlockingQueue<Boolean>(count, false));
@@ -107,7 +107,7 @@
}
void prettyPrintResults() {
- List<String> classNames = new ArrayList<String>(results.keySet());
+ List<String> classNames = new ArrayList<>(results.keySet());
Collections.sort(classNames);
int maxClassNameLength = 0;
int maxNanosLength = 0;
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java Thu Feb 09 23:15:52 2017 +0100
@@ -195,7 +195,7 @@
((BlockingQueue)q).remainingCapacity() :
Integer.MAX_VALUE;
final int capacity = Math.min(20, remainingCapacity);
- List<Iterator> its = new ArrayList<Iterator>();
+ List<Iterator> its = new ArrayList<>();
// Move to "middle"
for (int i = 0; i < capacity/2; i++) {
check(q.add(i));
@@ -229,7 +229,7 @@
it.remove();
}
break;
- default: throw new Error();
+ default: throw new AssertionError();
}
for (int i = 0; i < capacity; i++) {
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/RemovePollRace.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/RemovePollRace.java Thu Feb 09 23:15:52 2017 +0100
@@ -59,10 +59,10 @@
// Suitable for benchmarking. Overridden by args[0] for testing.
int count = 1024 * 1024;
- final Map<String,String> results = new ConcurrentHashMap<String,String>();
+ final Map<String,String> results = new ConcurrentHashMap<>();
Collection<Queue<Boolean>> concurrentQueues() {
- List<Queue<Boolean>> queues = new ArrayList<Queue<Boolean>>();
+ List<Queue<Boolean>> queues = new ArrayList<>();
queues.add(new ConcurrentLinkedDeque<Boolean>());
queues.add(new ConcurrentLinkedQueue<Boolean>());
queues.add(new ArrayBlockingQueue<Boolean>(count, false));
@@ -81,7 +81,7 @@
}
void prettyPrintResults() {
- List<String> classNames = new ArrayList<String>(results.keySet());
+ List<String> classNames = new ArrayList<>(results.keySet());
Collections.sort(classNames);
int maxClassNameLength = 0;
int maxNanosLength = 0;
@@ -173,9 +173,9 @@
addersDone.countDown();
}};
- final List<Thread> adders = new ArrayList<Thread>();
- final List<Thread> removers = new ArrayList<Thread>();
- final List<Thread> pollers = new ArrayList<Thread>();
+ final List<Thread> adders = new ArrayList<>();
+ final List<Thread> removers = new ArrayList<>();
+ final List<Thread> pollers = new ArrayList<>();
for (int i = 0; i < adderCount; i++)
adders.add(checkedThread(adder));
for (int i = 0; i < removerCount; i++)
@@ -183,7 +183,7 @@
for (int i = 0; i < pollerCount; i++)
pollers.add(checkedThread(poller));
- final List<Thread> allThreads = new ArrayList<Thread>();
+ final List<Thread> allThreads = new ArrayList<>();
allThreads.addAll(removers);
allThreads.addAll(pollers);
allThreads.addAll(adders);
--- a/jdk/test/java/util/concurrent/CopyOnWriteArrayList/EqualsRace.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/CopyOnWriteArrayList/EqualsRace.java Thu Feb 09 23:15:52 2017 +0100
@@ -36,7 +36,7 @@
public class EqualsRace {
private static void realMain(String[] args) throws Throwable {
final int iterations = 100000;
- final List<Integer> list = new CopyOnWriteArrayList<Integer>();
+ final List<Integer> list = new CopyOnWriteArrayList<>();
final Integer one = Integer.valueOf(1);
final List<Integer> oneElementList = Arrays.asList(one);
final Thread t = new CheckedThread() { public void realRun() {
--- a/jdk/test/java/util/concurrent/CopyOnWriteArraySet/RacingCows.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/CopyOnWriteArraySet/RacingCows.java Thu Feb 09 23:15:52 2017 +0100
@@ -40,8 +40,8 @@
final Integer three = Integer.valueOf(3);
//------------ CopyOnWriteArraySet -------------------------------
- final Set<Integer> s1 = new CopyOnWriteArraySet<Integer>();
- final Set<Integer> s2 = new CopyOnWriteArraySet<Integer>();
+ final Set<Integer> s1 = new CopyOnWriteArraySet<>();
+ final Set<Integer> s2 = new CopyOnWriteArraySet<>();
s1.add(1);
final Thread t1 = new CheckedThread() { public void realRun() {
@@ -58,9 +58,9 @@
t1.join();
//------------ CopyOnWriteArrayList ------------------------------
- final List<Integer> l1 = new CopyOnWriteArrayList<Integer>();
- final List<Integer> l2 = new CopyOnWriteArrayList<Integer>();
- final List<Integer> l3 = new CopyOnWriteArrayList<Integer>();
+ final List<Integer> l1 = new CopyOnWriteArrayList<>();
+ final List<Integer> l2 = new CopyOnWriteArrayList<>();
+ final List<Integer> l3 = new CopyOnWriteArrayList<>();
l1.add(1);
final Thread t2 = new CheckedThread() { public void realRun() {
--- a/jdk/test/java/util/concurrent/CyclicBarrier/Basic.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/CyclicBarrier/Basic.java Thu Feb 09 23:15:52 2017 +0100
@@ -332,7 +332,7 @@
//----------------------------------------------------------------
try {
final CountDownLatch doneSignal = new CountDownLatch(1);
- final List<Waiter> waiters = new ArrayList<Waiter>(N);
+ final List<Waiter> waiters = new ArrayList<>(N);
// work around finality of closed-over variables
final Runnable[] realAction = new Runnable[1];
@@ -379,7 +379,7 @@
try {
final CountDownLatch doneSignal = new CountDownLatch(1);
final CyclicBarrier barrier = new CyclicBarrier(N+1);
- final List<Waiter> waiters = new ArrayList<Waiter>(N);
+ final List<Waiter> waiters = new ArrayList<>(N);
for (int i = 0; i < N; i++) {
Waiter waiter = new Waiter(i < N/2, doneSignal, barrier);
waiter.start();
--- a/jdk/test/java/util/concurrent/DelayQueue/Iterate.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/DelayQueue/Iterate.java Thu Feb 09 23:15:52 2017 +0100
@@ -42,7 +42,7 @@
private static void realMain(String[] args) throws Throwable {
Godot[] godots = new Godot[] { new Godot(), new Godot(), new Godot() };
- DelayQueue<Godot> q = new DelayQueue<Godot>(Arrays.asList(godots));
+ DelayQueue<Godot> q = new DelayQueue<>(Arrays.asList(godots));
Iterator<Godot> it = q.iterator();
q.clear();
check(it.hasNext());
--- a/jdk/test/java/util/concurrent/DelayQueue/PollUnexpired.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/DelayQueue/PollUnexpired.java Thu Feb 09 23:15:52 2017 +0100
@@ -39,7 +39,7 @@
}
private static void realMain(String[] args) throws Throwable {
- DelayQueue<Godot> q = new DelayQueue<Godot>();
+ DelayQueue<Godot> q = new DelayQueue<>();
for (int i = 0; i < 3; i++) {
equal(q.size(), i);
equal(q.poll(), null);
--- a/jdk/test/java/util/concurrent/DelayQueue/Stress.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/DelayQueue/Stress.java Thu Feb 09 23:15:52 2017 +0100
@@ -38,7 +38,7 @@
public static void main(String[] args) throws Throwable {
- final DelayQueue<Delayed> q = new DelayQueue<Delayed>();
+ final DelayQueue<Delayed> q = new DelayQueue<>();
final long t0 = System.nanoTime();
for (long i = 0; i < 1000; i++) {
final long expiry = t0 + i*10L*1000L*1000L;
--- a/jdk/test/java/util/concurrent/Exchanger/ExchangeLoops.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/Exchanger/ExchangeLoops.java Thu Feb 09 23:15:52 2017 +0100
@@ -116,8 +116,8 @@
barrier.await();
}
- catch (Exception ie) {
- ie.printStackTrace();
+ catch (Exception ex) {
+ ex.printStackTrace();
return;
}
}
@@ -127,7 +127,7 @@
LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer();
CyclicBarrier barrier = new CyclicBarrier(nthreads + 1, timer);
Exchanger<Int> l = null;
- Exchanger<Int> r = new Exchanger<Int>();
+ Exchanger<Int> r = new Exchanger<>();
for (int i = 0; i < nthreads; ++i) {
pool.execute(new Stage(l, r, barrier, iters));
l = r;
--- a/jdk/test/java/util/concurrent/Executors/PrivilegedCallables.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/Executors/PrivilegedCallables.java Thu Feb 09 23:15:52 2017 +0100
@@ -45,7 +45,7 @@
public class PrivilegedCallables {
Callable<Integer> real;
- final Callable<Integer> realCaller = new Callable<Integer>() {
+ final Callable<Integer> realCaller = new Callable<>() {
public Integer call() throws Exception {
return real.call(); }};
@@ -132,7 +132,7 @@
for (int i = 0; i < 20; i++)
if (rnd.nextBoolean()) {
final Throwable t = randomThrowable();
- real = new Callable<Integer>() {
+ real = new Callable<>() {
public Integer call() throws Exception {
throwThrowable(t);
return null; }};
@@ -142,7 +142,7 @@
} catch (Throwable tt) { check(t == tt); }
} else {
final int n = rnd.nextInt();
- real = new Callable<Integer>() {
+ real = new Callable<>() {
public Integer call() { return n; }};
equal(c.call(), n);
}
--- a/jdk/test/java/util/concurrent/FutureTask/BlockingTaskExecutor.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/FutureTask/BlockingTaskExecutor.java Thu Feb 09 23:15:52 2017 +0100
@@ -55,8 +55,7 @@
final NotificationReceiver notifiee1 = new NotificationReceiver();
final NotificationReceiver notifiee2 = new NotificationReceiver();
- final Collection<Callable<Object>> tasks =
- new ArrayList<Callable<Object>>();
+ final Collection<Callable<Object>> tasks = new ArrayList<>();
tasks.add(new BlockingTask(notifiee1));
tasks.add(new BlockingTask(notifiee2));
tasks.add(new NonBlockingTask());
--- a/jdk/test/java/util/concurrent/FutureTask/Customized.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/FutureTask/Customized.java Thu Feb 09 23:15:52 2017 +0100
@@ -119,7 +119,7 @@
public void run() { throw new Error(); }};
try {
- final MyFutureTask<Long> task = new MyFutureTask<Long>(nop, 42L);
+ final MyFutureTask<Long> task = new MyFutureTask<>(nop, 42L);
checkReady(task);
equalCounts(0,0,0);
check(task.runAndReset());
@@ -136,7 +136,7 @@
} catch (Throwable t) { unexpected(t); }
try {
- final MyFutureTask<Long> task = new MyFutureTask<Long>(nop, 42L);
+ final MyFutureTask<Long> task = new MyFutureTask<>(nop, 42L);
cancel(task, false);
equalCounts(2,1,0);
cancel(task, false);
@@ -147,7 +147,7 @@
} catch (Throwable t) { unexpected(t); }
try {
- final MyFutureTask<Long> task = new MyFutureTask<Long>(bad, 42L);
+ final MyFutureTask<Long> task = new MyFutureTask<>(bad, 42L);
checkReady(task);
run(task);
checkThrew(task);
@@ -157,7 +157,7 @@
} catch (Throwable t) { unexpected(t); }
try {
- final MyFutureTask<Long> task = new MyFutureTask<Long>(nop, 42L);
+ final MyFutureTask<Long> task = new MyFutureTask<>(nop, 42L);
checkReady(task);
task.set(99L);
checkDone(task);
@@ -170,7 +170,7 @@
} catch (Throwable t) { unexpected(t); }
try {
- final MyFutureTask<Long> task = new MyFutureTask<Long>(nop, 42L);
+ final MyFutureTask<Long> task = new MyFutureTask<>(nop, 42L);
checkReady(task);
task.setException(new Throwable());
checkThrew(task);
--- a/jdk/test/java/util/concurrent/FutureTask/DoneMeansDone.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/FutureTask/DoneMeansDone.java Thu Feb 09 23:15:52 2017 +0100
@@ -63,7 +63,7 @@
final AtomicBoolean done = new AtomicBoolean(false);
final AtomicReference<FutureTask<Boolean>> a = new AtomicReference<>();
final CountDownLatch threadsStarted = new CountDownLatch(nThreads);
- final Callable<Boolean> alwaysTrue = new Callable<Boolean>() {
+ final Callable<Boolean> alwaysTrue = new Callable<>() {
public Boolean call() {
return true;
}};
--- a/jdk/test/java/util/concurrent/FutureTask/DoneTimedGetLoops.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/FutureTask/DoneTimedGetLoops.java Thu Feb 09 23:15:52 2017 +0100
@@ -66,9 +66,9 @@
final long timeoutMillis = 10L * 1000L;
final AtomicReference<PublicFutureTask> normalRef
- = new AtomicReference<PublicFutureTask>();
+ = new AtomicReference<>();
final AtomicReference<PublicFutureTask> abnormalRef
- = new AtomicReference<PublicFutureTask>();
+ = new AtomicReference<>();
final Throwable throwable = new Throwable();
--- a/jdk/test/java/util/concurrent/LinkedBlockingQueue/ToArray.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/LinkedBlockingQueue/ToArray.java Thu Feb 09 23:15:52 2017 +0100
@@ -33,7 +33,7 @@
public class ToArray {
public static void main(String[] args) throws Throwable {
- Collection<Integer> c = new LinkedBlockingQueue<Integer>();
+ Collection<Integer> c = new LinkedBlockingQueue<>();
if (c.toArray(new Integer[]{42})[0] != null)
throw new Error("should be null");
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/LinkedTransferQueue/WhiteBox.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,408 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Martin Buchholz with assistance from members of JCP
+ * JSR-166 Expert Group and released to the public domain, as
+ * explained at http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/*
+ * @test
+ * @modules java.base/java.util.concurrent:open
+ * @run testng WhiteBox
+ * @summary White box tests of implementation details
+ */
+
+import static org.testng.Assert.*;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.LinkedTransferQueue;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import static java.util.stream.Collectors.toList;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+@Test
+public class WhiteBox {
+ final ThreadLocalRandom rnd = ThreadLocalRandom.current();
+ final VarHandle HEAD, TAIL, ITEM, NEXT;
+ final int SWEEP_THRESHOLD;
+
+ public WhiteBox() throws ReflectiveOperationException {
+ Class<?> qClass = LinkedTransferQueue.class;
+ Class<?> nodeClass = Class.forName(qClass.getName() + "$Node");
+ MethodHandles.Lookup lookup
+ = MethodHandles.privateLookupIn(qClass, MethodHandles.lookup());
+ HEAD = lookup.findVarHandle(qClass, "head", nodeClass);
+ TAIL = lookup.findVarHandle(qClass, "tail", nodeClass);
+ NEXT = lookup.findVarHandle(nodeClass, "next", nodeClass);
+ ITEM = lookup.findVarHandle(nodeClass, "item", Object.class);
+ SWEEP_THRESHOLD = (int)
+ lookup.findStaticVarHandle(qClass, "SWEEP_THRESHOLD", int.class)
+ .get();
+ }
+
+ Object head(LinkedTransferQueue q) { return HEAD.getVolatile(q); }
+ Object tail(LinkedTransferQueue q) { return TAIL.getVolatile(q); }
+ Object item(Object node) { return ITEM.getVolatile(node); }
+ Object next(Object node) { return NEXT.getVolatile(node); }
+
+ int nodeCount(LinkedTransferQueue q) {
+ int i = 0;
+ for (Object p = head(q); p != null; ) {
+ i++;
+ if (p == (p = next(p))) p = head(q);
+ }
+ return i;
+ }
+
+ int tailCount(LinkedTransferQueue q) {
+ int i = 0;
+ for (Object p = tail(q); p != null; ) {
+ i++;
+ if (p == (p = next(p))) p = head(q);
+ }
+ return i;
+ }
+
+ Object findNode(LinkedTransferQueue q, Object e) {
+ for (Object p = head(q); p != null; ) {
+ if (item(p) != null && e.equals(item(p)))
+ return p;
+ if (p == (p = next(p))) p = head(q);
+ }
+ throw new AssertionError("not found");
+ }
+
+ Iterator iteratorAt(LinkedTransferQueue q, Object e) {
+ for (Iterator it = q.iterator(); it.hasNext(); )
+ if (it.next().equals(e))
+ return it;
+ throw new AssertionError("not found");
+ }
+
+ void assertIsSelfLinked(Object node) {
+ assertSame(next(node), node);
+ assertNull(item(node));
+ }
+ void assertIsNotSelfLinked(Object node) {
+ assertNotSame(node, next(node));
+ }
+
+ @Test
+ public void addRemove() {
+ LinkedTransferQueue q = new LinkedTransferQueue();
+ assertInvariants(q);
+ assertNull(next(head(q)));
+ assertNull(item(head(q)));
+ q.add(1);
+ assertEquals(nodeCount(q), 2);
+ assertInvariants(q);
+ q.remove(1);
+ assertEquals(nodeCount(q), 1);
+ assertInvariants(q);
+ }
+
+ /**
+ * Traversal actions that visit every node and do nothing, but
+ * have side effect of squeezing out dead nodes.
+ */
+ @DataProvider
+ public Object[][] traversalActions() {
+ return List.<Consumer<LinkedTransferQueue>>of(
+ q -> q.forEach(e -> {}),
+ q -> assertFalse(q.contains(new Object())),
+ q -> assertFalse(q.remove(new Object())),
+ q -> q.spliterator().forEachRemaining(e -> {}),
+ q -> q.stream().collect(toList()),
+ q -> assertFalse(q.removeIf(e -> false)),
+ q -> assertFalse(q.removeAll(List.of())))
+ .stream().map(x -> new Object[]{ x }).toArray(Object[][]::new);
+ }
+
+ @Test(dataProvider = "traversalActions")
+ public void traversalOperationsCollapseLeadingNodes(
+ Consumer<LinkedTransferQueue> traversalAction) {
+ LinkedTransferQueue q = new LinkedTransferQueue();
+ Object oldHead;
+ int n = 1 + rnd.nextInt(5);
+ for (int i = 0; i < n; i++) q.add(i);
+ assertEquals(nodeCount(q), n + 1);
+ oldHead = head(q);
+ traversalAction.accept(q);
+ assertInvariants(q);
+ assertEquals(nodeCount(q), n);
+ assertIsSelfLinked(oldHead);
+ }
+
+ @Test(dataProvider = "traversalActions")
+ public void traversalOperationsCollapseInteriorNodes(
+ Consumer<LinkedTransferQueue> traversalAction) {
+ LinkedTransferQueue q = new LinkedTransferQueue();
+ int n = 6;
+ for (int i = 0; i < n; i++) q.add(i);
+
+ // We must be quite devious to reliably create an interior dead node
+ Object p0 = findNode(q, 0);
+ Object p1 = findNode(q, 1);
+ Object p2 = findNode(q, 2);
+ Object p3 = findNode(q, 3);
+ Object p4 = findNode(q, 4);
+ Object p5 = findNode(q, 5);
+
+ Iterator it1 = iteratorAt(q, 1);
+ Iterator it2 = iteratorAt(q, 2);
+
+ it2.remove(); // causes it2's ancestor to advance to 1
+ assertSame(next(p1), p3);
+ assertSame(next(p2), p3);
+ assertNull(item(p2));
+ it1.remove(); // removes it2's ancestor
+ assertSame(next(p0), p3);
+ assertSame(next(p1), p3);
+ assertSame(next(p2), p3);
+ assertNull(item(p1));
+ assertEquals(it2.next(), 3);
+ it2.remove(); // it2's ancestor can't unlink
+
+ assertSame(next(p0), p3); // p3 is now interior dead node
+ assertSame(next(p1), p4); // it2 uselessly CASed p1.next
+ assertSame(next(p2), p3);
+ assertSame(next(p3), p4);
+ assertInvariants(q);
+
+ int c = nodeCount(q);
+ traversalAction.accept(q);
+ assertEquals(nodeCount(q), c - 1);
+
+ assertSame(next(p0), p4);
+ assertSame(next(p1), p4);
+ assertSame(next(p2), p3);
+ assertSame(next(p3), p4);
+ assertInvariants(q);
+
+ // trailing nodes are not unlinked
+ Iterator it5 = iteratorAt(q, 5); it5.remove();
+ traversalAction.accept(q);
+ assertSame(next(p4), p5);
+ assertNull(next(p5));
+ assertEquals(nodeCount(q), c - 1);
+ }
+
+ /**
+ * Checks that traversal operations collapse a random pattern of
+ * dead nodes as could normally only occur with a race.
+ */
+ @Test(dataProvider = "traversalActions")
+ public void traversalOperationsCollapseRandomNodes(
+ Consumer<LinkedTransferQueue> traversalAction) {
+ LinkedTransferQueue q = new LinkedTransferQueue();
+ int n = rnd.nextInt(6);
+ for (int i = 0; i < n; i++) q.add(i);
+ ArrayList nulledOut = new ArrayList();
+ for (Object p = head(q); p != null; p = next(p))
+ if (rnd.nextBoolean()) {
+ nulledOut.add(item(p));
+ ITEM.setVolatile(p, null);
+ }
+ traversalAction.accept(q);
+ int c = nodeCount(q);
+ assertEquals(q.size(), c - (q.contains(n - 1) ? 0 : 1));
+ for (int i = 0; i < n; i++)
+ assertTrue(nulledOut.contains(i) ^ q.contains(i));
+ }
+
+ /**
+ * Traversal actions that remove every element, and are also
+ * expected to squeeze out dead nodes.
+ */
+ @DataProvider
+ public Object[][] bulkRemovalActions() {
+ return List.<Consumer<LinkedTransferQueue>>of(
+ q -> q.clear(),
+ q -> assertTrue(q.removeIf(e -> true)),
+ q -> assertTrue(q.retainAll(List.of())))
+ .stream().map(x -> new Object[]{ x }).toArray(Object[][]::new);
+ }
+
+ @Test(dataProvider = "bulkRemovalActions")
+ public void bulkRemovalOperationsCollapseNodes(
+ Consumer<LinkedTransferQueue> bulkRemovalAction) {
+ LinkedTransferQueue q = new LinkedTransferQueue();
+ int n = 1 + rnd.nextInt(5);
+ for (int i = 0; i < n; i++) q.add(i);
+ bulkRemovalAction.accept(q);
+ assertEquals(nodeCount(q), 1);
+ assertInvariants(q);
+ }
+
+ /**
+ * Actions that remove the first element, and are expected to
+ * leave at most one slack dead node at head.
+ */
+ @DataProvider
+ public Object[][] pollActions() {
+ return List.<Consumer<LinkedTransferQueue>>of(
+ q -> assertNotNull(q.poll()),
+ q -> { try { assertNotNull(q.poll(1L, TimeUnit.DAYS)); }
+ catch (Throwable x) { throw new AssertionError(x); }},
+ q -> { try { assertNotNull(q.take()); }
+ catch (Throwable x) { throw new AssertionError(x); }},
+ q -> assertNotNull(q.remove()))
+ .stream().map(x -> new Object[]{ x }).toArray(Object[][]::new);
+ }
+
+ @Test(dataProvider = "pollActions")
+ public void pollActionsOneNodeSlack(
+ Consumer<LinkedTransferQueue> pollAction) {
+ LinkedTransferQueue q = new LinkedTransferQueue();
+ int n = 1 + rnd.nextInt(5);
+ for (int i = 0; i < n; i++) q.add(i);
+ assertEquals(nodeCount(q), n + 1);
+ for (int i = 0; i < n; i++) {
+ int c = nodeCount(q);
+ boolean slack = item(head(q)) == null;
+ if (slack) assertNotNull(item(next(head(q))));
+ pollAction.accept(q);
+ assertEquals(nodeCount(q), q.isEmpty() ? 1 : c - (slack ? 2 : 0));
+ }
+ assertInvariants(q);
+ }
+
+ /**
+ * Actions that append an element, and are expected to
+ * leave at most one slack node at tail.
+ */
+ @DataProvider
+ public Object[][] addActions() {
+ return List.<Consumer<LinkedTransferQueue>>of(
+ q -> q.add(1),
+ q -> q.offer(1))
+ .stream().map(x -> new Object[]{ x }).toArray(Object[][]::new);
+ }
+
+ @Test(dataProvider = "addActions")
+ public void addActionsOneNodeSlack(
+ Consumer<LinkedTransferQueue> addAction) {
+ LinkedTransferQueue q = new LinkedTransferQueue();
+ int n = 1 + rnd.nextInt(9);
+ for (int i = 0; i < n; i++) {
+ boolean slack = next(tail(q)) != null;
+ addAction.accept(q);
+ if (slack)
+ assertNull(next(tail(q)));
+ else {
+ assertNotNull(next(tail(q)));
+ assertNull(next(next(tail(q))));
+ }
+ assertInvariants(q);
+ }
+ }
+
+ byte[] serialBytes(Object o) {
+ try {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(bos);
+ oos.writeObject(o);
+ oos.flush();
+ oos.close();
+ return bos.toByteArray();
+ } catch (Exception fail) {
+ throw new AssertionError(fail);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ <T> T serialClone(T o) {
+ try {
+ ObjectInputStream ois = new ObjectInputStream
+ (new ByteArrayInputStream(serialBytes(o)));
+ T clone = (T) ois.readObject();
+ assertNotSame(o, clone);
+ assertSame(o.getClass(), clone.getClass());
+ return clone;
+ } catch (Exception fail) {
+ throw new AssertionError(fail);
+ }
+ }
+
+ public void testSerialization() {
+ LinkedTransferQueue q = serialClone(new LinkedTransferQueue());
+ assertInvariants(q);
+ }
+
+ public void cancelledNodeSweeping() throws Throwable {
+ assertEquals(SWEEP_THRESHOLD & (SWEEP_THRESHOLD - 1), 0);
+ LinkedTransferQueue q = new LinkedTransferQueue();
+ Thread blockHead = null;
+ if (rnd.nextBoolean()) {
+ blockHead = new Thread(
+ () -> { try { q.take(); } catch (InterruptedException ok) {}});
+ blockHead.start();
+ while (nodeCount(q) != 2) { Thread.yield(); }
+ assertTrue(q.hasWaitingConsumer());
+ assertEquals(q.getWaitingConsumerCount(), 1);
+ }
+ int initialNodeCount = nodeCount(q);
+
+ // Some dead nodes do in fact accumulate ...
+ if (blockHead != null)
+ while (nodeCount(q) < initialNodeCount + SWEEP_THRESHOLD / 2)
+ q.poll(1L, TimeUnit.MICROSECONDS);
+
+ // ... but no more than SWEEP_THRESHOLD nodes accumulate
+ for (int i = rnd.nextInt(SWEEP_THRESHOLD * 10); i-->0; )
+ q.poll(1L, TimeUnit.MICROSECONDS);
+ assertTrue(nodeCount(q) <= initialNodeCount + SWEEP_THRESHOLD);
+
+ if (blockHead != null) {
+ blockHead.interrupt();
+ blockHead.join();
+ }
+ }
+
+ /** Checks conditions which should always be true. */
+ void assertInvariants(LinkedTransferQueue q) {
+ assertNotNull(head(q));
+ assertNotNull(tail(q));
+ // head is never self-linked (but tail may!)
+ for (Object h; next(h = head(q)) == h; )
+ assertNotSame(h, head(q)); // must be update race
+ }
+}
--- a/jdk/test/java/util/concurrent/Phaser/Arrive.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/Phaser/Arrive.java Thu Feb 09 23:15:52 2017 +0100
@@ -52,7 +52,7 @@
final int n = ThreadLocalRandom.current().nextInt(1, 10);
final Phaser startingGate = new Phaser(n);
final Phaser phaser = new Phaser(n);
- final List<Thread> threads = new ArrayList<Thread>();
+ final List<Thread> threads = new ArrayList<>();
final AtomicInteger count0 = new AtomicInteger(0);
final AtomicInteger count1 = new AtomicInteger(0);
final Runnable task = new Runnable() { public void run() {
--- a/jdk/test/java/util/concurrent/Phaser/Basic.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/Phaser/Basic.java Thu Feb 09 23:15:52 2017 +0100
@@ -69,8 +69,8 @@
try {
equal(phase, phaser.awaitAdvanceInterruptibly(0));
equal(phase, phaser.awaitAdvanceInterruptibly(0, 10, SECONDS));
- } catch (Exception ie) {
- unexpected(ie);
+ } catch (Exception ex) {
+ unexpected(ex);
}
equal(phaser.getUnarrivedParties(), unarriverParties);
equal(phaser.getRegisteredParties(), registeredParties);
@@ -323,7 +323,7 @@
try {
Phaser phaser = new Phaser(1);
Iterator<Arriver> arrivers = arriverIterator(phaser);
- LinkedList<Arriver> arriverList = new LinkedList<Arriver>();
+ LinkedList<Arriver> arriverList = new LinkedList<>();
int phase = phaser.getPhase();
for (int i = 1; i < 5; i++) {
startingGate = new Phaser(1+(3*i));
--- a/jdk/test/java/util/concurrent/Phaser/FickleRegister.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/Phaser/FickleRegister.java Thu Feb 09 23:15:52 2017 +0100
@@ -93,7 +93,7 @@
};
int reps = 4;
- ArrayList<Thread> threads = new ArrayList<Thread>();
+ ArrayList<Thread> threads = new ArrayList<>();
for (int j = 0; j < reps; ++j) {
threads.add(new Thread(new Runner(subchild1)));
threads.add(new Thread(new Runner(child1)));
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java Thu Feb 09 23:15:52 2017 +0100
@@ -44,6 +44,7 @@
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
+import java.util.function.Supplier;
import jdk.testlibrary.RandomFactory;
public class ConfigChanges {
@@ -124,6 +125,22 @@
}
}
+ /**
+ * Waits for condition to become true, first spin-polling, then sleep-polling.
+ */
+ static void spinAwait(Supplier<Boolean> waitingForGodot) {
+ for (int spins = 0; !waitingForGodot.get(); ) {
+ if ((spins = (spins + 1) & 3) > 0) {
+ Thread.yield();
+ } else {
+ try { Thread.sleep(4); }
+ catch (InterruptedException unexpected) {
+ throw new AssertionError(unexpected);
+ }
+ }
+ }
+ }
+
private static void realMain(String[] args) throws Throwable {
if (rnd.nextBoolean())
System.setSecurityManager(new PermissiveSecurityManger());
@@ -210,10 +227,7 @@
pumpedUp2.await();
pumpedUp.await();
- while (tg.activeCount() != 2*n &&
- tg.activeCount() != 2*n)
- Thread.yield();
- equal(2*n, tg.activeCount());
+ spinAwait(() -> tg.activeCount() == 2*n);
equal(2*n, tpe.getMaximumPoolSize());
equal(4*n, tpe.getLargestPoolSize());
@@ -232,10 +246,7 @@
long t0 = System.nanoTime();
tpe.setKeepAliveTime(7L, MILLISECONDS);
equal(7L, tpe.getKeepAliveTime(MILLISECONDS));
- while (tg.activeCount() > n &&
- tg.activeCount() > n)
- Thread.sleep(4);
- equal(n, tg.activeCount());
+ spinAwait(() -> tg.activeCount() == n);
check(System.nanoTime() - t0 >= tpe.getKeepAliveTime(NANOSECONDS));
//report("idle", tpe);
@@ -243,10 +254,7 @@
t0 = System.nanoTime();
tpe.allowCoreThreadTimeOut(true);
check(tpe.allowsCoreThreadTimeOut());
- while (tg.activeCount() > 0 &&
- tg.activeCount() > 0)
- Thread.sleep(4);
- equal(tg.activeCount(), 0);
+ spinAwait(() -> tg.activeCount() == 0);
// The following assertion is almost always true, but may
// exceptionally not be during a transition from core count
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java Thu Feb 09 23:15:52 2017 +0100
@@ -72,8 +72,7 @@
void test(String[] args) throws Throwable {
final int threadCount = 10;
final int timeoutMillis = 30;
- BlockingQueue<Runnable> q
- = new ArrayBlockingQueue<Runnable>(2*threadCount);
+ BlockingQueue<Runnable> q = new ArrayBlockingQueue<>(2*threadCount);
ThreadPoolExecutor tpe
= new ThreadPoolExecutor(threadCount, threadCount,
timeoutMillis, TimeUnit.MILLISECONDS,
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThrowingTasks.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThrowingTasks.java Thu Feb 09 23:15:52 2017 +0100
@@ -45,6 +45,7 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.Supplier;
public class ThrowingTasks {
static final Random rnd = new Random();
@@ -139,7 +140,7 @@
public void run() { execute.run(); }
}
- static final List<Flaky> flakes = new ArrayList<Flaky>();
+ static final List<Flaky> flakes = new ArrayList<>();
static {
for (Thrower x : throwers)
for (Thrower y : throwers)
@@ -167,6 +168,22 @@
} catch (Throwable t) { unexpected(t); }
}
+ /**
+ * Waits for condition to become true, first spin-polling, then sleep-polling.
+ */
+ static void spinAwait(Supplier<Boolean> waitingForGodot) {
+ for (int spins = 0; !waitingForGodot.get(); ) {
+ if ((spins = (spins + 1) & 3) > 0) {
+ Thread.yield();
+ } else {
+ try { Thread.sleep(4); }
+ catch (InterruptedException unexpected) {
+ throw new AssertionError(unexpected);
+ }
+ }
+ }
+ }
+
static class CheckingExecutor extends ThreadPoolExecutor {
private final ReentrantLock lock = new ReentrantLock();
CheckingExecutor() {
@@ -238,10 +255,7 @@
//System.out.printf("thread count = %d%n", tg.activeCount());
uncaughtExceptionsLatch.await();
- while (tg.activeCount() != tpe.getCorePoolSize() ||
- tg.activeCount() != tpe.getCorePoolSize())
- Thread.sleep(10);
- equal(tg.activeCount(), tpe.getCorePoolSize());
+ spinAwait(() -> tg.activeCount() == tpe.getCorePoolSize());
tpe.shutdown();
@@ -250,8 +264,7 @@
//while (tg.activeCount() > 0) Thread.sleep(10);
//System.out.println(uncaughtExceptions);
- List<Map<Class<?>, Integer>> maps
- = new ArrayList<Map<Class<?>, Integer>>();
+ List<Map<Class<?>, Integer>> maps = new ArrayList<>();
maps.add(uncaughtExceptions);
maps.add(uncaughtExceptionsTable);
for (Map<Class<?>, Integer> map : maps) {
--- a/jdk/test/java/util/concurrent/atomic/Lazy.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/atomic/Lazy.java Thu Feb 09 23:15:52 2017 +0100
@@ -48,11 +48,11 @@
final AtomicBoolean b = new AtomicBoolean();
final AtomicInteger i = new AtomicInteger();
final AtomicLong l = new AtomicLong();
- final AtomicReference<Long> r = new AtomicReference<Long>();
+ final AtomicReference<Long> r = new AtomicReference<>();
final AtomicIntegerArray ia = new AtomicIntegerArray(1);
final AtomicLongArray la = new AtomicLongArray(1);
- final AtomicReferenceArray<Long> ra = new AtomicReferenceArray<Long>(1);
+ final AtomicReferenceArray<Long> ra = new AtomicReferenceArray<>(1);
final AtomicIntegerFieldUpdater<Lazy> iu =
AtomicIntegerFieldUpdater.newUpdater(Lazy.class, "ii");
--- a/jdk/test/java/util/concurrent/locks/Lock/CheckedLockLoops.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/locks/Lock/CheckedLockLoops.java Thu Feb 09 23:15:52 2017 +0100
@@ -40,11 +40,11 @@
import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import java.util.SplittableRandom;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
+import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -53,7 +53,6 @@
public final class CheckedLockLoops {
static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static ExecutorService pool;
- static final SplittableRandom rnd = new SplittableRandom();
public static void main(String[] args) throws Exception {
final int maxThreads = (args.length > 0)
@@ -73,7 +72,7 @@
static void oneTest(int nthreads, int iters) throws Exception {
System.out.println("Threads: " + nthreads);
- int v = rnd.nextInt();
+ int v = ThreadLocalRandom.current().nextInt();
System.out.print("builtin lock ");
new BuiltinLockLoop().test(v, nthreads, iters);
@@ -151,7 +150,7 @@
result += loop(iters);
barrier.await();
}
- catch (Exception ie) {
+ catch (Exception ex) {
return;
}
}
--- a/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java Thu Feb 09 23:15:52 2017 +0100
@@ -42,7 +42,6 @@
import java.io.PrintStream;
import java.io.Reader;
import java.lang.ref.WeakReference;
-import java.util.SplittableRandom;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
@@ -52,6 +51,7 @@
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
+import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.regex.Matcher;
@@ -192,7 +192,7 @@
final String childClassName = Job.class.getName();
final String classToCheckForLeaks = Job.classToCheckForLeaks();
final String uniqueID =
- String.valueOf(new SplittableRandom().nextInt(Integer.MAX_VALUE));
+ String.valueOf(ThreadLocalRandom.current().nextInt(Integer.MAX_VALUE));
final String[] jobCmd = {
java, "-Xmx8m", "-XX:+UsePerfData",
@@ -259,7 +259,7 @@
= rwlock.writeLock();
rwlock.writeLock().lock();
- final BlockingQueue<Object> q = new LinkedBlockingQueue<Object>();
+ final BlockingQueue<Object> q = new LinkedBlockingQueue<>();
final Semaphore fairSem = new Semaphore(0, true);
final Semaphore unfairSem = new Semaphore(0, false);
//final int threads =
@@ -275,7 +275,7 @@
for (int i = 0; i < threads; i++)
new Thread() { public void run() {
try {
- final SplittableRandom rnd = new SplittableRandom();
+ final ThreadLocalRandom rnd = ThreadLocalRandom.current();
for (int j = 0; j < iterations; j++) {
if (j == iterations/10 || j == iterations - 1) {
cb.await(); // Quiesce
--- a/jdk/test/java/util/concurrent/locks/ReentrantLock/CancelledLockLoops.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/locks/ReentrantLock/CancelledLockLoops.java Thu Feb 09 23:15:52 2017 +0100
@@ -40,13 +40,11 @@
import static java.util.concurrent.TimeUnit.NANOSECONDS;
-import java.util.SplittableRandom;
import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.locks.ReentrantLock;
public final class CancelledLockLoops {
- static final SplittableRandom rnd = new SplittableRandom();
-
public static void main(String[] args) throws Exception {
final int maxThreads = (args.length > 0) ? Integer.parseInt(args[0]) : 5;
final int reps = 1; // increase for stress testing
@@ -61,7 +59,7 @@
static final class Loops implements Runnable {
private final boolean print = false;
private volatile boolean done = false;
- private int v = rnd.nextInt();
+ private int v = ThreadLocalRandom.current().nextInt();
private int completed = 0;
private volatile int result = 17;
private final ReentrantLock lock = new ReentrantLock();
@@ -76,6 +74,7 @@
}
final void test() throws Exception {
+ final ThreadLocalRandom rnd = ThreadLocalRandom.current();
Thread[] threads = new Thread[nthreads];
for (int i = 0; i < threads.length; ++i)
threads[i] = new Thread(this);
--- a/jdk/test/java/util/concurrent/locks/ReentrantLock/LockOncePerThreadLoops.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/locks/ReentrantLock/LockOncePerThreadLoops.java Thu Feb 09 23:15:52 2017 +0100
@@ -40,17 +40,16 @@
import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import java.util.SplittableRandom;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.locks.ReentrantLock;
import jdk.testlibrary.Utils;
public final class LockOncePerThreadLoops {
static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static final ExecutorService pool = Executors.newCachedThreadPool();
- static final SplittableRandom rnd = new SplittableRandom();
static boolean print = false;
static int nlocks = 20_000;
static int nthreads = 20;
@@ -75,7 +74,7 @@
}
static final class ReentrantLockLoop implements Runnable {
- private int v = rnd.nextInt();
+ private int v = ThreadLocalRandom.current().nextInt();
private volatile int result = 17;
final ReentrantLock[]locks = new ReentrantLock[nlocks];
@@ -112,7 +111,7 @@
for (int i = 0; i < locks.length; ++i) {
locks[i].lock();
try {
- v = x += ~(v - i);
+ v = x += ~(v - i);
}
finally {
locks[i].unlock();
@@ -127,7 +126,7 @@
barrier.await();
result += sum;
}
- catch (Exception ie) {
+ catch (Exception ex) {
return;
}
}
--- a/jdk/test/java/util/concurrent/locks/ReentrantLock/SimpleReentrantLockLoops.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/locks/ReentrantLock/SimpleReentrantLockLoops.java Thu Feb 09 23:15:52 2017 +0100
@@ -40,17 +40,16 @@
import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import java.util.SplittableRandom;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.ThreadLocalRandom;
import jdk.testlibrary.Utils;
public final class SimpleReentrantLockLoops {
static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static final ExecutorService pool = Executors.newCachedThreadPool();
- static final SplittableRandom rnd = new SplittableRandom();
static boolean print = false;
static int iters = 100_000;
@@ -76,7 +75,7 @@
}
static final class ReentrantLockLoop implements Runnable {
- private int v = rnd.nextInt();
+ private int v = ThreadLocalRandom.current().nextInt();
private volatile int result = 17;
private final ReentrantLock lock = new ReentrantLock();
private final LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer();
@@ -132,7 +131,7 @@
barrier.await();
result += sum;
}
- catch (Exception ie) {
+ catch (Exception ex) {
return;
}
}
--- a/jdk/test/java/util/concurrent/locks/ReentrantLock/TimeoutLockLoops.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/locks/ReentrantLock/TimeoutLockLoops.java Thu Feb 09 23:15:52 2017 +0100
@@ -40,10 +40,10 @@
import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import java.util.SplittableRandom;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import jdk.testlibrary.Utils;
@@ -51,7 +51,6 @@
public final class TimeoutLockLoops {
static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000);
static final ExecutorService pool = Executors.newCachedThreadPool();
- static final SplittableRandom rnd = new SplittableRandom();
static boolean print = false;
static final long TIMEOUT = 10;
@@ -72,7 +71,7 @@
}
static final class ReentrantLockLoop implements Runnable {
- private int v = rnd.nextInt();
+ private int v = ThreadLocalRandom.current().nextInt();
private volatile int result = 17;
private final ReentrantLock lock = new ReentrantLock();
private final LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer();
@@ -91,7 +90,7 @@
lock.unlock();
}
barrier.await();
- Thread.sleep(rnd.nextInt(5));
+ Thread.sleep(ThreadLocalRandom.current().nextInt(5));
while (!lock.tryLock()); // Jam lock
// lock.lock();
barrier.await();
--- a/jdk/test/java/util/concurrent/tck/AbstractExecutorServiceTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/AbstractExecutorServiceTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -294,7 +294,7 @@
public void testInvokeAny3() throws Exception {
final ExecutorService e = new DirectExecutorService();
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<Long>> l = new ArrayList<Callable<Long>>();
+ List<Callable<Long>> l = new ArrayList<>();
l.add(new Callable<Long>() {
public Long call() { throw new ArithmeticException(); }});
l.add(null);
@@ -311,7 +311,7 @@
public void testInvokeAny4() throws InterruptedException {
final ExecutorService e = new DirectExecutorService();
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
try {
e.invokeAny(l);
@@ -328,7 +328,7 @@
public void testInvokeAny5() throws Exception {
final ExecutorService e = new DirectExecutorService();
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
String result = e.invokeAny(l);
@@ -366,7 +366,7 @@
public void testInvokeAll3() throws InterruptedException {
final ExecutorService e = new DirectExecutorService();
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(null);
try {
@@ -382,7 +382,7 @@
public void testInvokeAll4() throws Exception {
final ExecutorService e = new DirectExecutorService();
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
List<Future<String>> futures = e.invokeAll(l);
assertEquals(1, futures.size());
@@ -401,7 +401,7 @@
public void testInvokeAll5() throws Exception {
final ExecutorService e = new DirectExecutorService();
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
List<Future<String>> futures = e.invokeAll(l);
@@ -430,7 +430,7 @@
public void testTimedInvokeAnyNullTimeUnit() throws Exception {
final ExecutorService e = new DirectExecutorService();
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
try {
e.invokeAny(l, MEDIUM_DELAY_MS, null);
@@ -459,7 +459,7 @@
public void testTimedInvokeAny3() throws Exception {
final ExecutorService e = new DirectExecutorService();
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<Long>> l = new ArrayList<Callable<Long>>();
+ List<Callable<Long>> l = new ArrayList<>();
l.add(new Callable<Long>() {
public Long call() { throw new ArithmeticException(); }});
l.add(null);
@@ -477,7 +477,7 @@
final ExecutorService e = new DirectExecutorService();
try (PoolCleaner cleaner = cleaner(e)) {
long startTime = System.nanoTime();
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
try {
e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
@@ -496,7 +496,7 @@
final ExecutorService e = new DirectExecutorService();
try (PoolCleaner cleaner = cleaner(e)) {
long startTime = System.nanoTime();
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
@@ -524,7 +524,7 @@
public void testTimedInvokeAllNullTimeUnit() throws InterruptedException {
final ExecutorService e = new DirectExecutorService();
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
try {
e.invokeAll(l, MEDIUM_DELAY_MS, null);
@@ -550,7 +550,7 @@
public void testTimedInvokeAll3() throws InterruptedException {
final ExecutorService e = new DirectExecutorService();
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(null);
try {
@@ -566,7 +566,7 @@
public void testTimedInvokeAll4() throws Exception {
final ExecutorService e = new DirectExecutorService();
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
List<Future<String>> futures =
e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
@@ -586,7 +586,7 @@
public void testTimedInvokeAll5() throws Exception {
final ExecutorService e = new DirectExecutorService();
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
List<Future<String>> futures =
--- a/jdk/test/java/util/concurrent/tck/AbstractQueuedLongSynchronizerTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/AbstractQueuedLongSynchronizerTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -262,8 +262,8 @@
* default timeout duration).
*/
void assertAwaitTimesOut(ConditionObject c, AwaitMethod awaitMethod) {
- long timeoutMillis = timeoutMillis();
- long startTime;
+ final long timeoutMillis = timeoutMillis();
+ final long startTime;
try {
switch (awaitMethod) {
case awaitTimed:
@@ -282,7 +282,7 @@
case awaitUntil:
// We shouldn't assume that nanoTime and currentTimeMillis
// use the same time source, so don't use nanoTime here.
- java.util.Date delayedDate = delayedDate(timeoutMillis());
+ java.util.Date delayedDate = delayedDate(timeoutMillis);
assertFalse(c.awaitUntil(delayedDate(timeoutMillis)));
assertTrue(new java.util.Date().getTime() >= delayedDate.getTime());
break;
--- a/jdk/test/java/util/concurrent/tck/AbstractQueuedSynchronizerTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/AbstractQueuedSynchronizerTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -265,8 +265,8 @@
* default timeout duration).
*/
void assertAwaitTimesOut(ConditionObject c, AwaitMethod awaitMethod) {
- long timeoutMillis = timeoutMillis();
- long startTime;
+ final long timeoutMillis = timeoutMillis();
+ final long startTime;
try {
switch (awaitMethod) {
case awaitTimed:
@@ -285,7 +285,7 @@
case awaitUntil:
// We shouldn't assume that nanoTime and currentTimeMillis
// use the same time source, so don't use nanoTime here.
- java.util.Date delayedDate = delayedDate(timeoutMillis());
+ java.util.Date delayedDate = delayedDate(timeoutMillis);
assertFalse(c.awaitUntil(delayedDate(timeoutMillis)));
assertTrue(new java.util.Date().getTime() >= delayedDate.getTime());
break;
--- a/jdk/test/java/util/concurrent/tck/Atomic8Test.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/Atomic8Test.java Thu Feb 09 23:15:52 2017 +0100
@@ -316,7 +316,7 @@
* result of supplied function
*/
public void testReferenceArrayGetAndUpdate() {
- AtomicReferenceArray<Integer> a = new AtomicReferenceArray<Integer>(1);
+ AtomicReferenceArray<Integer> a = new AtomicReferenceArray<>(1);
a.set(0, one);
assertEquals((Integer) 1, a.getAndUpdate(0, Atomic8Test::addInteger17));
assertEquals((Integer) 18, a.getAndUpdate(0, Atomic8Test::addInteger17));
@@ -328,7 +328,7 @@
* returns result.
*/
public void testReferenceArrayUpdateAndGet() {
- AtomicReferenceArray<Integer> a = new AtomicReferenceArray<Integer>(1);
+ AtomicReferenceArray<Integer> a = new AtomicReferenceArray<>(1);
a.set(0, one);
assertEquals((Integer) 18, a.updateAndGet(0, Atomic8Test::addInteger17));
assertEquals((Integer) 35, a.updateAndGet(0, Atomic8Test::addInteger17));
@@ -339,7 +339,7 @@
* with supplied function.
*/
public void testReferenceArrayGetAndAccumulate() {
- AtomicReferenceArray<Integer> a = new AtomicReferenceArray<Integer>(1);
+ AtomicReferenceArray<Integer> a = new AtomicReferenceArray<>(1);
a.set(0, one);
assertEquals((Integer) 1, a.getAndAccumulate(0, 2, Atomic8Test::sumInteger));
assertEquals((Integer) 3, a.getAndAccumulate(0, 3, Atomic8Test::sumInteger));
@@ -351,7 +351,7 @@
* returns result.
*/
public void testReferenceArrayAccumulateAndGet() {
- AtomicReferenceArray<Integer> a = new AtomicReferenceArray<Integer>(1);
+ AtomicReferenceArray<Integer> a = new AtomicReferenceArray<>(1);
a.set(0, one);
assertEquals((Integer) 7, a.accumulateAndGet(0, 6, Atomic8Test::sumInteger));
assertEquals((Integer) 10, a.accumulateAndGet(0, 3, Atomic8Test::sumInteger));
--- a/jdk/test/java/util/concurrent/tck/AtomicReferenceArrayTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/AtomicReferenceArrayTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -51,7 +51,7 @@
* constructor creates array of given size with all elements null
*/
public void testConstructor() {
- AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<Integer>(SIZE);
+ AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
for (int i = 0; i < SIZE; i++) {
assertNull(aa.get(i));
}
@@ -73,7 +73,7 @@
*/
public void testConstructor2() {
Integer[] a = { two, one, three, four, seven };
- AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<Integer>(a);
+ AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(a);
assertEquals(a.length, aa.length());
for (int i = 0; i < a.length; i++)
assertEquals(a[i], aa.get(i));
@@ -98,7 +98,7 @@
* get and set for out of bound indices throw IndexOutOfBoundsException
*/
public void testIndexing() {
- AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<Integer>(SIZE);
+ AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
for (int index : new int[] { -1, SIZE }) {
try {
aa.get(index);
@@ -240,7 +240,7 @@
*/
public void testToString() {
Integer[] a = { two, one, three, four, seven };
- AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<Integer>(a);
+ AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(a);
assertEquals(Arrays.toString(a), aa.toString());
}
--- a/jdk/test/java/util/concurrent/tck/Collection8Test.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/Collection8Test.java Thu Feb 09 23:15:52 2017 +0100
@@ -754,6 +754,31 @@
}
/**
+ * Concurrent Spliterators, once exhausted, stay exhausted.
+ */
+ public void testStickySpliteratorExhaustion() throws Throwable {
+ if (!impl.isConcurrent()) return;
+ if (!testImplementationDetails) return;
+ final ThreadLocalRandom rnd = ThreadLocalRandom.current();
+ final Consumer alwaysThrows = e -> { throw new AssertionError(); };
+ final Collection c = impl.emptyCollection();
+ final Spliterator s = c.spliterator();
+ if (rnd.nextBoolean()) {
+ assertFalse(s.tryAdvance(alwaysThrows));
+ } else {
+ s.forEachRemaining(alwaysThrows);
+ }
+ final Object one = impl.makeElement(1);
+ // Spliterator should not notice added element
+ c.add(one);
+ if (rnd.nextBoolean()) {
+ assertFalse(s.tryAdvance(alwaysThrows));
+ } else {
+ s.forEachRemaining(alwaysThrows);
+ }
+ }
+
+ /**
* Motley crew of threads concurrently randomly hammer the collection.
*/
public void testDetectRaces() throws Throwable {
--- a/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -120,10 +120,10 @@
* Returns the "raw" internal exceptional completion of f,
* without any additional wrapping with CompletionException.
*/
- <U> Throwable exceptionalCompletion(CompletableFuture<U> f) {
- // handle (and whenComplete) can distinguish between "direct"
- // and "wrapped" exceptional completion
- return f.handle((U u, Throwable t) -> t).join();
+ Throwable exceptionalCompletion(CompletableFuture<?> f) {
+ // handle (and whenComplete and exceptionally) can distinguish
+ // between "direct" and "wrapped" exceptional completion
+ return f.handle((u, t) -> t).join();
}
void checkCompletedExceptionally(CompletableFuture<?> f,
@@ -3559,7 +3559,7 @@
*/
public void testCompletedStage() {
AtomicInteger x = new AtomicInteger(0);
- AtomicReference<Throwable> r = new AtomicReference<Throwable>();
+ AtomicReference<Throwable> r = new AtomicReference<>();
CompletionStage<Integer> f = CompletableFuture.completedStage(1);
f.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
assertEquals(x.get(), 1);
@@ -3661,7 +3661,7 @@
CompletableFuture<Integer> f = new CompletableFuture<>();
CompletionStage<Integer> g = f.minimalCompletionStage();
AtomicInteger x = new AtomicInteger(0);
- AtomicReference<Throwable> r = new AtomicReference<Throwable>();
+ AtomicReference<Throwable> r = new AtomicReference<>();
checkIncomplete(f);
g.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
f.complete(1);
@@ -3678,7 +3678,7 @@
CompletableFuture<Integer> f = new CompletableFuture<>();
CompletionStage<Integer> g = f.minimalCompletionStage();
AtomicInteger x = new AtomicInteger(0);
- AtomicReference<Throwable> r = new AtomicReference<Throwable>();
+ AtomicReference<Throwable> r = new AtomicReference<>();
g.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
checkIncomplete(f);
CFException ex = new CFException();
@@ -3696,7 +3696,7 @@
CFException ex = new CFException();
CompletionStage<Integer> f = CompletableFuture.failedStage(ex);
AtomicInteger x = new AtomicInteger(0);
- AtomicReference<Throwable> r = new AtomicReference<Throwable>();
+ AtomicReference<Throwable> r = new AtomicReference<>();
f.whenComplete((v, e) -> {if (e != null) r.set(e); else x.set(v);});
assertEquals(x.get(), 0);
assertEquals(r.get(), ex);
--- a/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/ConcurrentHashMapTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -61,7 +61,7 @@
* Returns a new map from Integers 1-5 to Strings "A"-"E".
*/
private static ConcurrentHashMap<Integer, String> map5() {
- ConcurrentHashMap map = new ConcurrentHashMap<Integer, String>(5);
+ ConcurrentHashMap<Integer, String> map = new ConcurrentHashMap<>(5);
assertTrue(map.isEmpty());
map.put(one, "A");
map.put(two, "B");
--- a/jdk/test/java/util/concurrent/tck/ConcurrentLinkedDequeTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/ConcurrentLinkedDequeTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -68,7 +68,7 @@
* Integers 0 ... n - 1.
*/
private ConcurrentLinkedDeque<Integer> populatedDeque(int n) {
- ConcurrentLinkedDeque<Integer> q = new ConcurrentLinkedDeque<Integer>();
+ ConcurrentLinkedDeque<Integer> q = new ConcurrentLinkedDeque<>();
assertTrue(q.isEmpty());
for (int i = 0; i < n; ++i)
assertTrue(q.offer(new Integer(i)));
--- a/jdk/test/java/util/concurrent/tck/ConcurrentLinkedQueueTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/ConcurrentLinkedQueueTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -66,7 +66,7 @@
* Integers 0 ... n - 1.
*/
private ConcurrentLinkedQueue<Integer> populatedQueue(int n) {
- ConcurrentLinkedQueue<Integer> q = new ConcurrentLinkedQueue<Integer>();
+ ConcurrentLinkedQueue<Integer> q = new ConcurrentLinkedQueue<>();
assertTrue(q.isEmpty());
for (int i = 0; i < n; ++i)
assertTrue(q.offer(new Integer(i)));
--- a/jdk/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/CopyOnWriteArrayListTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -54,7 +54,7 @@
public static Test suite() {
class Implementation implements CollectionImplementation {
- public Class<?> klazz() { return ArrayList.class; }
+ public Class<?> klazz() { return CopyOnWriteArrayList.class; }
public List emptyCollection() { return new CopyOnWriteArrayList(); }
public Object makeElement(int i) { return i; }
public boolean isConcurrent() { return true; }
@@ -72,7 +72,7 @@
}
static CopyOnWriteArrayList<Integer> populatedArray(int n) {
- CopyOnWriteArrayList<Integer> a = new CopyOnWriteArrayList<Integer>();
+ CopyOnWriteArrayList<Integer> a = new CopyOnWriteArrayList<>();
assertTrue(a.isEmpty());
for (int i = 0; i < n; i++)
a.add(i);
@@ -82,7 +82,7 @@
}
static CopyOnWriteArrayList<Integer> populatedArray(Integer[] elements) {
- CopyOnWriteArrayList<Integer> a = new CopyOnWriteArrayList<Integer>();
+ CopyOnWriteArrayList<Integer> a = new CopyOnWriteArrayList<>();
assertTrue(a.isEmpty());
for (int i = 0; i < elements.length; i++)
a.add(elements[i]);
--- a/jdk/test/java/util/concurrent/tck/CopyOnWriteArraySetTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/CopyOnWriteArraySetTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -53,7 +53,7 @@
}
static CopyOnWriteArraySet<Integer> populatedSet(int n) {
- CopyOnWriteArraySet<Integer> a = new CopyOnWriteArraySet<Integer>();
+ CopyOnWriteArraySet<Integer> a = new CopyOnWriteArraySet<>();
assertTrue(a.isEmpty());
for (int i = 0; i < n; i++)
a.add(i);
@@ -63,7 +63,7 @@
}
static CopyOnWriteArraySet populatedSet(Integer[] elements) {
- CopyOnWriteArraySet<Integer> a = new CopyOnWriteArraySet<Integer>();
+ CopyOnWriteArraySet<Integer> a = new CopyOnWriteArraySet<>();
assertTrue(a.isEmpty());
for (int i = 0; i < elements.length; i++)
a.add(elements[i]);
--- a/jdk/test/java/util/concurrent/tck/CountedCompleterTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/CountedCompleterTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -238,7 +238,7 @@
final AtomicInteger onCompletionN = new AtomicInteger(0);
final AtomicInteger onExceptionalCompletionN = new AtomicInteger(0);
final AtomicInteger setRawResultN = new AtomicInteger(0);
- final AtomicReference<Object> rawResult = new AtomicReference<Object>(null);
+ final AtomicReference<Object> rawResult = new AtomicReference<>(null);
int computeN() { return computeN.get(); }
int onCompletionN() { return onCompletionN.get(); }
int onExceptionalCompletionN() { return onExceptionalCompletionN.get(); }
--- a/jdk/test/java/util/concurrent/tck/DelayQueueTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/DelayQueueTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -79,20 +79,15 @@
}
/**
- * A delayed implementation for testing.
- * Most tests use Pseudodelays, where delays are all elapsed
+ * A fake Delayed implementation for testing.
+ * Most tests use PDelays, where delays are all elapsed
* (so, no blocking solely for delays) but are still ordered
*/
static class PDelay implements Delayed {
- int pseudodelay;
- PDelay(int i) { pseudodelay = i; }
- public int compareTo(PDelay other) {
- int a = this.pseudodelay;
- int b = other.pseudodelay;
- return (a < b) ? -1 : (a > b) ? 1 : 0;
- }
+ final int pseudodelay;
+ PDelay(int pseudodelay) { this.pseudodelay = pseudodelay; }
public int compareTo(Delayed y) {
- return compareTo((PDelay)y);
+ return Integer.compare(this.pseudodelay, ((PDelay)y).pseudodelay);
}
public boolean equals(Object other) {
return (other instanceof PDelay) &&
@@ -112,20 +107,13 @@
* Delayed implementation that actually delays
*/
static class NanoDelay implements Delayed {
- long trigger;
+ final long trigger;
NanoDelay(long i) {
trigger = System.nanoTime() + i;
}
- public int compareTo(NanoDelay y) {
- long i = trigger;
- long j = y.trigger;
- if (i < j) return -1;
- if (i > j) return 1;
- return 0;
- }
public int compareTo(Delayed y) {
- return compareTo((NanoDelay)y);
+ return Long.compare(trigger, ((NanoDelay)y).trigger);
}
public boolean equals(Object other) {
@@ -155,7 +143,7 @@
* PDelays 0 ... n - 1.
*/
private DelayQueue<PDelay> populatedQueue(int n) {
- DelayQueue<PDelay> q = new DelayQueue<PDelay>();
+ DelayQueue<PDelay> q = new DelayQueue<>();
assertTrue(q.isEmpty());
for (int i = n - 1; i >= 0; i -= 2)
assertTrue(q.offer(new PDelay(i)));
@@ -713,7 +701,7 @@
* Delayed actions do not occur until their delay elapses
*/
public void testDelay() throws InterruptedException {
- DelayQueue<NanoDelay> q = new DelayQueue<NanoDelay>();
+ DelayQueue<NanoDelay> q = new DelayQueue<>();
for (int i = 0; i < SIZE; ++i)
q.add(new NanoDelay(1000000L * (SIZE - i)));
--- a/jdk/test/java/util/concurrent/tck/ExecutorsTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/ExecutorsTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -308,7 +308,7 @@
delay(LONG_DELAY_MS);
}};
- List<Thread> threads = new ArrayList<Thread>();
+ List<Thread> threads = new ArrayList<>();
for (final ExecutorService executor : executors) {
threads.add(newStartedThread(new CheckedRunnable() {
public void realRun() {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/tck/ForkJoinPool9Test.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea and Martin Buchholz with assistance from
+ * members of JCP JSR-166 Expert Group and released to the public
+ * domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.concurrent.CompletableFuture;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class ForkJoinPool9Test extends JSR166TestCase {
+ public static void main(String[] args) {
+ main(suite(), args);
+ }
+
+ public static Test suite() {
+ return new TestSuite(ForkJoinPool9Test.class);
+ }
+
+ /**
+ * Check handling of common pool thread context class loader
+ */
+ public void testCommonPoolThreadContextClassLoader() throws Throwable {
+ if (!testImplementationDetails) return;
+ VarHandle CCL =
+ MethodHandles.privateLookupIn(Thread.class, MethodHandles.lookup())
+ .findVarHandle(Thread.class, "contextClassLoader", ClassLoader.class);
+ ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
+ boolean haveSecurityManager = (System.getSecurityManager() != null);
+ CompletableFuture.runAsync(
+ () -> {
+ assertSame(systemClassLoader,
+ Thread.currentThread().getContextClassLoader());
+ assertSame(systemClassLoader,
+ CCL.get(Thread.currentThread()));
+ if (haveSecurityManager)
+ assertThrows(
+ SecurityException.class,
+ () -> System.getProperty("foo"),
+ () -> Thread.currentThread().setContextClassLoader(null));
+
+ // TODO ?
+// if (haveSecurityManager
+// && Thread.currentThread().getClass().getSimpleName()
+// .equals("InnocuousForkJoinWorkerThread"))
+// assertThrows(SecurityException.class, /* ?? */);
+ }).join();
+ }
+
+}
--- a/jdk/test/java/util/concurrent/tck/ForkJoinPoolTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/ForkJoinPoolTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -658,7 +658,7 @@
public void testInvokeAny3() throws Throwable {
ExecutorService e = new ForkJoinPool(1);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(null);
try {
e.invokeAny(l);
@@ -674,7 +674,7 @@
CountDownLatch latch = new CountDownLatch(1);
ExecutorService e = new ForkJoinPool(1);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(latchAwaitingStringTask(latch));
l.add(null);
try {
@@ -691,7 +691,7 @@
public void testInvokeAny5() throws Throwable {
ExecutorService e = new ForkJoinPool(1);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
try {
e.invokeAny(l);
@@ -708,7 +708,7 @@
public void testInvokeAny6() throws Throwable {
ExecutorService e = new ForkJoinPool(1);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
String result = e.invokeAny(l);
@@ -747,7 +747,7 @@
public void testInvokeAll3() throws InterruptedException {
ExecutorService e = new ForkJoinPool(1);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(null);
try {
@@ -764,7 +764,7 @@
public void testInvokeAll4() throws Throwable {
ExecutorService e = new ForkJoinPool(1);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
List<Future<String>> futures = e.invokeAll(l);
assertEquals(1, futures.size());
@@ -783,7 +783,7 @@
public void testInvokeAll5() throws Throwable {
ExecutorService e = new ForkJoinPool(1);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
List<Future<String>> futures = e.invokeAll(l);
@@ -812,7 +812,7 @@
public void testTimedInvokeAnyNullTimeUnit() throws Throwable {
ExecutorService e = new ForkJoinPool(1);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
try {
e.invokeAny(l, MEDIUM_DELAY_MS, null);
@@ -842,7 +842,7 @@
CountDownLatch latch = new CountDownLatch(1);
ExecutorService e = new ForkJoinPool(1);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(latchAwaitingStringTask(latch));
l.add(null);
try {
@@ -860,7 +860,7 @@
ExecutorService e = new ForkJoinPool(1);
try (PoolCleaner cleaner = cleaner(e)) {
long startTime = System.nanoTime();
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
try {
e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
@@ -879,7 +879,7 @@
ExecutorService e = new ForkJoinPool(1);
try (PoolCleaner cleaner = cleaner(e)) {
long startTime = System.nanoTime();
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
@@ -907,7 +907,7 @@
public void testTimedInvokeAllNullTimeUnit() throws Throwable {
ExecutorService e = new ForkJoinPool(1);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
try {
e.invokeAll(l, MEDIUM_DELAY_MS, null);
@@ -935,7 +935,7 @@
public void testTimedInvokeAll3() throws InterruptedException {
ExecutorService e = new ForkJoinPool(1);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(null);
try {
@@ -951,7 +951,7 @@
public void testTimedInvokeAll4() throws Throwable {
ExecutorService e = new ForkJoinPool(1);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
List<Future<String>> futures
= e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
@@ -971,7 +971,7 @@
public void testTimedInvokeAll5() throws Throwable {
ForkJoinPool e = new ForkJoinPool(1);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
List<Future<String>> futures
--- a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java Thu Feb 09 23:15:52 2017 +0100
@@ -46,6 +46,7 @@
* @summary JSR-166 tck tests (whitebox tests allowed)
* @build *
* @modules java.base/java.util.concurrent:open
+ * java.base/java.lang:open
* java.management
* @run junit/othervm/timeout=1000
* -Djsr166.testImplementationDetails=true
@@ -59,6 +60,9 @@
* -Djava.util.concurrent.ForkJoinPool.common.parallelism=1
* -Djava.util.secureRandomSeed=true
* JSR166TestCase
+ * @run junit/othervm/timeout=1000/policy=tck.policy
+ * -Djsr166.testImplementationDetails=true
+ * JSR166TestCase
*/
import static java.util.concurrent.TimeUnit.MILLISECONDS;
@@ -584,6 +588,7 @@
"AtomicReference9Test",
"AtomicReferenceArray9Test",
"ExecutorCompletionService9Test",
+ "ForkJoinPool9Test",
};
addNamedTestClasses(suite, java9TestClassNames);
}
@@ -594,7 +599,7 @@
/** Returns list of junit-style test method names in given class. */
public static ArrayList<String> testMethodNames(Class<?> testClass) {
Method[] methods = testClass.getDeclaredMethods();
- ArrayList<String> names = new ArrayList<String>(methods.length);
+ ArrayList<String> names = new ArrayList<>(methods.length);
for (Method method : methods) {
if (method.getName().startsWith("test")
&& Modifier.isPublic(method.getModifiers())
@@ -700,7 +705,7 @@
* The first exception encountered if any threadAssertXXX method fails.
*/
private final AtomicReference<Throwable> threadFailure
- = new AtomicReference<Throwable>(null);
+ = new AtomicReference<>(null);
/**
* Records an exception so that it can be rethrown later in the test
@@ -1262,7 +1267,7 @@
}
public void refresh() {}
public String toString() {
- List<Permission> ps = new ArrayList<Permission>();
+ List<Permission> ps = new ArrayList<>();
for (Enumeration<Permission> e = perms.elements(); e.hasMoreElements();)
ps.add(e.nextElement());
return "AdjustablePolicy with permissions " + ps;
--- a/jdk/test/java/util/concurrent/tck/LinkedListTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/LinkedListTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -71,7 +71,7 @@
* Integers 0 ... n - 1.
*/
private LinkedList<Integer> populatedQueue(int n) {
- LinkedList<Integer> q = new LinkedList<Integer>();
+ LinkedList<Integer> q = new LinkedList<>();
assertTrue(q.isEmpty());
for (int i = 0; i < n; ++i)
assertTrue(q.offer(new Integer(i)));
--- a/jdk/test/java/util/concurrent/tck/LinkedTransferQueueTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/LinkedTransferQueueTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -209,7 +209,7 @@
* all elements successfully put are contained
*/
public void testPut() {
- LinkedTransferQueue<Integer> q = new LinkedTransferQueue<Integer>();
+ LinkedTransferQueue<Integer> q = new LinkedTransferQueue<>();
for (int i = 0; i < SIZE; ++i) {
assertEquals(i, q.size());
q.put(i);
@@ -442,7 +442,7 @@
*/
public void testContainsAll() {
LinkedTransferQueue<Integer> q = populatedQueue(SIZE);
- LinkedTransferQueue<Integer> p = new LinkedTransferQueue<Integer>();
+ LinkedTransferQueue<Integer> p = new LinkedTransferQueue<>();
for (int i = 0; i < SIZE; ++i) {
assertTrue(q.containsAll(p));
assertFalse(p.containsAll(q));
@@ -571,8 +571,7 @@
* iterator ordering is FIFO
*/
public void testIteratorOrdering() {
- final LinkedTransferQueue<Integer> q
- = new LinkedTransferQueue<Integer>();
+ final LinkedTransferQueue<Integer> q = new LinkedTransferQueue<>();
assertEquals(Integer.MAX_VALUE, q.remainingCapacity());
q.add(one);
q.add(two);
@@ -794,8 +793,7 @@
* is returned by this associated poll.
*/
public void testTransfer2() throws InterruptedException {
- final LinkedTransferQueue<Integer> q
- = new LinkedTransferQueue<Integer>();
+ final LinkedTransferQueue<Integer> q = new LinkedTransferQueue<>();
final CountDownLatch threadStarted = new CountDownLatch(1);
Thread t = newStartedThread(new CheckedRunnable() {
@@ -817,8 +815,7 @@
* transfer waits until a poll occurs, and then transfers in fifo order
*/
public void testTransfer3() throws InterruptedException {
- final LinkedTransferQueue<Integer> q
- = new LinkedTransferQueue<Integer>();
+ final LinkedTransferQueue<Integer> q = new LinkedTransferQueue<>();
Thread first = newStartedThread(new CheckedRunnable() {
public void realRun() throws InterruptedException {
@@ -874,8 +871,7 @@
* is returned by this associated take.
*/
public void testTransfer5() throws InterruptedException {
- final LinkedTransferQueue<Integer> q
- = new LinkedTransferQueue<Integer>();
+ final LinkedTransferQueue<Integer> q = new LinkedTransferQueue<>();
Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() throws InterruptedException {
@@ -1056,7 +1052,7 @@
}
private LinkedTransferQueue<Integer> populatedQueue(int n) {
- LinkedTransferQueue<Integer> q = new LinkedTransferQueue<Integer>();
+ LinkedTransferQueue<Integer> q = new LinkedTransferQueue<>();
checkEmpty(q);
for (int i = 0; i < n; i++) {
assertEquals(i, q.size());
--- a/jdk/test/java/util/concurrent/tck/PhaserTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/PhaserTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -329,7 +329,7 @@
public void testArrive2() {
final Phaser phaser = new Phaser();
assertEquals(0, phaser.register());
- List<Thread> threads = new ArrayList<Thread>();
+ List<Thread> threads = new ArrayList<>();
for (int i = 0; i < 10; i++) {
assertEquals(0, phaser.register());
threads.add(newStartedThread(new CheckedRunnable() {
@@ -647,7 +647,7 @@
public void testAwaitAdvance4() {
final Phaser phaser = new Phaser(4);
final AtomicInteger count = new AtomicInteger(0);
- List<Thread> threads = new ArrayList<Thread>();
+ List<Thread> threads = new ArrayList<>();
for (int i = 0; i < 4; i++)
threads.add(newStartedThread(new CheckedRunnable() {
public void realRun() {
@@ -671,7 +671,7 @@
assertEquals(1, phaser.awaitAdvance(phaser.arrive()));
assertEquals(1, phaser.getPhase());
assertEquals(1, phaser.register());
- List<Thread> threads = new ArrayList<Thread>();
+ List<Thread> threads = new ArrayList<>();
for (int i = 0; i < 8; i++) {
final CountDownLatch latch = new CountDownLatch(1);
final boolean goesFirst = ((i & 1) == 0);
@@ -699,13 +699,13 @@
*/
public void testAwaitAdvanceTieredPhaser() throws Exception {
final Phaser parent = new Phaser();
- final List<Phaser> zeroPartyChildren = new ArrayList<Phaser>(3);
- final List<Phaser> onePartyChildren = new ArrayList<Phaser>(3);
+ final List<Phaser> zeroPartyChildren = new ArrayList<>(3);
+ final List<Phaser> onePartyChildren = new ArrayList<>(3);
for (int i = 0; i < 3; i++) {
zeroPartyChildren.add(new Phaser(parent, 0));
onePartyChildren.add(new Phaser(parent, 1));
}
- final List<Phaser> phasers = new ArrayList<Phaser>();
+ final List<Phaser> phasers = new ArrayList<>();
phasers.addAll(zeroPartyChildren);
phasers.addAll(onePartyChildren);
phasers.add(parent);
@@ -747,7 +747,7 @@
public void testAwaitAdvance6() {
final Phaser phaser = new Phaser(3);
final CountDownLatch pleaseForceTermination = new CountDownLatch(2);
- final List<Thread> threads = new ArrayList<Thread>();
+ final List<Thread> threads = new ArrayList<>();
for (int i = 0; i < 2; i++) {
Runnable r = new CheckedRunnable() {
public void realRun() {
@@ -791,7 +791,7 @@
final Phaser phaser = new Phaser(1);
final int THREADS = 3;
final CountDownLatch pleaseArrive = new CountDownLatch(THREADS);
- final List<Thread> threads = new ArrayList<Thread>();
+ final List<Thread> threads = new ArrayList<>();
for (int i = 0; i < THREADS; i++)
threads.add(newStartedThread(new CheckedRunnable() {
public void realRun() {
--- a/jdk/test/java/util/concurrent/tck/PriorityQueueTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/PriorityQueueTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -71,7 +71,7 @@
* Integers 0 ... n - 1.
*/
private PriorityQueue<Integer> populatedQueue(int n) {
- PriorityQueue<Integer> q = new PriorityQueue<Integer>(n);
+ PriorityQueue<Integer> q = new PriorityQueue<>(n);
assertTrue(q.isEmpty());
for (int i = n - 1; i >= 0; i -= 2)
assertTrue(q.offer(new Integer(i)));
--- a/jdk/test/java/util/concurrent/tck/ReentrantLockTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/ReentrantLockTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -236,7 +236,7 @@
public void testUnlock_IMSE() { testUnlock_IMSE(false); }
public void testUnlock_IMSE_fair() { testUnlock_IMSE(true); }
public void testUnlock_IMSE(boolean fair) {
- ReentrantLock lock = new ReentrantLock(fair);
+ final ReentrantLock lock = new ReentrantLock(fair);
try {
lock.unlock();
shouldThrow();
@@ -426,11 +426,11 @@
public void testTryLock_Timeout_fair() { testTryLock_Timeout(true); }
public void testTryLock_Timeout(boolean fair) {
final PublicReentrantLock lock = new PublicReentrantLock(fair);
+ final long timeoutMillis = timeoutMillis();
lock.lock();
Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() throws InterruptedException {
long startTime = System.nanoTime();
- long timeoutMillis = 10;
assertFalse(lock.tryLock(timeoutMillis, MILLISECONDS));
assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
}});
@@ -445,7 +445,7 @@
public void testGetHoldCount() { testGetHoldCount(false); }
public void testGetHoldCount_fair() { testGetHoldCount(true); }
public void testGetHoldCount(boolean fair) {
- ReentrantLock lock = new ReentrantLock(fair);
+ final ReentrantLock lock = new ReentrantLock(fair);
for (int i = 1; i <= SIZE; i++) {
lock.lock();
assertEquals(i, lock.getHoldCount());
@@ -462,8 +462,8 @@
public void testIsLocked() { testIsLocked(false); }
public void testIsLocked_fair() { testIsLocked(true); }
public void testIsLocked(boolean fair) {
+ final ReentrantLock lock = new ReentrantLock(fair);
try {
- final ReentrantLock lock = new ReentrantLock(fair);
assertFalse(lock.isLocked());
lock.lock();
assertTrue(lock.isLocked());
@@ -550,18 +550,18 @@
public void testAwaitNanos_Timeout() { testAwaitNanos_Timeout(false); }
public void testAwaitNanos_Timeout_fair() { testAwaitNanos_Timeout(true); }
public void testAwaitNanos_Timeout(boolean fair) {
+ final ReentrantLock lock = new ReentrantLock(fair);
+ final Condition c = lock.newCondition();
+ final long timeoutMillis = timeoutMillis();
+ final long timeoutNanos = MILLISECONDS.toNanos(timeoutMillis);
+ lock.lock();
+ final long startTime = System.nanoTime();
try {
- final ReentrantLock lock = new ReentrantLock(fair);
- final Condition c = lock.newCondition();
- lock.lock();
- long startTime = System.nanoTime();
- long timeoutMillis = 10;
- long timeoutNanos = MILLISECONDS.toNanos(timeoutMillis);
long nanosRemaining = c.awaitNanos(timeoutNanos);
assertTrue(nanosRemaining <= 0);
- assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
- lock.unlock();
} catch (InterruptedException fail) { threadUnexpectedException(fail); }
+ assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
+ lock.unlock();
}
/**
@@ -570,16 +570,16 @@
public void testAwait_Timeout() { testAwait_Timeout(false); }
public void testAwait_Timeout_fair() { testAwait_Timeout(true); }
public void testAwait_Timeout(boolean fair) {
+ final ReentrantLock lock = new ReentrantLock(fair);
+ final Condition c = lock.newCondition();
+ final long timeoutMillis = timeoutMillis();
+ lock.lock();
+ final long startTime = System.nanoTime();
try {
- final ReentrantLock lock = new ReentrantLock(fair);
- final Condition c = lock.newCondition();
- lock.lock();
- long startTime = System.nanoTime();
- long timeoutMillis = 10;
assertFalse(c.await(timeoutMillis, MILLISECONDS));
- assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
- lock.unlock();
} catch (InterruptedException fail) { threadUnexpectedException(fail); }
+ assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
+ lock.unlock();
}
/**
@@ -588,17 +588,17 @@
public void testAwaitUntil_Timeout() { testAwaitUntil_Timeout(false); }
public void testAwaitUntil_Timeout_fair() { testAwaitUntil_Timeout(true); }
public void testAwaitUntil_Timeout(boolean fair) {
+ final ReentrantLock lock = new ReentrantLock(fair);
+ final Condition c = lock.newCondition();
+ lock.lock();
+ // We shouldn't assume that nanoTime and currentTimeMillis
+ // use the same time source, so don't use nanoTime here.
+ final java.util.Date delayedDate = delayedDate(timeoutMillis());
try {
- final ReentrantLock lock = new ReentrantLock(fair);
- final Condition c = lock.newCondition();
- lock.lock();
- // We shouldn't assume that nanoTime and currentTimeMillis
- // use the same time source, so don't use nanoTime here.
- java.util.Date delayedDate = delayedDate(timeoutMillis());
assertFalse(c.awaitUntil(delayedDate));
- assertTrue(new java.util.Date().getTime() >= delayedDate.getTime());
- lock.unlock();
} catch (InterruptedException fail) { threadUnexpectedException(fail); }
+ assertTrue(new java.util.Date().getTime() >= delayedDate.getTime());
+ lock.unlock();
}
/**
@@ -1127,7 +1127,7 @@
public void testSerialization() { testSerialization(false); }
public void testSerialization_fair() { testSerialization(true); }
public void testSerialization(boolean fair) {
- ReentrantLock lock = new ReentrantLock(fair);
+ final ReentrantLock lock = new ReentrantLock(fair);
lock.lock();
ReentrantLock clone = serialClone(lock);
@@ -1153,10 +1153,10 @@
public void testToString() { testToString(false); }
public void testToString_fair() { testToString(true); }
public void testToString(boolean fair) {
- ReentrantLock lock = new ReentrantLock(fair);
+ final ReentrantLock lock = new ReentrantLock(fair);
assertTrue(lock.toString().contains("Unlocked"));
lock.lock();
- assertTrue(lock.toString().contains("Locked"));
+ assertTrue(lock.toString().contains("Locked by"));
lock.unlock();
assertTrue(lock.toString().contains("Unlocked"));
}
--- a/jdk/test/java/util/concurrent/tck/ReentrantReadWriteLockTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/ReentrantReadWriteLockTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -258,7 +258,7 @@
public void testGetWriteHoldCount() { testGetWriteHoldCount(false); }
public void testGetWriteHoldCount_fair() { testGetWriteHoldCount(true); }
public void testGetWriteHoldCount(boolean fair) {
- ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair);
+ final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair);
for (int i = 1; i <= SIZE; i++) {
lock.writeLock().lock();
assertEquals(i,lock.getWriteHoldCount());
@@ -275,7 +275,7 @@
public void testGetHoldCount() { testGetHoldCount(false); }
public void testGetHoldCount_fair() { testGetHoldCount(true); }
public void testGetHoldCount(boolean fair) {
- ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair);
+ final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair);
for (int i = 1; i <= SIZE; i++) {
lock.writeLock().lock();
assertEquals(i,lock.writeLock().getHoldCount());
@@ -292,7 +292,7 @@
public void testGetReadHoldCount() { testGetReadHoldCount(false); }
public void testGetReadHoldCount_fair() { testGetReadHoldCount(true); }
public void testGetReadHoldCount(boolean fair) {
- ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair);
+ final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair);
for (int i = 1; i <= SIZE; i++) {
lock.readLock().lock();
assertEquals(i,lock.getReadHoldCount());
@@ -309,7 +309,7 @@
public void testWriteUnlock_IMSE() { testWriteUnlock_IMSE(false); }
public void testWriteUnlock_IMSE_fair() { testWriteUnlock_IMSE(true); }
public void testWriteUnlock_IMSE(boolean fair) {
- ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair);
+ final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair);
try {
lock.writeLock().unlock();
shouldThrow();
@@ -322,7 +322,7 @@
public void testReadUnlock_IMSE() { testReadUnlock_IMSE(false); }
public void testReadUnlock_IMSE_fair() { testReadUnlock_IMSE(true); }
public void testReadUnlock_IMSE(boolean fair) {
- ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair);
+ final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair);
try {
lock.readLock().unlock();
shouldThrow();
@@ -815,11 +815,11 @@
public void testWriteTryLock_Timeout(boolean fair) {
final PublicReentrantReadWriteLock lock =
new PublicReentrantReadWriteLock(fair);
+ final long timeoutMillis = timeoutMillis();
lock.writeLock().lock();
Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() throws InterruptedException {
long startTime = System.nanoTime();
- long timeoutMillis = 10;
assertFalse(lock.writeLock().tryLock(timeoutMillis, MILLISECONDS));
assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
}});
@@ -839,7 +839,7 @@
Thread t = newStartedThread(new CheckedRunnable() {
public void realRun() throws InterruptedException {
long startTime = System.nanoTime();
- long timeoutMillis = 10;
+ long timeoutMillis = timeoutMillis();
assertFalse(lock.readLock().tryLock(timeoutMillis, MILLISECONDS));
assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
}});
@@ -951,19 +951,18 @@
public void testAwaitNanos_Timeout() { testAwaitNanos_Timeout(false); }
public void testAwaitNanos_Timeout_fair() { testAwaitNanos_Timeout(true); }
public void testAwaitNanos_Timeout(boolean fair) {
+ final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair);
+ final Condition c = lock.writeLock().newCondition();
+ final long timeoutMillis = timeoutMillis();
+ lock.writeLock().lock();
+ final long startTime = System.nanoTime();
+ final long timeoutNanos = MILLISECONDS.toNanos(timeoutMillis);
try {
- final ReentrantReadWriteLock lock =
- new ReentrantReadWriteLock(fair);
- final Condition c = lock.writeLock().newCondition();
- lock.writeLock().lock();
- long startTime = System.nanoTime();
- long timeoutMillis = 10;
- long timeoutNanos = MILLISECONDS.toNanos(timeoutMillis);
long nanosRemaining = c.awaitNanos(timeoutNanos);
assertTrue(nanosRemaining <= 0);
- assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
- lock.writeLock().unlock();
} catch (InterruptedException fail) { threadUnexpectedException(fail); }
+ assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
+ lock.writeLock().unlock();
}
/**
@@ -972,17 +971,16 @@
public void testAwait_Timeout() { testAwait_Timeout(false); }
public void testAwait_Timeout_fair() { testAwait_Timeout(true); }
public void testAwait_Timeout(boolean fair) {
+ final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair);
+ final Condition c = lock.writeLock().newCondition();
+ final long timeoutMillis = timeoutMillis();
+ lock.writeLock().lock();
+ final long startTime = System.nanoTime();
try {
- final ReentrantReadWriteLock lock =
- new ReentrantReadWriteLock(fair);
- final Condition c = lock.writeLock().newCondition();
- lock.writeLock().lock();
- long startTime = System.nanoTime();
- long timeoutMillis = 10;
assertFalse(c.await(timeoutMillis, MILLISECONDS));
- assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
- lock.writeLock().unlock();
} catch (InterruptedException fail) { threadUnexpectedException(fail); }
+ assertTrue(millisElapsedSince(startTime) >= timeoutMillis);
+ lock.writeLock().unlock();
}
/**
@@ -991,18 +989,17 @@
public void testAwaitUntil_Timeout() { testAwaitUntil_Timeout(false); }
public void testAwaitUntil_Timeout_fair() { testAwaitUntil_Timeout(true); }
public void testAwaitUntil_Timeout(boolean fair) {
+ final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair);
+ final Condition c = lock.writeLock().newCondition();
+ lock.writeLock().lock();
+ // We shouldn't assume that nanoTime and currentTimeMillis
+ // use the same time source, so don't use nanoTime here.
+ final java.util.Date delayedDate = delayedDate(timeoutMillis());
try {
- final ReentrantReadWriteLock lock =
- new ReentrantReadWriteLock(fair);
- final Condition c = lock.writeLock().newCondition();
- lock.writeLock().lock();
- // We shouldn't assume that nanoTime and currentTimeMillis
- // use the same time source, so don't use nanoTime here.
- java.util.Date delayedDate = delayedDate(timeoutMillis());
assertFalse(c.awaitUntil(delayedDate));
- assertTrue(new java.util.Date().getTime() >= delayedDate.getTime());
- lock.writeLock().unlock();
} catch (InterruptedException fail) { threadUnexpectedException(fail); }
+ assertTrue(new java.util.Date().getTime() >= delayedDate.getTime());
+ lock.writeLock().unlock();
}
/**
@@ -1258,7 +1255,7 @@
public void testSerialization() { testSerialization(false); }
public void testSerialization_fair() { testSerialization(true); }
public void testSerialization(boolean fair) {
- ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair);
+ final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair);
lock.writeLock().lock();
lock.readLock().lock();
@@ -1660,14 +1657,20 @@
public void testToString() { testToString(false); }
public void testToString_fair() { testToString(true); }
public void testToString(boolean fair) {
- ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair);
+ final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair);
assertTrue(lock.toString().contains("Write locks = 0"));
assertTrue(lock.toString().contains("Read locks = 0"));
lock.writeLock().lock();
assertTrue(lock.toString().contains("Write locks = 1"));
assertTrue(lock.toString().contains("Read locks = 0"));
+ lock.writeLock().lock();
+ assertTrue(lock.toString().contains("Write locks = 2"));
+ assertTrue(lock.toString().contains("Read locks = 0"));
+ lock.writeLock().unlock();
lock.writeLock().unlock();
lock.readLock().lock();
+ assertTrue(lock.toString().contains("Write locks = 0"));
+ assertTrue(lock.toString().contains("Read locks = 1"));
lock.readLock().lock();
assertTrue(lock.toString().contains("Write locks = 0"));
assertTrue(lock.toString().contains("Read locks = 2"));
@@ -1679,11 +1682,16 @@
public void testReadLockToString() { testReadLockToString(false); }
public void testReadLockToString_fair() { testReadLockToString(true); }
public void testReadLockToString(boolean fair) {
- ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair);
+ final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair);
assertTrue(lock.readLock().toString().contains("Read locks = 0"));
lock.readLock().lock();
+ assertTrue(lock.readLock().toString().contains("Read locks = 1"));
lock.readLock().lock();
assertTrue(lock.readLock().toString().contains("Read locks = 2"));
+ lock.readLock().unlock();
+ assertTrue(lock.readLock().toString().contains("Read locks = 1"));
+ lock.readLock().unlock();
+ assertTrue(lock.readLock().toString().contains("Read locks = 0"));
}
/**
@@ -1692,10 +1700,10 @@
public void testWriteLockToString() { testWriteLockToString(false); }
public void testWriteLockToString_fair() { testWriteLockToString(true); }
public void testWriteLockToString(boolean fair) {
- ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair);
+ final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(fair);
assertTrue(lock.writeLock().toString().contains("Unlocked"));
lock.writeLock().lock();
- assertTrue(lock.writeLock().toString().contains("Locked"));
+ assertTrue(lock.writeLock().toString().contains("Locked by"));
lock.writeLock().unlock();
assertTrue(lock.writeLock().toString().contains("Unlocked"));
}
--- a/jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -967,7 +967,7 @@
final CountDownLatch latch = new CountDownLatch(1);
final ExecutorService e = new CustomExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(latchAwaitingStringTask(latch));
l.add(null);
try {
@@ -984,7 +984,7 @@
public void testInvokeAny4() throws Exception {
final ExecutorService e = new CustomExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
try {
e.invokeAny(l);
@@ -1001,7 +1001,7 @@
public void testInvokeAny5() throws Exception {
final ExecutorService e = new CustomExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
String result = e.invokeAny(l);
@@ -1039,7 +1039,7 @@
public void testInvokeAll3() throws Exception {
final ExecutorService e = new CustomExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(null);
try {
@@ -1055,7 +1055,7 @@
public void testInvokeAll4() throws Exception {
final ExecutorService e = new CustomExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
List<Future<String>> futures = e.invokeAll(l);
assertEquals(1, futures.size());
@@ -1074,7 +1074,7 @@
public void testInvokeAll5() throws Exception {
final ExecutorService e = new CustomExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
List<Future<String>> futures = e.invokeAll(l);
@@ -1103,7 +1103,7 @@
public void testTimedInvokeAnyNullTimeUnit() throws Exception {
final ExecutorService e = new CustomExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
try {
e.invokeAny(l, MEDIUM_DELAY_MS, null);
@@ -1132,7 +1132,7 @@
CountDownLatch latch = new CountDownLatch(1);
final ExecutorService e = new CustomExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(latchAwaitingStringTask(latch));
l.add(null);
try {
@@ -1150,7 +1150,7 @@
final ExecutorService e = new CustomExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
long startTime = System.nanoTime();
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
try {
e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
@@ -1169,7 +1169,7 @@
final ExecutorService e = new CustomExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
long startTime = System.nanoTime();
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
@@ -1197,7 +1197,7 @@
public void testTimedInvokeAllNullTimeUnit() throws Exception {
final ExecutorService e = new CustomExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
try {
e.invokeAll(l, MEDIUM_DELAY_MS, null);
@@ -1223,7 +1223,7 @@
public void testTimedInvokeAll3() throws Exception {
final ExecutorService e = new CustomExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(null);
try {
@@ -1239,7 +1239,7 @@
public void testTimedInvokeAll4() throws Exception {
final ExecutorService e = new CustomExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
List<Future<String>> futures =
e.invokeAll(l, MEDIUM_DELAY_MS, MILLISECONDS);
@@ -1259,7 +1259,7 @@
public void testTimedInvokeAll5() throws Exception {
final ExecutorService e = new CustomExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
List<Future<String>> futures =
--- a/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -915,7 +915,7 @@
CountDownLatch latch = new CountDownLatch(1);
final ExecutorService e = new ScheduledThreadPoolExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(latchAwaitingStringTask(latch));
l.add(null);
try {
@@ -932,7 +932,7 @@
public void testInvokeAny4() throws Exception {
final ExecutorService e = new ScheduledThreadPoolExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
try {
e.invokeAny(l);
@@ -949,7 +949,7 @@
public void testInvokeAny5() throws Exception {
final ExecutorService e = new ScheduledThreadPoolExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
String result = e.invokeAny(l);
@@ -987,7 +987,7 @@
public void testInvokeAll3() throws Exception {
final ExecutorService e = new ScheduledThreadPoolExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(null);
try {
@@ -1003,7 +1003,7 @@
public void testInvokeAll4() throws Exception {
final ExecutorService e = new ScheduledThreadPoolExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
List<Future<String>> futures = e.invokeAll(l);
assertEquals(1, futures.size());
@@ -1022,7 +1022,7 @@
public void testInvokeAll5() throws Exception {
final ExecutorService e = new ScheduledThreadPoolExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
List<Future<String>> futures = e.invokeAll(l);
@@ -1051,7 +1051,7 @@
public void testTimedInvokeAnyNullTimeUnit() throws Exception {
final ExecutorService e = new ScheduledThreadPoolExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
try {
e.invokeAny(l, MEDIUM_DELAY_MS, null);
@@ -1080,7 +1080,7 @@
CountDownLatch latch = new CountDownLatch(1);
final ExecutorService e = new ScheduledThreadPoolExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(latchAwaitingStringTask(latch));
l.add(null);
try {
@@ -1098,7 +1098,7 @@
final ExecutorService e = new ScheduledThreadPoolExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
long startTime = System.nanoTime();
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
try {
e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
@@ -1117,7 +1117,7 @@
final ExecutorService e = new ScheduledThreadPoolExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
long startTime = System.nanoTime();
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
@@ -1145,7 +1145,7 @@
public void testTimedInvokeAllNullTimeUnit() throws Exception {
final ExecutorService e = new ScheduledThreadPoolExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
try {
e.invokeAll(l, MEDIUM_DELAY_MS, null);
@@ -1172,7 +1172,7 @@
public void testTimedInvokeAll3() throws Exception {
final ExecutorService e = new ScheduledThreadPoolExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(null);
try {
@@ -1188,7 +1188,7 @@
public void testTimedInvokeAll4() throws Exception {
final ExecutorService e = new ScheduledThreadPoolExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
List<Future<String>> futures =
e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
@@ -1208,7 +1208,7 @@
public void testTimedInvokeAll5() throws Exception {
final ExecutorService e = new ScheduledThreadPoolExecutor(2);
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
List<Future<String>> futures =
--- a/jdk/test/java/util/concurrent/tck/SubmissionPublisherTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/SubmissionPublisherTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -173,7 +173,7 @@
* defaultExecutor
*/
public void testConstructor1() {
- SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>();
+ SubmissionPublisher<Integer> p = new SubmissionPublisher<>();
checkInitialState(p);
assertEquals(p.getMaxBufferCapacity(), Flow.defaultBufferSize());
Executor e = p.getExecutor(), c = ForkJoinPool.commonPool();
@@ -189,7 +189,7 @@
*/
public void testConstructor2() {
Executor e = Executors.newFixedThreadPool(1);
- SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(e, 8);
+ SubmissionPublisher<Integer> p = new SubmissionPublisher<>(e, 8);
checkInitialState(p);
assertSame(p.getExecutor(), e);
assertEquals(8, p.getMaxBufferCapacity());
@@ -471,9 +471,8 @@
*/
public void testThrowOnNextHandler() {
AtomicInteger calls = new AtomicInteger();
- SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>
- (basicExecutor, 8,
- (s, e) -> calls.getAndIncrement());
+ SubmissionPublisher<Integer> p = new SubmissionPublisher<>(
+ basicExecutor, 8, (s, e) -> calls.getAndIncrement());
TestSubscriber s1 = new TestSubscriber();
TestSubscriber s2 = new TestSubscriber();
p.subscribe(s1);
@@ -654,8 +653,8 @@
* submit eventually issues requested items when buffer capacity is 1
*/
public void testCap1Submit() {
- SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(
- basicExecutor, 1);
+ SubmissionPublisher<Integer> p
+ = new SubmissionPublisher<>(basicExecutor, 1);
TestSubscriber s1 = new TestSubscriber();
TestSubscriber s2 = new TestSubscriber();
p.subscribe(s1);
@@ -733,8 +732,8 @@
* offer reports drops if saturated
*/
public void testDroppedOffer() {
- SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(
- basicExecutor, 4);
+ SubmissionPublisher<Integer> p
+ = new SubmissionPublisher<>(basicExecutor, 4);
TestSubscriber s1 = new TestSubscriber();
s1.request = false;
TestSubscriber s2 = new TestSubscriber();
@@ -762,8 +761,8 @@
*/
public void testHandledDroppedOffer() {
AtomicInteger calls = new AtomicInteger();
- SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(
- basicExecutor, 4);
+ SubmissionPublisher<Integer> p
+ = new SubmissionPublisher<>(basicExecutor, 4);
TestSubscriber s1 = new TestSubscriber();
s1.request = false;
TestSubscriber s2 = new TestSubscriber();
@@ -790,8 +789,8 @@
*/
public void testRecoveredHandledDroppedOffer() {
AtomicInteger calls = new AtomicInteger();
- SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(
- basicExecutor, 4);
+ SubmissionPublisher<Integer> p
+ = new SubmissionPublisher<>(basicExecutor, 4);
TestSubscriber s1 = new TestSubscriber();
s1.request = false;
TestSubscriber s2 = new TestSubscriber();
@@ -871,8 +870,8 @@
* Timed offer reports drops if saturated
*/
public void testDroppedTimedOffer() {
- SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(
- basicExecutor, 4);
+ SubmissionPublisher<Integer> p
+ = new SubmissionPublisher<>(basicExecutor, 4);
TestSubscriber s1 = new TestSubscriber();
s1.request = false;
TestSubscriber s2 = new TestSubscriber();
@@ -903,8 +902,8 @@
*/
public void testHandledDroppedTimedOffer() {
AtomicInteger calls = new AtomicInteger();
- SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(
- basicExecutor, 4);
+ SubmissionPublisher<Integer> p
+ = new SubmissionPublisher<>(basicExecutor, 4);
TestSubscriber s1 = new TestSubscriber();
s1.request = false;
TestSubscriber s2 = new TestSubscriber();
@@ -933,8 +932,8 @@
*/
public void testRecoveredHandledDroppedTimedOffer() {
AtomicInteger calls = new AtomicInteger();
- SubmissionPublisher<Integer> p = new SubmissionPublisher<Integer>(
- basicExecutor, 4);
+ SubmissionPublisher<Integer> p
+ = new SubmissionPublisher<>(basicExecutor, 4);
TestSubscriber s1 = new TestSubscriber();
s1.request = false;
TestSubscriber s2 = new TestSubscriber();
--- a/jdk/test/java/util/concurrent/tck/SynchronousQueueTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/SynchronousQueueTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -428,8 +428,7 @@
public void testToArray2() { testToArray2(false); }
public void testToArray2_fair() { testToArray2(true); }
public void testToArray2(boolean fair) {
- final SynchronousQueue<Integer> q
- = new SynchronousQueue<Integer>(fair);
+ final SynchronousQueue<Integer> q = new SynchronousQueue<>(fair);
Integer[] a;
a = new Integer[0];
--- a/jdk/test/java/util/concurrent/tck/ThreadPoolExecutorSubclassTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/ThreadPoolExecutorSubclassTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -678,7 +678,7 @@
*/
public void testGetQueue() throws InterruptedException {
final CountDownLatch done = new CountDownLatch(1);
- final BlockingQueue<Runnable> q = new ArrayBlockingQueue<Runnable>(10);
+ final BlockingQueue<Runnable> q = new ArrayBlockingQueue<>(10);
final ThreadPoolExecutor p =
new CustomTPE(1, 1,
LONG_DELAY_MS, MILLISECONDS,
@@ -687,7 +687,7 @@
final CountDownLatch threadStarted = new CountDownLatch(1);
FutureTask[] tasks = new FutureTask[5];
for (int i = 0; i < tasks.length; i++) {
- Callable task = new CheckedCallable<Boolean>() {
+ Callable<Boolean> task = new CheckedCallable<Boolean>() {
public Boolean realCall() throws InterruptedException {
threadStarted.countDown();
assertSame(q, p.getQueue());
@@ -710,7 +710,7 @@
*/
public void testRemove() throws InterruptedException {
final CountDownLatch done = new CountDownLatch(1);
- BlockingQueue<Runnable> q = new ArrayBlockingQueue<Runnable>(10);
+ BlockingQueue<Runnable> q = new ArrayBlockingQueue<>(10);
final ThreadPoolExecutor p =
new CustomTPE(1, 1,
LONG_DELAY_MS, MILLISECONDS,
@@ -745,7 +745,7 @@
public void testPurge() throws InterruptedException {
final CountDownLatch threadStarted = new CountDownLatch(1);
final CountDownLatch done = new CountDownLatch(1);
- final BlockingQueue<Runnable> q = new ArrayBlockingQueue<Runnable>(10);
+ final BlockingQueue<Runnable> q = new ArrayBlockingQueue<>(10);
final ThreadPoolExecutor p =
new CustomTPE(1, 1,
LONG_DELAY_MS, MILLISECONDS,
@@ -753,7 +753,7 @@
try (PoolCleaner cleaner = cleaner(p, done)) {
FutureTask[] tasks = new FutureTask[5];
for (int i = 0; i < tasks.length; i++) {
- Callable task = new CheckedCallable<Boolean>() {
+ Callable<Boolean> task = new CheckedCallable<Boolean>() {
public Boolean realCall() throws InterruptedException {
threadStarted.countDown();
await(done);
@@ -1532,7 +1532,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(latchAwaitingStringTask(latch));
l.add(null);
try {
@@ -1552,7 +1552,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
try {
e.invokeAny(l);
@@ -1572,7 +1572,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
String result = e.invokeAny(l);
@@ -1619,7 +1619,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(null);
try {
@@ -1638,7 +1638,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
List<Future<String>> futures = e.invokeAll(l);
assertEquals(1, futures.size());
@@ -1660,7 +1660,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
List<Future<String>> futures = e.invokeAll(l);
@@ -1695,7 +1695,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
try {
e.invokeAny(l, MEDIUM_DELAY_MS, null);
@@ -1731,7 +1731,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(latchAwaitingStringTask(latch));
l.add(null);
try {
@@ -1752,7 +1752,7 @@
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
long startTime = System.nanoTime();
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
try {
e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
@@ -1774,7 +1774,7 @@
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
long startTime = System.nanoTime();
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
@@ -1808,7 +1808,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
try {
e.invokeAll(l, MEDIUM_DELAY_MS, null);
@@ -1841,7 +1841,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(null);
try {
@@ -1860,7 +1860,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
List<Future<String>> futures =
e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
@@ -1883,7 +1883,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
List<Future<String>> futures =
--- a/jdk/test/java/util/concurrent/tck/ThreadPoolExecutorTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/ThreadPoolExecutorTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -563,7 +563,7 @@
*/
public void testGetQueue() throws InterruptedException {
final CountDownLatch done = new CountDownLatch(1);
- final BlockingQueue<Runnable> q = new ArrayBlockingQueue<Runnable>(10);
+ final BlockingQueue<Runnable> q = new ArrayBlockingQueue<>(10);
final ThreadPoolExecutor p =
new ThreadPoolExecutor(1, 1,
LONG_DELAY_MS, MILLISECONDS,
@@ -595,7 +595,7 @@
*/
public void testRemove() throws InterruptedException {
final CountDownLatch done = new CountDownLatch(1);
- BlockingQueue<Runnable> q = new ArrayBlockingQueue<Runnable>(10);
+ BlockingQueue<Runnable> q = new ArrayBlockingQueue<>(10);
final ThreadPoolExecutor p =
new ThreadPoolExecutor(1, 1,
LONG_DELAY_MS, MILLISECONDS,
@@ -630,7 +630,7 @@
public void testPurge() throws InterruptedException {
final CountDownLatch threadStarted = new CountDownLatch(1);
final CountDownLatch done = new CountDownLatch(1);
- final BlockingQueue<Runnable> q = new ArrayBlockingQueue<Runnable>(10);
+ final BlockingQueue<Runnable> q = new ArrayBlockingQueue<>(10);
final ThreadPoolExecutor p =
new ThreadPoolExecutor(1, 1,
LONG_DELAY_MS, MILLISECONDS,
@@ -1534,7 +1534,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(latchAwaitingStringTask(latch));
l.add(null);
try {
@@ -1554,7 +1554,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
try {
e.invokeAny(l);
@@ -1574,7 +1574,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
String result = e.invokeAny(l);
@@ -1621,7 +1621,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(null);
try {
@@ -1640,7 +1640,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
List<Future<String>> futures = e.invokeAll(l);
assertEquals(1, futures.size());
@@ -1662,7 +1662,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
List<Future<String>> futures = e.invokeAll(l);
@@ -1697,7 +1697,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
try {
e.invokeAny(l, MEDIUM_DELAY_MS, null);
@@ -1733,7 +1733,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(latchAwaitingStringTask(latch));
l.add(null);
try {
@@ -1754,7 +1754,7 @@
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
long startTime = System.nanoTime();
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
try {
e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
@@ -1776,7 +1776,7 @@
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
long startTime = System.nanoTime();
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
String result = e.invokeAny(l, LONG_DELAY_MS, MILLISECONDS);
@@ -1810,7 +1810,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
try {
e.invokeAll(l, MEDIUM_DELAY_MS, null);
@@ -1843,7 +1843,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(null);
try {
@@ -1862,7 +1862,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new NPETask());
List<Future<String>> futures =
e.invokeAll(l, LONG_DELAY_MS, MILLISECONDS);
@@ -1885,7 +1885,7 @@
LONG_DELAY_MS, MILLISECONDS,
new ArrayBlockingQueue<Runnable>(10));
try (PoolCleaner cleaner = cleaner(e)) {
- List<Callable<String>> l = new ArrayList<Callable<String>>();
+ List<Callable<String>> l = new ArrayList<>();
l.add(new StringTask());
l.add(new StringTask());
List<Future<String>> futures =
--- a/jdk/test/java/util/concurrent/tck/TreeSetTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/TreeSetTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -70,7 +70,7 @@
* Integers 0 ... n - 1.
*/
private TreeSet<Integer> populatedSet(int n) {
- TreeSet<Integer> q = new TreeSet<Integer>();
+ TreeSet<Integer> q = new TreeSet<>();
assertTrue(q.isEmpty());
for (int i = n - 1; i >= 0; i -= 2)
assertTrue(q.add(new Integer(i)));
--- a/jdk/test/java/util/concurrent/tck/TreeSubSetTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/TreeSubSetTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -61,7 +61,7 @@
* Integers 0 ... n - 1.
*/
private NavigableSet<Integer> populatedSet(int n) {
- TreeSet<Integer> q = new TreeSet<Integer>();
+ TreeSet<Integer> q = new TreeSet<>();
assertTrue(q.isEmpty());
for (int i = n - 1; i >= 0; i -= 2)
--- a/jdk/test/java/util/concurrent/tck/VectorTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/java/util/concurrent/tck/VectorTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -67,12 +67,18 @@
* tests for setSize()
*/
public void testSetSize() {
- Vector v = new Vector();
+ final Vector v = new Vector();
for (int n : new int[] { 100, 5, 50 }) {
v.setSize(n);
assertEquals(n, v.size());
assertNull(v.get(0));
assertNull(v.get(n - 1));
+ assertThrows(
+ ArrayIndexOutOfBoundsException.class,
+ new Runnable() { public void run() { v.setSize(-1); }});
+ assertEquals(n, v.size());
+ assertNull(v.get(0));
+ assertNull(v.get(n - 1));
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/tck/tck.policy Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,15 @@
+grant {
+ // Permissions j.u.c. needs directly
+ permission java.lang.RuntimePermission "modifyThread";
+ permission java.lang.RuntimePermission "getClassLoader";
+ permission java.lang.RuntimePermission "setContextClassLoader";
+ permission java.util.PropertyPermission "*", "read";
+ // Permissions needed to change permissions!
+ permission java.security.SecurityPermission "getPolicy";
+ permission java.security.SecurityPermission "setPolicy";
+ permission java.security.SecurityPermission "setSecurityManager";
+ // Permissions needed by the junit test harness
+ permission java.lang.RuntimePermission "accessDeclaredMembers";
+ permission java.io.FilePermission "<<ALL FILES>>", "read";
+ permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/spi/ResourceBundleControlProvider/UserDefaultControlTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2012, 2017, 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 6959653 8172365
+ * @summary Test ResourceBundle.Control provided using SPI.
+ * @library test
+ * @build test/*
+ * @build com.foo.UserControlProvider
+ * @run main/othervm UserDefaultControlTest false
+ * @run main/othervm UserDefaultControlTest true
+ */
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.net.*;
+import java.nio.file.*;
+import java.util.*;
+
+import jdk.test.*;
+
+public class UserDefaultControlTest {
+ public static void main(String... args) throws Exception {
+ boolean smExists = Boolean.valueOf(args[0]);
+ initServices();
+ if (smExists) {
+ System.out.println("test with security manager present:");
+ System.setSecurityManager(new SecurityManager());
+ } else {
+ System.out.println("test without security manager present:");
+ }
+
+ test(smExists);
+ }
+
+ private static void initServices() throws IOException {
+ Path testClasses = Paths.get(System.getProperty("test.classes"));
+ Path services = testClasses.resolve(Paths.get("META-INF", "services"));
+ Files.createDirectories(services);
+ Files.write(services.resolve("java.util.spi.ResourceBundleControlProvider"),
+ List.of("com.foo.UserControlProvider"));
+ Path comfoo = testClasses.resolve(Paths.get("com", "foo"));
+ Path testSrcComFoo =
+ Paths.get(System.getProperty("test.src")).resolve(Paths.get("com", "foo"));
+ Files.copy(testSrcComFoo.resolve("XmlRB.xml"), comfoo.resolve("XmlRB.xml"),
+ StandardCopyOption.REPLACE_EXISTING);
+ Files.copy(testSrcComFoo.resolve("XmlRB_ja.xml"), comfoo.resolve("XmlRB_ja.xml"),
+ StandardCopyOption.REPLACE_EXISTING);
+ }
+
+ private static void test(boolean smExists) {
+ ResourceBundle rb;
+
+ try {
+ rb = ResourceBundle.getBundle("com.foo.XmlRB", Locale.ROOT);
+ if (smExists) {
+ throw new RuntimeException("getBundle did not throw " +
+ "MissingResourceException with a security manager");
+ }
+ } catch (MissingResourceException e) {
+ if (smExists) {
+ // failed successfully
+ return;
+ } else {
+ throw e;
+ }
+ }
+
+ String type = rb.getString("type");
+ if (!type.equals("XML")) {
+ throw new RuntimeException("Root Locale: type: got " + type
+ + ", expected XML (ASCII)");
+ }
+
+ rb = ResourceBundle.getBundle("com.foo.XmlRB", Locale.JAPAN);
+ type = rb.getString("type");
+ // Expect fullwidth "XML"
+ if (!type.equals("\uff38\uff2d\uff2c")) {
+ throw new RuntimeException("Locale.JAPAN: type: got " + type
+ + ", expected \uff38\uff2d\uff2c (fullwidth XML)");
+ }
+
+ try {
+ rb = ResourceBundle.getBundle("com.bar.XmlRB", Locale.JAPAN);
+ throw new RuntimeException("com.bar.XmlRB test failed.");
+ } catch (MissingResourceException e) {
+ // OK
+ }
+
+ // tests with named module. Only resource bundles on the classpath
+ // should be available, unless an unnamed module is explicitly
+ // specified.
+ rb = ResourceBundleDelegate.getBundle("simple", Locale.ROOT);
+ try {
+ rb = ResourceBundleDelegate.getBundle("com.foo.XmlRB", Locale.ROOT);
+ throw new RuntimeException("getBundle in a named module incorrectly loaded " +
+ "a resouce bundle through RBControlProvider");
+ } catch (MissingResourceException e) {
+ // OK
+ }
+
+ Module unnamedModule = UserDefaultControlTest.class
+ .getClassLoader()
+ .getUnnamedModule();
+ rb = ResourceBundleDelegate.getBundle("com.foo.XmlRB", Locale.JAPAN, unnamedModule);
+ type = rb.getString("type");
+ // Expect fullwidth "XML"
+ if (!type.equals("\uff38\uff2d\uff2c")) {
+ throw new RuntimeException("getBundle called from named module for unnamed module."
+ + " Locale.JAPAN: type: got " + type
+ + ", expected \uff38\uff2d\uff2c (fullwidth XML)");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/spi/ResourceBundleControlProvider/com/foo/UserControlProvider.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2012, 2017, 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.foo;
+
+import java.util.ResourceBundle;
+import java.util.spi.ResourceBundleControlProvider;
+
+public class UserControlProvider implements ResourceBundleControlProvider {
+ static final ResourceBundle.Control XMLCONTROL = new UserXMLControl();
+
+ public ResourceBundle.Control getControl(String baseName) {
+ System.out.println(getClass().getName()+".getControl called for " + baseName);
+
+ // Throws a NPE if baseName is null.
+ if (baseName.startsWith("com.foo.Xml")) {
+ System.out.println("\treturns " + XMLCONTROL);
+ return XMLCONTROL;
+ }
+ System.out.println("\treturns null");
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/spi/ResourceBundleControlProvider/com/foo/UserXMLControl.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2012, 2017, 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.foo;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import static java.util.ResourceBundle.Control.*;
+
+public class UserXMLControl extends ResourceBundle.Control {
+ @Override
+ public List<String> getFormats(String baseName) {
+ if (baseName == null) {
+ throw new NullPointerException();
+ }
+ return Arrays.asList("xml");
+ }
+
+ @Override
+ public ResourceBundle newBundle(String baseName, Locale locale,
+ String format,
+ ClassLoader loader,
+ boolean reload)
+ throws IllegalAccessException,
+ InstantiationException, IOException {
+ if (baseName == null || locale == null
+ || format == null || loader == null) {
+ throw new NullPointerException();
+ }
+ ResourceBundle bundle = null;
+ if (format.equals("xml")) {
+ String bundleName = toBundleName(baseName, locale);
+ String resourceName = toResourceName(bundleName, format);
+ URL url = loader.getResource(resourceName);
+ if (url != null) {
+ URLConnection connection = url.openConnection();
+ if (connection != null) {
+ if (reload) {
+ // disable caches if reloading
+ connection.setUseCaches(false);
+ }
+ try (InputStream stream = connection.getInputStream()) {
+ if (stream != null) {
+ BufferedInputStream bis = new BufferedInputStream(stream);
+ bundle = new XMLResourceBundle(bis);
+ }
+ }
+ }
+ }
+ }
+ return bundle;
+ }
+
+ private static class XMLResourceBundle extends ResourceBundle {
+ private Properties props;
+
+ XMLResourceBundle(InputStream stream) throws IOException {
+ props = new Properties();
+ props.loadFromXML(stream);
+ }
+
+ protected Object handleGetObject(String key) {
+ if (key == null) {
+ throw new NullPointerException();
+ }
+ return props.get(key);
+ }
+
+ public Enumeration<String> getKeys() {
+ // Not implemented
+ return null;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/spi/ResourceBundleControlProvider/com/foo/XmlRB.xml Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2012, 2017, 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.
+-->
+<!---->
+
+<!-- DTD for properties -->
+<!DOCTYPE properties [
+<!ELEMENT properties ( comment?, entry* ) >
+<!ATTLIST properties version CDATA #FIXED "1.0">
+<!ELEMENT comment (#PCDATA) >
+<!ELEMENT entry (#PCDATA) >
+<!ATTLIST entry key CDATA #REQUIRED>
+]>
+
+<properties>
+ <comment>Test data for UserDefaultControlTest.java</comment>
+ <entry key="type">XML</entry>
+</properties>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/spi/ResourceBundleControlProvider/com/foo/XmlRB_ja.xml Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2012, 2017, 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.
+-->
+<!---->
+
+<!-- DTD for properties -->
+<!DOCTYPE properties [
+<!ELEMENT properties ( comment?, entry* ) >
+<!ATTLIST properties version CDATA #FIXED "1.0">
+<!ELEMENT comment (#PCDATA) >
+<!ELEMENT entry (#PCDATA) >
+<!ATTLIST entry key CDATA #REQUIRED>
+]>
+
+<properties>
+ <comment>Test data for UserDefaultControlTest.java</comment>
+ <entry key="type">Xï¼ï¼¬</entry>
+</properties>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/spi/ResourceBundleControlProvider/simple.properties Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 2017, 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.
+#
+key = value
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/spi/ResourceBundleControlProvider/test/jdk/test/ResourceBundleDelegate.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 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 jdk.test;
+
+import java.lang.reflect.Module;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+public class ResourceBundleDelegate {
+ public static ResourceBundle getBundle(String baseName, Locale locale) {
+ return ResourceBundle.getBundle(baseName, locale);
+ }
+
+ public static ResourceBundle getBundle(String baseName, Locale locale, Module module) {
+ return ResourceBundle.getBundle(baseName, locale, module);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/spi/ResourceBundleControlProvider/test/module-info.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+module test {
+ exports jdk.test;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/plugins/tiff/TIFFCreateArrayForTypeTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2017, 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 8152561
+ * @summary Test verifies whether all boundary conditions are checked
+ * properly in TIFFField.createArrayForType().
+ * @run main TIFFCreateArrayForTypeTest
+ */
+
+import javax.imageio.plugins.tiff.TIFFField;
+import javax.imageio.plugins.tiff.TIFFTag;
+
+public class TIFFCreateArrayForTypeTest {
+
+ static int count = 0;
+ static boolean unknownDataType, negativeCount, zeroCount, countNotOne;
+ static String errorMsg = "";
+
+ private static void testCase1() {
+ // check passing unknown data type to createArrayForType()
+ count = 2;
+ int dataType = 15;
+ try {
+ TIFFField.createArrayForType(dataType, count);
+ } catch (IllegalArgumentException e) {
+ unknownDataType = true;
+ } catch (Exception e) {
+ // just consume if it throws any other exception.
+ }
+ if (!unknownDataType) {
+ errorMsg = errorMsg + "testCase1 ";
+ }
+ }
+
+ private static void testCase2() {
+ // check passing negative count value for createArrayForType()
+ count = -1;
+ try {
+ TIFFField.createArrayForType(TIFFTag.TIFF_LONG, count);
+ } catch (IllegalArgumentException e) {
+ negativeCount = true;
+ } catch (Exception e) {
+ // just consume if it throws any other exception.
+ }
+ if (!negativeCount) {
+ errorMsg = errorMsg + "testCase2 ";
+ }
+ }
+
+ private static void testCase3() {
+ /*
+ * check passing zero count value for createArrayForType() with
+ * TIFFTag.TIFF_RATIONAL or TIFFTag.TIFF_SRATIONAL data type.
+ */
+ count = 0;
+ try {
+ TIFFField.createArrayForType(TIFFTag.TIFF_RATIONAL, count);
+ } catch (IllegalArgumentException e) {
+ zeroCount = true;
+ } catch (Exception e) {
+ // just consume if it throws any other exception.
+ }
+ if (!zeroCount) {
+ errorMsg = errorMsg + "testCase3 ";
+ }
+ }
+
+ private static void testCase4() {
+ /*
+ * check passing count value other than 1 for createArrayForType() with
+ * TIFFTag.TIFF_IFD_POINTER data type.
+ */
+ count = 2;
+ try {
+ TIFFField.createArrayForType(TIFFTag.TIFF_IFD_POINTER, count);
+ } catch (IllegalArgumentException e) {
+ countNotOne = true;
+ } catch (Exception e) {
+ // just consume if it throws any other exception.
+ }
+ if (!countNotOne) {
+ errorMsg = errorMsg + "testCase4 ";
+ }
+ }
+
+ public static void main(String[] args) {
+ /*
+ * test different scenarios where TIFFField.createArrayForType()
+ * is required to throw IllegalArgumentException.
+ */
+ testCase1();
+ testCase2();
+ testCase3();
+ testCase4();
+ if ((!unknownDataType) ||
+ (!negativeCount) ||
+ (!zeroCount) ||
+ (!countNotOne))
+ {
+ throw new RuntimeException(errorMsg + "is/are not throwing"
+ + " required IllegalArgumentException");
+ }
+ }
+}
+
--- a/jdk/test/javax/management/MBeanInfo/NotificationInfoTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/MBeanInfo/NotificationInfoTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,7 @@
* @summary Test that JMX classes use fully-qualified class names
* in MBeanNotificationInfo
* @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
* @run clean NotificationInfoTest
* @run build NotificationInfoTest
* @run main NotificationInfoTest
--- a/jdk/test/javax/management/MBeanServer/ExceptionTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/MBeanServer/ExceptionTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 8058865
* @summary Checks that exceptions are correctly wired (compared to reference).
* @author Olivier Lagneau
- * @modules java.management
+ * @modules java.management.rmi
* @run main/othervm/timeout=300 -DDEBUG_STANDARD ExceptionTest
*/
@@ -368,5 +368,3 @@
}
}
-
-
--- a/jdk/test/javax/management/MBeanServer/OldMBeanServerTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/MBeanServer/OldMBeanServerTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -97,7 +97,7 @@
* @bug 5072268
* @summary Test that nothing assumes a post-1.2 MBeanServer
* @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
* @run main/othervm -ea OldMBeanServerTest
*/
--- a/jdk/test/javax/management/modelmbean/UnserializableTargetObjectTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/modelmbean/UnserializableTargetObjectTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,7 @@
* @summary Test that a RequiredModelMBean operation can have a targetObject
* that is not serializable
* @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
* @run clean UnserializableTargetObjectTest
* @run build UnserializableTargetObjectTest
* @run main UnserializableTargetObjectTest
--- a/jdk/test/javax/management/mxbean/GenericArrayTypeTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/mxbean/GenericArrayTypeTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,7 @@
* @summary Test support for arrays in parameterized types.
* @author Luis-Miguel Alventosa
* @key intermittent
- * @modules java.management
+ * @modules java.management.rmi
* @run clean GenericArrayTypeTest
* @run build GenericArrayTypeTest
* @run main GenericArrayTypeTest
--- a/jdk/test/javax/management/mxbean/MXBeanExceptionHandlingTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/mxbean/MXBeanExceptionHandlingTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 8058865
* @summary Checks correct exception and error events from NotificationListener
* @author Olivier Lagneau
- * @modules java.management
+ * @modules java.management.rmi
* @library /lib/testlibrary
* @compile Basic.java
* @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanExceptionHandlingTest -timeForNotificationInSeconds 3
--- a/jdk/test/javax/management/mxbean/MXBeanInteropTest1.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/mxbean/MXBeanInteropTest1.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 8058865
* @summary Test all MXBeans available by default on the platform
* @author Olivier Lagneau
- * @modules java.management
+ * @modules java.management.rmi
* @library /lib/testlibrary
* @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanInteropTest1
*/
--- a/jdk/test/javax/management/mxbean/MXBeanInteropTest2.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/mxbean/MXBeanInteropTest2.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 8058865
* @summary Checks access to test MXBean
* @author Olivier Lagneau
- * @modules java.management
+ * @modules java.management.rmi
* @library /lib/testlibrary
* @compile Basic.java
* @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanInteropTest2
--- a/jdk/test/javax/management/mxbean/MXBeanNotifTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/mxbean/MXBeanNotifTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 8058865
* @summary Checks MXBean proper registration both as its implementation class and interface
* @author Olivier Lagneau
- * @modules java.management
+ * @modules java.management.rmi
* @library /lib/testlibrary
* @compile Basic.java
* @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanNotifTest -numOfNotifications 239 -timeForNotificationInSeconds 4
--- a/jdk/test/javax/management/mxbean/MXBeanTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/mxbean/MXBeanTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,7 @@
* @summary General MXBean test.
* @author Eamonn McManus
* @author Jaroslav Bachorik
- * @modules java.management
+ * @modules java.management.rmi
* @run clean MXBeanTest MerlinMXBean TigerMXBean
* @run build MXBeanTest MerlinMXBean TigerMXBean
* @run main MXBeanTest
--- a/jdk/test/javax/management/mxbean/MXBeanWeirdParamTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/mxbean/MXBeanWeirdParamTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,7 @@
* @summary Checks that a serialized instance is not transmitted from an MXBean.
* All the communication should be done via Open Types
* @author Olivier Lagneau
- * @modules java.management
+ * @modules java.management.rmi
* @library /lib/testlibrary
* @compile Basic.java
* @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanWeirdParamTest
--- a/jdk/test/javax/management/query/SupportedQueryTypesTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/query/SupportedQueryTypesTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 8058865
* @summary Tests most of the existing query types.
* @author Olivier Lagneau
- * @modules java.management
+ * @modules java.management.rmi
* @compile TestQuery.java
* @run main/othervm/timeout=300 -DDEBUG_STANDARD SupportedQueryTypesTest -mbeanClassName TestQuery
*/
--- a/jdk/test/javax/management/remote/mandatory/connection/AddressableTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/connection/AddressableTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 6238815
* @summary test the new interface Addressable
* @author Shanliang JIANG
- * @modules java.management
+ * @modules java.management.rmi
* @run clean AddressableTest
* @run build AddressableTest
* @run main AddressableTest
--- a/jdk/test/javax/management/remote/mandatory/connection/BrokenConnectionTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/connection/BrokenConnectionTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,7 @@
* @summary Tests behaviour when connections break
* @author Eamonn McManus
* @key intermittent
- * @modules java.management
+ * @modules java.management.rmi
* @run clean BrokenConnectionTest
* @run build BrokenConnectionTest
* @run main BrokenConnectionTest
--- a/jdk/test/javax/management/remote/mandatory/connection/CloseableTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/connection/CloseableTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -28,7 +28,7 @@
* the method "void close() throws IOException;" extend
* or implement the java.io.Closeable interface.
* @author Luis-Miguel Alventosa
- * @modules java.management
+ * @modules java.management.rmi
* @run clean CloseableTest
* @run build CloseableTest
* @run main CloseableTest
--- a/jdk/test/javax/management/remote/mandatory/connection/ConnectionListenerNullTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/connection/ConnectionListenerNullTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 4943248
* @summary Tests that NullPointerException is thrown when listener is null.
* @author Daniel Fuchs
- * @modules java.management
+ * @modules java.management.rmi
* @run clean ConnectionListenerNullTest
* @run build ConnectionListenerNullTest
* @run main ConnectionListenerNullTest
--- a/jdk/test/javax/management/remote/mandatory/connection/ConnectionTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/connection/ConnectionTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 4865397
* @summary Tests remote JMX connections
* @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
* @run clean ConnectionTest
* @run build ConnectionTest
* @run main ConnectionTest
--- a/jdk/test/javax/management/remote/mandatory/connection/DaemonRMIExporterTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/connection/DaemonRMIExporterTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -28,7 +28,7 @@
* @summary test the connector server option that causes it not to prevent the
* VM from exiting
* @author Shanliang JIANG, Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
* @run main/othervm DaemonRMIExporterTest
*/
import java.util.Arrays;
--- a/jdk/test/javax/management/remote/mandatory/connection/GetConnectionTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/connection/GetConnectionTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 4951414
* @summary Try to get an IOException.
* @author Shanliang JIANG
- * @modules java.management
+ * @modules java.management.rmi
* @run clean GetConnectionTest
* @run build GetConnectionTest
* @run main GetConnectionTest
--- a/jdk/test/javax/management/remote/mandatory/connection/IIOPURLTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/connection/IIOPURLTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 4886799
* @summary Check that IIOP URLs have /ior/ in the path
* @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
* @run clean IIOPURLTest
* @run build IIOPURLTest
* @run main IIOPURLTest
--- a/jdk/test/javax/management/remote/mandatory/connection/IdleTimeoutTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/connection/IdleTimeoutTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,8 @@
* @bug 4886838 4886830 8025204
* @summary Tests that idle timeouts happen at appropriate times
* @author Eamonn McManus
- * @modules java.management/com.sun.jmx.remote.util
+ * @modules java.management.rmi
+ * java.management/com.sun.jmx.remote.util
* @run clean IdleTimeoutTest
* @run build IdleTimeoutTest
* @run main IdleTimeoutTest
--- a/jdk/test/javax/management/remote/mandatory/connection/MultiThreadDeadLockTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/connection/MultiThreadDeadLockTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -45,7 +45,7 @@
* @bug 6697180
* @summary test on a client notification deadlock.
* @author Shanliang JIANG
- * @modules java.management
+ * @modules java.management.rmi
* @run clean MultiThreadDeadLockTest
* @run build MultiThreadDeadLockTest
* @run main MultiThreadDeadLockTest
--- a/jdk/test/javax/management/remote/mandatory/connection/ObjectInputStreamWithLoaderNullCheckTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/connection/ObjectInputStreamWithLoaderNullCheckTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -29,7 +29,7 @@
* thrown when constructor is invoked with null class loader as
* an argument.
* @author Amit Sapre
- * @modules java.management/javax.management.remote.rmi:open
+ * @modules java.management.rmi/javax.management.remote.rmi:open
* @run clean ObjectInputStreamWithLoaderNullCheckTest
* @run build ObjectInputStreamWithLoaderNullCheckTest
* @run main ObjectInputStreamWithLoaderNullCheckTest
--- a/jdk/test/javax/management/remote/mandatory/connection/RMIConnectorInternalMapTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/connection/RMIConnectorInternalMapTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -42,7 +42,7 @@
* @bug 6566891
* @summary Check no memory leak on RMIConnector's rmbscMap
* @author Shanliang JIANG
- * @modules java.management/javax.management.remote.rmi:open
+ * @modules java.management.rmi/javax.management.remote.rmi:open
* @run clean RMIConnectorInternalMapTest
* @run build RMIConnectorInternalMapTest
* @run main RMIConnectorInternalMapTest
--- a/jdk/test/javax/management/remote/mandatory/connection/RMIConnectorNullSubjectConnTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/connection/RMIConnectorNullSubjectConnTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -38,7 +38,7 @@
* @bug 6566891
* @summary Check no memory leak on RMIConnector's nullSubjectConn
* @author Shanliang JIANG
- * @modules java.management/javax.management.remote.rmi:open
+ * @modules java.management.rmi/javax.management.remote.rmi:open
* @run clean RMIConnectorNullSubjectConnTest
* @run build RMIConnectorNullSubjectConnTest
* @run main RMIConnectorNullSubjectConnTest
--- a/jdk/test/javax/management/remote/mandatory/connection/RMIConnector_NPETest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/connection/RMIConnector_NPETest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @summary NPE IN RMIConnector.connect
* @bug 6984520
* @library /java/rmi/testlibrary
- * @modules java.management
+ * @modules java.management.rmi
* java.rmi/sun.rmi.registry
* java.rmi/sun.rmi.server
* java.rmi/sun.rmi.transport
@@ -75,4 +75,3 @@
}
}
-
--- a/jdk/test/javax/management/remote/mandatory/connection/RMIExitTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/connection/RMIExitTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,7 @@
* @bug 4917237
* @summary test that process exit immediately after stop() / close() called
* @author Jean Francois Denise
- * @modules java.management
+ * @modules java.management.rmi
* @run clean RMIExitTest
* @run build RMIExitTest
* @run main RMIExitTest
--- a/jdk/test/javax/management/remote/mandatory/connection/RMISerializeTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/connection/RMISerializeTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @summary Tests to serialize RMIConnector
* @bug 5032052
* @author Shanliang JIANG
- * @modules java.management
+ * @modules java.management.rmi
* @run clean RMISerializeTest
* @run build RMISerializeTest
* @run main RMISerializeTest
--- a/jdk/test/javax/management/remote/mandatory/connectorServer/ConnectorStopDeadlockTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/connectorServer/ConnectorStopDeadlockTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 6475157
* @summary Tests deadlock in simultaneous connection and connector-server close
* @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
*/
/* This test is somewhat dependent on implementation details. If it suddenly
--- a/jdk/test/javax/management/remote/mandatory/connectorServer/JNDIFailureTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/connectorServer/JNDIFailureTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,7 @@
* @summary Tests that JNDI bind failure doesn't leave an orphan RMI
* Connector Server object
* @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
* @run clean JNDIFailureTest
* @run build JNDIFailureTest
* @run main JNDIFailureTest
--- a/jdk/test/javax/management/remote/mandatory/connectorServer/MBSFPreStartPostStartTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/connectorServer/MBSFPreStartPostStartTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,7 @@
* @summary Test that setting an MBeanServerForwarder on an already
* started RMI connector server has the expected behavior.
* @author Luis-Miguel Alventosa
- * @modules java.management
+ * @modules java.management.rmi
* @run clean MBSFPreStartPostStartTest
* @run build MBSFPreStartPostStartTest
* @run main MBSFPreStartPostStartTest
--- a/jdk/test/javax/management/remote/mandatory/connectorServer/RMIExporterTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/connectorServer/RMIExporterTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 5016705
* @summary Tests the use of the RMIExporter class.
* @author Luis-Miguel Alventosa
- * @modules java.management/com.sun.jmx.remote.internal
+ * @modules java.management.rmi/com.sun.jmx.remote.internal.rmi
* @run clean RMIExporterTest
* @run build RMIExporterTest
* @run main RMIExporterTest
@@ -46,7 +46,7 @@
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
-import com.sun.jmx.remote.internal.RMIExporter;
+import com.sun.jmx.remote.internal.rmi.RMIExporter;
public class RMIExporterTest {
--- a/jdk/test/javax/management/remote/mandatory/connectorServer/SetMBeanServerForwarder.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/connectorServer/SetMBeanServerForwarder.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,8 @@
* @summary Tests that IllegalArgumentException is thrown when
* MBeanServerForwrder is null.
* @author Daniel Fuchs
- * @modules java.management/com.sun.jmx.remote.security
+ * @modules java.management.rmi
+ * java.management/com.sun.jmx.remote.security
* @run clean SetMBeanServerForwarder
* @run build SetMBeanServerForwarder
* @run main SetMBeanServerForwarder
--- a/jdk/test/javax/management/remote/mandatory/loading/DeserializeEncodedURLTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/loading/DeserializeEncodedURLTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 4924683
* @summary Check RMI/JRMP stubs can be deserialized using user's loader
* @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
* @run clean DeserializeEncodedURLTest SingleClassLoader
* @run build DeserializeEncodedURLTest SingleClassLoader
* @run main DeserializeEncodedURLTest
--- a/jdk/test/javax/management/remote/mandatory/loading/MissingClassTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/loading/MissingClassTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 4915825 4921009 4934965 4977469 8019584
* @summary Tests behavior when client or server gets object of unknown class
* @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
* @run clean MissingClassTest SingleClassLoader
* @run build MissingClassTest SingleClassLoader
* @run main MissingClassTest
--- a/jdk/test/javax/management/remote/mandatory/loading/RMIDownloadTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/loading/RMIDownloadTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 5021246
* @summary Check that class downloading is supported by RMI connector
* @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
* @run main RMIDownloadTest receive without
* @run main RMIDownloadTest send without
* @run main RMIDownloadTest receive with
--- a/jdk/test/javax/management/remote/mandatory/loading/TargetMBeanTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/loading/TargetMBeanTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 4910428
* @summary Tests target MBean class loader used before JSR 160 loader
* @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
* @run clean TargetMBeanTest
* @run build TargetMBeanTest
* @run main TargetMBeanTest
--- a/jdk/test/javax/management/remote/mandatory/notif/ConcurrentModificationTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/notif/ConcurrentModificationTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 7120365
* @summary test on Concurrent Modification
* @author Shanliang JIANG
- * @modules java.management
+ * @modules java.management.rmi
* @run main ConcurrentModificationTest
*/
--- a/jdk/test/javax/management/remote/mandatory/notif/DeadListenerTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/notif/DeadListenerTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -25,7 +25,7 @@
* @test
* @bug 6957378
* @summary Test that a listener can be removed remotely from an MBean that no longer exists.
- * @modules java.management/javax.management.remote.rmi:open
+ * @modules java.management.rmi/javax.management.remote.rmi:open
* java.management/com.sun.jmx.remote.internal:+open
* @author Eamonn McManus
* @run main/othervm -XX:+UsePerfData DeadListenerTest
--- a/jdk/test/javax/management/remote/mandatory/notif/EmptyDomainNotificationTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/notif/EmptyDomainNotificationTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,7 @@
* @summary Check that the expected notification is received by the JMX
* client even when the domain in the ObjectName is not specified
* @author Shanliang JIANG
- * @modules java.management
+ * @modules java.management.rmi
* @run clean EmptyDomainNotificationTest
* @run build EmptyDomainNotificationTest
* @run main EmptyDomainNotificationTest
--- a/jdk/test/javax/management/remote/mandatory/notif/ListenerScaleTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/notif/ListenerScaleTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 6338874
* @summary Check that notification dispatch is not linear in number of MBeans.
* @author Eamonn McManus
- * @modules java.management
+ * @modules java.management.rmi
*
* @library /lib/testlibrary
* @run build jdk.testlibrary.* ListenerScaleTest
--- a/jdk/test/javax/management/remote/mandatory/notif/NotSerializableNotifTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/notif/NotSerializableNotifTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @summary Tests to send a not serializable notification.
* @bug 5022196 8132003
* @author Shanliang JIANG
- * @modules java.management
+ * @modules java.management.rmi
* @run clean NotSerializableNotifTest
* @run build NotSerializableNotifTest
* @run main NotSerializableNotifTest
--- a/jdk/test/javax/management/remote/mandatory/notif/NotifReconnectDeadlockTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/notif/NotifReconnectDeadlockTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 6199899
* @summary Tests reconnection done by a fetching notif thread.
* @author Shanliang JIANG
- * @modules java.management
+ * @modules java.management.rmi
* @run clean NotifReconnectDeadlockTest
* @run build NotifReconnectDeadlockTest
* @run main NotifReconnectDeadlockTest
--- a/jdk/test/javax/management/remote/mandatory/notif/NotificationAccessControllerTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/notif/NotificationAccessControllerTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,8 @@
* @bug 5106721
* @summary Check the NotificationAccessController methods are properly called.
* @author Luis-Miguel Alventosa
- * @modules java.management/com.sun.jmx.remote.security
+ * @modules java.management.rmi
+ * java.management/com.sun.jmx.remote.security
* @run clean NotificationAccessControllerTest
* @run build NotificationAccessControllerTest
* @run main NotificationAccessControllerTest
--- a/jdk/test/javax/management/remote/mandatory/notif/NotificationBufferCreationTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/notif/NotificationBufferCreationTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 4934236
* @summary Tests that NotificationBuffer is created when used.
* @author jfd@...
- * @modules java.management
+ * @modules java.management.rmi
* @run clean NotificationBufferCreationTest NotificationSender
* @run build NotificationBufferCreationTest
* @run main NotificationBufferCreationTest
--- a/jdk/test/javax/management/remote/mandatory/notif/NotificationEmissionTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/notif/NotificationEmissionTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -28,7 +28,7 @@
* installed. Test the property "jmx.remote.x.check.notification.emission".
* @author Luis-Miguel Alventosa
* @key intermittent
- * @modules java.management
+ * @modules java.management.rmi
* @run clean NotificationEmissionTest
* @run build NotificationEmissionTest
* @run main NotificationEmissionTest 1
--- a/jdk/test/javax/management/remote/mandatory/notif/RMINotifTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/notif/RMINotifTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,7 @@
* @summary Tests to receive notifications for opened and closed connections
ions
* @author sjiang
- * @modules java.management
+ * @modules java.management.rmi
* @run clean RMINotifTest
* @run build RMINotifTest
* @run main RMINotifTest
--- a/jdk/test/javax/management/remote/mandatory/notif/ServerNotifs.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/notif/ServerNotifs.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,7 @@
* @summary Tests the reception of the notifications for opened and closed
* connections
* @author sjiang
- * @modules java.management
+ * @modules java.management.rmi
* @run clean ServerNotifs
* @run build ServerNotifs
* @run main ServerNotifs
--- a/jdk/test/javax/management/remote/mandatory/notif/UnexpectedNotifTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/notif/UnexpectedNotifTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,7 @@
* @summary Tests whether a listener receives notifs emitted before the
* listener is registered.
* @author Shanliang JIANG
- * @modules java.management
+ * @modules java.management.rmi
* @run clean UnexpectedNotifTest
* @run build UnexpectedNotifTest
* @run main UnexpectedNotifTest
--- a/jdk/test/javax/management/remote/mandatory/passwordAccessFile/NonJMXPrincipalsTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/passwordAccessFile/NonJMXPrincipalsTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,7 @@
* @summary Tests that MBeanServerFileAccessController supports
* principals other than JMXPrincipal.
* @author Luis-Miguel Alventosa
- * @modules java.management
+ * @modules java.management.rmi
* @run clean NonJMXPrincipalsTest SimpleStandard SimpleStandardMBean
* @run build NonJMXPrincipalsTest SimpleStandard SimpleStandardMBean
* @run main NonJMXPrincipalsTest
--- a/jdk/test/javax/management/remote/mandatory/passwordAccessFile/PasswordAccessFileTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/passwordAccessFile/PasswordAccessFileTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,7 @@
* @summary Tests the use of the "jmx.remote.x.password.file" and
* "jmx.remote.x.access.file" environment map properties.
* @author Luis-Miguel Alventosa
- * @modules java.management
+ * @modules java.management.rmi
* @run clean PasswordAccessFileTest SimpleStandard SimpleStandardMBean
* @run build PasswordAccessFileTest SimpleStandard SimpleStandardMBean
* @run main PasswordAccessFileTest
--- a/jdk/test/javax/management/remote/mandatory/passwordAuthenticator/RMIAltAuthTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/passwordAuthenticator/RMIAltAuthTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,8 @@
* @bug 5016508
* @summary Supplies an alternative JAAS configuration for authenticating RMI clients
* @author Luis-Miguel Alventosa
- * @modules java.management/com.sun.jmx.remote.security
+ * @modules java.management.rmi
+ * java.management/com.sun.jmx.remote.security
* @run clean RMIAltAuthTest
* @run build RMIAltAuthTest SimpleStandard SimpleStandardMBean
* @run main RMIAltAuthTest
--- a/jdk/test/javax/management/remote/mandatory/passwordAuthenticator/RMIPasswdAuthTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/passwordAuthenticator/RMIPasswdAuthTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,8 @@
* @bug 5016508
* @summary Tests the default JAAS configuration for authenticating RMI clients
* @author Luis-Miguel Alventosa
- * @modules java.management/com.sun.jmx.remote.security
+ * @modules java.management.rmi
+ * java.management/com.sun.jmx.remote.security
* @run clean RMIPasswdAuthTest
* @run build RMIPasswdAuthTest SimpleStandard SimpleStandardMBean
* @run main RMIPasswdAuthTest
--- a/jdk/test/javax/management/remote/mandatory/provider/ProviderTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/provider/ProviderTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -24,7 +24,7 @@
/*
* @test ProviderTest.java
* @summary Tests jar services provider are called
- * @modules java.management
+ * @modules java.management.rmi
* @run clean ProviderTest provider.JMXConnectorProviderImpl provider.JMXConnectorServerProviderImpl
* @run build ProviderTest provider.JMXConnectorProviderImpl provider.JMXConnectorServerProviderImpl
* @run main ProviderTest
--- a/jdk/test/javax/management/remote/mandatory/serverError/JMXServerErrorTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/serverError/JMXServerErrorTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,8 @@
* @bug 4871761
* @summary Tests that JMXServiceErrorException is correctly emitted.
* @author Daniel Fuchs
- * @modules java.management/com.sun.jmx.remote.security
+ * @modules java.management.rmi
+ * java.management/com.sun.jmx.remote.security
* @run clean JMXServerErrorTest
* @run build JMXServerErrorTest
* @run main JMXServerErrorTest
--- a/jdk/test/javax/management/remote/mandatory/socketFactories/RMISocketFactoriesTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/socketFactories/RMISocketFactoriesTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 7654321
* @summary Tests the use of the custom RMI socket factories.
* @author Luis-Miguel Alventosa
- * @modules java.management
+ * @modules java.management.rmi
* @run clean RMISocketFactoriesTest
* @run build RMISocketFactoriesTest RMIClientFactory RMIServerFactory
* @run main RMISocketFactoriesTest test_server_factory
--- a/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation1Test.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation1Test.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,8 @@
* @summary Tests the use of the subject delegation feature in the
* RMI connector
* @author Luis-Miguel Alventosa
- * @modules java.management/com.sun.jmx.remote.security
+ * @modules java.management.rmi
+ * java.management/com.sun.jmx.remote.security
* @run clean SubjectDelegation1Test SimpleStandard SimpleStandardMBean
* @run build SubjectDelegation1Test SimpleStandard SimpleStandardMBean
* @run main SubjectDelegation1Test policy11 ok
--- a/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,8 @@
* @summary Tests the use of the subject delegation feature on the authenticated
* principals within the RMI connector server's creator codebase.
* @author Luis-Miguel Alventosa
- * @modules java.management/com.sun.jmx.remote.security
+ * @modules java.management.rmi
+ * java.management/com.sun.jmx.remote.security
* @run clean SubjectDelegation2Test SimpleStandard SimpleStandardMBean
* @run build SubjectDelegation2Test SimpleStandard SimpleStandardMBean
* @run main SubjectDelegation2Test policy21 ok
--- a/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java Thu Feb 09 23:15:52 2017 +0100
@@ -28,7 +28,8 @@
* principals within the RMI connector server's creator codebase with
* subject delegation.
* @author Luis-Miguel Alventosa
- * @modules java.management/com.sun.jmx.remote.security
+ * @modules java.management.rmi
+ * java.management/com.sun.jmx.remote.security
* @run clean SubjectDelegation3Test SimpleStandard SimpleStandardMBean
* @run build SubjectDelegation3Test SimpleStandard SimpleStandardMBean
* @run main SubjectDelegation3Test policy31 ok
--- a/jdk/test/javax/management/remote/mandatory/util/MapNullValuesTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/remote/mandatory/util/MapNullValuesTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -31,7 +31,8 @@
* Check also that null values for keys are not allowed in
* the maps passed to the JMXConnector[Server] factories.
* @author Luis-Miguel Alventosa
- * @modules java.management/com.sun.jmx.remote.util
+ * @modules java.management.rmi
+ * java.management/com.sun.jmx.remote.util
* @run clean MapNullValuesTest
* @run build MapNullValuesTest
* @run main MapNullValuesTest
--- a/jdk/test/javax/management/security/AuthorizationTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/security/AuthorizationTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 8058865
* @summary Checks various authentication behavior from remote jmx client
* @author Olivier Lagneau
- * @modules java.management
+ * @modules java.management.rmi
* @library /lib/testlibrary
* @compile Simple.java
* @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=username1 -Dpassword=password1 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials
--- a/jdk/test/javax/management/security/SecurityTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/management/security/SecurityTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
* @bug 8058865
* @summary Checks various secure ways of connecting from remote jmx client
* @author Olivier Lagneau
- * @modules java.management
+ * @modules java.management.rmi
* @library /lib/testlibrary
* @compile MBS_Light.java ServerDelegate.java TestSampleLoginModule.java
* @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=SQE_username -Dpassword=SQE_password SecurityTest -server -mapType x.password.file -client -mapType credentials
--- a/jdk/test/javax/net/ssl/FixingJavadocs/SSLSessionNulls.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/net/ssl/FixingJavadocs/SSLSessionNulls.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
* @summary Need to revisit the javadocs for JSSE, especially the
* promoted classes.
* @library /javax/net/ssl/templates
+ * @modules jdk.crypto.ec
* @run main/othervm SSLSessionNulls
*
* SunJSSE does not support dynamic system properties, no way to re-use
--- a/jdk/test/javax/net/ssl/interop/ClientHelloChromeInterOp.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/net/ssl/interop/ClientHelloChromeInterOp.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,8 @@
* @test
* @bug 8169362
* @summary Interop automated testing with Chrome
- * @modules java.base/sun.security.util
+ * @modules jdk.crypto.ec
+ * java.base/sun.security.util
* @run main/othervm ClientHelloChromeInterOp
*/
--- a/jdk/test/javax/net/ssl/templates/SSLSocketTemplate.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/net/ssl/templates/SSLSocketTemplate.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,11 +29,22 @@
/*
* @test
* @bug 8161106 8170329
+ * @modules jdk.crypto.ec
* @summary Improve SSLSocket test template
* @run main/othervm SSLSocketTemplate
*/
-import java.io.*;
-import javax.net.ssl.*;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManagerFactory;
import java.net.InetSocketAddress;
import java.net.SocketTimeoutException;
import java.security.KeyStore;
@@ -41,7 +52,7 @@
import java.security.KeyFactory;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
-import java.security.spec.*;
+import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.concurrent.CountDownLatch;
--- a/jdk/test/javax/swing/plaf/basic/BasicSplitPaneUI/Test6657026.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/javax/swing/plaf/basic/BasicSplitPaneUI/Test6657026.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2017, 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,7 +23,7 @@
/*
* @test
- * @bug 6657026
+ * @bug 6657026 7190595
* @summary Tests shared BasicSplitPaneUI in different application contexts
* @author Sergey Malenkov
* @modules java.desktop/sun.awt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/internal/agent/AgentCMETest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2012, 2015, 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.
+ */
+
+/*
+ * Portions Copyright (c) 2012 IBM Corporation
+ */
+
+/**
+ * @test
+ * @bug 7164191
+ * @summary properties.putAll API may fail with ConcurrentModifcationException on multi-thread scenario
+ * @modules jdk.management.agent/jdk.internal.agent
+ * @author Deven You
+ */
+
+import java.util.Properties;
+import jdk.internal.agent.Agent;
+
+public class AgentCMETest {
+ static Class<?> agentClass;
+
+ /**
+ * In jdk.internal.agent.Agent.loadManagementProperties(), call
+ * properties.putAll API may fail with ConcurrentModifcationException if the
+ * system properties are modified simultaneously by another thread
+ *
+ * @param args
+ * @throws Exception
+ */
+ public static void main(String[] args) throws Exception {
+ System.out.println("Start...");
+
+ final Properties properties = System.getProperties();
+ Thread t1 = new Thread(new Runnable() {
+ public void run() {
+ for (int i = 0; i < 100; i++) {
+ properties.put(String.valueOf(i), "");
+ try {
+ Thread.sleep(1);
+ } catch (InterruptedException e) {
+ // do nothing
+ }
+ }
+ }
+ });
+ t1.start();
+
+ for (int i = 0; i < 10000; i++) {
+ Agent.loadManagementProperties();
+ }
+
+ System.out.println("Finished...");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/internal/agent/AgentCheckTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2004, 2015, 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 5013605
+ * @summary Localize log messages from the management agents
+ * @modules jdk.management.agent/jdk.internal.agent
+ *
+ * @author Tim Bell
+ */
+import jdk.internal.agent.Agent;
+
+public class AgentCheckTest {
+
+ public static void main(String[] args){
+ String [][] testStrings = {
+ {"agent.err.error", "", ""},
+ {"jmxremote.ConnectorBootstrap.starting", "", ""},
+ {"jmxremote.ConnectorBootstrap.noAuthentication", "", ""},
+ {"jmxremote.ConnectorBootstrap.ready", "Phony JMXServiceURL", ""},
+ {"jmxremote.ConnectorBootstrap.password.readonly", "Phony passwordFileName", ""},
+ };
+
+ boolean pass = true;
+ System.out.println("Start...");
+ for (int ii = 0; ii < testStrings.length; ii++) {
+ String key = testStrings[ii][0];
+ String p1 = testStrings[ii][1];
+ String p2 = testStrings[ii][2];
+ String ss = Agent.getText(key, p1, p2);
+ if (ss.startsWith("missing resource key")) {
+ pass = false;
+ System.out.println(" lookup failed for key = " + key);
+ }
+ }
+ if (!pass) {
+ throw new Error ("Resource lookup(s) failed; Test failed");
+ }
+ System.out.println("...Finished.");
+ }
+}
--- a/jdk/test/sun/management/AgentCMETest.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2012, 2015, 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.
- */
-
-/*
- * Portions Copyright (c) 2012 IBM Corporation
- */
-
-/**
- * @test
- * @bug 7164191
- * @summary properties.putAll API may fail with ConcurrentModifcationException on multi-thread scenario
- * @modules java.management/sun.management
- * @author Deven You
- */
-
-import java.util.Properties;
-import sun.management.Agent;
-
-public class AgentCMETest {
- static Class<?> agentClass;
-
- /**
- * In sun.management.Agent.loadManagementProperties(), call
- * properties.putAll API may fail with ConcurrentModifcationException if the
- * system properties are modified simultaneously by another thread
- *
- * @param args
- * @throws Exception
- */
- public static void main(String[] args) throws Exception {
- System.out.println("Start...");
-
- final Properties properties = System.getProperties();
- Thread t1 = new Thread(new Runnable() {
- public void run() {
- for (int i = 0; i < 100; i++) {
- properties.put(String.valueOf(i), "");
- try {
- Thread.sleep(1);
- } catch (InterruptedException e) {
- // do nothing
- }
- }
- }
- });
- t1.start();
-
- for (int i = 0; i < 10000; i++) {
- Agent.loadManagementProperties();
- }
-
- System.out.println("Finished...");
- }
-}
--- a/jdk/test/sun/management/AgentCheckTest.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2004, 2015, 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 5013605
- * @summary Localize log messages from the management agents
- * @modules java.management/sun.management
- *
- * @author Tim Bell
- */
-import sun.management.Agent;
-
-public class AgentCheckTest {
-
- public static void main(String[] args){
- String [][] testStrings = {
- {"agent.err.error", "", ""},
- {"jmxremote.ConnectorBootstrap.starting", "", ""},
- {"jmxremote.ConnectorBootstrap.noAuthentication", "", ""},
- {"jmxremote.ConnectorBootstrap.ready", "Phony JMXServiceURL", ""},
- {"jmxremote.ConnectorBootstrap.password.readonly", "Phony passwordFileName", ""},
- };
-
- boolean pass = true;
- System.out.println("Start...");
- for (int ii = 0; ii < testStrings.length; ii++) {
- String key = testStrings[ii][0];
- String p1 = testStrings[ii][1];
- String p2 = testStrings[ii][2];
- String ss = Agent.getText(key, p1, p2);
- if (ss.startsWith("missing resource key")) {
- pass = false;
- System.out.println(" lookup failed for key = " + key);
- }
- }
- if (!pass) {
- throw new Error ("Resource lookup(s) failed; Test failed");
- }
- System.out.println("...Finished.");
- }
-}
--- a/jdk/test/sun/management/jdp/JdpDefaultsTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/sun/management/jdp/JdpDefaultsTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -31,7 +31,7 @@
* @test JdpDefaultsTest
* @summary Assert that we can read JDP packets from a multicast socket connection, on default IP and port.
* @library /lib/testlibrary
- * @modules java.management/sun.management.jdp
+ * @modules jdk.management.agent/sun.management.jdp
* @build jdk.testlibrary.* ClientConnection JdpTestUtil JdpTestCase JdpOnTestCase DynamicLauncher
* @run main JdpDefaultsTest
*/
--- a/jdk/test/sun/management/jdp/JdpOffTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/sun/management/jdp/JdpOffTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -32,7 +32,7 @@
* @test JdpOffTest.java
* @summary Assert that no JDP packets are sent to the default address and port.
* @library /lib/testlibrary
- * @modules java.management/sun.management.jdp
+ * @modules jdk.management.agent/sun.management.jdp
* @build jdk.testlibrary.* ClientConnection JdpTestUtil JdpTestCase JdpOffTestCase DynamicLauncher
* @run main JdpOffTest
*/
--- a/jdk/test/sun/management/jdp/JdpSpecificAddressTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/sun/management/jdp/JdpSpecificAddressTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -31,7 +31,7 @@
* @test JdpSpecificAddressTest
* @summary Assert that we can read JDP packets from a multicast socket connection, on specific IP and port.
* @library /lib/testlibrary
- * @modules java.management/sun.management.jdp
+ * @modules jdk.management.agent/sun.management.jdp
* @build jdk.testlibrary.* ClientConnection JdpTestUtil JdpTestCase JdpOnTestCase DynamicLauncher
* @run main JdpSpecificAddressTest
*/
--- a/jdk/test/sun/management/jmxremote/LocalRMIServerSocketFactoryTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/sun/management/jmxremote/LocalRMIServerSocketFactoryTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -28,7 +28,7 @@
*
* @author Daniel Fuchs
*
- * @modules java.management/sun.management.jmxremote
+ * @modules jdk.management.agent/sun.management.jmxremote
* @run compile -XDignore.symbol.file=true -g LocalRMIServerSocketFactoryTest.java
* @run main LocalRMIServerSocketFactoryTest
*/
--- a/jdk/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -41,8 +41,7 @@
* @test
* @bug 6434402 8004926
* @library /lib/testlibrary
- * @modules java.management/sun.management
- * java.management
+ * @modules jdk.management.agent/jdk.internal.agent
* @build jdk.testlibrary.*
* @build TestManager TestApplication CustomLauncherTest
* @run main/othervm CustomLauncherTest
@@ -147,7 +146,7 @@
ProcessBuilder client = ProcessTools.createJavaProcessBuilder(
"-cp",
TEST_CLASSPATH,
- "--add-exports", "java.management/sun.management=ALL-UNNAMED",
+ "--add-exports", "jdk.management.agent/jdk.internal.agent=ALL-UNNAMED",
"TestManager",
String.valueOf(serverPrc.getPid()),
port.get(),
--- a/jdk/test/sun/management/jmxremote/bootstrap/JMXInterfaceBindingTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/sun/management/jmxremote/bootstrap/JMXInterfaceBindingTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -48,8 +48,8 @@
* @summary Test JMX agent host address binding. Same ports but different
* interfaces to bind to (using plain sockets and SSL sockets).
*
- * @modules java.management/sun.management
- * java.management/sun.management.jmxremote
+ * @modules jdk.management.agent/jdk.internal.agent
+ * jdk.management.agent/sun.management.jmxremote
* @library /lib/testlibrary
* @build jdk.testlibrary.* JMXAgentInterfaceBinding
* @run main/timeout=5 JMXInterfaceBindingTest
--- a/jdk/test/sun/management/jmxremote/bootstrap/JvmstatCountersTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/sun/management/jmxremote/bootstrap/JvmstatCountersTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,7 @@
* @summary Tests that the jvmstat counters published by the out-of-the-box
* management agent for the JMX connection details are correct.
* @author Luis-Miguel Alventosa
- * @modules java.management/sun.management
+ * @modules jdk.management.agent/jdk.internal.agent
* @run clean JvmstatCountersTest
* @run build JvmstatCountersTest
* @run main/othervm/timeout=600 -XX:+UsePerfData JvmstatCountersTest 1
@@ -42,7 +42,7 @@
import javax.management.*;
import javax.management.remote.*;
import com.sun.tools.attach.*;
-import sun.management.ConnectorAddressLink;
+import jdk.internal.agent.ConnectorAddressLink;
public class JvmstatCountersTest {
--- a/jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -38,7 +38,7 @@
* without connection or username/password details.
* TestManager will attempt a connection to the address obtained from
* both agent properties and jvmstat buffer.
- * @modules java.management/sun.management
+ * @modules jdk.management.agent/jdk.internal.agent
* @build jdk.testlibrary.* TestManager TestApplication
* @run main/othervm/timeout=300 LocalManagementTest
*/
@@ -131,7 +131,7 @@
ProcessBuilder client = ProcessTools.createJavaProcessBuilder(
"-cp",
TEST_CLASSPATH,
- "--add-exports", "java.management/sun.management=ALL-UNNAMED",
+ "--add-exports", "jdk.management.agent/jdk.internal.agent=ALL-UNNAMED",
"TestManager",
String.valueOf(serverPrc.getPid()),
port.get(),
--- a/jdk/test/sun/management/jmxremote/bootstrap/PasswordFilePermissionTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/sun/management/jmxremote/bootstrap/PasswordFilePermissionTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -28,7 +28,7 @@
* @library /lib/testlibrary
* @bug 6557093
* @summary Check SSL config file permission for out-of-the-box management
- * @modules java.management
+ * @modules jdk.management.agent
* @build jdk.testlibrary.* AbstractFilePermissionTest Dummy
* @run main/timeout=300 PasswordFilePermissionTest
*
--- a/jdk/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -40,7 +40,7 @@
import javax.management.remote.*;
import javax.management.*;
-import sun.management.AgentConfigurationError;
+import jdk.internal.agent.AgentConfigurationError;
import java.security.Security;
--- a/jdk/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.sh Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.sh Thu Feb 09 23:15:52 2017 +0100
@@ -28,9 +28,8 @@
#
# @key intermittent
# @library /lib/testlibrary
-# @modules java.management/sun.management
-# java.management/sun.management.jmxremote
-# java.management
+# @modules jdk.management.agent/jdk.internal.agent
+# jdk.management.agent/sun.management.jmxremote
# @build jdk.testlibrary.* TestLogger Utils RmiBootstrapTest
# @run shell/timeout=300 RmiBootstrapTest.sh
@@ -51,8 +50,8 @@
DEBUGOPTIONS=""
export DEBUGOPTIONS
-EXTRAOPTIONS="--add-exports java.management/sun.management=ALL-UNNAMED \
- --add-exports java.management/sun.management.jmxremote=ALL-UNNAMED"
+EXTRAOPTIONS="--add-exports jdk.management.agent/jdk.internal.agent=ALL-UNNAMED \
+ --add-exports jdk.management.agent/sun.management.jmxremote=ALL-UNNAMED"
export EXTRAOPTIONS
# Call the common generic test
--- a/jdk/test/sun/management/jmxremote/bootstrap/RmiRegistrySslTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/sun/management/jmxremote/bootstrap/RmiRegistrySslTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -42,7 +42,7 @@
* @library /lib/testlibrary
* @bug 6228231
* @summary Test that RMI registry uses SSL.
- * @modules java.management
+ * @modules jdk.management.agent
* @build jdk.testlibrary.* RmiRegistrySslTestApp
* @run main/timeout=300 RmiRegistrySslTest
* @author Luis-Miguel Alventosa, Taras Ledkov
--- a/jdk/test/sun/management/jmxremote/bootstrap/RmiSslBootstrapTest.sh Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/sun/management/jmxremote/bootstrap/RmiSslBootstrapTest.sh Thu Feb 09 23:15:52 2017 +0100
@@ -27,8 +27,8 @@
# @summary Test RMI Bootstrap with SSL
#
# @library /lib/testlibrary
-# @modules java.management/sun.management
-# java.management/sun.management.jmxremote
+# @modules jdk.management.agent/jdk.internal.agent
+# jdk.management.agent/sun.management.jmxremote
# @build jdk.testlibrary.* TestLogger Utils RmiBootstrapTest
# @run shell/timeout=300 RmiSslBootstrapTest.sh
@@ -49,8 +49,8 @@
DEBUGOPTIONS=""
export DEBUGOPTIONS
-EXTRAOPTIONS="--add-exports java.management/sun.management=ALL-UNNAMED \
- --add-exports java.management/sun.management.jmxremote=ALL-UNNAMED"
+EXTRAOPTIONS="--add-exports jdk.management.agent/jdk.internal.agent=ALL-UNNAMED \
+ --add-exports jdk.management.agent/sun.management.jmxremote=ALL-UNNAMED"
export EXTRAOPTIONS
# Call the common generic test
--- a/jdk/test/sun/management/jmxremote/bootstrap/RmiSslNoKeyStoreTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/sun/management/jmxremote/bootstrap/RmiSslNoKeyStoreTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -43,7 +43,7 @@
import javax.management.remote.*;
import javax.management.*;
-import sun.management.AgentConfigurationError;
+import jdk.internal.agent.AgentConfigurationError;
/**
* <p>This class implements unit test for RMI Bootstrap.
--- a/jdk/test/sun/management/jmxremote/bootstrap/RmiSslNoKeyStoreTest.sh Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/sun/management/jmxremote/bootstrap/RmiSslNoKeyStoreTest.sh Thu Feb 09 23:15:52 2017 +0100
@@ -26,8 +26,8 @@
# @summary Test RMI Bootstrap with SSL and no keystore.
#
# @bug 4932854
-# @modules java.management/sun.management
-# java.management/sun.management.jmxremote
+# @modules jdk.management.agent/jdk.internal.agent
+# jdk.management.agent/sun.management.jmxremote
# @build TestLogger RmiSslNoKeyStoreTest
# @run shell/timeout=300 RmiSslNoKeyStoreTest.sh
@@ -48,8 +48,8 @@
DEBUGOPTIONS=""
export DEBUGOPTIONS
-EXTRAOPTIONS="--add-exports java.management/sun.management=ALL-UNNAMED \
- --add-exports java.management/sun.management.jmxremote=ALL-UNNAMED"
+EXTRAOPTIONS="--add-exports jdk.management.agent/jdk.internal.agent=ALL-UNNAMED \
+ --add-exports jdk.management.agent/sun.management.jmxremote=ALL-UNNAMED"
export EXTRAOPTIONS
# Call the common generic test
--- a/jdk/test/sun/management/jmxremote/bootstrap/SSLConfigFilePermissionTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/sun/management/jmxremote/bootstrap/SSLConfigFilePermissionTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,7 @@
* @test
* @library /lib/testlibrary
* @bug 6557093
- * @modules java.management
+ * @modules jdk.management.agent
* @build jdk.testlibrary.* Dummy AbstractFilePermissionTest
* @summary Check SSL config file permission for out-of-the-box management
* @run main/timeout=300 SSLConfigFilePermissionTest
--- a/jdk/test/sun/management/jmxremote/bootstrap/TestManager.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/sun/management/jmxremote/bootstrap/TestManager.java Thu Feb 09 23:15:52 2017 +0100
@@ -46,7 +46,7 @@
import com.sun.tools.attach.VirtualMachine;
// Sun implementation specific
-import sun.management.ConnectorAddressLink;
+import jdk.internal.agent.ConnectorAddressLink;
public class TestManager {
@@ -57,7 +57,7 @@
try {
VirtualMachine.attach(pid).startLocalManagementAgent();
} catch (Exception x) {
- throw new IOException(x.getMessage());
+ throw new IOException(x.getMessage(), x);
}
}
--- a/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -46,14 +46,15 @@
import jdk.testlibrary.ProcessTools;
import jdk.testlibrary.Utils;
-import sun.management.Agent;
-import sun.management.AgentConfigurationError;
+import jdk.internal.agent.Agent;
+import jdk.internal.agent.AgentConfigurationError;
+import jdk.internal.agent.ConnectorAddressLink;
/**
* @test
* @bug 7110104
* @library /lib/testlibrary
- * @modules java.management/sun.management
+ * @modules jdk.management.agent/jdk.internal.agent
* @build jdk.testlibrary.* JMXStartStopTest PortAllocator TestApp ManagementAgentJcmd
* @run main/othervm/timeout=600 -XX:+UsePerfData JMXStartStopTest
* @summary Makes sure that enabling/disabling the management agent through JCMD
@@ -103,7 +104,7 @@
String jmxUrlStr = null;
try {
- jmxUrlStr = sun.management.ConnectorAddressLink.importFrom((int)pid);
+ jmxUrlStr = ConnectorAddressLink.importFrom((int)pid);
dbg_print("Local Service URL: " +jmxUrlStr);
if ( jmxUrlStr == null ) {
throw new Exception("No Service URL. Local agent not started?");
--- a/jdk/test/sun/management/jmxremote/startstop/JMXStatusPerfCountersTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/sun/management/jmxremote/startstop/JMXStatusPerfCountersTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -42,7 +42,7 @@
* in the related performance counters.
* @key intermittent
* @library /lib/testlibrary
- * @modules java.management/sun.management
+ * @modules jdk.management.agent/jdk.internal.agent
* @build jdk.testlibrary.* PortAllocator TestApp ManagementAgentJcmd
* @run testng/othervm -XX:+UsePerfData JMXStatusPerfCountersTest
*/
--- a/jdk/test/sun/management/jmxremote/startstop/JMXStatusTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/sun/management/jmxremote/startstop/JMXStatusTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -38,7 +38,7 @@
* Management agent may be disabled, started (only local connections) and started.
* The test asserts that the expected text is being printed.
* @library /lib/testlibrary
- * @modules java.management/sun.management
+ * @modules jdk.management.agent/jdk.internal.agent
* @build jdk.testlibrary.* PortAllocator TestApp ManagementAgentJcmd
* JMXStatusTest JMXStatus1Test JMXStatus2Test
* @run testng/othervm -XX:+UsePerfData JMXStatus1Test
--- a/jdk/test/sun/management/jmxremote/startstop/ManagementAgentJcmd.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/sun/management/jmxremote/startstop/ManagementAgentJcmd.java Thu Feb 09 23:15:52 2017 +0100
@@ -30,8 +30,8 @@
import java.util.function.Consumer;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
-import sun.management.Agent;
-import sun.management.AgentConfigurationError;
+import jdk.internal.agent.Agent;
+import jdk.internal.agent.AgentConfigurationError;
import jdk.testlibrary.JDKToolLauncher;
import jdk.testlibrary.ProcessTools;
--- a/jdk/test/sun/net/www/protocol/https/HttpsClient/ProxyAuthTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/sun/net/www/protocol/https/HttpsClient/ProxyAuthTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, 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,7 +31,8 @@
* @bug 4323990 4413069 8160838
* @summary HttpsURLConnection doesn't send Proxy-Authorization on CONNECT
* Incorrect checking of proxy server response
- * @modules java.base/sun.net.www
+ * @modules jdk.crypto.ec
+ * java.base/sun.net.www
* @library /javax/net/ssl/templates
* @run main/othervm ProxyAuthTest fail
* @run main/othervm -Djdk.http.auth.tunneling.disabledSchemes=Basic
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/pkcs12/MixedcaseAlias.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017, 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 8173956
+ * @summary KeyStore regression due to default keystore being changed to PKCS12
+ */
+
+import java.io.*;
+import java.security.KeyStore;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+
+/**
+ * Test that a PKCS12 keystore entry with mixed-case alias can be retrieved.
+ */
+public class MixedcaseAlias {
+ private static final String DIR = System.getProperty("test.src", ".");
+ private static final String CERT = DIR + "/trusted.pem";
+ private static final String ALIAS = "Mixed-case Alias";
+
+ public static void main(String[] ignored) throws Exception {
+ KeyStore keystore = KeyStore.getInstance("PKCS12");
+ keystore.load(null, null);
+
+ keystore.setCertificateEntry(ALIAS, loadCertificate(CERT));
+ KeyStore.Entry entry = keystore.getEntry(ALIAS, null);
+
+ if (entry == null) {
+ throw new Exception(
+ "Error retrieving keystore entry using a mixed-case alias");
+ }
+
+ System.out.println("OK");
+ }
+
+ private static Certificate loadCertificate(String certFile)
+ throws Exception {
+ X509Certificate cert = null;
+ try (FileInputStream certStream = new FileInputStream(certFile)) {
+ CertificateFactory factory =
+ CertificateFactory.getInstance("X.509");
+ return factory.generateCertificate(certStream);
+ }
+ }
+}
--- a/jdk/test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
/*
* @test
* @bug 4392475
+ * @modules jdk.crypto.ec
* @library /javax/net/ssl/templates
* @summary Calling setWantClientAuth(true) disables anonymous suites
* @run main/othervm -Djavax.net.debug=all AnonCipherWithWantClientAuth
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/ServerHandshaker/HelloExtensionsTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2017, 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 8173783
+ * @summary 6u141 IllegalArgumentException: jdk.tls.namedGroups
+ * run main/othervm HelloExtensionsTest
+ * run main/othervm HelloExtensionsTest -Djdk.tls.namedGroups="bug, bug"
+ * run main/othervm HelloExtensionsTest -Djdk.tls.namedGroups="secp521r1"
+ *
+ */
+import javax.crypto.*;
+import javax.net.ssl.*;
+import javax.net.ssl.SSLEngineResult.*;
+import java.io.*;
+import java.nio.*;
+import java.security.*;
+
+public class HelloExtensionsTest {
+
+ private static boolean debug = false;
+ private static boolean proceed = true;
+ private static boolean EcAvailable = isEcAvailable();
+
+ static String pathToStores = "../../../../javax/net/ssl/etc";
+ private static String keyStoreFile = "keystore";
+ private static String trustStoreFile = "truststore";
+ private static String passwd = "passphrase";
+
+ private static String keyFilename =
+ System.getProperty("test.src", "./") + "/" + pathToStores +
+ "/" + keyStoreFile;
+ private static String trustFilename =
+ System.getProperty("test.src", "./") + "/" + pathToStores +
+ "/" + trustStoreFile;
+
+ private static void checkDone(SSLEngine ssle) throws Exception {
+ if (!ssle.isInboundDone()) {
+ throw new Exception("isInboundDone isn't done");
+ }
+ if (!ssle.isOutboundDone()) {
+ throw new Exception("isOutboundDone isn't done");
+ }
+ }
+
+ private static void runTest(SSLEngine ssle) throws Exception {
+
+ /*
+
+ A client hello message captured via wireshark by selecting
+ a TLSv1.2 Client Hello record and clicking through to the
+ TLSv1.2 Record Layer line and then selecting the hex stream
+ via "copy -> bytes -> hex stream".
+
+ For Record purposes, here's the ClientHello :
+
+ *** ClientHello, TLSv1.2
+ RandomCookie: GMT: 1469560450 bytes = { 108, 140, 12, 202,
+ 2, 213, 10, 236, 143, 223, 58, 162, 228, 155, 239, 3, 98,
+ 232, 89, 41, 116, 120, 13, 37, 105, 153, 97, 241 }
+ Session ID: {}
+ Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256,
+ TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
+ TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
+ TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+ TLS_RSA_WITH_AES_128_CBC_SHA,
+ TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
+ TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
+ TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
+ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ TLS_RSA_WITH_AES_128_GCM_SHA256,
+ TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
+ TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
+ TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
+ TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,
+ TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
+ TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
+ SSL_RSA_WITH_3DES_EDE_CBC_SHA,
+ TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
+ TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
+ SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
+ SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
+ TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
+ Compression Methods: { 0 }
+ Extension elliptic_curves, curve names: {secp256r1,
+ sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1,
+ sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1,
+ sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1,
+ secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
+ Extension ec_point_formats, formats: [uncompressed]
+ Extension signature_algorithms, signature_algorithms:
+ SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA,
+ SHA256withECDSA, SHA256withRSA, Unknown (hash:0x3, signature:0x3),
+ Unknown (hash:0x3, signature:0x1), SHA1withECDSA,
+ SHA1withRSA, SHA1withDSA
+ Extension server_name, server_name:
+ [host_name: bugs.openjdk.java.net]
+ */
+
+ String hello = "16030300df010000db03035898b7826c8c0cc" +
+ "a02d50aec8fdf3aa2e49bef0362e8592974780d25699961f" +
+ "100003ac023c027003cc025c02900670040c009c013002fc" +
+ "004c00e00330032c02bc02f009cc02dc031009e00a2c008c" +
+ "012000ac003c00d0016001300ff01000078000a003400320" +
+ "0170001000300130015000600070009000a0018000b000c0" +
+ "019000d000e000f001000110002001200040005001400080" +
+ "016000b00020100000d00180016060306010503050104030" +
+ "401030303010203020102020000001a00180000156275677" +
+ "32e6f70656e6a646b2e6a6176612e6e6574";
+
+ byte[] msg_clihello = hexStringToByteArray(hello);
+ ByteBuffer bf_clihello = ByteBuffer.wrap(msg_clihello);
+
+ SSLSession session = ssle.getSession();
+ int appBufferMax = session.getApplicationBufferSize();
+ int netBufferMax = session.getPacketBufferSize();
+
+ ByteBuffer serverIn = ByteBuffer.allocate(appBufferMax + 50);
+ ByteBuffer serverOut = ByteBuffer.wrap("I'm Server".getBytes());
+ ByteBuffer sTOc = ByteBuffer.allocate(netBufferMax);
+
+ ssle.beginHandshake();
+
+ // unwrap the clientHello message.
+ SSLEngineResult result = ssle.unwrap(bf_clihello, serverIn);
+ System.out.println("server unwrap " + result);
+ runDelegatedTasks(result, ssle);
+
+ if (!proceed) {
+ //expected exception occurred. Don't process anymore
+ return;
+ }
+
+ // one more step, ensure the clientHello message is parsed.
+ SSLEngineResult.HandshakeStatus status = ssle.getHandshakeStatus();
+ if ( status == HandshakeStatus.NEED_UNWRAP) {
+ result = ssle.unwrap(bf_clihello, serverIn);
+ System.out.println("server unwrap " + result);
+ runDelegatedTasks(result, ssle);
+ } else if ( status == HandshakeStatus.NEED_WRAP) {
+ result = ssle.wrap(serverOut, sTOc);
+ System.out.println("server wrap " + result);
+ runDelegatedTasks(result, ssle);
+ } else {
+ throw new Exception("unexpected handshake status " + status);
+ }
+
+ // enough, stop
+ }
+
+ /*
+ * If the result indicates that we have outstanding tasks to do,
+ * go ahead and run them in this thread.
+ */
+ private static void runDelegatedTasks(SSLEngineResult result,
+ SSLEngine engine) throws Exception {
+
+ if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
+ Runnable runnable;
+ try {
+ while ((runnable = engine.getDelegatedTask()) != null) {
+ log("\trunning delegated task...");
+ runnable.run();
+ }
+ } catch (ExceptionInInitializerError e) {
+ String v = System.getProperty("jdk.tls.namedGroups");
+ if (!EcAvailable || v == null) {
+ // we weren't expecting this if no EC providers
+ throw new RuntimeException("Unexpected Error :" + e);
+ }
+ if (v != null && v.contains("bug")) {
+ // OK - we were expecting this Error
+ log("got expected error for bad jdk.tls.namedGroups");
+ proceed = false;
+ return;
+ } else {
+ System.out.println("Unexpected error. " +
+ "jdk.tls.namedGroups value: " + v);
+ throw e;
+ }
+ }
+ HandshakeStatus hsStatus = engine.getHandshakeStatus();
+ if (hsStatus == HandshakeStatus.NEED_TASK) {
+ throw new Exception(
+ "handshake shouldn't need additional tasks");
+ }
+ log("\tnew HandshakeStatus: " + hsStatus);
+ }
+ }
+
+ private static byte[] hexStringToByteArray(String s) {
+ int len = s.length();
+ byte[] data = new byte[len / 2];
+ for (int i = 0; i < len; i += 2) {
+ data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ + Character.digit(s.charAt(i+1), 16));
+ }
+ return data;
+ }
+
+ private static boolean isEcAvailable() {
+ try {
+ Signature.getInstance("SHA1withECDSA");
+ Signature.getInstance("NONEwithECDSA");
+ KeyAgreement.getInstance("ECDH");
+ KeyFactory.getInstance("EC");
+ KeyPairGenerator.getInstance("EC");
+ AlgorithmParameters.getInstance("EC");
+ } catch (Exception e) {
+ log("EC not available. Received: " + e);
+ return false;
+ }
+ return true;
+ }
+
+ public static void main(String args[]) throws Exception {
+ SSLEngine ssle = createSSLEngine(keyFilename, trustFilename);
+ runTest(ssle);
+ System.out.println("Test Passed.");
+ }
+
+ /*
+ * Create an initialized SSLContext to use for this test.
+ */
+ static private SSLEngine createSSLEngine(String keyFile, String trustFile)
+ throws Exception {
+
+ SSLEngine ssle;
+
+ KeyStore ks = KeyStore.getInstance("JKS");
+ KeyStore ts = KeyStore.getInstance("JKS");
+
+ char[] passphrase = "passphrase".toCharArray();
+
+ ks.load(new FileInputStream(keyFile), passphrase);
+ ts.load(new FileInputStream(trustFile), passphrase);
+
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+ kmf.init(ks, passphrase);
+
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
+ tmf.init(ts);
+
+ SSLContext sslCtx = SSLContext.getInstance("TLS");
+
+ sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+
+ ssle = sslCtx.createSSLEngine();
+ ssle.setUseClientMode(false);
+
+ return ssle;
+ }
+
+
+ private static void log(String str) {
+ if (debug) {
+ System.out.println(str);
+ }
+ }
+}
--- a/jdk/test/tools/jlink/JLinkTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/tools/jlink/JLinkTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -284,6 +284,13 @@
helper.generateDefaultJModule(moduleName, "composite2");
helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: orphan argument: bar");
}
+
+ // basic check for --help - JDK-8173717
+ {
+ JImageGenerator.getJLinkTask()
+ .option("--help")
+ .call().assertSuccess();
+ }
}
private static void testCompress(Helper helper, String moduleName, String... userOptions) throws IOException {
--- a/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/SystemModulesTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/SystemModulesTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -25,6 +25,9 @@
import java.lang.module.ModuleDescriptor.*;
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -36,6 +39,7 @@
/**
* @test
+ * @bug 8142968 8173381
* @modules java.base/jdk.internal.misc
* @run testng SystemModulesTest
* @summary Verify the properties of ModuleDescriptor created
@@ -43,7 +47,72 @@
*/
public class SystemModulesTest {
- private static final JavaLangModuleAccess jlma = SharedSecrets.getJavaLangModuleAccess();
+ private static final JavaLangModuleAccess JLMA =
+ SharedSecrets.getJavaLangModuleAccess();
+ private static final String OS_NAME = System.getProperty("os.name");
+ private static final String OS_ARCH = System.getProperty("os.arch");
+ // system modules containing no package
+ private static final Set<String> EMPTY_MODULES =
+ Set.of("java.se", "java.se.ee", "jdk.jdwp.agent", "jdk.pack");
+
+ @Test
+ public void testSystemModules() {
+ Path jimage = Paths.get(System.getProperty("java.home"), "lib", "modules");
+ if (Files.notExists(jimage))
+ return;
+
+ ModuleFinder.ofSystem().findAll().stream()
+ .map(ModuleReference::descriptor)
+ .forEach(this::checkAttributes);
+ }
+
+ // JMOD files are created with osName and osArch that may be different
+ // than os.name and os.arch system property
+ private boolean checkOSName(String name) {
+ if (name.equals(OS_NAME))
+ return true;
+
+ if (OS_NAME.equals("Mac OS X")) {
+ return name.equals("Darwin");
+ } else if (OS_NAME.startsWith("Windows")) {
+ return name.startsWith("Windows");
+ } else {
+ System.err.println("ERROR: " + name + " but expected: " + OS_NAME);
+ return false;
+ }
+ }
+
+ private boolean checkOSArch(String name) {
+ if (name.equals(OS_ARCH))
+ return true;
+
+ switch (OS_ARCH) {
+ case "i386":
+ case "x86":
+ return name.equals("i586");
+ default:
+ System.err.println("ERROR: " + name + " but expected: " + OS_ARCH);
+ return false;
+ }
+ }
+
+ private void checkAttributes(ModuleDescriptor md) {
+ System.out.format("%s %s %s %s%n", md.name(),
+ md.osName(), md.osArch(), md.osVersion());
+
+ if (md.name().equals("java.base")) {
+ assertTrue(checkOSName(md.osName().get()));
+ assertTrue(checkOSArch(md.osArch().get()));
+ assertTrue(md.osVersion().isPresent());
+ } else {
+ // target platform attribute is dropped by jlink plugin
+ assertFalse(md.osName().isPresent());
+ assertFalse(md.osArch().isPresent());
+ assertFalse(md.osVersion().isPresent());
+ assertTrue(md.packages().size() > 0
+ || EMPTY_MODULES.contains(md.name()), md.name());
+ }
+ }
/**
* Verify ModuleDescriptor contains unmodifiable sets
@@ -59,18 +128,19 @@
private void testModuleDescriptor(ModuleDescriptor md) {
assertUnmodifiable(md.packages(), "package");
assertUnmodifiable(md.requires(),
- jlma.newRequires(Set.of(Requires.Modifier.TRANSITIVE), "require", null));
+ JLMA.newRequires(Set.of(Requires.Modifier.TRANSITIVE),
+ "require", null));
for (Requires req : md.requires()) {
assertUnmodifiable(req.modifiers(), Requires.Modifier.TRANSITIVE);
}
- assertUnmodifiable(md.exports(), jlma.newExports(Set.of(), "export", Set.of()));
+ assertUnmodifiable(md.exports(), JLMA.newExports(Set.of(), "export", Set.of()));
for (Exports exp : md.exports()) {
assertUnmodifiable(exp.modifiers(), Exports.Modifier.SYNTHETIC);
assertUnmodifiable(exp.targets(), "target");
}
- assertUnmodifiable(md.opens(), jlma.newOpens(Set.of(), "open", Set.of()));
+ assertUnmodifiable(md.opens(), JLMA.newOpens(Set.of(), "open", Set.of()));
for (Opens opens : md.opens()) {
assertUnmodifiable(opens.modifiers(), Opens.Modifier.SYNTHETIC);
assertUnmodifiable(opens.targets(), "target");
@@ -79,7 +149,7 @@
assertUnmodifiable(md.uses(), "use");
assertUnmodifiable(md.provides(),
- jlma.newProvides("provide", List.of("provide")));
+ JLMA.newProvides("provide", List.of("provide")));
for (Provides provides : md.provides()) {
assertUnmodifiable(provides.providers(), "provide");
}
--- a/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/UserModuleTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/UserModuleTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -22,13 +22,20 @@
*/
import java.io.File;
+import java.io.IOException;
+import java.lang.module.ModuleDescriptor;
+import java.lang.reflect.Layer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
+import java.util.Set;
+import java.util.spi.ToolProvider;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import jdk.testlibrary.FileUtils;
+
import static jdk.testlibrary.ProcessTools.*;
@@ -38,6 +45,7 @@
/**
* @test
+ * @bug 8142968 8173381
* @library /lib/testlibrary
* @modules jdk.compiler jdk.jlink
* @build UserModuleTest CompilerUtils jdk.testlibrary.FileUtils jdk.testlibrary.ProcessTools
@@ -50,8 +58,9 @@
private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
private static final Path MODS_DIR = Paths.get("mods");
+ private static final Path JMODS_DIR = Paths.get("jmods");
+
private static final Path IMAGE = Paths.get("image");
- private static final Path JMODS = Paths.get(JAVA_HOME, "jmods");
private static final String MAIN_MID = "m1/p1.Main";
// the names of the modules in this test
@@ -59,7 +68,7 @@
private static boolean hasJmods() {
- if (!Files.exists(JMODS)) {
+ if (!Files.exists(Paths.get(JAVA_HOME, "jmods"))) {
System.err.println("Test skipped. NO jmods directory");
return false;
}
@@ -75,25 +84,17 @@
for (String mn : modules) {
Path msrc = SRC_DIR.resolve(mn);
- assertTrue(CompilerUtils.compile(msrc, MODS_DIR, "--module-source-path", SRC_DIR.toString()));
+ assertTrue(CompilerUtils.compile(msrc, MODS_DIR,
+ "--module-source-path", SRC_DIR.toString()));
}
if (Files.exists(IMAGE)) {
FileUtils.deleteFileTreeUnchecked(IMAGE);
}
- createImage(IMAGE, "java.base", "m1", "m3");
- }
+ createImage(IMAGE, "m1", "m3");
- private void createImage(Path outputDir, String... modules) throws Throwable {
- Path jlink = Paths.get(JAVA_HOME, "bin", "jlink");
- String mp = JMODS.toString() + File.pathSeparator + MODS_DIR.toString();
- assertTrue(executeProcess(jlink.toString(), "--output", outputDir.toString(),
- "--add-modules", Arrays.stream(modules).collect(Collectors.joining(",")),
- "--module-path", mp)
- .outputTo(System.out)
- .errorTo(System.out)
- .getExitValue() == 0);
+ createJmods("m1", "m4");
}
/*
@@ -120,9 +121,9 @@
Path java = IMAGE.resolve("bin").resolve("java");
assertTrue(executeProcess(java.toString(), "-m", "m3/p3.Main")
- .outputTo(System.out)
- .errorTo(System.out)
- .getExitValue() == 0);
+ .outputTo(System.out)
+ .errorTo(System.out)
+ .getExitValue() == 0);
}
/*
@@ -150,12 +151,114 @@
public void testDedupSet() throws Throwable {
if (!hasJmods()) return;
- Path dir = Paths.get("newImage");
- createImage(dir, "java.base", "m1", "m2", "m3", "m4");
+ Path dir = Paths.get("dedupSetTest");
+ createImage(dir, "m1", "m2", "m3", "m4");
Path java = dir.resolve("bin").resolve("java");
assertTrue(executeProcess(java.toString(), "-m", MAIN_MID)
.outputTo(System.out)
.errorTo(System.out)
.getExitValue() == 0);
}
+
+ private void createJmods(String... modules) throws IOException {
+ // use the same target platform as in java.base
+ ModuleDescriptor md = Layer.boot().findModule("java.base").get()
+ .getDescriptor();
+ String osName = md.osName().get();
+ String osArch = md.osArch().get();
+
+ // create JMOD files
+ Files.createDirectories(JMODS_DIR);
+ Stream.of(modules).forEach(mn ->
+ assertTrue(jmod("create",
+ "--class-path", MODS_DIR.resolve(mn).toString(),
+ "--os-name", osName,
+ "--os-arch", osArch,
+ "--main-class", mn.replace('m', 'p') + ".Main",
+ JMODS_DIR.resolve(mn + ".jmod").toString()) == 0)
+ );
+ }
+
+
+ /**
+ * Verify the module descriptor if package p4.dummy is excluded at link time.
+ */
+ @Test
+ public void testModulePackagesAttribute() throws Throwable {
+ if (!hasJmods()) return;
+
+ // create an image using JMOD files
+ Path dir = Paths.get("packagesTest");
+ String mp = Paths.get(JAVA_HOME, "jmods").toString() +
+ File.pathSeparator + JMODS_DIR.toString();
+
+ Set<String> modules = Set.of("m1", "m4");
+ assertTrue(JLINK_TOOL.run(System.out, System.out,
+ "--output", dir.toString(),
+ "--exclude-resources", "m4/p4/dummy/*",
+ "--add-modules", modules.stream().collect(Collectors.joining(",")),
+ "--module-path", mp) == 0);
+
+ // verify ModuleDescriptor
+ Path java = dir.resolve("bin").resolve("java");
+ assertTrue(executeProcess(java.toString(),
+ "--add-modules=m1", "-m", "m4")
+ .outputTo(System.out)
+ .errorTo(System.out)
+ .getExitValue() == 0);
+ }
+
+ /**
+ * Verify the plugin to retain ModuleTarget attribute
+ */
+ @Test
+ public void testRetainModuleTarget() throws Throwable {
+ if (!hasJmods()) return;
+
+ // create an image using JMOD files
+ Path dir = Paths.get("retainModuleTargetTest");
+ String mp = Paths.get(JAVA_HOME, "jmods").toString() +
+ File.pathSeparator + JMODS_DIR.toString();
+
+ Set<String> modules = Set.of("m1", "m4");
+ assertTrue(JLINK_TOOL.run(System.out, System.out,
+ "--output", dir.toString(),
+ "--system-modules", "retainModuleTarget",
+ "--exclude-resources", "m4/p4/dummy/*",
+ "--add-modules", modules.stream().collect(Collectors.joining(",")),
+ "--module-path", mp) == 0);
+
+ // verify ModuleDescriptor
+ Path java = dir.resolve("bin").resolve("java");
+ assertTrue(executeProcess(java.toString(),
+ "--add-modules=m1", "-m", "m4", "retainModuleTarget")
+ .outputTo(System.out)
+ .errorTo(System.out)
+ .getExitValue() == 0);
+ }
+
+ static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink")
+ .orElseThrow(() ->
+ new RuntimeException("jlink tool not found")
+ );
+
+ static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod")
+ .orElseThrow(() ->
+ new RuntimeException("jmod tool not found")
+ );
+
+ static final String MODULE_PATH = Paths.get(JAVA_HOME, "jmods").toString()
+ + File.pathSeparator + MODS_DIR.toString();
+
+ private void createImage(Path outputDir, String... modules) throws Throwable {
+ assertTrue(JLINK_TOOL.run(System.out, System.out,
+ "--output", outputDir.toString(),
+ "--add-modules", Arrays.stream(modules).collect(Collectors.joining(",")),
+ "--module-path", MODULE_PATH) == 0);
+ }
+
+ private static int jmod(String... options) {
+ System.out.println("jmod " + Arrays.asList(options));
+ return JMOD_TOOL.run(System.out, System.out, options);
+ }
}
--- a/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m1/p1/Main.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m1/p1/Main.java Thu Feb 09 23:15:52 2017 +0100
@@ -23,7 +23,10 @@
package p1;
+import java.io.IOException;
import java.lang.module.ModuleDescriptor;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
@@ -37,25 +40,48 @@
// load another package
p2.T.test();
- // check the module descriptor of a system module
- validate(Main.class.getModule().getDescriptor());
+ // validate the module descriptor
+ validate(Main.class.getModule());
+
+ // validate the Moduletarget attribute for java.base
+ ModuleDescriptor md = Layer.boot().findModule("java.base").get()
+ .getDescriptor();
+ if (!md.osName().isPresent() || !md.osArch().isPresent() ||
+ !md.osVersion().isPresent()) {
+ throw new RuntimeException("java.base: " + md.osName() + " " +
+ md.osArch() + " " + md.osVersion());
+ }
+ }
+
+ static void validate(Module module) throws IOException {
+ ModuleDescriptor md = module.getDescriptor();
// read m1/module-info.class
FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"),
Collections.emptyMap());
- Path path = fs.getPath("/", "modules", "m1", "module-info.class");
- validate(ModuleDescriptor.read(Files.newInputStream(path)));
- }
+ Path path = fs.getPath("/", "modules", module.getName(), "module-info.class");
+ ModuleDescriptor md1 = ModuleDescriptor.read(Files.newInputStream(path));
+
- static void validate(ModuleDescriptor md) {
+ // check the module descriptor of a system module and read from jimage
checkPackages(md.packages(), "p1", "p2");
+ checkPackages(md1.packages(), "p1", "p2");
+
+ // check ModuleTarget attribute
+ checkModuleTargetAttribute(md);
+ checkModuleTargetAttribute(md1);
}
static void checkPackages(Set<String> pkgs, String... expected) {
- for (String pn : expected) {
- if (!pkgs.contains(pn)) {
- throw new RuntimeException(pn + " missing in " + pkgs);
- }
+ if (!pkgs.equals(Set.of(expected))) {
+ throw new RuntimeException(pkgs + " expected: " + Set.of(expected));
+ }
+ }
+
+ static void checkModuleTargetAttribute(ModuleDescriptor md) {
+ if (md.osName().isPresent() || md.osArch().isPresent() ||
+ md.osVersion().isPresent()) {
+ throw new RuntimeException(md.osName() + " " + md.osArch() + " " + md.osVersion());
}
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m4/p4/Main.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2017, 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 p4;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.reflect.Layer;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.Set;
+
+public class Main {
+ // the system module plugin by default drops ModuleTarget attribute
+ private static boolean expectModuleTarget = false;
+ public static void main(String... args) throws IOException {
+ if (args.length > 0) {
+ if (!args[0].equals("retainModuleTarget")) {
+ throw new IllegalArgumentException(args[0]);
+ }
+
+ expectModuleTarget = true;
+ }
+
+ // java.base is packaged with osName/osArch/osVersion
+ ModuleDescriptor md = Layer.boot().findModule("java.base").get()
+ .getDescriptor();
+ if (!md.osName().isPresent() ||
+ !md.osArch().isPresent() ||
+ !md.osVersion().isPresent()) {
+ throw new RuntimeException("osName/osArch/osVersion is missing: " +
+ md.osName() + " " + md.osArch() + " " + md.osVersion());
+ }
+
+ // verify module-info.class for m1 and m4
+ checkModule("m1", "p1", "p2");
+ checkModule("m4", "p4");
+ }
+
+ private static void checkModule(String mn, String... packages) throws IOException {
+ // verify ModuleDescriptor from the runtime module
+ ModuleDescriptor md = Layer.boot().findModule(mn).get()
+ .getDescriptor();
+ checkModuleDescriptor(md, packages);
+
+ // verify ModuleDescriptor from module-info.class read from ModuleReader
+ try (InputStream in = ModuleFinder.ofSystem().find(mn).get()
+ .open().open("module-info.class").get()) {
+ checkModuleDescriptor(ModuleDescriptor.read(in), packages);
+ }
+
+ // verify ModuleDescriptor from module-info.class read from jimage
+ FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"),
+ Collections.emptyMap());
+ Path path = fs.getPath("/", "modules", mn, "module-info.class");
+ checkModuleDescriptor(ModuleDescriptor.read(Files.newInputStream(path)), packages);
+ }
+
+ static void checkModuleDescriptor(ModuleDescriptor md, String... packages) {
+ String mainClass = md.name().replace('m', 'p') + ".Main";
+ if (!md.mainClass().get().equals(mainClass)) {
+ throw new RuntimeException(md.mainClass().toString());
+ }
+
+ if (expectModuleTarget) {
+ // ModuleTarget attribute is retained
+ if (!md.osName().isPresent() || !md.osArch().isPresent()) {
+ throw new RuntimeException("osName or osArch is missing: " +
+ md.osName() + " " + md.osArch());
+ }
+ } else {
+ // by default ModuleTarget attribute is dropped
+ if (md.osName().isPresent() || md.osArch().isPresent()) {
+ throw new RuntimeException("osName and osArch should not be set: " +
+ md.osName() + " " + md.osArch());
+ }
+ }
+
+ if (md.osVersion().isPresent()) {
+ throw new RuntimeException("Expected no osVersion set: " + md.osVersion());
+ }
+
+ Set<String> pkgs = md.packages();
+ if (!pkgs.equals(Set.of(packages))) {
+ throw new RuntimeException(pkgs + " expected: " + Set.of(packages));
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/plugins/SystemModuleDescriptors/src/m4/p4/dummy/dummy.properties Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,1 @@
+key=dummy
--- a/jdk/test/tools/launcher/ArgsEnvVar.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/tools/launcher/ArgsEnvVar.java Thu Feb 09 23:15:52 2017 +0100
@@ -40,7 +40,7 @@
private static File testJar = null;
private static Map<String, String> env = new HashMap<>();
- private static String JAVA_OPTIONS = "JAVA_OPTIONS";
+ private static String JDK_JAVA_OPTIONS = "JDK_JAVA_OPTIONS";
static void init() throws IOException {
if (testJar != null) {
@@ -105,7 +105,7 @@
File argFile2 = createArgFile("argFile2", List.of("-Darg.file2=TWO"));
File argFile3 = createArgFile("argFile3", List.of("-Darg.file3=THREE"));
- env.put(JAVA_OPTIONS, "@argFile1\n-Xint\r-cp @@escaped\t@argFile2");
+ env.put(JDK_JAVA_OPTIONS, "@argFile1\n-Xint\r-cp @@escaped\t@argFile2");
TestResult tr = doExec(env, javaCmd, "@argFile3", "-cp", "test.jar", "Foo", "uarg1", "@uarg2");
@@ -133,13 +133,13 @@
}
private TestResult testInEnv(List<String> options) {
- env.put(JAVA_OPTIONS, String.join(" ", options));
+ env.put(JDK_JAVA_OPTIONS, String.join(" ", options));
return doExec(env, javaCmd, "-jar", "test.jar");
}
private TestResult testInEnvAsArgFile(List<String> options) throws IOException {
File argFile = createArgFile("argFile", options);
- env.put(JAVA_OPTIONS, "@argFile");
+ env.put(JDK_JAVA_OPTIONS, "@argFile");
TestResult tr = doExec(env, javaCmd, "-jar", "test.jar");
argFile.delete();
return tr;
@@ -187,7 +187,7 @@
File argFile1 = createArgFile("arg File 1", List.of("-Xint"));
File argFile2 = createArgFile("arg File 2", List.of("-Dprop='value with spaces'"));
File argFile3 = createArgFile("arg File 3", List.of("-Xmx32m"));
- env.put(JAVA_OPTIONS, "'@arg File 1' @\"arg File 2\" @'arg File'\" 3\"");
+ env.put(JDK_JAVA_OPTIONS, "'@arg File 1' @\"arg File 2\" @'arg File'\" 3\"");
TestResult tr = doExec(env, javaCmd, "-jar", "test.jar");
List<String> options = new ArrayList<>();
@@ -204,7 +204,7 @@
@Test
public void openQuoteShouldFail() {
- env.put(JAVA_OPTIONS, "-Dprop='value missing close quote");
+ env.put(JDK_JAVA_OPTIONS, "-Dprop='value missing close quote");
TestResult tr = doExec(env, javaCmd, "-version");
tr.checkNegative();
if (!tr.testStatus) {
@@ -215,11 +215,11 @@
@Test
public void noWildcard() {
- env.put(JAVA_OPTIONS, "-cp *");
+ env.put(JDK_JAVA_OPTIONS, "-cp *");
TestResult tr = doExec(env, javaCmd, "-jar", "test.jar");
verifyOptions(List.of("-cp", "*", "-jar", "test.jar"), tr);
- env.put(JAVA_OPTIONS, "-p ?");
+ env.put(JDK_JAVA_OPTIONS, "-p ?");
tr = doExec(env, javaCmd, "-jar", "test.jar", "one", "two");
verifyOptions(List.of("-p", "?", "-jar", "test.jar", "one", "two"), tr);
}
--- a/jdk/test/tools/launcher/I18NArgTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/tools/launcher/I18NArgTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -95,13 +95,13 @@
throw new RuntimeException("test fails");
}
- // Test via JAVA_OPTIONS
+ // Test via JDK_JAVA_OPTIONS
Map<String, String> env = new HashMap<>();
String cmd = "-Dtest.src=" + TEST_SOURCES_DIR.getAbsolutePath() +
" -Dtest.classes=" + TEST_CLASSES_DIR.getAbsolutePath() +
" -cp " + TEST_CLASSES_DIR.getAbsolutePath() +
" I18NArgTest " + unicodeStr + " " + hexValue;
- env.put("JAVA_OPTIONS", cmd);
+ env.put("JDK_JAVA_OPTIONS", cmd);
tr = doExec(env, javaCmd);
System.out.println(tr.testOutput);
if (!tr.isOK()) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/LauncherMessageTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2017, 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 8167063
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.FileUtils
+ * @run main LauncherMessageTest
+ * @summary LauncherHelper should not throw JNI error for LinkageError
+ */
+import java.io.File;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import jdk.testlibrary.FileUtils;
+
+public class LauncherMessageTest {
+
+ public static void main(String[] args) throws Exception {
+ String userDir = System.getProperty("user.dir", ".");
+ File testDir = new File(userDir, "test");
+ List<String> srcContent = new ArrayList<>();
+
+ // Try to create a test directory before proceeding further
+ if (!testDir.mkdir()) {
+ throw new Exception("Test failed: unable to create"
+ + " writable working directory "
+ + testDir.getAbsolutePath());
+ }
+
+ // Create test sub-directories for sources, classes and modules respectively
+ File srcA = new File(testDir.getPath(), "srcA");
+ srcA.mkdir();
+ File srcB = new File(testDir.getPath(), "srcB");
+ srcB.mkdir();
+ File classesA = new File(testDir.getPath(), "classesA");
+ classesA.mkdir();
+ File classesB = new File(testDir.getPath(), "classesB");
+ classesB.mkdir();
+ File modules = new File(testDir.getPath(), "modules");
+ modules.mkdir();
+
+ // Define content and create module-info.java and corresponding source files
+ File modAinfo = new File(srcA.getPath(), "module-info.java");
+ srcContent.add("module mod.a { exports pkgA; }");
+ TestHelper.createFile(modAinfo, srcContent);
+
+ File classA = new File(srcA.getPath(), "ClassA.java");
+ srcContent.clear();
+ srcContent.add("package pkgA; public class ClassA { }");
+ TestHelper.createFile(classA, srcContent);
+
+ File modBinfo = new File(srcB.getPath(), "module-info.java");
+ srcContent.clear();
+ srcContent.add("module mod.b { requires mod.a; }");
+ TestHelper.createFile(modBinfo, srcContent);
+
+ File classB = new File(srcB.getPath(), "ClassB.java");
+ srcContent.clear();
+ srcContent.add("package pkgB;");
+ srcContent.add("import pkgA.ClassA;");
+ srcContent.add("public class ClassB extends ClassA {");
+ srcContent.add("public static void main(String[] args) { } }");
+ TestHelper.createFile(classB, srcContent);
+
+ // Compile all source files and create Jars
+ TestHelper.compile("-d", classesA.getPath(), classA.getPath(), modAinfo.getPath());
+ TestHelper.createJar("cf", Paths.get(modules.getPath(), "mod.a.jar").toString(),
+ "-C", classesA.getPath(), ".");
+ TestHelper.compile("-d", classesB.getPath(), "--module-path", modules.getPath(),
+ classB.getPath(), modBinfo.getPath());
+ TestHelper.createJar("cf", Paths.get(modules.getPath(), "mod.b.jar").toString(),
+ "-C", classesB.getPath(), ".");
+
+ // Delete the module-info.java and Jar file corresponding to mod.a
+ FileUtils.deleteFileWithRetry(Paths.get(modAinfo.getPath()));
+ FileUtils.deleteFileWithRetry(Paths.get(modules.getPath(), "mod.a.jar"));
+
+ // Re-create module-info.java (by removing "exports pkgA;")
+ // and corresponding Jar file
+ srcContent.clear();
+ srcContent.add("module mod.a { }");
+ TestHelper.createFile(modAinfo, srcContent);
+ TestHelper.compile("-d", classesA.getPath(), classA.getPath(), modAinfo.getPath());
+ TestHelper.createJar("cf", Paths.get(modules.getPath(), "mod.a.jar").toString(),
+ "-C", classesA.getPath(), ".");
+
+ // Execute the main class
+ String[] commands = {TestHelper.javaCmd, "--module-path", modules.getPath(),
+ "-m", "mod.b/pkgB.ClassB"};
+ TestHelper.TestResult result = TestHelper.doExec(commands);
+
+ // Clean the test directory and check test status
+ FileUtils.deleteFileTreeWithRetry(Paths.get(testDir.getPath()));
+ if (result.isOK()) {
+ throw new Exception("Test Passed Unexpectedly!");
+ } else {
+ result.testOutput.forEach(System.err::println);
+ if (result.contains("JNI error")) {
+ throw new Exception("Test Failed with JNI error!");
+ }
+ }
+ System.out.println("Test passes, failed with expected error message");
+ }
+}
--- a/jdk/test/tools/launcher/modules/addmods/AddModsTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/tools/launcher/modules/addmods/AddModsTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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
@@ -98,7 +98,7 @@
}
/**
- * Basic test of --add-modules ALL-DEFAULT. Module java.annotations.common
+ * Basic test of --add-modules ALL-DEFAULT. Module java.xml.ws.annotation
* should not resolved and so the types in that module should not be
* visible.
*/
--- a/jdk/test/tools/launcher/modules/listmods/ListModsTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/jdk/test/tools/launcher/modules/listmods/ListModsTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -147,7 +147,7 @@
@Test
public void testListWithLimitMods1() throws Exception {
OutputAnalyzer output
- = executeTestJava("--limit-modules", "java.management", "--list-modules")
+ = executeTestJava("--limit-modules", "java.management.rmi", "--list-modules")
.outputTo(System.out)
.errorTo(System.out);
output.shouldContain("java.rmi");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/schemagen/MultiReleaseJarTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2017, 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
+ * @summary Test Multi-Release jar support in schemagen tool
+ * @library /test/lib
+ * @library /lib/testlibrary
+ * @modules jdk.compiler java.xml.ws
+ * @build jdk.test.lib.JDKToolFinder jdk.test.lib.JDKToolLauncher
+ * jdk.test.lib.process.OutputAnalyzer
+ * jdk.test.lib.process.ProcessTools
+ * jdk.test.lib.Utils
+ * CompilerUtils MultiReleaseJarTest
+ * @run testng MultiReleaseJarTest
+ */
+
+import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.Utils;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.stream.Stream;
+
+import static org.testng.Assert.assertTrue;
+
+public class MultiReleaseJarTest {
+ private static final int SUCCESS = 0;
+
+ @DataProvider(name = "jarFiles")
+ public Object[][] jarFiles() {
+ return new Object[][]{{"MV_BOTH.jar", 9},
+ {"MV_ONLY_9.jar", 9},
+ {"NON_MV.jar", 8}};
+ }
+
+ @BeforeClass
+ public void setUpTest() throws Throwable {
+ compile();
+ Path classes = Paths.get("classes");
+ jar("cf", "MV_BOTH.jar",
+ "-C", classes.resolve("base").toString(), ".",
+ "--release", "9", "-C", classes.resolve("v9").toString(), ".",
+ "--release", "10", "-C", classes.resolve("v10").toString(), ".")
+ .shouldHaveExitValue(SUCCESS);
+
+ jar("cf", "MV_ONLY_9.jar",
+ "-C", classes.resolve("base").toString(), ".",
+ "--release", "9", "-C", classes.resolve("v9").toString(), ".")
+ .shouldHaveExitValue(SUCCESS);
+ jar("cf", "NON_MV.jar",
+ "-C", classes.resolve("base").toString(), ".")
+ .shouldHaveExitValue(SUCCESS);
+ }
+
+ @Test(dataProvider = "jarFiles")
+ public void testSchemagen(String jar, int mainVer) throws Throwable {
+ JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("schemagen");
+ Utils.getForwardVmOptions().forEach(launcher::addToolArg);
+ launcher.addToolArg("-cp").addToolArg(jar)
+ .addToolArg("schemagen.Person");
+ ProcessTools.executeCommand(launcher.getCommand())
+ .shouldHaveExitValue(SUCCESS);
+
+ String pattern = "version" + mainVer;
+ assertTrue(grep(pattern, Paths.get("schema1.xsd")),
+ "Pattern " + pattern + " not found in the generated file.");
+ }
+
+ private boolean grep(String pattern, Path file) throws IOException {
+ return new String(Files.readAllBytes(file)).contains(pattern);
+ }
+
+ private OutputAnalyzer jar(String... args) throws Throwable {
+ JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jar");
+ Stream.of(args).forEach(launcher::addToolArg);
+ return ProcessTools.executeCommand(launcher.getCommand());
+ }
+
+ private void compile() throws Throwable {
+ String[] vers = {"base", "v9", "v10"};
+ for (String ver : vers) {
+ Path classes = Paths.get("classes", ver);
+ Files.createDirectories(classes);
+ Path source = Paths.get(Utils.TEST_SRC,"data", "mr", ver);
+ assertTrue(CompilerUtils.compile(source, classes,
+ "--add-modules", "java.xml.ws"));
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/schemagen/data/mr/base/schemagen/Person.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017, 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 schemagen;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+public class Person {
+
+ @XmlAttribute
+ private String version8;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/schemagen/data/mr/v10/schemagen/Person.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017, 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 schemagen;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+public class Person {
+
+ @XmlAttribute
+ private String version10;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/schemagen/data/mr/v9/schemagen/Person.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017, 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 schemagen;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+public class Person {
+
+ @XmlAttribute
+ private String version9;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/wsgen/MultiReleaseJarTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2017, 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
+ * @summary Test Multi-Release jar support in wsgen tool
+ * @library /test/lib
+ * @library /lib/testlibrary
+ * @modules jdk.compiler java.xml.ws
+ * @build jdk.test.lib.JDKToolFinder jdk.test.lib.JDKToolLauncher
+ * jdk.test.lib.process.OutputAnalyzer
+ * jdk.test.lib.process.ProcessTools
+ * jdk.test.lib.Utils
+ * CompilerUtils MultiReleaseJarTest
+ * @run testng MultiReleaseJarTest
+ */
+
+import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.Utils;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.stream.Stream;
+
+import static org.testng.Assert.assertTrue;
+
+public class MultiReleaseJarTest {
+ private static final int SUCCESS = 0;
+
+ @DataProvider(name = "jarFiles")
+ public Object[][] jarFiles() {
+ return new Object[][]{{"MV_BOTH.jar", 9},
+ {"MV_ONLY_9.jar", 9},
+ {"NON_MV.jar", 8}};
+ }
+
+ @BeforeClass
+ public void setUpTest() throws Throwable {
+ compile();
+ Path classes = Paths.get("classes");
+ jar("cf", "MV_BOTH.jar",
+ "-C", classes.resolve("base").toString(), ".",
+ "--release", "9", "-C", classes.resolve("v9").toString(), ".",
+ "--release", "10", "-C", classes.resolve("v10").toString(), ".")
+ .shouldHaveExitValue(SUCCESS);
+
+ jar("cf", "MV_ONLY_9.jar",
+ "-C", classes.resolve("base").toString(), ".",
+ "--release", "9", "-C", classes.resolve("v9").toString(), ".")
+ .shouldHaveExitValue(SUCCESS);
+ jar("cf", "NON_MV.jar",
+ "-C", classes.resolve("base").toString(), ".")
+ .shouldHaveExitValue(SUCCESS);
+ }
+
+
+ @Test(dataProvider = "jarFiles")
+ public void testWsgen(String jar, int mainVer) throws Throwable {
+ JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("wsgen");
+ Utils.getForwardVmOptions().forEach(launcher::addToolArg);
+ launcher.addToolArg("-cp").addToolArg(jar)
+ .addToolArg("-keep")
+ .addToolArg("wsgen.TestServer");
+ ProcessTools.executeCommand(launcher.getCommand())
+ .shouldHaveExitValue(SUCCESS);
+
+ String pattern = "version" + mainVer;
+ assertTrue(grep(pattern,
+ Paths.get("wsgen/jaxws/GetJavaVersion.java")),
+ "Pattern " + pattern + " not found in the generated file.");
+ }
+
+ private boolean grep(String pattern, Path file) throws IOException {
+ return new String(Files.readAllBytes(file)).contains(pattern);
+ }
+
+ private OutputAnalyzer jar(String... args) throws Throwable {
+ JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jar");
+ Stream.of(args).forEach(launcher::addToolArg);
+ return ProcessTools.executeCommand(launcher.getCommand());
+ }
+
+ private void compile() throws Throwable {
+ String[] vers = {"base", "v9", "v10"};
+ for (String ver : vers) {
+ Path classes = Paths.get("classes", ver);
+ Files.createDirectories(classes);
+ Path source = Paths.get(Utils.TEST_SRC,"data", "mr", ver);
+ assertTrue(CompilerUtils.compile(source, classes,
+ "--add-modules", "java.xml.ws"));
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/wsgen/data/mr/base/wsgen/TestServer.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017, 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 wsgen;
+
+import javax.jws.WebMethod;
+import javax.jws.WebService;
+
+@WebService
+public class TestServer {
+
+ @WebMethod(operationName = "version8")
+ public String getJavaVersion() {
+ return "8";
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/wsgen/data/mr/v10/wsgen/TestServer.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017, 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 wsgen;
+
+import javax.jws.WebMethod;
+import javax.jws.WebService;
+
+@WebService
+public class TestServer {
+
+ @WebMethod(operationName = "version10")
+ public String getJavaVersion() {
+ return "10";
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/wsgen/data/mr/v9/wsgen/TestServer.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017, 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 wsgen;
+
+import javax.jws.WebMethod;
+import javax.jws.WebService;
+
+@WebService
+public class TestServer {
+
+ @WebMethod(operationName = "version9")
+ public String getJavaVersion() {
+ return "9";
+ }
+}
\ No newline at end of file
--- a/langtools/.hgtags Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/.hgtags Thu Feb 09 23:15:52 2017 +0100
@@ -396,3 +396,5 @@
4f348bd05341581df84ff1510d5b3a9b5b488367 jdk-9+151
5b6f12de6f9167a582fa2c6ac54e69c591b09e68 jdk-9+152
03f48cd283f5dd6b7153fd7e0cf2df8582b14391 jdk-9+153
+6a9dd3d893b0a493a3e5d8d392815b5ee76a02d9 jdk-9+154
+dfcfdb2db85f1bb434209f56ca557ea6f9830aa8 jdk-9+155
--- a/langtools/src/java.compiler/share/classes/javax/annotation/processing/AbstractProcessor.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/java.compiler/share/classes/javax/annotation/processing/AbstractProcessor.java Thu Feb 09 23:15:52 2017 +0100
@@ -83,7 +83,7 @@
if (so == null)
return Collections.emptySet();
else
- return arrayToSet(so.value());
+ return arrayToSet(so.value(), false);
}
/**
@@ -92,21 +92,31 @@
* same set of strings as the annotation. If the class is not so
* annotated, an empty set is returned.
*
+ * If the {@link ProcessingEvironment#getSourceVersion source
+ * version} does not support modules, in other words if it is less
+ * than or equal to {@link SourceVersion#RELEASE_8 RELEASE_8},
+ * then any leading {@link Processor#getSupportedAnnotationTypes
+ * module prefixes} are stripped from the names.
+ *
* @return the names of the annotation types supported by this
* processor, or an empty set if none
*/
public Set<String> getSupportedAnnotationTypes() {
SupportedAnnotationTypes sat = this.getClass().getAnnotation(SupportedAnnotationTypes.class);
+ boolean initialized = isInitialized();
if (sat == null) {
- if (isInitialized())
+ if (initialized)
processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,
"No SupportedAnnotationTypes annotation " +
"found on " + this.getClass().getName() +
", returning an empty set.");
return Collections.emptySet();
+ } else {
+ boolean stripModulePrefixes =
+ initialized &&
+ processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_8) <= 0;
+ return arrayToSet(sat.value(), stripModulePrefixes);
}
- else
- return arrayToSet(sat.value());
}
/**
@@ -185,11 +195,18 @@
return initialized;
}
- private static Set<String> arrayToSet(String[] array) {
+ private static Set<String> arrayToSet(String[] array,
+ boolean stripModulePrefixes) {
assert array != null;
Set<String> set = new HashSet<>(array.length);
- for (String s : array)
+ for (String s : array) {
+ if (stripModulePrefixes) {
+ int index = s.indexOf('/');
+ if (index != -1)
+ s = s.substring(index + 1);
+ }
set.add(s);
+ }
return Collections.unmodifiableSet(set);
}
}
--- a/langtools/src/java.compiler/share/classes/javax/annotation/processing/Filer.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/java.compiler/share/classes/javax/annotation/processing/Filer.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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
@@ -264,7 +264,7 @@
* @param moduleAndPkg module and/or package relative to which the file
* should be named, or the empty string if none
* @param relativeName final pathname components of the file
- * @param originatingElements type or package elements causally
+ * @param originatingElements type or package or module elements causally
* associated with the creation of this file, may be elided or
* {@code null}
* @return a {@code FileObject} to write the new resource
--- a/langtools/src/java.compiler/share/classes/javax/annotation/processing/FilerException.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/java.compiler/share/classes/javax/annotation/processing/FilerException.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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,7 +31,7 @@
* Indicates a {@link Filer} detected an attempt to open a file that
* would violate the guarantees provided by the {@code Filer}. Those
* guarantees include not creating the same file more than once, not
- * creating multiple files corresponding to the same type, and not
+ * creating multiple files corresponding to the same type or package, and not
* creating files for types with invalid names.
*
* @author Joseph D. Darcy
--- a/langtools/src/java.compiler/share/classes/javax/annotation/processing/Processor.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/java.compiler/share/classes/javax/annotation/processing/Processor.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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
@@ -194,7 +194,7 @@
* <p>The {@link Filer} interface discusses restrictions on how
* processors can operate on files.
*
- * <p>Note that implementors of this interface may find it convenient
+ * @apiNote Implementors of this interface may find it convenient
* to extend {@link AbstractProcessor} rather than implementing this
* interface directly.
*
@@ -254,6 +254,14 @@
* a.B} which reside in different modules. To only support {@code
* a.B} in the {@code Foo} module, instead use {@code "Foo/a.B"}.
*
+ * If a module name is included, only an annotation in that module
+ * is matched. In particular, if a module name is given in an
+ * environment where modules are not supported, such as an
+ * annotation processing environment configured for a {@linkplain
+ * javax.annotation.processing.ProcessingEnvironment#getSourceVersion
+ * source version} without modules, then the annotation types with
+ * a module name do <em>not</em> match.
+ *
* Finally, {@code "*"} by itself represents the set of all
* annotation types, including the empty set. Note that a
* processor should not claim {@code "*"} unless it is actually
@@ -280,6 +288,14 @@
* where <i>TypeName</i> is as defined in
* <cite>The Java™ Language Specification</cite>.
*
+ * @apiNote When running in an environment which supports modules,
+ * processors are encouraged to include the module prefix when
+ * describing their supported annotation types. The method {@link
+ * AbstractProcessor.getSupportedAnnotationTypes
+ * AbstractProcessor.getSupportedAnnotationTypes} provides support
+ * for stripping off the module prefix when running in an
+ * environment without modules.
+ *
* @return the names of the annotation types supported by this processor
* @see javax.annotation.processing.SupportedAnnotationTypes
* @jls 3.8 Identifiers
@@ -315,7 +331,7 @@
* is returned, the annotation types are unclaimed and subsequent
* processors may be asked to process them. A processor may
* always return the same boolean value or may vary the result
- * based on chosen criteria.
+ * based on its own chosen criteria.
*
* <p>The input set will be empty if the processor supports {@code
* "*"} and the root elements have no annotations. A {@code
@@ -343,8 +359,8 @@
* <p>Since incomplete programs are being modeled, some of the
* parameters may only have partial information or may be {@code
* null}. At least one of {@code element} and {@code userText}
- * must be non-{@code null}. If {@code element} is non-{@code
- * null}, {@code annotation} and {@code member} may be {@code
+ * must be non-{@code null}. If {@code element} is non-{@code null},
+ * {@code annotation} and {@code member} may be {@code
* null}. Processors may not throw a {@code NullPointerException}
* if some parameters are {@code null}; if a processor has no
* completions to offer based on the provided information, an
--- a/langtools/src/java.compiler/share/classes/javax/annotation/processing/RoundEnvironment.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/java.compiler/share/classes/javax/annotation/processing/RoundEnvironment.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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
@@ -65,7 +65,7 @@
boolean errorRaised();
/**
- * Returns the root elements for annotation processing generated
+ * Returns the {@linkplain Processor root elements} for annotation processing generated
* by the prior round.
*
* @return the root elements for annotation processing generated
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/AnnotatedConstruct.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/AnnotatedConstruct.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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
@@ -62,7 +62,7 @@
*
* If there are multiple annotations of type <i>AT</i> present on
* <i>C</i>, then if <i>AT</i> is repeatable annotation type, an
- * annotation of type <i>ATC</i> is implicitly declared on <i>C</i>.
+ * annotation of type <i>ATC</i> is {@linkplain javax.lang.model.util.Elements#getOrigin(AnnotatedConstruct, AnnotationMirror) implicitly declared} on <i>C</i>.
*
* <li> A representation of <i>A</i> appears in the executable output
* for <i>C</i>, such as the {@code RuntimeVisibleAnnotations} or
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/UnknownEntityException.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/UnknownEntityException.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2017, 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,8 +32,9 @@
* this exception may be thrown by visitors to indicate that the
* visitor was created for a prior version of the language.
*
- * <p>A common superclass for those exceptions allows a single catch
- * block to have code handling them uniformly.
+ * @apiNote A common superclass for exceptions specific to different
+ * kinds of unknown entities allows a single catch block to easily
+ * provide uniform handling of those related conditions.
*
* @author Joseph D. Darcy
* @see javax.lang.model.element.UnknownElementException
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/element/Element.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/element/Element.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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,7 +37,7 @@
/**
- * Represents a program element such as a package, class, or method.
+ * Represents a program element such as a module, package, class, or method.
* Each element represents a static, language-level construct
* (and not, for example, a runtime construct of the virtual machine).
*
@@ -139,7 +139,7 @@
*
* <li> If this is a {@linkplain
* PackageElement#getEnclosingElement package}, its module is
- * returned.
+ * returned if such a module exists. Otherwise, {@code null} is returned.
*
* <li> If this is a {@linkplain
* TypeParameterElement#getEnclosingElement type parameter},
@@ -176,11 +176,14 @@
* A {@linkplain ModuleElement#getEnclosedElements module}
* encloses packages within it.
*
+ * Enclosed elements may include implicitly declared {@linkplain
+ * Elements.Origin#MANDATED mandated} elements.
+ *
* Other kinds of elements are not currently considered to enclose
* any elements; however, that may change as this API or the
* programming language evolves.
*
- * <p>Note that elements of certain kinds can be isolated using
+ * @apiNote Elements of certain kinds can be isolated using
* methods in {@link ElementFilter}.
*
* @return the enclosed elements, or an empty list if none
@@ -197,7 +200,7 @@
* Returns {@code true} if the argument represents the same
* element as {@code this}, or {@code false} otherwise.
*
- * <p>Note that the identity of an element involves implicit state
+ * @apiNote The identity of an element involves implicit state
* not directly accessible from the element's methods, including
* state about the presence of unrelated types. Element objects
* created by different implementations of these interfaces should
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/element/ModuleElement.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/element/ModuleElement.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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,17 +37,18 @@
public interface ModuleElement extends Element, QualifiedNameable {
/**
- * Returns the fully qualified name of this module.
+ * Returns the fully qualified name of this module. For an
+ * {@linkplain #isUnnamed() unnamed module}, an empty name is returned.
*
- * @return the qualified name of this module, or an
+ * @return the fully qualified name of this module, or an
* empty name if this is an unnamed module
*/
@Override
Name getQualifiedName();
/**
- * Returns the simple name of this module. For an unnamed
- * module, an empty name is returned.
+ * Returns the simple name of this module. For an {@linkplain
+ * #isUnnamed() unnamed module}, an empty name is returned.
*
* @return the simple name of this module or an empty name if
* this is an unnamed module
@@ -63,6 +64,15 @@
List<? extends Element> getEnclosedElements();
/**
+ * Returns {@code true} if this is an open module and {@code
+ * false} otherwise.
+ *
+ * @return {@code true} if this is an open module and {@code
+ * false} otherwise
+ */ // TODO: add @jls to unnamed module section
+ boolean isOpen();
+
+ /**
* Returns {@code true} if this is an unnamed module and {@code
* false} otherwise.
*
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/element/NestingKind.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/element/NestingKind.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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
@@ -89,25 +89,29 @@
/**
* A type that is a named member of another type.
+ * @jls 8.5 Member Type Declarations
*/
MEMBER,
/**
* A named type declared within a construct other than a type.
+ * @jls 14.3 Local Class Declarations
*/
LOCAL,
/**
* A type without a name.
+ * @jls 15.9.5 Anonymous Class Declarations
*/
ANONYMOUS;
/**
* Does this constant correspond to a nested type element?
* A <i>nested</i> type element is any that is not top-level.
- * An <i>inner</i> type element is any nested type element that
+ * More specifically, an <i>inner</i> type element is any nested type element that
* is not {@linkplain Modifier#STATIC static}.
* @return whether or not the constant is nested
+ * @jls 14.3 Inner Classes and Enclosing Instances
*/
public boolean isNested() {
return this != TOP_LEVEL;
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/element/PackageElement.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/element/PackageElement.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,6 +42,7 @@
/**
* Returns the fully qualified name of this package.
* This is also known as the package's <i>canonical</i> name.
+ * For an {@linkplain #isUnnamed() unnamed package}, an empty name is returned.
*
* @return the fully qualified name of this package, or an
* empty name if this is an unnamed package
@@ -50,8 +51,8 @@
Name getQualifiedName();
/**
- * Returns the simple name of this package. For an unnamed
- * package, an empty name is returned.
+ * Returns the simple name of this package. For an {@linkplain
+ * #isUnnamed() unnamed package}, an empty name is returned.
*
* @return the simple name of this package or an empty name if
* this is an unnamed package
@@ -82,9 +83,16 @@
boolean isUnnamed();
/**
- * Returns the enclosing module.
+ * Returns the enclosing module if such a module exists; otherwise
+ * returns {@code null}.
*
- * @return the enclosing module
+ * One situation where a module does not exist for a package is if
+ * the environment does not include modules, such as an annotation
+ * processing environment configured for a {@linkplain
+ * javax.annotation.processing.ProcessingEnvironment#getSourceVersion
+ * source version} without modules.
+ *
+ * @return the enclosing module or {@code null} if no such module exists
*/
@Override
Element getEnclosingElement();
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/element/Parameterizable.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/element/Parameterizable.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2017, 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 @@
*/
public interface Parameterizable extends Element {
/**
- * Returns the formal type parameters of the type element in
+ * Returns the formal type parameters of an element in
* declaration order.
*
* @return the formal type parameters, or an empty list
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/element/TypeElement.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/element/TypeElement.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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
@@ -63,21 +63,25 @@
* Returns the fields, methods, constructors, and member types
* that are directly declared in this class or interface.
*
- * This includes any (implicit) default constructor and
- * the implicit {@code values} and {@code valueOf} methods of an
- * enum type.
+ * This includes any {@linkplain Elements.Origin#MANDATED
+ * mandated} elements such as the (implicit) default constructor
+ * and the implicit {@code values} and {@code valueOf} methods of
+ * an enum type.
*
- * <p> Note that as a particular instance of the {@linkplain
+ * @apiNote As a particular instance of the {@linkplain
* javax.lang.model.element general accuracy requirements} and the
* ordering behavior required of this interface, the list of
* enclosed elements will be returned in the natural order for the
* originating source of information about the type. For example,
* if the information about the type is originating from a source
* file, the elements will be returned in source code order.
- * (However, in that case the the ordering of synthesized
- * elements, such as a default constructor, is not specified.)
+ * (However, in that case the the ordering of elements, such as a
+ * default constructor, is not specified.)
*
* @return the enclosed elements in proper order, or an empty list if none
+ *
+ * @jls 8.8.9 Default Constructor
+ * @jls 8.9.3 Enum Members
*/
@Override
List<? extends Element> getEnclosedElements();
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/element/UnknownAnnotationValueException.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/element/UnknownAnnotationValueException.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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
@@ -79,7 +79,7 @@
/**
* Returns the additional argument.
*
- * @return the additional argument
+ * @return the additional argument, or {@code null} if unavailable
*/
public Object getArgument() {
return parameter;
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/element/UnknownElementException.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/element/UnknownElementException.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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
@@ -77,7 +77,7 @@
/**
* Returns the additional argument.
*
- * @return the additional argument
+ * @return the additional argument, or {@code null} if unavailable
*/
public Object getArgument() {
return parameter;
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/element/package-info.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/element/package-info.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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
@@ -87,14 +87,14 @@
* If a program is syntactically valid but erroneous in some other
* fashion, any returned model must have no less information than if
* all the method bodies in the program were replaced by {@code "throw
- * new RuntimeException();"}. If a program refers to a missing type XYZ,
+ * new RuntimeException();"}. If a program refers to a missing type Xyz,
* the returned model must contain no less information than if the
- * declaration of type XYZ were assumed to be {@code "class XYZ {}"},
- * {@code "interface XYZ {}"}, {@code "enum XYZ {}"}, or {@code
- * "@interface XYZ {}"}. If a program refers to a missing type {@code
- * XYZ<K1, ... ,Kn>}, the returned model must contain no less
- * information than if the declaration of XYZ were assumed to be
- * {@code "class XYZ<T1, ... ,Tn> {}"} or {@code "interface XYZ<T1,
+ * declaration of type Xyz were assumed to be {@code "class Xyz {}"},
+ * {@code "interface Xyz {}"}, {@code "enum Xyz {}"}, or {@code
+ * "@interface Xyz {}"}. If a program refers to a missing type {@code
+ * Xyz<K1, ... ,Kn>}, the returned model must contain no less
+ * information than if the declaration of Xyz were assumed to be
+ * {@code "class Xyz<T1, ... ,Tn> {}"} or {@code "interface Xyz<T1,
* ... ,Tn> {}"}
*
* <p> Unless otherwise specified in a particular implementation, the
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/type/IntersectionType.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/type/IntersectionType.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -33,14 +33,12 @@
* <p>An intersection type can be either implicitly or explicitly
* declared in a program. For example, the bound of the type parameter
* {@code <T extends Number & Runnable>} is an (implicit) intersection
- * type. As of {@link javax.lang.model.SourceVersion#RELEASE_8
- * RELEASE_8}, this is represented by an {@code IntersectionType} with
+ * type. This is represented by an {@code IntersectionType} with
* {@code Number} and {@code Runnable} as its bounds.
*
- * @implNote Also as of {@link
- * javax.lang.model.SourceVersion#RELEASE_8 RELEASE_8}, in the
- * reference implementation an {@code IntersectionType} is used to
- * model the explicit target type of a cast expression.
+ * @implNote In the reference implementation an {@code
+ * IntersectionType} is used to model the explicit target type of a
+ * cast expression.
*
* @since 1.8
*/
@@ -49,7 +47,7 @@
/**
* Return the bounds comprising this intersection type.
*
- * @return the bounds of this intersection types.
+ * @return the bounds of this intersection type
*/
List<? extends TypeMirror> getBounds();
}
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/type/NoType.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/type/NoType.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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,6 +34,7 @@
* <ul>
* <li>{@link TypeKind#VOID VOID} - corresponds to the keyword {@code void}.
* <li>{@link TypeKind#PACKAGE PACKAGE} - the pseudo-type of a package element.
+ * <li>{@link TypeKind#MODULE MODULE} - the pseudo-type of a module element.
* <li>{@link TypeKind#NONE NONE} - used in other cases
* where no actual type is appropriate; for example, the superclass
* of {@code java.lang.Object}.
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/type/UnionType.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/type/UnionType.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2017, 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,9 +30,8 @@
/**
* Represents a union type.
*
- * As of the {@link javax.lang.model.SourceVersion#RELEASE_7
- * RELEASE_7} source version, union types can appear as the type
- * of a multi-catch exception parameter.
+ * Union types can appear as the type of a multi-catch exception
+ * parameter.
*
* @since 1.7
*/
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/type/UnknownTypeException.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/type/UnknownTypeException.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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
@@ -77,7 +77,7 @@
/**
* Returns the additional argument.
*
- * @return the additional argument
+ * @return the additional argument, or {@code null} if unavailable
*/
public Object getArgument() {
return parameter;
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementFilter.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/ElementFilter.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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
@@ -55,15 +55,6 @@
* arguments to methods in this class, a {@code NullPointerException}
* will be thrown.
*
- * <p>Note that a <i>static import</i> statement can make the text of
- * calls to the methods in this class more concise; for example:
- *
- * <blockquote><pre>
- * import static javax.lang.model.util.ElementFilter.*;
- * ...
- * {@code List<VariableElement>} fs = fieldsIn(someClass.getEnclosedElements());
- * </pre></blockquote>
- *
* @author Joseph D. Darcy
* @author Scott Seligman
* @author Peter von der Ahé
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/Elements.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/Elements.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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
@@ -52,19 +52,24 @@
* If running with modules, all modules in the modules graph are searched for matching packages.
*
* @param name fully qualified package name, or an empty string for an unnamed package
- * @return the named package, or {@code null} if it cannot be uniquely found
+ * @return the specified package, or {@code null} if it cannot be uniquely found
*/
PackageElement getPackageElement(CharSequence name);
/**
* Returns a package given its fully qualified name, as seen from the given module.
*
+ * @implSpec The default implementation of this method returns
+ * {@code null}.
+ *
* @param name fully qualified package name, or an empty string for an unnamed package
* @param module module relative to which the lookup should happen
- * @return the named package, or {@code null} if it cannot be found
+ * @return the specified package, or {@code null} if it cannot be found
* @since 9
*/
- PackageElement getPackageElement(ModuleElement module, CharSequence name);
+ default PackageElement getPackageElement(ModuleElement module, CharSequence name) {
+ return null;
+ }
/**
* Returns a type element given its canonical name if the type element is unique in the environment.
@@ -79,12 +84,17 @@
/**
* Returns a type element given its canonical name, as seen from the given module.
*
+ * @implSpec The default implementation of this method returns
+ * {@code null}.
+ *
* @param name the canonical name
* @param module module relative to which the lookup should happen
* @return the named type element, or {@code null} if it cannot be found
* @since 9
*/
- TypeElement getTypeElement(ModuleElement module, CharSequence name);
+ default TypeElement getTypeElement(ModuleElement module, CharSequence name) {
+ return null;
+ }
/**
* Returns a module element given its fully qualified name.
@@ -95,11 +105,16 @@
* javax.annotation.processing.ProcessingEnvironment#getSourceVersion
* source version} without modules.
*
+ * @implSpec The default implementation of this method returns
+ * {@code null}.
+ *
* @param name the name
* @return the named module element, or {@code null} if it cannot be found
* @since 9
*/
- ModuleElement getModuleElement(CharSequence name);
+ default ModuleElement getModuleElement(CharSequence name) {
+ return null;
+ }
/**
* Returns the values of an annotation's elements, including defaults.
@@ -267,6 +282,7 @@
* multiple annotations of a repeatable annotation type.
*
* @jls 8.8.9 Default Constructor
+ * @jls 8.9.3 Enum Members
* @jls 9.6.3 Repeatable Annotation Types
* @jls 9.7.5 Multiple Annotations of the Same Type
*/
@@ -337,18 +353,23 @@
* javax.annotation.processing.ProcessingEnvironment#getSourceVersion
* source version} without modules.
*
+ * @implSpec The default implementation of this method returns
+ * {@code null}.
+ *
* @param type the element being examined
* @return the module of an element
* @since 9
*/
- ModuleElement getModuleOf(Element type);
+ default ModuleElement getModuleOf(Element type) {
+ return null;
+ }
/**
* Returns all members of a type element, whether inherited or
* declared directly. For a class the result also includes its
* constructors, but not local or anonymous classes.
*
- * <p>Note that elements of certain kinds can be isolated using
+ * @apiNote Elements of certain kinds can be isolated using
* methods in {@link ElementFilter}.
*
* @param type the type being examined
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ImportTree.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/tree/ImportTree.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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 com.sun.source.tree;
/**
- * A tree node for an import statement.
+ * A tree node for an import declaration.
*
* For example:
* <pre>
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -821,7 +821,11 @@
break;
}
} else {
- foundParams.add(paramElement);
+ boolean unique = foundParams.add(paramElement);
+
+ if (!unique) {
+ env.messages.warning(REFERENCE, tree, "dc.exists.param", nameTree);
+ }
}
warnIfEmpty(tree, tree.getDescription());
@@ -870,6 +874,10 @@
@Override @DefinedBy(Api.COMPILER_TREE)
public Void visitReturn(ReturnTree tree, Void ignore) {
+ if (foundReturn) {
+ env.messages.warning(REFERENCE, tree, "dc.exists.return");
+ }
+
Element e = env.trees.getElement(env.currPath);
if (e.getKind() != ElementKind.METHOD
|| ((ExecutableElement) e).getReturnType().getKind() == TypeKind.VOID)
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/resources/doclint.properties Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/resources/doclint.properties Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 2017, 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
@@ -39,6 +39,8 @@
dc.empty = no description for @{0}
dc.entity.invalid = invalid entity &{0};
dc.exception.not.thrown = exception not thrown: {0}
+dc.exists.param = @param "{0}" has already been specified
+dc.exists.return = @return has already been specified
dc.invalid.anchor = invalid name for anchor: "{0}"
dc.invalid.param = invalid use of @param
dc.invalid.provides = invalid use of @provides
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java Thu Feb 09 23:15:52 2017 +0100
@@ -190,7 +190,7 @@
compiler.genEndPos = true;
notYetEntered = new HashMap<>();
if (forParse) {
- compiler.initProcessAnnotations(processors);
+ compiler.initProcessAnnotations(processors, args.getFileObjects(), args.getClassNames());
for (JavaFileObject file: args.getFileObjects())
notYetEntered.put(file, null);
genList = new ListBuffer<>();
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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
@@ -118,6 +118,7 @@
if (source.compareTo(Source.JDK1_9) >= 0) {
values.add(LintCategory.DEP_ANN);
}
+ values.add(LintCategory.OPENS);
values.add(LintCategory.MODULE);
values.add(LintCategory.REMOVAL);
}
@@ -211,6 +212,11 @@
MODULE("module"),
/**
+ * Warn about issues regarding module opens.
+ */
+ OPENS("opens"),
+
+ /**
* Warn about issues relating to use of command line options
*/
OPTIONS("options"),
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java Thu Feb 09 23:15:52 2017 +0100
@@ -948,6 +948,11 @@
}
@Override @DefinedBy(Api.LANGUAGE_MODEL)
+ public boolean isOpen() {
+ return flags.contains(ModuleFlags.OPEN);
+ }
+
+ @Override @DefinedBy(Api.LANGUAGE_MODEL)
public boolean isUnnamed() {
return name.isEmpty() && owner == null;
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Thu Feb 09 23:15:52 2017 +0100
@@ -2947,6 +2947,14 @@
return;
}
+ if (!env.info.isSpeculative && that.getMode() == JCMemberReference.ReferenceMode.NEW) {
+ Type enclosingType = exprType.getEnclosingType();
+ if (enclosingType != null && enclosingType.hasTag(CLASS)) {
+ // Check for the existence of an apropriate outer instance
+ rs.resolveImplicitThis(that.pos(), env, exprType);
+ }
+ }
+
if (resultInfo.checkContext.deferredAttrContext().mode == AttrMode.CHECK) {
if (that.getMode() == ReferenceMode.INVOKE &&
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Thu Feb 09 23:15:52 2017 +0100
@@ -3876,4 +3876,14 @@
}
}
+ void checkPackageExistsForOpens(final DiagnosticPosition pos, PackageSymbol packge) {
+ if (packge.members().isEmpty() &&
+ ((packge.flags() & Flags.HAS_RESOURCE) == 0)) {
+ deferredLintHandler.report(() -> {
+ if (lint.isEnabled(LintCategory.OPENS))
+ log.warning(pos, Warnings.PackageEmptyOrNotFound(packge));
+ });
+ }
+ }
+
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java Thu Feb 09 23:15:52 2017 +0100
@@ -165,6 +165,7 @@
private final boolean lintOptions;
private Set<ModuleSymbol> rootModules = null;
+ private final Set<ModuleSymbol> warnedMissing = new HashSet<>();
public static Modules instance(Context context) {
Modules instance = context.get(Modules.class);
@@ -525,7 +526,6 @@
ModuleSymbol msym = moduleFinder.findModule((ModuleSymbol) sym);
if (msym.kind == ERR) {
- log.error(Errors.ModuleNotFound(msym));
//make sure the module is initialized:
msym.directives = List.nil();
msym.exports = List.nil();
@@ -674,6 +674,7 @@
ModuleSymbol msym = lookupModule(tree.moduleName);
if (msym.kind != MDL) {
log.error(tree.moduleName.pos(), Errors.ModuleNotFound(msym));
+ warnedMissing.add(msym);
} else if (allRequires.contains(msym)) {
log.error(tree.moduleName.pos(), Errors.DuplicateRequires(msym));
} else {
@@ -695,9 +696,6 @@
PackageSymbol packge = syms.enterPackage(sym, name);
attr.setPackageSymbols(tree.qualid, packge);
- if (tree.hasTag(Tag.OPENS) && sym.flags.contains(ModuleFlags.OPEN)) {
- log.error(tree.pos(), Errors.NoOpensUnlessStrong);
- }
List<ExportsDirective> exportsForPackage = allExports.computeIfAbsent(packge, p -> List.nil());
for (ExportsDirective d : exportsForPackage) {
reportExportsConflict(tree, packge);
@@ -898,10 +896,7 @@
@Override
public void visitOpens(JCOpens tree) {
- if (tree.directive.packge.members().isEmpty() &&
- ((tree.directive.packge.flags() & Flags.HAS_RESOURCE) == 0)) {
- log.error(tree.qualid.pos(), Errors.PackageEmptyOrNotFound(tree.directive.packge));
- }
+ chk.checkPackageExistsForOpens(tree.qualid, tree.directive.packge);
msym.directives = msym.directives.prepend(tree.directive);
}
@@ -931,6 +926,9 @@
public void visitProvides(JCProvides tree) {
Type st = attr.attribType(tree.serviceName, env, syms.objectType);
ClassSymbol service = (ClassSymbol) st.tsym;
+ if (allProvides.containsKey(service)) {
+ log.error(tree.serviceName.pos(), Errors.RepeatedProvidesForService(service));
+ }
ListBuffer<ClassSymbol> impls = new ListBuffer<>();
for (JCExpression implName : tree.implNames) {
Type it = attr.attribType(implName, env, syms.objectType);
@@ -959,8 +957,6 @@
}
}
if (it.hasTag(CLASS)) {
- // For now, we just check the pair (service-type, impl-type) is unique
- // TODO, check only one provides per service type as well
if (allProvides.computeIfAbsent(service, s -> new HashSet<>()).add(impl)) {
impls.append(impl);
} else {
@@ -1183,26 +1179,44 @@
return allModules == null || allModules.contains(msym);
}
- private Set<ModuleSymbol> computeTransitiveClosure(Iterable<? extends ModuleSymbol> base, Set<ModuleSymbol> observable) {
- List<ModuleSymbol> todo = List.nil();
+ private Set<ModuleSymbol> computeTransitiveClosure(Set<? extends ModuleSymbol> base, Set<ModuleSymbol> observable) {
+ List<ModuleSymbol> primaryTodo = List.nil();
+ List<ModuleSymbol> secondaryTodo = List.nil();
for (ModuleSymbol ms : base) {
- todo = todo.prepend(ms);
+ primaryTodo = primaryTodo.prepend(ms);
}
Set<ModuleSymbol> result = new LinkedHashSet<>();
result.add(syms.java_base);
- while (todo.nonEmpty()) {
- ModuleSymbol current = todo.head;
- todo = todo.tail;
+ while (primaryTodo.nonEmpty() || secondaryTodo.nonEmpty()) {
+ ModuleSymbol current;
+ boolean isPrimaryTodo;
+ if (primaryTodo.nonEmpty()) {
+ current = primaryTodo.head;
+ primaryTodo = primaryTodo.tail;
+ isPrimaryTodo = true;
+ } else {
+ current = secondaryTodo.head;
+ secondaryTodo = secondaryTodo.tail;
+ isPrimaryTodo = false;
+ }
if (observable != null && !observable.contains(current))
continue;
if (!result.add(current) || current == syms.unnamedModule || ((current.flags_field & Flags.AUTOMATIC_MODULE) != 0))
continue;
current.complete();
+ if (current.kind == ERR && isPrimaryTodo && warnedMissing.add(current)) {
+ log.error(Errors.ModuleNotFound(current));
+ }
for (RequiresDirective rd : current.requires) {
- todo = todo.prepend(rd.module);
+ if (rd.module == syms.java_base) continue;
+ if ((rd.isTransitive() && isPrimaryTodo) || base.contains(current)) {
+ primaryTodo = primaryTodo.prepend(rd.module);
+ } else {
+ secondaryTodo = secondaryTodo.prepend(rd.module);
+ }
}
}
@@ -1582,5 +1596,6 @@
public void newRound() {
rootModules = null;
allModules = null;
+ warnedMissing.clear();
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java Thu Feb 09 23:15:52 2017 +0100
@@ -502,7 +502,7 @@
private final class ArchiveContainer implements Container {
private final Path archivePath;
private final FileSystem fileSystem;
- private final Map<RelativePath, Path> pathCache = new HashMap<>();
+ private final Map<RelativePath, Path> packages;
public ArchiveContainer(Path archivePath) throws IOException, ProviderNotFoundException, SecurityException {
this.archivePath = archivePath;
@@ -514,6 +514,21 @@
} else {
this.fileSystem = FileSystems.newFileSystem(archivePath, null);
}
+ packages = new HashMap<>();
+ for (Path root : fileSystem.getRootDirectories()) {
+ Files.walkFileTree(root, EnumSet.noneOf(FileVisitOption.class), Integer.MAX_VALUE,
+ new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
+ if (isValid(dir.getFileName())) {
+ packages.put(new RelativeDirectory(root.relativize(dir).toString()), dir);
+ return FileVisitResult.CONTINUE;
+ } else {
+ return FileVisitResult.SKIP_SUBTREE;
+ }
+ }
+ });
+ }
}
/**
@@ -526,7 +541,7 @@
Set<JavaFileObject.Kind> fileKinds,
boolean recurse,
ListBuffer<JavaFileObject> resultList) throws IOException {
- Path resolvedSubdirectory = resolvePath(subdirectory);
+ Path resolvedSubdirectory = packages.get(subdirectory);
if (resolvedSubdirectory == null)
return ;
@@ -544,18 +559,6 @@
}
}
- boolean isValid(Path fileName) {
- if (fileName == null) {
- return true;
- } else {
- String name = fileName.toString();
- if (name.endsWith("/")) {
- name = name.substring(0, name.length() - 1);
- }
- return SourceVersion.isIdentifier(name);
- }
- }
-
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
if (attrs.isRegularFile() && fileKinds.contains(getKind(file.getFileName().toString()))) {
@@ -569,27 +572,29 @@
}
- @Override
- public JavaFileObject getFileObject(Path userPath, RelativeFile name) throws IOException {
- Path p = resolvePath(name);
- if (p != null)
- return PathFileObject.forJarPath(JavacFileManager.this, p, userPath);
-
- return null;
+ private boolean isValid(Path fileName) {
+ if (fileName == null) {
+ return true;
+ } else {
+ String name = fileName.toString();
+ if (name.endsWith("/")) {
+ name = name.substring(0, name.length() - 1);
+ }
+ return SourceVersion.isIdentifier(name);
+ }
}
- private synchronized Path resolvePath(RelativePath path) {
- if (!pathCache.containsKey(path)) {
- Path relativePath = path.resolveAgainst(fileSystem);
-
- if (!Files.exists(relativePath)) {
- relativePath = null;
+ @Override
+ public JavaFileObject getFileObject(Path userPath, RelativeFile name) throws IOException {
+ RelativeDirectory root = name.dirname();
+ Path packagepath = packages.get(root);
+ if (packagepath != null) {
+ Path relpath = packagepath.resolve(name.basename());
+ if (Files.exists(relpath)) {
+ return PathFileObject.forJarPath(JavacFileManager.this, relpath, userPath);
}
-
- pathCache.put(path, relativePath);
- return relativePath;
}
- return pathCache.get(path);
+ return null;
}
@Override
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Thu Feb 09 23:15:52 2017 +0100
@@ -43,6 +43,7 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.ProviderNotFoundException;
+import java.nio.file.spi.FileSystemProvider;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -1119,8 +1120,12 @@
}
if (p.getFileName().toString().endsWith(".jar") && fsInfo.exists(p)) {
- URI uri = URI.create("jar:" + p.toUri());
- try (FileSystem fs = FileSystems.newFileSystem(uri, fsEnv, null)) {
+ FileSystemProvider jarFSProvider = fsInfo.getJarFSProvider();
+ if (jarFSProvider == null) {
+ log.error(Errors.NoZipfsForArchive(p));
+ return null;
+ }
+ try (FileSystem fs = jarFSProvider.newFileSystem(p, fsEnv)) {
Path moduleInfoClass = fs.getPath("module-info.class");
if (Files.exists(moduleInfoClass)) {
String moduleName = readModuleName(moduleInfoClass);
@@ -1132,9 +1137,6 @@
} catch (IOException e) {
log.error(Errors.LocnCantReadFile(p));
return null;
- } catch (ProviderNotFoundException e) {
- log.error(Errors.NoZipfsForArchive(p));
- return null;
}
//automatic module:
@@ -1177,8 +1179,12 @@
// workaround for now
FileSystem fs = fileSystems.get(p);
if (fs == null) {
- URI uri = URI.create("jar:" + p.toUri());
- fs = FileSystems.newFileSystem(uri, Collections.emptyMap(), null);
+ FileSystemProvider jarFSProvider = fsInfo.getJarFSProvider();
+ if (jarFSProvider == null) {
+ log.error(Errors.LocnCantReadFile(p));
+ return null;
+ }
+ fs = jarFSProvider.newFileSystem(p, Collections.emptyMap());
try {
Path moduleInfoClass = fs.getPath("classes/module-info.class");
String moduleName = readModuleName(moduleInfoClass);
@@ -1194,7 +1200,7 @@
}
} catch (ModuleNameReader.BadClassFile e) {
log.error(Errors.LocnBadModuleInfo(p));
- } catch (IOException | ProviderNotFoundException e) {
+ } catch (IOException e) {
log.error(Errors.LocnCantReadFile(p));
return null;
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Thu Feb 09 23:15:52 2017 +0100
@@ -45,6 +45,7 @@
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
import javax.tools.StandardLocation;
import com.sun.source.util.TaskEvent;
@@ -623,7 +624,8 @@
keepComments = true;
genEndPos = true;
}
- Parser parser = parserFactory.newParser(content, keepComments(), genEndPos, lineDebugInfo);
+ Parser parser = parserFactory.newParser(content, keepComments(), genEndPos,
+ lineDebugInfo, filename.isNameCompatible("module-info", Kind.SOURCE));
tree = parser.parseCompilationUnit();
if (verbose) {
log.printVerbose("parsing.done", Long.toString(elapsed(msec)));
@@ -921,7 +923,7 @@
start_msec = now();
try {
- initProcessAnnotations(processors);
+ initProcessAnnotations(processors, sourceFileObjects, classnames);
for (String className : classnames) {
int sep = className.indexOf('/');
@@ -1123,7 +1125,9 @@
* @param processors user provided annotation processors to bypass
* discovery, {@code null} means that no processors were provided
*/
- public void initProcessAnnotations(Iterable<? extends Processor> processors) {
+ public void initProcessAnnotations(Iterable<? extends Processor> processors,
+ Collection<? extends JavaFileObject> initialFiles,
+ Collection<String> initialClassNames) {
// Process annotations if processing is not disabled and there
// is at least one Processor available.
if (options.isSet(PROC, "none")) {
@@ -1141,6 +1145,7 @@
if (!taskListener.isEmpty())
taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING));
deferredDiagnosticHandler = new Log.DeferredDiagnosticHandler(log);
+ procEnvImpl.getFiler().setInitialState(initialFiles, initialClassNames);
} else { // free resources
procEnvImpl.close();
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java Thu Feb 09 23:15:52 2017 +0100
@@ -701,7 +701,7 @@
MULTIRELEASE("--multi-release", "opt.arg.multi-release", "opt.multi-release", HIDDEN, FILEMANAGER),
INHERIT_RUNTIME_ENVIRONMENT("--inherit-runtime-environment", "opt.inherit_runtime_environment",
- EXTENDED, BASIC) {
+ HIDDEN, BASIC) {
@Override
public void process(OptionHelper helper, String option) throws InvalidValueException {
try {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java Thu Feb 09 23:15:52 2017 +0100
@@ -140,8 +140,6 @@
private PackageSymbol doGetPackageElement(ModuleElement module, CharSequence name) {
ensureEntered("getPackageElement");
- if (name.length() == 0)
- return syms.unnamedModule.unnamedPackage;
return doGetElement(module, "getPackageElement", name, PackageSymbol.class);
}
@@ -165,7 +163,7 @@
private <S extends Symbol> S doGetElement(ModuleElement module, String methodName,
CharSequence name, Class<S> clazz) {
String strName = name.toString();
- if (!SourceVersion.isName(strName)) {
+ if (!SourceVersion.isName(strName) && (!strName.isEmpty() || clazz == ClassSymbol.class)) {
return null;
}
if (module == null) {
@@ -290,7 +288,9 @@
List<JCAnnotation> trees) {
for (Attribute.Compound anno : annos) {
for (JCAnnotation tree : trees) {
- JCTree match = matchAnnoToTree(findme, anno, tree);
+ if (tree.type.tsym != anno.type.tsym)
+ continue;
+ JCTree match = matchAttributeToTree(findme, anno, tree);
if (match != null)
return match;
}
@@ -299,15 +299,15 @@
}
/**
- * Returns the tree for an annotation given an Attribute to
- * search (recursively) and its corresponding tree.
+ * Returns the tree for an attribute given an enclosing attribute to
+ * search (recursively) and the enclosing attribute's corresponding tree.
* Returns null if the tree cannot be found.
*/
- private JCTree matchAnnoToTree(final Attribute.Compound findme,
- final Attribute attr,
- final JCTree tree) {
+ private JCTree matchAttributeToTree(final Attribute findme,
+ final Attribute attr,
+ final JCTree tree) {
if (attr == findme)
- return (tree.type.tsym == findme.type.tsym) ? tree : null;
+ return tree;
class Vis implements Attribute.Visitor {
JCTree result = null;
@@ -319,7 +319,7 @@
for (Pair<MethodSymbol, Attribute> pair : anno.values) {
JCExpression expr = scanForAssign(pair.fst, tree);
if (expr != null) {
- JCTree match = matchAnnoToTree(findme, pair.snd, expr);
+ JCTree match = matchAttributeToTree(findme, pair.snd, expr);
if (match != null) {
result = match;
return;
@@ -328,16 +328,19 @@
}
}
public void visitArray(Attribute.Array array) {
- if (tree.hasTag(NEWARRAY) &&
- types.elemtype(array.type).tsym == findme.type.tsym) {
- List<JCExpression> elems = ((JCNewArray) tree).elems;
+ if (tree.hasTag(NEWARRAY)) {
+ List<JCExpression> elems = ((JCNewArray)tree).elems;
for (Attribute value : array.values) {
- if (value == findme) {
- result = elems.head;
+ JCTree match = matchAttributeToTree(findme, value, elems.head);
+ if (match != null) {
+ result = match;
return;
}
elems = elems.tail;
}
+ } else if (array.values.length == 1) {
+ // the tree may not be a NEWARRAY for single-element array initializers
+ result = matchAttributeToTree(findme, array.values[0], tree);
}
}
public void visitEnum(Attribute.Enum e) {
@@ -712,10 +715,15 @@
if (annoTree == null)
return elemTreeTop;
- // 6388543: if v != null, we should search within annoTree to find
- // the tree matching v. For now, we ignore v and return the tree of
- // the annotation.
- return new Pair<>(annoTree, elemTreeTop.snd);
+ if (v == null)
+ return new Pair<>(annoTree, elemTreeTop.snd);
+
+ JCTree valueTree = matchAttributeToTree(
+ cast(Attribute.class, v), cast(Attribute.class, a), annoTree);
+ if (valueTree == null)
+ return new Pair<>(annoTree, elemTreeTop.snd);
+
+ return new Pair<>(valueTree, elemTreeTop.snd);
}
/**
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Thu Feb 09 23:15:52 2017 +0100
@@ -70,6 +70,10 @@
*/
private static final int infixPrecedenceLevels = 10;
+ /** Is the parser instantiated to parse a module-info file ?
+ */
+ private final boolean parseModuleInfo;
+
/** The scanner used for lexical analysis.
*/
protected Lexer S;
@@ -138,10 +142,21 @@
/** Construct a parser from a given scanner, tree factory and log.
*/
protected JavacParser(ParserFactory fac,
+ Lexer S,
+ boolean keepDocComments,
+ boolean keepLineMap,
+ boolean keepEndPositions) {
+ this(fac, S, keepDocComments, keepLineMap, keepEndPositions, false);
+
+ }
+ /** Construct a parser from a given scanner, tree factory and log.
+ */
+ protected JavacParser(ParserFactory fac,
Lexer S,
boolean keepDocComments,
boolean keepLineMap,
- boolean keepEndPositions) {
+ boolean keepEndPositions,
+ boolean parseModuleInfo) {
this.S = S;
nextToken(); // prime the pump
this.F = fac.F;
@@ -165,6 +180,7 @@
this.allowUnderscoreIdentifier = source.allowUnderscoreIdentifier();
this.allowPrivateInterfaceMethods = source.allowPrivateInterfaceMethods();
this.keepDocComments = keepDocComments;
+ this.parseModuleInfo = parseModuleInfo;
docComments = newDocCommentTable(keepDocComments, fac);
this.keepLineMap = keepLineMap;
this.errorTree = F.Erroneous();
@@ -3347,8 +3363,13 @@
} else {
errs = List.of(mods);
}
- return toP(F.Exec(syntaxError(pos, errs, "expected3",
- CLASS, INTERFACE, ENUM)));
+ final JCErroneous erroneousTree;
+ if (parseModuleInfo) {
+ erroneousTree = syntaxError(pos, errs, "expected.module.or.open");
+ } else {
+ erroneousTree = syntaxError(pos, errs, "expected3", CLASS, INTERFACE, ENUM);
+ }
+ return toP(F.Exec(erroneousTree));
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/ParserFactory.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/ParserFactory.java Thu Feb 09 23:15:52 2017 +0100
@@ -81,7 +81,11 @@
}
public JavacParser newParser(CharSequence input, boolean keepDocComments, boolean keepEndPos, boolean keepLineMap) {
+ return newParser(input, keepDocComments, keepEndPos, keepLineMap, false);
+ }
+
+ public JavacParser newParser(CharSequence input, boolean keepDocComments, boolean keepEndPos, boolean keepLineMap, boolean parseModuleInfo) {
Lexer lexer = scannerFactory.newScanner(input, keepDocComments);
- return new JavacParser(this, lexer, keepDocComments, keepLineMap, keepEndPos);
+ return new JavacParser(this, lexer, keepDocComments, keepLineMap, keepEndPos, parseModuleInfo);
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.java Thu Feb 09 23:15:52 2017 +0100
@@ -51,9 +51,11 @@
import static javax.tools.StandardLocation.CLASS_OUTPUT;
import com.sun.tools.javac.code.Lint;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.ModuleSymbol;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.comp.Modules;
+import com.sun.tools.javac.model.JavacElements;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.DefinedBy.Api;
@@ -321,6 +323,7 @@
}
JavaFileManager fileManager;
+ JavacElements elementUtils;
Log log;
Modules modules;
Names names;
@@ -331,6 +334,12 @@
private final boolean lint;
/**
+ * Initial inputs passed to the tool. This set must be
+ * synchronized.
+ */
+ private final Set<FileObject> initialInputs;
+
+ /**
* Logical names of all created files. This set must be
* synchronized.
*/
@@ -373,26 +382,30 @@
*/
private final Set<Pair<ModuleSymbol, String>> aggregateGeneratedClassNames;
+ private final Set<String> initialClassNames;
JavacFiler(Context context) {
this.context = context;
fileManager = context.get(JavaFileManager.class);
+ elementUtils = JavacElements.instance(context);
log = Log.instance(context);
modules = Modules.instance(context);
names = Names.instance(context);
syms = Symtab.instance(context);
- fileObjectHistory = synchronizedSet(new LinkedHashSet<FileObject>());
- generatedSourceNames = synchronizedSet(new LinkedHashSet<String>());
- generatedSourceFileObjects = synchronizedSet(new LinkedHashSet<JavaFileObject>());
+ initialInputs = synchronizedSet(new LinkedHashSet<>());
+ fileObjectHistory = synchronizedSet(new LinkedHashSet<>());
+ generatedSourceNames = synchronizedSet(new LinkedHashSet<>());
+ generatedSourceFileObjects = synchronizedSet(new LinkedHashSet<>());
generatedClasses = synchronizedMap(new LinkedHashMap<>());
- openTypeNames = synchronizedSet(new LinkedHashSet<String>());
+ openTypeNames = synchronizedSet(new LinkedHashSet<>());
aggregateGeneratedSourceNames = new LinkedHashSet<>();
aggregateGeneratedClassNames = new LinkedHashSet<>();
+ initialClassNames = new LinkedHashSet<>();
lint = (Lint.instance(context)).isEnabled(PROCESSING);
}
@@ -596,8 +609,13 @@
// TODO: Check if type already exists on source or class path?
// If so, use warning message key proc.type.already.exists
checkName(typename, allowUnnamedPackageInfo);
- if (aggregateGeneratedSourceNames.contains(Pair.of(mod, typename)) ||
- aggregateGeneratedClassNames.contains(Pair.of(mod, typename))) {
+ ClassSymbol existing;
+ boolean alreadySeen = aggregateGeneratedSourceNames.contains(Pair.of(mod, typename)) ||
+ aggregateGeneratedClassNames.contains(Pair.of(mod, typename)) ||
+ initialClassNames.contains(typename) ||
+ ((existing = elementUtils.getTypeElement(typename)) != null &&
+ initialInputs.contains(existing.sourcefile));
+ if (alreadySeen) {
if (lint)
log.warning("proc.type.recreate", typename);
throw new FilerException("Attempt to recreate a file for type " + typename);
@@ -611,16 +629,48 @@
* Check to see if the file has already been opened; if so, throw
* an exception, otherwise add it to the set of files.
*/
- private void checkFileReopening(FileObject fileObject, boolean addToHistory) throws FilerException {
+ private void checkFileReopening(FileObject fileObject, boolean forWriting) throws FilerException {
+ if (isInFileObjectHistory(fileObject, forWriting)) {
+ if (lint)
+ log.warning("proc.file.reopening", fileObject.getName());
+ throw new FilerException("Attempt to reopen a file for path " + fileObject.getName());
+ }
+ if (forWriting)
+ fileObjectHistory.add(fileObject);
+ }
+
+ private boolean isInFileObjectHistory(FileObject fileObject, boolean forWriting) {
+ if (forWriting) {
+ for(FileObject veteran : initialInputs) {
+ try {
+ if (fileManager.isSameFile(veteran, fileObject)) {
+ return true;
+ }
+ } catch (IllegalArgumentException e) {
+ //ignore...
+ }
+ }
+ for (String className : initialClassNames) {
+ try {
+ ClassSymbol existing = elementUtils.getTypeElement(className);
+ if ( existing != null
+ && ( (existing.sourcefile != null && fileManager.isSameFile(existing.sourcefile, fileObject))
+ || (existing.classfile != null && fileManager.isSameFile(existing.classfile, fileObject)))) {
+ return true;
+ }
+ } catch (IllegalArgumentException e) {
+ //ignore...
+ }
+ }
+ }
+
for(FileObject veteran : fileObjectHistory) {
if (fileManager.isSameFile(veteran, fileObject)) {
- if (lint)
- log.warning("proc.file.reopening", fileObject.getName());
- throw new FilerException("Attempt to reopen a file for path " + fileObject.getName());
+ return true;
}
}
- if (addToHistory)
- fileObjectHistory.add(fileObject);
+
+ return false;
}
public boolean newFiles() {
@@ -656,9 +706,17 @@
this.lastRound = lastRound;
}
+ public void setInitialState(Collection<? extends JavaFileObject> initialInputs,
+ Collection<String> initialClassNames) {
+ this.initialInputs.addAll(initialInputs);
+ this.initialClassNames.addAll(initialClassNames);
+ }
+
public void close() {
clearRoundState();
// Cross-round state
+ initialClassNames.clear();
+ initialInputs.clear();
fileObjectHistory.clear();
openTypeNames.clear();
aggregateGeneratedSourceNames.clear();
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Thu Feb 09 23:15:52 2017 +0100
@@ -1628,7 +1628,7 @@
}
@DefinedBy(Api.ANNOTATION_PROCESSING)
- public Filer getFiler() {
+ public JavacFiler getFiler() {
return filer;
}
@@ -1671,14 +1671,14 @@
if (s.equals("*")) {
return MatchingUtils.validImportStringToPattern(s);
}
- module = ".*/";
+ module = allowModules ? ".*/" : "";
pkg = s;
} else {
module = Pattern.quote(s.substring(0, slash + 1));
pkg = s.substring(slash + 1);
}
if (MatchingUtils.isValidImportString(pkg)) {
- return Pattern.compile((allowModules ? module : "") + MatchingUtils.validImportStringToPatternString(pkg));
+ return Pattern.compile(module + MatchingUtils.validImportStringToPatternString(pkg));
} else {
log.warning("proc.malformed.supported.string", s, p.getClass().getName());
return noMatches; // won't match any valid identifier
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, 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,12 +30,15 @@
import javax.lang.model.element.*;
import static javax.lang.model.element.ElementKind.*;
import static javax.lang.model.element.NestingKind.*;
+import static javax.lang.model.element.ModuleElement.DirectiveKind.*;
+import static javax.lang.model.element.ModuleElement.*;
import javax.lang.model.type.*;
import javax.lang.model.util.*;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.*;
+import java.util.stream.Collectors;
import com.sun.tools.javac.util.DefinedBy;
import com.sun.tools.javac.util.DefinedBy.Api;
@@ -298,6 +301,96 @@
return this;
}
+ @Override @DefinedBy(Api.LANGUAGE_MODEL)
+ public PrintingElementVisitor visitModule(ModuleElement e, Boolean p) {
+ defaultAction(e, false);
+
+ if (!e.isUnnamed()) {
+ if (e.isOpen()) {
+ writer.print("open ");
+ }
+ writer.println("module " + e.getQualifiedName() + " {");
+ indentation++;
+ for (ModuleElement.Directive directive : e.getDirectives()) {
+ printDirective(directive);
+ }
+ indentation--;
+ writer.println("}");
+ } else
+ writer.println("// Unnamed module"); // Should we do more here?
+ return this;
+ }
+
+ private void printDirective(ModuleElement.Directive directive) {
+ indent();
+ switch (directive.getKind()) {
+ case EXPORTS: // "exports package-name [to module-name-list]"
+ {
+ ExportsDirective exportsDirective = (ExportsDirective) directive;
+ writer.print("exports ");
+ writer.print(exportsDirective.getPackage().getQualifiedName());
+ printModuleList(exportsDirective.getTargetModules());
+ }
+ break;
+
+ case OPENS: // opens package-name [to module-name-list]
+ {
+ OpensDirective opensDirective = (OpensDirective) directive;
+ writer.print("opens ");
+ writer.print(opensDirective.getPackage().getQualifiedName());
+ printModuleList(opensDirective.getTargetModules());
+ }
+ break;
+
+ case PROVIDES: // provides service-name with implementation-name
+ {
+ ProvidesDirective providesDirective = (ProvidesDirective) directive;
+ writer.print("provides ");
+ writer.print(providesDirective.getService().getQualifiedName());
+ writer.print(" with ");
+ printNameableList(providesDirective.getImplementations());
+ }
+ break;
+
+ case REQUIRES: // requires (static|transitive)* module-name
+ {
+ RequiresDirective requiresDirective = (RequiresDirective) directive;
+ writer.print("requires ");
+ if (requiresDirective.isStatic())
+ writer.print("static ");
+ if (requiresDirective.isTransitive())
+ writer.print("transitive ");
+ writer.print(requiresDirective.getDependency().getQualifiedName());
+ }
+ break;
+
+ case USES: // uses service-name
+ {
+ UsesDirective usesDirective = (UsesDirective) directive;
+ writer.print("uses ");
+ writer.print(usesDirective.getService().getQualifiedName());
+ }
+ break;
+
+ default:
+ throw new UnsupportedOperationException("unknown directive " + directive);
+ }
+ writer.println(";");
+ }
+
+ private void printModuleList(List<? extends ModuleElement> modules) {
+ if (modules != null) {
+ writer.print(" to ");
+ printNameableList(modules);
+ }
+ }
+
+ private void printNameableList(List<? extends QualifiedNameable> nameables) {
+ writer.print(nameables.stream().
+ map(QualifiedNameable::getQualifiedName).
+ collect(Collectors.joining(", ")));
+ }
+
public void flush() {
writer.flush();
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Feb 09 23:15:52 2017 +0100
@@ -1895,6 +1895,9 @@
compiler.err.expected.module=\
''module'' expected
+compiler.err.expected.module.or.open=\
+ ''module'' or ''open'' expected
+
compiler.err.dot.class.expected=\
''.class'' expected
@@ -2882,6 +2885,10 @@
compiler.err.no.opens.unless.strong=\
''opens'' only allowed in strong modules
+# 0: symbol
+compiler.err.repeated.provides.for.service=\
+ multiple ''provides'' for service {0}
+
# 0: symbol, 1: symbol
compiler.err.duplicate.provides=\
duplicate provides: service {0}, implementation {1}
@@ -2921,6 +2928,10 @@
compiler.err.package.empty.or.not.found=\
package is empty or does not exist: {0}
+# 0: symbol
+compiler.warn.package.empty.or.not.found=\
+ package is empty or does not exist: {0}
+
compiler.err.no.output.dir=\
no class output directory specified
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties Thu Feb 09 23:15:52 2017 +0100
@@ -204,6 +204,9 @@
javac.opt.Xlint.desc.module=\
Warn about module system related issues.
+javac.opt.Xlint.desc.opens=\
+ Warn about issues regarding module opens.
+
javac.opt.Xlint.desc.options=\
Warn about issues relating to use of command line options.
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, 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
@@ -1723,9 +1723,29 @@
break main;
ch = text.charAt(currPos);
}
- if (ch == '>' && blockTags.contains(StringUtils.toLowerCase(text.substring(tagPos, currPos)))) {
+ String tagFound = StringUtils.toLowerCase(text.substring(tagPos, currPos));
+ if (blockTags.contains(tagFound)) {
result.append(text, startPos, lessThanPos);
+ currPos = tagPos + tagFound.length();
+ boolean foundGT = false;
+ Character quoteKind = null;
+ while (!foundGT) {
+ if (ch == '\"' || ch == '\'') {
+ if (quoteKind == null) {
+ quoteKind = ch;
+ } else if (quoteKind == ch) {
+ quoteKind = null;
+ }
+ }
+ if (ch == '>' && quoteKind == null) {
+ foundGT = true;
+ }
+ if (++currPos == len)
+ break;
+ ch = text.charAt(currPos);
+ }
startPos = currPos + 1;
+ currPos = startPos;
}
lessThanPos = text.indexOf('<', currPos);
}
@@ -1740,6 +1760,10 @@
('1' <= ch && ch <= '6');
}
+ private static boolean isWhitespace(char ch) {
+ return Character.isWhitespace(ch);
+ }
+
/**
* Add a link to the stylesheet file.
*
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractIndexWriter.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractIndexWriter.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, 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
@@ -437,23 +437,23 @@
protected void createSearchIndexFiles() throws DocFileIOException {
if (configuration.showModules) {
createSearchIndexFile(DocPaths.MODULE_SEARCH_INDEX_JSON, DocPaths.MODULE_SEARCH_INDEX_ZIP,
- configuration.moduleSearchIndex);
+ DocPaths.MODULE_SEARCH_INDEX_JS, configuration.moduleSearchIndex, "moduleSearchIndex");
}
createSearchIndexFile(DocPaths.PACKAGE_SEARCH_INDEX_JSON, DocPaths.PACKAGE_SEARCH_INDEX_ZIP,
- configuration.packageSearchIndex);
+ DocPaths.PACKAGE_SEARCH_INDEX_JS, configuration.packageSearchIndex, "packageSearchIndex");
createSearchIndexFile(DocPaths.TYPE_SEARCH_INDEX_JSON, DocPaths.TYPE_SEARCH_INDEX_ZIP,
- configuration.typeSearchIndex);
+ DocPaths.TYPE_SEARCH_INDEX_JS, configuration.typeSearchIndex, "typeSearchIndex");
createSearchIndexFile(DocPaths.MEMBER_SEARCH_INDEX_JSON, DocPaths.MEMBER_SEARCH_INDEX_ZIP,
- configuration.memberSearchIndex);
+ DocPaths.MEMBER_SEARCH_INDEX_JS, configuration.memberSearchIndex, "memberSearchIndex");
createSearchIndexFile(DocPaths.TAG_SEARCH_INDEX_JSON, DocPaths.TAG_SEARCH_INDEX_ZIP,
- configuration.tagSearchIndex);
+ DocPaths.TAG_SEARCH_INDEX_JS, configuration.tagSearchIndex, "tagSearchIndex");
}
/**
* @throws DocFileIOException if there is a problem creating the search index file
*/
protected void createSearchIndexFile(DocPath searchIndexFile, DocPath searchIndexZip,
- List<SearchIndexItem> searchIndex) throws DocFileIOException {
+ DocPath searchIndexJS, List<SearchIndexItem> searchIndex, String varName) throws DocFileIOException {
if (!searchIndex.isEmpty()) {
StringBuilder searchVar = new StringBuilder("[");
boolean first = true;
@@ -466,6 +466,14 @@
}
}
searchVar.append("]");
+ DocFile jsFile = DocFile.createFileForOutput(configuration, searchIndexJS);
+ try (Writer wr = jsFile.openWriter()) {
+ wr.write(varName);
+ wr.write(" = ");
+ wr.write(searchVar.toString());
+ } catch (IOException ie) {
+ throw new DocFileIOException(jsFile, DocFileIOException.Mode.WRITE, ie);
+ }
DocFile zipFile = DocFile.createFileForOutput(configuration, searchIndexZip);
try (OutputStream fos = zipFile.openOutputStream();
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,10 +29,12 @@
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
+import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
/**
@@ -92,6 +94,15 @@
Content frame = getFrameDetails();
HtmlTree body = new HtmlTree(HtmlTag.BODY);
body.addAttr(HtmlAttr.ONLOAD, "loadFrames()");
+ String topFilePath = configuration.topFile.getPath();
+ String javaScriptRefresh = "\nif (targetPage == \"\" || targetPage == \"undefined\")\n" +
+ " window.location.replace('" + topFilePath + "');\n";
+ RawHtml scriptContent = new RawHtml(javaScriptRefresh.replace("\n", DocletConstants.NL));
+ HtmlTree scriptTree = HtmlTree.SCRIPT();
+ scriptTree.addContent(scriptContent);
+ body.addContent(scriptTree);
+ Content noScript = HtmlTree.NOSCRIPT(contents.noScriptMessage);
+ body.addContent(noScript);
if (configuration.allowTag(HtmlTag.MAIN)) {
HtmlTree main = HtmlTree.MAIN(frame);
body.addContent(main);
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -74,6 +74,11 @@
return memberTree;
}
+ @Override
+ public boolean showTabs() {
+ return false;
+ }
+
/**
* {@inheritDoc}
*/
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/script.js Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/script.js Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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
@@ -77,6 +77,21 @@
tagSearchIndex = JSON.parse(zip.file("tag-search-index.json").asText());
});
});
+ if (!moduleSearchIndex) {
+ createElem(doc, tag, 'module-search-index.js');
+ }
+ if (!packageSearchIndex) {
+ createElem(doc, tag, 'package-search-index.js');
+ }
+ if (!typeSearchIndex) {
+ createElem(doc, tag, 'type-search-index.js');
+ }
+ if (!memberSearchIndex) {
+ createElem(doc, tag, 'member-search-index.js');
+ }
+ if (!tagSearchIndex) {
+ createElem(doc, tag, 'tag-search-index.js');
+ }
}
function createElem(doc, tag, path) {
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, 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
@@ -121,12 +121,18 @@
/** The name of the member search index zip file. */
public static final DocPath MEMBER_SEARCH_INDEX_ZIP = DocPath.create("member-search-index.zip");
+ /** The name of the member search index js file. */
+ public static final DocPath MEMBER_SEARCH_INDEX_JS = DocPath.create("member-search-index.js");
+
/** The name of the module search index file. */
public static final DocPath MODULE_SEARCH_INDEX_JSON = DocPath.create("module-search-index.json");
- /** The name of the module search index zipfile. */
+ /** The name of the module search index zip file. */
public static final DocPath MODULE_SEARCH_INDEX_ZIP = DocPath.create("module-search-index.zip");
+ /** The name of the module search index js file. */
+ public static final DocPath MODULE_SEARCH_INDEX_JS = DocPath.create("module-search-index.js");
+
/** The name of the file for the overview frame. */
public static final DocPath OVERVIEW_FRAME = DocPath.create("overview-frame.html");
@@ -149,9 +155,12 @@
/** The name of the package search index file. */
public static final DocPath PACKAGE_SEARCH_INDEX_JSON = DocPath.create("package-search-index.json");
- /** The name of the package search index zipfile. */
+ /** The name of the package search index zip file. */
public static final DocPath PACKAGE_SEARCH_INDEX_ZIP = DocPath.create("package-search-index.zip");
+ /** The name of the package search index js file. */
+ public static final DocPath PACKAGE_SEARCH_INDEX_JS = DocPath.create("package-search-index.js");
+
/** The name of the file for the package summary. */
public static final DocPath PACKAGE_SUMMARY = DocPath.create("package-summary.html");
@@ -202,12 +211,18 @@
/** The name of the tag search index zip file. */
public static final DocPath TAG_SEARCH_INDEX_ZIP = DocPath.create("tag-search-index.zip");
+ /** The name of the tag search index js file. */
+ public static final DocPath TAG_SEARCH_INDEX_JS = DocPath.create("tag-search-index.js");
+
/** The name of the type search index file. */
public static final DocPath TYPE_SEARCH_INDEX_JSON = DocPath.create("type-search-index.json");
/** The name of the type search index zip file. */
public static final DocPath TYPE_SEARCH_INDEX_ZIP = DocPath.create("type-search-index.zip");
+ /** The name of the type search index js file. */
+ public static final DocPath TYPE_SEARCH_INDEX_JS = DocPath.create("type-search-index.js");
+
/** The name of the image file for undo button on the search box. */
public static final DocPath X_IMG = DocPath.create("x.png");
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, 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
@@ -1773,14 +1773,14 @@
/**
* Returns a Comparator for index file presentations, and are sorted as follows.
* If comparing modules then simply compare the simple names,
- * comparing packages then simply compare the qualified names, otherwise
- * 1. if equal, then compare the ElementKind ex: Module, Package, Interface etc.
- * 2. sort on simple names of entities
- * 3a. if equal and if the type is of ExecutableElement(Constructor, Methods),
+ * comparing packages then simply compare the qualified names, if comparing a package with a
+ * module/type/member then compare the FullyQualifiedName of the package
+ * with the SimpleName of the entity, otherwise
+ * 1. compare the ElementKind ex: Module, Package, Interface etc.
+ * 2a. if equal and if the type is of ExecutableElement(Constructor, Methods),
* a case insensitive comparison of parameter the type signatures
- * 3b. if equal, case sensitive comparison of the type signatures
- * 4. finally, if equal, compare the FQNs of the entities
- * Iff comparing packages then simply sort on qualified names.
+ * 2b. if equal, case sensitive comparison of the type signatures
+ * 3. finally, if equal, compare the FQNs of the entities
* @return a comparator for index file use
*/
public Comparator<Element> makeIndexUseComparator() {
@@ -1788,8 +1788,10 @@
/**
* Compare two given elements, if comparing two modules, return the
* comparison of SimpleName, if comparing two packages, return the
- * comparison of FullyQualifiedName, first sort on kinds, then on the
- * names, then on the parameters only if the type is an ExecutableElement,
+ * comparison of FullyQualifiedName, if comparing a package with a
+ * module/type/member then compare the FullyQualifiedName of the package
+ * with the SimpleName of the entity, then sort on the kinds, then on
+ * the parameters only if the type is an ExecutableElement,
* the parameters are compared and finally the qualified names.
*
* @param e1 - an element.
@@ -1806,11 +1808,17 @@
if (isPackage(e1) && isPackage(e2)) {
return compareFullyQualifiedNames(e1, e2);
}
- result = compareElementTypeKinds(e1, e2);
+ if (isPackage(e1) || isPackage(e2)) {
+ result = (isPackage(e1))
+ ? compareStrings(getFullyQualifiedName(e1), getSimpleName(e2))
+ : compareStrings(getSimpleName(e1), getFullyQualifiedName(e2));
+ } else {
+ result = compareNames(e1, e2);
+ }
if (result != 0) {
return result;
}
- result = compareNames(e1, e2);
+ result = compareElementTypeKinds(e1, e2);
if (result != 0) {
return result;
}
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties Thu Feb 09 23:15:52 2017 +0100
@@ -33,16 +33,20 @@
where options include:
main.opt.public.desc=\
- Show only public classes and members
+ Show only public types and members. For named modules,\n\
+ show exported packages and the module''s API.
main.opt.protected.desc=\
- Show protected/public classes and members (default)
+ Show protected/public types and members (default). For\n\
+ named modules, show exported packages and the module''s API.
main.opt.package.desc=\
- Show package/protected/public classes and members
+ Show package/protected/public types and members. For \n\
+ named modules, show all packages and all module details.
main.opt.private.desc=\
- Show all classes and members
+ Show all types and members. For named modules,\n\
+ show all packages and all module details.
main.opt.show.members.arg=\
<value>
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, 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,6 +56,7 @@
import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute;
import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute;
import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute;
+import com.sun.tools.classfile.RuntimeParameterAnnotations_attribute;
import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute;
import com.sun.tools.classfile.RuntimeVisibleParameterAnnotations_attribute;
import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute;
@@ -164,6 +165,7 @@
print("default_value: ");
annotationWriter.write(attr.default_value);
indent(-1);
+ println();
return null;
}
@@ -764,9 +766,8 @@
return null;
}
- @Override
- public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, Void ignore) {
- println("RuntimeVisibleParameterAnnotations:");
+ private void visitParameterAnnotations(String message, RuntimeParameterAnnotations_attribute attr) {
+ println(message);
indent(+1);
for (int param = 0; param < attr.parameter_annotations.length; param++) {
println("parameter " + param + ": ");
@@ -779,24 +780,17 @@
indent(-1);
}
indent(-1);
+ }
+
+ @Override
+ public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, Void ignore) {
+ visitParameterAnnotations("RuntimeVisibleParameterAnnotations:", (RuntimeParameterAnnotations_attribute) attr);
return null;
}
@Override
public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, Void ignore) {
- println("RuntimeInvisibleParameterAnnotations:");
- indent(+1);
- for (int param = 0; param < attr.parameter_annotations.length; param++) {
- println(param + ": ");
- indent(+1);
- for (int i = 0; i < attr.parameter_annotations[param].length; i++) {
- print(i + ": ");
- annotationWriter.write(attr.parameter_annotations[param][i]);
- println();
- }
- indent(-1);
- }
- indent(-1);
+ visitParameterAnnotations("RuntimeInvisibleParameterAnnotations:", (RuntimeParameterAnnotations_attribute) attr);
return null;
}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java Thu Feb 09 23:15:52 2017 +0100
@@ -45,6 +45,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -57,6 +58,7 @@
import jdk.internal.jline.WindowsTerminal;
import jdk.internal.jline.console.ConsoleReader;
import jdk.internal.jline.console.KeyMap;
+import jdk.internal.jline.console.Operation;
import jdk.internal.jline.console.UserInterruptException;
import jdk.internal.jline.console.completer.Completer;
import jdk.internal.jline.console.history.History;
@@ -90,7 +92,12 @@
term = new JShellUnixTerminal(input);
}
term.init();
- in = new ConsoleReader(cmdin, cmdout, term);
+ AtomicBoolean allowSmart = new AtomicBoolean();
+ in = new ConsoleReader(cmdin, cmdout, term) {
+ @Override public KeyMap getKeys() {
+ return new CheckCompletionKeyMap(super.getKeys(), allowSmart);
+ }
+ };
in.setExpandEvents(false);
in.setHandleUserInterrupt(true);
List<String> persistenHistory = Stream.of(repl.prefs.keys())
@@ -106,9 +113,6 @@
in.setBellEnabled(true);
in.setCopyPasteDetection(true);
in.addCompleter(new Completer() {
- private String lastTest;
- private int lastCursor;
- private boolean allowSmart = false;
@Override public int complete(String test, int cursor, List<CharSequence> result) {
int[] anchor = new int[] {-1};
List<Suggestion> suggestions;
@@ -119,16 +123,11 @@
suggestions = repl.analysis.completionSuggestions(prefix + test, cursor + prefixLength, anchor);
anchor[0] -= prefixLength;
}
- if (!Objects.equals(lastTest, test) || lastCursor != cursor)
- allowSmart = true;
-
- boolean smart = allowSmart &&
+ boolean smart = allowSmart.get() &&
suggestions.stream()
.anyMatch(Suggestion::matchesType);
- lastTest = test;
- lastCursor = cursor;
- allowSmart = !allowSmart;
+ allowSmart.set(!allowSmart.get());
suggestions.stream()
.filter(s -> !smart || s.matchesType())
@@ -391,27 +390,23 @@
@Override
public boolean terminalEditorRunning() {
Terminal terminal = in.getTerminal();
- if (terminal instanceof JShellUnixTerminal)
- return ((JShellUnixTerminal) terminal).isRaw();
+ if (terminal instanceof SuspendableTerminal)
+ return ((SuspendableTerminal) terminal).isRaw();
return false;
}
@Override
public void suspend() {
- try {
- in.getTerminal().restore();
- } catch (Exception ex) {
- throw new IllegalStateException(ex);
- }
+ Terminal terminal = in.getTerminal();
+ if (terminal instanceof SuspendableTerminal)
+ ((SuspendableTerminal) terminal).suspend();
}
@Override
public void resume() {
- try {
- in.getTerminal().init();
- } catch (Exception ex) {
- throw new IllegalStateException(ex);
- }
+ Terminal terminal = in.getTerminal();
+ if (terminal instanceof SuspendableTerminal)
+ ((SuspendableTerminal) terminal).resume();
}
@Override
@@ -667,7 +662,7 @@
}
};
- private static final class JShellUnixTerminal extends NoInterruptUnixTerminal {
+ private static final class JShellUnixTerminal extends NoInterruptUnixTerminal implements SuspendableTerminal {
private final StopDetectingInputStream input;
@@ -696,9 +691,28 @@
public void enableInterruptCharacter() {
}
+ @Override
+ public void suspend() {
+ try {
+ getSettings().restore();
+ super.disableInterruptCharacter();
+ } catch (Exception ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+
+ @Override
+ public void resume() {
+ try {
+ init();
+ } catch (Exception ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+
}
- private static final class JShellWindowsTerminal extends WindowsTerminal {
+ private static final class JShellWindowsTerminal extends WindowsTerminal implements SuspendableTerminal {
private final StopDetectingInputStream input;
@@ -717,6 +731,31 @@
return input.setInputStream(super.wrapInIfNeeded(in));
}
+ @Override
+ public void suspend() {
+ try {
+ restore();
+ setConsoleMode(getConsoleMode() & ~ConsoleMode.ENABLE_PROCESSED_INPUT.code);
+ } catch (Exception ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+
+ @Override
+ public void resume() {
+ try {
+ restore();
+ init();
+ } catch (Exception ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+
+ @Override
+ public boolean isRaw() {
+ return (getConsoleMode() & ConsoleMode.ENABLE_LINE_INPUT.code) == 0;
+ }
+
}
private static final class TestTerminal extends TerminalSupport {
@@ -736,4 +775,63 @@
}
}
+
+ private interface SuspendableTerminal {
+ public void suspend();
+ public void resume();
+ public boolean isRaw();
+ }
+
+ private static final class CheckCompletionKeyMap extends KeyMap {
+
+ private final KeyMap del;
+ private final AtomicBoolean allowSmart;
+
+ public CheckCompletionKeyMap(KeyMap del, AtomicBoolean allowSmart) {
+ super(del.getName(), del.isViKeyMap());
+ this.del = del;
+ this.allowSmart = allowSmart;
+ }
+
+ @Override
+ public void bind(CharSequence keySeq, Object function) {
+ del.bind(keySeq, function);
+ }
+
+ @Override
+ public void bindIfNotBound(CharSequence keySeq, Object function) {
+ del.bindIfNotBound(keySeq, function);
+ }
+
+ @Override
+ public void from(KeyMap other) {
+ del.from(other);
+ }
+
+ @Override
+ public Object getAnotherKey() {
+ return del.getAnotherKey();
+ }
+
+ @Override
+ public Object getBound(CharSequence keySeq) {
+ Object res = del.getBound(keySeq);
+
+ if (res != Operation.COMPLETE) {
+ allowSmart.set(true);
+ }
+
+ return res;
+ }
+
+ @Override
+ public void setBlinkMatchingParen(boolean on) {
+ del.setBlinkMatchingParen(on);
+ }
+
+ @Override
+ public String toString() {
+ return "check: " + del.toString();
+ }
+ }
}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java Thu Feb 09 23:15:52 2017 +0100
@@ -197,7 +197,6 @@
private boolean debug = false;
public boolean testPrompt = false;
- private String defaultStartup = null;
private Startup startup = null;
private String executionControlSpec = null;
private EditorSetting editor = BUILT_IN_EDITOR;
@@ -205,9 +204,9 @@
private static final String[] EDITOR_ENV_VARS = new String[] {
"JSHELLEDITOR", "VISUAL", "EDITOR"};
- // Commands and snippets which should be replayed
- private List<String> replayableHistory;
- private List<String> replayableHistoryPrevious;
+ // Commands and snippets which can be replayed
+ private ReplayableHistory replayableHistory;
+ private ReplayableHistory replayableHistoryPrevious;
static final String STARTUP_KEY = "STARTUP";
static final String EDITOR_KEY = "EDITOR";
@@ -426,7 +425,8 @@
private final OptionSpecBuilder argHelp = parser.acceptsAll(asList("h", "help"));
private final OptionSpecBuilder argVersion = parser.accepts("version");
private final OptionSpecBuilder argFullVersion = parser.accepts("full-version");
- private final OptionSpecBuilder argX = parser.accepts("X");
+ private final OptionSpecBuilder argShowVersion = parser.accepts("show-version");
+ private final OptionSpecBuilder argHelpExtra = parser.acceptsAll(asList("X", "help-extra"));
private String feedbackMode = null;
private Startup initialStartup = null;
@@ -450,7 +450,7 @@
printUsage();
return null;
}
- if (options.has(argX)) {
+ if (options.has(argHelpExtra)) {
printUsageX();
return null;
}
@@ -462,6 +462,9 @@
cmdout.printf("jshell %s\n", fullVersion());
return null;
}
+ if (options.has(argShowVersion)) {
+ cmdout.printf("jshell %s\n", version());
+ }
if ((options.valuesOf(argFeedback).size() +
(options.has(argQ) ? 1 : 0) +
(options.has(argS) ? 1 : 0) +
@@ -503,6 +506,76 @@
}
/**
+ * Encapsulate a history of snippets and commands which can be replayed.
+ */
+ private static class ReplayableHistory {
+
+ // the history
+ private List<String> hist;
+
+ // the length of the history as of last save
+ private int lastSaved;
+
+ private ReplayableHistory(List<String> hist) {
+ this.hist = hist;
+ this.lastSaved = 0;
+ }
+
+ // factory for empty histories
+ static ReplayableHistory emptyHistory() {
+ return new ReplayableHistory(new ArrayList<>());
+ }
+
+ // factory for history stored in persistent storage
+ static ReplayableHistory fromPrevious(PersistentStorage prefs) {
+ // Read replay history from last jshell session
+ String prevReplay = prefs.get(REPLAY_RESTORE_KEY);
+ if (prevReplay == null) {
+ return null;
+ } else {
+ return new ReplayableHistory(Arrays.asList(prevReplay.split(RECORD_SEPARATOR)));
+ }
+
+ }
+
+ // store the history in persistent storage
+ void storeHistory(PersistentStorage prefs) {
+ if (hist.size() > lastSaved) {
+ // Prevent history overflow by calculating what will fit, starting
+ // with most recent
+ int sepLen = RECORD_SEPARATOR.length();
+ int length = 0;
+ int first = hist.size();
+ while (length < Preferences.MAX_VALUE_LENGTH && --first >= 0) {
+ length += hist.get(first).length() + sepLen;
+ }
+ if (first >= 0) {
+ hist = hist.subList(first + 1, hist.size());
+ }
+ String shist = String.join(RECORD_SEPARATOR, hist);
+ prefs.put(REPLAY_RESTORE_KEY, shist);
+ markSaved();
+ }
+ prefs.flush();
+ }
+
+ // add a snippet or command to the history
+ void add(String s) {
+ hist.add(s);
+ }
+
+ // return history to reloaded
+ Iterable<String> iterable() {
+ return hist;
+ }
+
+ // mark that persistent storage and current history are in sync
+ void markSaved() {
+ lastSaved = hist.size();
+ }
+ }
+
+ /**
* Is the input/output currently interactive
*
* @return true if console
@@ -752,10 +825,7 @@
// initialize JShell instance
resetState();
// Read replay history from last jshell session into previous history
- String prevReplay = prefs.get(REPLAY_RESTORE_KEY);
- if (prevReplay != null) {
- replayableHistoryPrevious = Arrays.asList(prevReplay.split(RECORD_SEPARATOR));
- }
+ replayableHistoryPrevious = ReplayableHistory.fromPrevious(prefs);
// load snippet/command files given on command-line
for (String loadFile : commandLineArgs.nonOptions()) {
runFile(loadFile, "jshell");
@@ -771,6 +841,13 @@
if (feedback.shouldDisplayCommandFluff()) {
hardmsg("jshell.msg.welcome", version());
}
+ // Be sure history is always saved so that user code isn't lost
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ @Override
+ public void run() {
+ replayableHistory.storeHistory(prefs);
+ }
+ });
// execute from user input
try (IOContext in = new ConsoleIOContext(this, cmdin, console)) {
start(in);
@@ -864,7 +941,7 @@
// Reset the replayable history, saving the old for restore
replayableHistoryPrevious = replayableHistory;
- replayableHistory = new ArrayList<>();
+ replayableHistory = ReplayableHistory.emptyHistory();
JShell.Builder builder =
JShell.builder()
.in(userin)
@@ -1929,20 +2006,7 @@
private boolean cmdExit() {
regenerateOnDeath = false;
live = false;
- if (!replayableHistory.isEmpty()) {
- // Prevent history overflow by calculating what will fit, starting
- // with most recent
- int sepLen = RECORD_SEPARATOR.length();
- int length = 0;
- int first = replayableHistory.size();
- while(length < Preferences.MAX_VALUE_LENGTH && --first >= 0) {
- length += replayableHistory.get(first).length() + sepLen;
- }
- String hist = String.join(RECORD_SEPARATOR,
- replayableHistory.subList(first + 1, replayableHistory.size()));
- prefs.put(REPLAY_RESTORE_KEY, hist);
- }
- prefs.flush();
+ replayableHistory.storeHistory(prefs);
fluffmsg("jshell.msg.goodbye");
return true;
}
@@ -2416,7 +2480,7 @@
if (!parseCommandLineLikeFlags(rawargs, ap)) {
return false;
}
- Iterable<String> history;
+ ReplayableHistory history;
if (ap.restore()) {
if (replayableHistoryPrevious == null) {
errormsg("jshell.err.reload.no.previous");
@@ -2428,7 +2492,13 @@
history = replayableHistory;
fluffmsg("jshell.err.reload.restarting.state");
}
- return doReload(history, !ap.quiet());
+ boolean success = doReload(history, !ap.quiet());
+ if (success && ap.restore()) {
+ // if we are restoring from previous, then if nothing was added
+ // before time of exit, there is nothing to save
+ replayableHistory.markSaved();
+ }
+ return success;
}
private boolean cmdEnv(String rawargs) {
@@ -2456,9 +2526,9 @@
return doReload(replayableHistory, false);
}
- private boolean doReload(Iterable<String> history, boolean echo) {
+ private boolean doReload(ReplayableHistory history, boolean echo) {
resetState();
- run(new ReloadIOContext(history,
+ run(new ReloadIOContext(history.iterable(),
echo ? cmdout : null));
return true;
}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties Thu Feb 09 23:15:52 2017 +0100
@@ -187,9 +187,10 @@
\ Use one -R for each remote flag or flag argument\n\
\ -C<flag> Pass <flag> to the compiler.\n\
\ Use one -C for each compiler flag or flag argument\n\
-\ --help Print this synopsis of standard options\n\
-\ --version Version information\n\
-\ -X Print help on non-standard options\n
+\ --version Print version information and exit\n\
+\ --show-version Print version information and continue\n\
+\ --help Print this synopsis of standard options and exit\n\
+\ --help-extra, -X Print help on non-standard options and exit\n
help.usage.x = \
\ --add-exports <module>/<package> Export specified module-private package to snippets\n\
\ --execution <spec> Specify an alternate execution engine.\n\
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java Thu Feb 09 23:15:52 2017 +0100
@@ -85,7 +85,7 @@
try {
Parser parser = new Parser(
() -> new Matched(scannerFactory.newScanner(s, false)),
- () -> proc.taskFactory.new ParseTask(s));
+ () -> proc.taskFactory.parse(s));
Completeness stat = parser.parseUnit();
int endPos = stat == Completeness.UNKNOWN
? s.length()
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java Thu Feb 09 23:15:52 2017 +0100
@@ -155,7 +155,7 @@
if (compileSource.length() == 0) {
return Collections.emptyList();
}
- ParseTask pt = state.taskFactory.new ParseTask(compileSource);
+ ParseTask pt = state.taskFactory.parse(compileSource);
List<? extends Tree> units = pt.units();
if (units.isEmpty()) {
return compileFailResult(pt, userSource, Kind.ERRONEOUS);
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ReplParser.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ReplParser.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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
@@ -39,7 +39,6 @@
import static com.sun.tools.javac.parser.Tokens.TokenKind.INTERFACE;
import static com.sun.tools.javac.parser.Tokens.TokenKind.LPAREN;
import static com.sun.tools.javac.parser.Tokens.TokenKind.MONKEYS_AT;
-import static com.sun.tools.javac.parser.Tokens.TokenKind.PACKAGE;
import static com.sun.tools.javac.parser.Tokens.TokenKind.SEMI;
import static com.sun.tools.javac.parser.Tokens.TokenKind.VOID;
import com.sun.tools.javac.tree.JCTree;
@@ -48,10 +47,8 @@
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCExpressionStatement;
import com.sun.tools.javac.tree.JCTree.JCModifiers;
-import com.sun.tools.javac.tree.JCTree.JCPackageDecl;
import com.sun.tools.javac.tree.JCTree.JCStatement;
import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
-import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.tree.JCTree.Tag;
import static com.sun.tools.javac.tree.JCTree.Tag.IDENT;
import com.sun.tools.javac.util.List;
@@ -68,12 +65,17 @@
*/
class ReplParser extends JavacParser {
+ // force starting in expression mode
+ private final boolean forceExpression;
+
public ReplParser(ParserFactory fac,
com.sun.tools.javac.parser.Lexer S,
boolean keepDocComments,
boolean keepLineMap,
- boolean keepEndPositions) {
+ boolean keepEndPositions,
+ boolean forceExpression) {
super(fac, S, keepDocComments, keepLineMap, keepEndPositions);
+ this.forceExpression = forceExpression;
}
/**
@@ -205,7 +207,10 @@
nextToken();
} else {
// return type of method, declared type of variable, or an expression
- t = term(EXPR | TYPE);
+ // unless expression is being forced
+ t = term(forceExpression
+ ? EXPR
+ : EXPR | TYPE);
}
if (token.kind == COLON && t.hasTag(IDENT)) {
// labelled statement
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ReplParserFactory.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ReplParserFactory.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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
@@ -36,24 +36,30 @@
*/
class ReplParserFactory extends ParserFactory {
- public static ParserFactory instance(Context context) {
- ParserFactory instance = context.get(parserFactoryKey);
- if (instance == null) {
- instance = new ReplParserFactory(context);
- }
- return instance;
+ // force starting in expression mode
+ private final boolean forceExpression;
+
+ public static void preRegister(Context context, boolean forceExpression) {
+ context.put(parserFactoryKey, (Context.Factory<ParserFactory>)
+ (c -> new ReplParserFactory(c, forceExpression)));
}
private final ScannerFactory scannerFactory;
- protected ReplParserFactory(Context context) {
+ protected ReplParserFactory(Context context, boolean forceExpression) {
super(context);
+ this.forceExpression = forceExpression;
this.scannerFactory = ScannerFactory.instance(context);
}
@Override
public JavacParser newParser(CharSequence input, boolean keepDocComments, boolean keepEndPos, boolean keepLineMap) {
com.sun.tools.javac.parser.Lexer lexer = scannerFactory.newScanner(input, keepDocComments);
- return new ReplParser(this, lexer, keepDocComments, keepLineMap, keepEndPos);
+ return new ReplParser(this, lexer, keepDocComments, keepLineMap, keepEndPos, forceExpression);
+ }
+
+ @Override
+ public JavacParser newParser(CharSequence input, boolean keepDocComments, boolean keepEndPos, boolean keepLineMap, boolean parseModuleInfo) {
+ return newParser(input, keepDocComments, keepEndPos, keepLineMap);
}
}
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java Thu Feb 09 23:15:52 2017 +0100
@@ -227,7 +227,7 @@
}
private Tree.Kind guessKind(String code) {
- ParseTask pt = proc.taskFactory.new ParseTask(code);
+ ParseTask pt = proc.taskFactory.parse(code);
List<? extends Tree> units = pt.units();
if (units.isEmpty()) {
return Tree.Kind.BLOCK;
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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
@@ -61,6 +61,7 @@
import javax.tools.FileObject;
import jdk.jshell.MemoryFileManager.SourceMemoryJavaFileObject;
import java.lang.Runtime.Version;
+import com.sun.source.tree.Tree.Kind;
/**
* The primary interface to the compiler API. Parsing, analysis, and
@@ -100,6 +101,23 @@
return fileManager;
}
+ // Parse a snippet and return our parse task handler
+ ParseTask parse(final String source) {
+ ParseTask pt = state.taskFactory.new ParseTask(source, false);
+ if (!pt.units().isEmpty()
+ && pt.units().get(0).getKind() == Kind.EXPRESSION_STATEMENT
+ && pt.getDiagnostics().hasOtherThanNotStatementErrors()) {
+ // It failed, it may be an expression being incorrectly
+ // parsed as having a leading type variable, example: a < b
+ // Try forcing interpretation as an expression
+ ParseTask ept = state.taskFactory.new ParseTask(source, true);
+ if (!ept.getDiagnostics().hasOtherThanNotStatementErrors()) {
+ return ept;
+ }
+ }
+ return pt;
+ }
+
private interface SourceHandler<T> {
JavaFileObject sourceToFileObject(MemoryFileManager fm, T t);
@@ -179,11 +197,11 @@
private final Iterable<? extends CompilationUnitTree> cuts;
private final List<? extends Tree> units;
- ParseTask(final String source) {
+ ParseTask(final String source, final boolean forceExpression) {
super(Stream.of(source),
new StringSourceHandler(),
"-XDallowStringFolding=false", "-proc:none");
- ReplParserFactory.instance(getContext());
+ ReplParserFactory.preRegister(getContext(), forceExpression);
cuts = parse();
units = Util.stream(cuts)
.flatMap(cut -> {
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/DirectExecutionControl.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/DirectExecutionControl.java Thu Feb 09 23:15:52 2017 +0100
@@ -28,6 +28,7 @@
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.util.stream.IntStream;
import jdk.jshell.spi.ExecutionControl;
import jdk.jshell.spi.SPIResolutionException;
@@ -41,6 +42,23 @@
*/
public class DirectExecutionControl implements ExecutionControl {
+ private static final String[] charRep;
+
+ static {
+ charRep = new String[256];
+ for (int i = 0; i < charRep.length; ++i) {
+ charRep[i] = Character.isISOControl(i)
+ ? String.format("\\%03o", i)
+ : "" + (char) i;
+ }
+ charRep['\b'] = "\\b";
+ charRep['\t'] = "\\t";
+ charRep['\n'] = "\\n";
+ charRep['\f'] = "\\f";
+ charRep['\r'] = "\\r";
+ charRep['\\'] = "\\\\";
+ }
+
private final LoaderDelegate loaderDelegate;
/**
@@ -192,9 +210,26 @@
if (value == null) {
return "null";
} else if (value instanceof String) {
- return "\"" + (String) value + "\"";
+ return "\"" + ((String) value).codePoints()
+ .flatMap(cp ->
+ (cp == '"')
+ ? "\\\"".codePoints()
+ : (cp < 256)
+ ? charRep[cp].codePoints()
+ : IntStream.of(cp))
+ .collect(
+ StringBuilder::new,
+ StringBuilder::appendCodePoint,
+ StringBuilder::append)
+ .toString() + "\"";
} else if (value instanceof Character) {
- return "'" + value + "'";
+ char cp = (char) (Character) value;
+ return "'" + (
+ (cp == '\'')
+ ? "\\\'"
+ : (cp < 256)
+ ? charRep[cp]
+ : String.valueOf(cp)) + "'";
} else if (value.getClass().isArray()) {
int dims = 0;
Class<?> t = value.getClass();
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/FailOverExecutionControlProvider.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/FailOverExecutionControlProvider.java Thu Feb 09 23:15:52 2017 +0100
@@ -111,7 +111,8 @@
PrintWriter log = new PrintWriter(writer);
log.println("FailOverExecutionControlProvider:");
ex.printStackTrace(log);
- logger().fine(log.toString());
+ log.flush();
+ logger().fine(writer.toString());
// only care about the first, and only if they all fail
if (thrown == null) {
thrown = ex;
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiDefaultExecutionControl.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiDefaultExecutionControl.java Thu Feb 09 23:15:52 2017 +0100
@@ -102,7 +102,6 @@
Process process = jdii.process();
List<Consumer<String>> deathListeners = new ArrayList<>();
- deathListeners.add(s -> env.closeDown());
Util.detectJdiExitEvent(vm, s -> {
for (Consumer<String> h : deathListeners) {
h.accept(s);
@@ -120,7 +119,8 @@
Map<String, InputStream> input = new HashMap<>();
input.put("in", env.userIn());
return remoteInputOutput(socket.getInputStream(), out, outputs, input,
- (objIn, objOut) -> new JdiDefaultExecutionControl(objOut, objIn, vm, process, remoteAgent, deathListeners));
+ (objIn, objOut) -> new JdiDefaultExecutionControl(env,
+ objOut, objIn, vm, process, remoteAgent, deathListeners));
}
}
@@ -130,15 +130,20 @@
* @param cmdout the output for commands
* @param cmdin the input for responses
*/
- private JdiDefaultExecutionControl(ObjectOutput cmdout, ObjectInput cmdin,
+ private JdiDefaultExecutionControl(ExecutionEnv env,
+ ObjectOutput cmdout, ObjectInput cmdin,
VirtualMachine vm, Process process, String remoteAgent,
List<Consumer<String>> deathListeners) {
super(cmdout, cmdin);
this.vm = vm;
this.process = process;
this.remoteAgent = remoteAgent;
+ // We have now succeeded in establishing the connection.
+ // If there is an exit now it propagates all the way up
+ // and the VM should be disposed of.
+ deathListeners.add(s -> env.closeDown());
deathListeners.add(s -> disposeVM());
- }
+ }
@Override
public String invoke(String classname, String methodname)
--- a/langtools/src/jdk.jshell/share/classes/module-info.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/src/jdk.jshell/share/classes/module-info.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -70,11 +70,10 @@
uses jdk.jshell.spi.ExecutionControlProvider;
uses jdk.internal.editor.spi.BuildInEditorProvider;
- provides javax.tools.Tool with jdk.internal.jshell.tool.JShellToolProvider;
- provides jdk.jshell.spi.ExecutionControlProvider
- with jdk.jshell.execution.JdiExecutionControlProvider;
+ provides javax.tools.Tool
+ with jdk.internal.jshell.tool.JShellToolProvider;
provides jdk.jshell.spi.ExecutionControlProvider
- with jdk.jshell.execution.LocalExecutionControlProvider;
- provides jdk.jshell.spi.ExecutionControlProvider
- with jdk.jshell.execution.FailOverExecutionControlProvider;
+ with jdk.jshell.execution.JdiExecutionControlProvider,
+ jdk.jshell.execution.LocalExecutionControlProvider,
+ jdk.jshell.execution.FailOverExecutionControlProvider;
}
--- a/langtools/test/ProblemList.txt Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/ProblemList.txt Thu Feb 09 23:15:52 2017 +0100
@@ -36,8 +36,7 @@
#
# jshell
-jdk/jshell/ToolFormatTest.java 8170216 solaris-sparcv9
-jdk/jshell/ReplaceTest.java 8170216 solaris-sparcv9
+jdk/jshell/UserJdiUserRemoteTest.java 8173204 linux-all
jdk/jshell/UserInputTest.java 8169536 generic-all
###########################################################################
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testNonInlineHtmlTagRemoval/C.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+public class C {
+ /**
+ * case1 <ul> <li> end of sentence. <li> more </ul>
+ */
+ public void case1() {}
+
+ /**
+ * case2 <ul compact> <li> end of sentence. <li> more </ul>
+ */
+ public void case2() {}
+
+ /**
+ * case3 <ul type="square"> <li> end of sentence. <li> more </ul>
+ */
+ public void case3() {}
+
+ /**
+ * case4 <ul type="a<b"> <li> end of sentence. <li> more </ul>
+ */
+ public void case4() {}
+
+ /**
+ * case5 <ul type="a>b"> <li> end of sentence. <li> more </ul>
+ */
+ public void case5() {}
+
+ /**
+ * case6 <ul type='a>b'> <li> end of sentence. <li> more </ul>
+ */
+ public void case6() {}
+
+ /**
+ * case7 <ul type='"a>b"'> <li> end of sentence. <li> more </ul>
+ */
+ public void case7() {}
+
+ /**
+ * case8 <ul type="'a>b'"> <li> end of sentence. <li> more </ul>
+ */
+ public void case8() {}
+
+ /**
+ * case9 <ul type="'a'>b"> <li> end of sentence. <li> more </ul>
+ */
+ public void case9() {}
+
+ /**
+ * caseA <ul type='"a">b'> <li> end of sentence. <li> more </ul>
+ */
+ public void caseA() {}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/com/sun/javadoc/testNonInlineHtmlTagRemoval/TestNonInlineHtmlTagRemoval.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017, 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 8048628
+ * @summary Verify html inline tags are removed correctly in the first sentence.
+ * @library ../lib
+ * @modules jdk.javadoc
+ * @build JavadocTester
+ * @run main TestNonInlineHtmlTagRemoval
+ */
+
+public class TestNonInlineHtmlTagRemoval extends JavadocTester {
+
+ public static void main(String... args) throws Exception {
+ TestNonInlineHtmlTagRemoval tester = new TestNonInlineHtmlTagRemoval();
+ tester.runTests();
+ }
+
+ @Test
+ void test() {
+ javadoc("-d", "out",
+ "-sourcepath", testSrc,
+ testSrc("C.java"));
+ checkExit(Exit.OK);
+
+ checkOutput("C.html", true,
+ "<div class=\"block\">case1 end of sentence.</div>",
+ "<div class=\"block\">case2 end of sentence.</div>",
+ "<div class=\"block\">case3 end of sentence.</div>",
+ "<div class=\"block\">case4 end of sentence.</div>",
+ "<div class=\"block\">case5 end of sentence.</div>",
+ "<div class=\"block\">case6 end of sentence.</div>",
+ "<div class=\"block\">case7 end of sentence.</div>",
+ "<div class=\"block\">case8 end of sentence.</div>",
+ "<div class=\"block\">case9 end of sentence.</div>",
+ "<div class=\"block\">caseA end of sentence.</div>");
+ }
+}
--- a/langtools/test/jdk/javadoc/doclet/testFramesNoFrames/TestFramesNoFrames.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/jdk/javadoc/doclet/testFramesNoFrames/TestFramesNoFrames.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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,7 +23,7 @@
/*
* @test
- * @bug 8162353 8164747
+ * @bug 8162353 8164747 8173707
* @summary javadoc should provide a way to disable use of frames
* @library /tools/lib ../lib
* @modules
@@ -323,10 +323,14 @@
}
private void checkIndex() {
- // the index.html page only contains frames in frames mode
+ // the index.html page only contains frames and Javascript to default to no-frames view,
+ // in frames mode
checkOutput("index.html", frames,
"<iframe ",
- "</iframe>");
+ "</iframe>",
+ "<body onload=\"loadFrames()\">\n"
+ + "<script type=\"text/javascript\">\n"
+ + "if (targetPage == \"\" || targetPage == \"undefined\")");
// the index.html contains the overview if one
// has been given, and not in frames mode
--- a/langtools/test/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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,7 +23,7 @@
/*
* @test
- * @bug 8072945 8081854 8141492 8148985 8150188 4649116
+ * @bug 8072945 8081854 8141492 8148985 8150188 4649116 8173707
* @summary Test the version of HTML generated by the javadoc tool.
* @author bpatel
* @library ../lib
@@ -607,6 +607,11 @@
"<!DOCTYPE HTML>",
"<link rel=\"stylesheet\" type=\"text/css\" href=\"stylesheet.css\" title=\"Style\">",
"<body onload=\"loadFrames()\">\n"
+ + "<script type=\"text/javascript\">\n"
+ + "if (targetPage == \"\" || targetPage == \"undefined\")\n"
+ + " window.location.replace('overview-summary.html');\n"
+ + "</script>\n"
+ + "<noscript>JavaScript is disabled on your browser.</noscript>\n"
+ "<main role=\"main\">\n"
+ "<div class=\"mainContainer\">\n"
+ "<div class=\"leftContainer\">\n"
@@ -1012,6 +1017,11 @@
checkOutput("index.html", false,
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">",
"<body>\n"
+ + "<script type=\"text/javascript\">\n"
+ + "if (targetPage == \"\" || targetPage == \"undefined\")\n"
+ + " window.location.replace('overview-summary.html');\n"
+ + "</script>\n"
+ + "<noscript>JavaScript is disabled on your browser.</noscript>\n"
+ "<div class=\"mainContainer\">\n");
}
@@ -1424,6 +1434,11 @@
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">",
"<link rel=\"stylesheet\" type=\"text/css\" href=\"stylesheet.css\" title=\"Style\">",
"<body onload=\"loadFrames()\">\n"
+ + "<script type=\"text/javascript\">\n"
+ + "if (targetPage == \"\" || targetPage == \"undefined\")\n"
+ + " window.location.replace('overview-summary.html');\n"
+ + "</script>\n"
+ + "<noscript>JavaScript is disabled on your browser.</noscript>\n"
+ "<div class=\"mainContainer\">\n"
+ "<div class=\"leftContainer\">\n"
+ "<div class=\"leftTop\">\n"
@@ -1924,6 +1939,11 @@
checkOutput("index.html", false,
"<!DOCTYPE HTML>",
"<body>\n"
+ + "<script type=\"text/javascript\">\n"
+ + "if (targetPage == \"\" || targetPage == \"undefined\")\n"
+ + " window.location.replace('overview-summary.html');\n"
+ + "</script>\n"
+ + "<noscript>JavaScript is disabled on your browser.</noscript>\n"
+ "<main role=\"main\">\n"
+ "<div class=\"mainContainer\">\n");
}
--- a/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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,7 +23,7 @@
/*
* @test
- * @bug 7112427 8012295 8025633 8026567 8061305 8081854 8150130 8162363 8167967
+ * @bug 7112427 8012295 8025633 8026567 8061305 8081854 8150130 8162363 8167967 8172528
* @summary Test of the JavaFX doclet features.
* @author jvalenta
* @library ../lib
@@ -50,93 +50,103 @@
checkOutput("pkg1/C.html", true,
"<dt><span class=\"seeLabel\">See Also:</span></dt>\n"
- + "<dd><a href=\"../pkg1/C.html#getRate--\"><code>getRate()</code></a>, \n"
- + "<a href=\"../pkg1/C.html#setRate-double-\">"
- + "<code>setRate(double)</code></a></dd>",
+ + "<dd><a href=\"../pkg1/C.html#getRate--\"><code>getRate()</code></a>, \n"
+ + "<a href=\"../pkg1/C.html#setRate-double-\">"
+ + "<code>setRate(double)</code></a></dd>",
"<pre>public final void setRate(double value)</pre>\n"
- + "<div class=\"block\">Sets the value of the property rate.</div>\n"
- + "<dl>\n"
- + "<dt><span class=\"simpleTagLabel\">Property description:</span></dt>",
+ + "<div class=\"block\">Sets the value of the property rate.</div>\n"
+ + "<dl>\n"
+ + "<dt><span class=\"simpleTagLabel\">Property description:</span></dt>",
"<pre>public final double getRate()</pre>\n"
- + "<div class=\"block\">Gets the value of the property rate.</div>\n"
- + "<dl>\n"
- + "<dt><span class=\"simpleTagLabel\">Property description:</span></dt>",
+ + "<div class=\"block\">Gets the value of the property rate.</div>\n"
+ + "<dl>\n"
+ + "<dt><span class=\"simpleTagLabel\">Property description:</span></dt>",
"<td class=\"colFirst\"><code><a href=\"../pkg1/C.DoubleProperty.html\" "
- + "title=\"class in pkg1\">C.DoubleProperty</a></code></td>\n"
- + "<th class=\"colSecond\" scope=\"row\"><code><span class=\"memberNameLink\">"
- + "<a href=\"../pkg1/C.html#rateProperty\">rate</a></span></code></th>\n"
- + "<td class=\"colLast\">\n"
- + "<div class=\"block\">Defines the direction/speed at which the "
- + "<code>Timeline</code> is expected to\n"
- + " be played.</div>\n</td>",
+ + "title=\"class in pkg1\">C.DoubleProperty</a></code></td>\n"
+ + "<th class=\"colSecond\" scope=\"row\"><code><span class=\"memberNameLink\">"
+ + "<a href=\"../pkg1/C.html#rateProperty\">rate</a></span></code></th>\n"
+ + "<td class=\"colLast\">\n"
+ + "<div class=\"block\">Defines the direction/speed at which the "
+ + "<code>Timeline</code> is expected to\n"
+ + " be played.</div>\n</td>",
"<span class=\"simpleTagLabel\">Default value:</span>",
"<span class=\"simpleTagLabel\">Since:</span></dt>\n"
- + "<dd>JavaFX 8.0</dd>",
+ + "<dd>JavaFX 8.0</dd>",
"<p>Sets the value of the property <code>Property</code>",
"<p>Gets the value of the property <code>Property</code>",
"<span class=\"simpleTagLabel\">Property description:</span>",
"<th class=\"colSecond\" scope=\"row\"><code><span class=\"memberNameLink\">"
- + "<a href=\"../pkg1/C.html#setTestMethodProperty--\">"
- + "setTestMethodProperty</a></span>()</code></th>",
+ + "<a href=\"../pkg1/C.html#setTestMethodProperty--\">"
+ + "setTestMethodProperty</a></span>()</code></th>",
"<th class=\"colSecond\" scope=\"row\"><code><span class=\"memberNameLink\">"
- + "<a href=\"../pkg1/C.html#pausedProperty\">paused</a></span></code></th>\n"
- + "<td class=\"colLast\">\n"
- + "<div class=\"block\">Defines if paused.</div>",
+ + "<a href=\"../pkg1/C.html#pausedProperty\">paused</a></span></code></th>\n"
+ + "<td class=\"colLast\">\n"
+ + "<div class=\"block\">Defines if paused.</div>",
"<h4>paused</h4>\n"
- + "<pre>public final <a href=\"../pkg1/C.BooleanProperty.html\" "
- + "title=\"class in pkg1\">C.BooleanProperty</a> pausedProperty</pre>\n"
- + "<div class=\"block\">Defines if paused. The second line.</div>",
+ + "<pre>public final <a href=\"../pkg1/C.BooleanProperty.html\" "
+ + "title=\"class in pkg1\">C.BooleanProperty</a> pausedProperty</pre>\n"
+ + "<div class=\"block\">Defines if paused. The second line.</div>",
"<h4>isPaused</h4>\n"
- + "<pre>public final double isPaused()</pre>\n"
- + "<div class=\"block\">Gets the value of the property paused.</div>",
+ + "<pre>public final double isPaused()</pre>\n"
+ + "<div class=\"block\">Gets the value of the property paused.</div>",
"<h4>setPaused</h4>\n"
- + "<pre>public final void setPaused(boolean value)</pre>\n"
- + "<div class=\"block\">Sets the value of the property paused.</div>\n"
- + "<dl>\n"
- + "<dt><span class=\"simpleTagLabel\">Property description:</span></dt>\n"
- + "<dd>Defines if paused. The second line.</dd>\n"
- + "<dt><span class=\"simpleTagLabel\">Default value:</span></dt>\n"
- + "<dd>false</dd>",
+ + "<pre>public final void setPaused(boolean value)</pre>\n"
+ + "<div class=\"block\">Sets the value of the property paused.</div>\n"
+ + "<dl>\n"
+ + "<dt><span class=\"simpleTagLabel\">Property description:</span></dt>\n"
+ + "<dd>Defines if paused. The second line.</dd>\n"
+ + "<dt><span class=\"simpleTagLabel\">Default value:</span></dt>\n"
+ + "<dd>false</dd>",
"<h4>isPaused</h4>\n"
- + "<pre>public final double isPaused()</pre>\n"
- + "<div class=\"block\">Gets the value of the property paused.</div>\n"
- + "<dl>\n"
- + "<dt><span class=\"simpleTagLabel\">Property description:</span></dt>\n"
- + "<dd>Defines if paused. The second line.</dd>\n"
- + "<dt><span class=\"simpleTagLabel\">Default value:</span></dt>\n"
- + "<dd>false</dd>",
+ + "<pre>public final double isPaused()</pre>\n"
+ + "<div class=\"block\">Gets the value of the property paused.</div>\n"
+ + "<dl>\n"
+ + "<dt><span class=\"simpleTagLabel\">Property description:</span></dt>\n"
+ + "<dd>Defines if paused. The second line.</dd>\n"
+ + "<dt><span class=\"simpleTagLabel\">Default value:</span></dt>\n"
+ + "<dd>false</dd>",
"<h4>rate</h4>\n"
- + "<pre>public final <a href=\"../pkg1/C.DoubleProperty.html\" "
- + "title=\"class in pkg1\">C.DoubleProperty</a> rateProperty</pre>\n"
- + "<div class=\"block\">Defines the direction/speed at which the "
- + "<code>Timeline</code> is expected to\n"
- + " be played. This is the second line.</div>",
+ + "<pre>public final <a href=\"../pkg1/C.DoubleProperty.html\" "
+ + "title=\"class in pkg1\">C.DoubleProperty</a> rateProperty</pre>\n"
+ + "<div class=\"block\">Defines the direction/speed at which the "
+ + "<code>Timeline</code> is expected to\n"
+ + " be played. This is the second line.</div>",
"<h4>setRate</h4>\n"
- + "<pre>public final void setRate(double value)</pre>\n"
- + "<div class=\"block\">Sets the value of the property rate.</div>\n"
- + "<dl>\n"
- + "<dt><span class=\"simpleTagLabel\">Property description:</span></dt>\n"
- + "<dd>Defines the direction/speed at which the <code>Timeline</code> is expected to\n"
- + " be played. This is the second line.</dd>\n"
- + "<dt><span class=\"simpleTagLabel\">Default value:</span></dt>\n"
- + "<dd>11</dd>\n"
- + "<dt><span class=\"simpleTagLabel\">Since:</span></dt>\n"
- + "<dd>JavaFX 8.0</dd>",
+ + "<pre>public final void setRate(double value)</pre>\n"
+ + "<div class=\"block\">Sets the value of the property rate.</div>\n"
+ + "<dl>\n"
+ + "<dt><span class=\"simpleTagLabel\">Property description:</span></dt>\n"
+ + "<dd>Defines the direction/speed at which the <code>Timeline</code> is expected to\n"
+ + " be played. This is the second line.</dd>\n"
+ + "<dt><span class=\"simpleTagLabel\">Default value:</span></dt>\n"
+ + "<dd>11</dd>\n"
+ + "<dt><span class=\"simpleTagLabel\">Since:</span></dt>\n"
+ + "<dd>JavaFX 8.0</dd>",
"<h4>getRate</h4>\n"
- + "<pre>public final double getRate()</pre>\n"
- + "<div class=\"block\">Gets the value of the property rate.</div>\n"
- + "<dl>\n"
- + "<dt><span class=\"simpleTagLabel\">Property description:</span></dt>\n"
- + "<dd>Defines the direction/speed at which the <code>Timeline</code> is expected to\n"
- + " be played. This is the second line.</dd>\n"
- + "<dt><span class=\"simpleTagLabel\">Default value:</span></dt>\n"
- + "<dd>11</dd>\n"
- + "<dt><span class=\"simpleTagLabel\">Since:</span></dt>\n"
- + "<dd>JavaFX 8.0</dd>",
+ + "<pre>public final double getRate()</pre>\n"
+ + "<div class=\"block\">Gets the value of the property rate.</div>\n"
+ + "<dl>\n"
+ + "<dt><span class=\"simpleTagLabel\">Property description:</span></dt>\n"
+ + "<dd>Defines the direction/speed at which the <code>Timeline</code> is expected to\n"
+ + " be played. This is the second line.</dd>\n"
+ + "<dt><span class=\"simpleTagLabel\">Default value:</span></dt>\n"
+ + "<dd>11</dd>\n"
+ + "<dt><span class=\"simpleTagLabel\">Since:</span></dt>\n"
+ + "<dd>JavaFX 8.0</dd>",
+ "<h3>Property Summary</h3>\n"
+ + "<table class=\"memberSummary\" summary=\"Property Summary table, listing properties, and an explanation\">\n"
+ + "<caption><span>Properties</span><span class=\"tabEnd\"> </span></caption>",
"");
checkOutput("pkg1/C.html", false,
- "A()");
+ "A()",
+ "<h3>Property Summary</h3>\n"
+ + "<table class=\"memberSummary\" summary=\"Property Summary table, listing properties, and an explanation\">\n"
+ + "<caption><span id=\"t0\" class=\"activeTableTab\"><span>All Methods</span><span class=\"tabEnd\"> </span>"
+ + "</span><span id=\"t2\" class=\"tableTab\"><span><a href=\"javascript:show(2);\">Instance Methods</a>"
+ + "</span><span class=\"tabEnd\"> </span></span><span id=\"t4\" class=\"tableTab\"><span>"
+ + "<a href=\"javascript:show(8);\">Concrete Methods</a></span><span class=\"tabEnd\"> </span></span>"
+ + "</caption>");
checkOutput("index-all.html", true,
"<div class=\"block\">Gets the value of the property paused.</div>",
@@ -193,7 +203,19 @@
+ "</li>\n"
+ "</ul>\n"
+ "</li>\n"
- + "</ul>");
+ + "</ul>",
+ "<h3>Property Summary</h3>\n"
+ + "<table class=\"memberSummary\" summary=\"Property Summary table, listing properties, and an explanation\">\n"
+ + "<caption><span>Properties</span><span class=\"tabEnd\"> </span></caption>");
+
+ checkOutput("pkg2/Test.html", false,
+ "<h3>Property Summary</h3>\n"
+ + "<table class=\"memberSummary\" summary=\"Property Summary table, listing properties, and an explanation\">\n"
+ + "<caption><span id=\"t0\" class=\"activeTableTab\"><span>All Methods</span><span class=\"tabEnd\"> </span>"
+ + "</span><span id=\"t2\" class=\"tableTab\"><span><a href=\"javascript:show(2);\">Instance Methods</a>"
+ + "</span><span class=\"tabEnd\"> </span></span><span id=\"t4\" class=\"tableTab\"><span>"
+ + "<a href=\"javascript:show(8);\">Concrete Methods</a></span><span class=\"tabEnd\"> </span></span>"
+ + "</caption>");
}
/*
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testNonInlineHtmlTagRemoval/C.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+public class C {
+ /**
+ * case1 <ul> <li> end of sentence. <li> more </ul>
+ */
+ public void case1() {}
+
+ /**
+ * case2 <ul compact> <li> end of sentence. <li> more </ul>
+ */
+ public void case2() {}
+
+ /**
+ * case3 <ul type="square"> <li> end of sentence. <li> more </ul>
+ */
+ public void case3() {}
+
+ /**
+ * case4 <ul type="a<b"> <li> end of sentence. <li> more </ul>
+ */
+ public void case4() {}
+
+ /**
+ * case5 <ul type="a>b"> <li> end of sentence. <li> more </ul>
+ */
+ public void case5() {}
+
+ /**
+ * case6 <ul type='a>b'> <li> end of sentence. <li> more </ul>
+ */
+ public void case6() {}
+
+ /**
+ * case7 <ul type='"a>b"'> <li> end of sentence. <li> more </ul>
+ */
+ public void case7() {}
+
+ /**
+ * case8 <ul type="'a>b'"> <li> end of sentence. <li> more </ul>
+ */
+ public void case8() {}
+
+ /**
+ * case9 <ul type="'a'>b"> <li> end of sentence. <li> more </ul>
+ */
+ public void case9() {}
+
+ /**
+ * caseA <ul type='"a">b'> <li> end of sentence. <li> more </ul>
+ */
+ public void caseA() {}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testNonInlineHtmlTagRemoval/TestNonInlineHtmlTagRemoval.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017, 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 8048628
+ * @summary Verify html inline tags are removed correctly in the first sentence.
+ * @library ../lib
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
+ * @build JavadocTester
+ * @run main TestNonInlineHtmlTagRemoval
+ */
+
+public class TestNonInlineHtmlTagRemoval extends JavadocTester {
+
+ public static void main(String... args) throws Exception {
+ TestNonInlineHtmlTagRemoval tester = new TestNonInlineHtmlTagRemoval();
+ tester.runTests();
+ }
+
+ @Test
+ void test() {
+ javadoc("-d", "out",
+ "-sourcepath", testSrc,
+ testSrc("C.java"));
+ checkExit(Exit.OK);
+
+ checkOutput("C.html", true,
+ "<div class=\"block\">case1 end of sentence.</div>",
+ "<div class=\"block\">case2 end of sentence.</div>",
+ "<div class=\"block\">case3 end of sentence.</div>",
+ "<div class=\"block\">case4 end of sentence.</div>",
+ "<div class=\"block\">case5 end of sentence.</div>",
+ "<div class=\"block\">case6 end of sentence.</div>",
+ "<div class=\"block\">case7 end of sentence.</div>",
+ "<div class=\"block\">case8 end of sentence.</div>",
+ "<div class=\"block\">case9 end of sentence.</div>",
+ "<div class=\"block\">caseA end of sentence.</div>");
+ }
+}
--- a/langtools/test/jdk/javadoc/doclet/testOrdering/TestOrdering.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/jdk/javadoc/doclet/testOrdering/TestOrdering.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, 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,7 +23,7 @@
/*
* @test
- * @bug 8039410 8042601 8042829 8049393 8050031 8155061 8155995 8167967
+ * @bug 8039410 8042601 8042829 8049393 8050031 8155061 8155995 8167967 8169813
* @summary test to determine if members are ordered correctly
* @library ../lib/
* @modules jdk.javadoc/jdk.javadoc.internal.tool
@@ -494,23 +494,23 @@
String[] composeTestVectors() {
List<String> testList = new ArrayList<>();
- testList.addAll(Arrays.asList(expectedPackageOrdering));
for (String x : expectedEnumOrdering) {
testList.add(x.replace("REPLACE_ME", "<Unnamed>"));
- for (int i = 0; i < MAX_PACKAGES; i++) {
- String wpkg = "add" + i;
- testList.add(wpkg + "/" + x.replace("REPLACE_ME",
- wpkg));
- String dpkg = wpkg;
- for (int j = 1; j < MAX_SUBPACKAGES_DEPTH; j++) {
- dpkg = dpkg + "/" + "add";
+ }
+ for (int i = 0; i < MAX_PACKAGES; i++) {
+ String wpkg = "add" + i;
+ for (String x : expectedEnumOrdering) {
+ testList.add(wpkg + "/" + x.replace("REPLACE_ME", wpkg));
+ }
+ String dpkg = wpkg;
+ for (int j = 1; j < MAX_SUBPACKAGES_DEPTH; j++) {
+ dpkg = dpkg + "/" + "add";
+ for (String x : expectedEnumOrdering) {
testList.add(dpkg + "/" + x.replace("REPLACE_ME", pathToPackage(dpkg)));
}
}
}
- testList.addAll(Arrays.asList(expectedFieldOrdering));
-
for (String x : expectedMethodOrdering) {
testList.add(x);
for (int i = 0; i < MAX_PACKAGES; i++) {
@@ -523,6 +523,8 @@
}
}
}
+ testList.addAll(Arrays.asList(expectedPackageOrdering));
+ testList.addAll(Arrays.asList(expectedFieldOrdering));
return testList.toArray(new String[testList.size()]);
}
--- a/langtools/test/jdk/javadoc/doclet/testSearch/TestSearch.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/jdk/javadoc/doclet/testSearch/TestSearch.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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,7 +23,7 @@
/*
* @test
- * @bug 8141492 8071982 8141636 8147890
+ * @bug 8141492 8071982 8141636 8147890 8166175
* @summary Test the search feature of javadoc.
* @author bpatel
* @library ../lib
@@ -47,10 +47,14 @@
checkSearchJS();
checkFiles(false,
"package-search-index.zip",
- "tag-search-index.zip");
+ "tag-search-index.zip",
+ "package-search-index.js",
+ "tag-search-index.js");
checkFiles(true,
"member-search-index.zip",
- "type-search-index.zip");
+ "type-search-index.zip",
+ "member-search-index.js",
+ "type-search-index.js");
}
@Test
@@ -67,7 +71,11 @@
"member-search-index.zip",
"package-search-index.zip",
"tag-search-index.zip",
- "type-search-index.zip");
+ "type-search-index.zip",
+ "member-search-index.js",
+ "package-search-index.js",
+ "tag-search-index.js",
+ "type-search-index.js");
}
@Test
@@ -84,7 +92,11 @@
"member-search-index.zip",
"package-search-index.zip",
"tag-search-index.zip",
- "type-search-index.zip");
+ "type-search-index.zip",
+ "member-search-index.js",
+ "package-search-index.js",
+ "tag-search-index.js",
+ "type-search-index.js");
}
@Test
@@ -100,6 +112,10 @@
"package-search-index.zip",
"tag-search-index.zip",
"type-search-index.zip",
+ "member-search-index.js",
+ "package-search-index.js",
+ "tag-search-index.js",
+ "type-search-index.js",
"index-all.html");
}
@@ -117,7 +133,11 @@
"member-search-index.zip",
"package-search-index.zip",
"tag-search-index.zip",
- "type-search-index.zip");
+ "type-search-index.zip",
+ "member-search-index.js",
+ "package-search-index.js",
+ "tag-search-index.js",
+ "type-search-index.js");
}
@Test
@@ -133,6 +153,10 @@
"package-search-index.zip",
"tag-search-index.zip",
"type-search-index.zip",
+ "member-search-index.js",
+ "package-search-index.js",
+ "tag-search-index.js",
+ "type-search-index.js",
"index-all.html");
}
@@ -150,7 +174,11 @@
"member-search-index.zip",
"package-search-index.zip",
"tag-search-index.zip",
- "type-search-index.zip");
+ "type-search-index.zip",
+ "member-search-index.js",
+ "package-search-index.js",
+ "tag-search-index.js",
+ "type-search-index.js");
}
@Test
@@ -167,7 +195,11 @@
"member-search-index.zip",
"package-search-index.zip",
"tag-search-index.zip",
- "type-search-index.zip");
+ "type-search-index.zip",
+ "member-search-index.js",
+ "package-search-index.js",
+ "tag-search-index.js",
+ "type-search-index.js");
}
@Test
@@ -184,7 +216,11 @@
"member-search-index.zip",
"package-search-index.zip",
"tag-search-index.zip",
- "type-search-index.zip");
+ "type-search-index.zip",
+ "member-search-index.js",
+ "package-search-index.js",
+ "tag-search-index.js",
+ "type-search-index.js");
}
@Test
@@ -197,11 +233,15 @@
checkJqueryAndImageFiles(true);
checkSearchJS();
checkFiles(false,
- "tag-search-index.zip");
+ "tag-search-index.zip",
+ "tag-search-index.js");
checkFiles(true,
"member-search-index.zip",
"package-search-index.zip",
- "type-search-index.zip");
+ "type-search-index.zip",
+ "member-search-index.js",
+ "package-search-index.js",
+ "type-search-index.js");
}
void checkDocLintErrors() {
--- a/langtools/test/jdk/javadoc/tool/api/basic/APITest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/jdk/javadoc/tool/api/basic/APITest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -224,9 +224,11 @@
"jquery/images/ui-icons_222222_256x240.png",
"jquery/images/ui-bg_glass_75_e6e6e6_1x400.png",
"jquery/images/ui-bg_flat_75_ffffff_40x100.png",
+ "member-search-index.js",
"member-search-index.zip",
"overview-tree.html",
"package-list",
+ "package-search-index.js",
"package-search-index.zip",
"pkg/C.html",
"pkg/package-frame.html",
@@ -237,12 +239,13 @@
"script.js",
"search.js",
"stylesheet.css",
+ "type-search-index.js",
"type-search-index.zip"
));
protected static Set<String> noIndexFiles = standardExpectFiles.stream()
.filter(s -> !s.startsWith("jquery") && !s.startsWith("resources") && !s.endsWith("zip")
- && !s.equals("index-all.html") && !s.equals("search.js"))
+ && !s.equals("index-all.html") && !s.equals("search.js") && !s.endsWith("-search-index.js"))
.collect(Collectors.toSet());
}
--- a/langtools/test/jdk/jshell/ExecutionControlTestBase.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/jdk/jshell/ExecutionControlTestBase.java Thu Feb 09 23:15:52 2017 +0100
@@ -23,6 +23,7 @@
import javax.tools.Diagnostic;
+import org.testng.annotations.Test;
import jdk.jshell.VarSnippet;
import static jdk.jshell.Snippet.Status.VALID;
@@ -30,6 +31,7 @@
public class ExecutionControlTestBase extends KullaTesting {
+ @Test
public void classesDeclaration() {
assertEval("interface A { }");
assertEval("class B implements A { }");
@@ -45,6 +47,7 @@
assertActiveKeys();
}
+ @Test
public void interfaceTest() {
String interfaceSource
= "interface A {\n"
@@ -72,6 +75,7 @@
assertEval("new B.Inner2();");
}
+ @Test
public void variables() {
VarSnippet snx = varKey(assertEval("int x = 10;"));
VarSnippet sny = varKey(assertEval("String y = \"hi\";"));
@@ -83,6 +87,7 @@
assertActiveKeys();
}
+ @Test
public void methodOverload() {
assertEval("int m() { return 1; }");
assertEval("int m(int x) { return 2; }");
@@ -107,6 +112,7 @@
assertActiveKeys();
}
+ @Test
public void testExprSanity() {
assertEval("int x = 3;", "3");
assertEval("int y = 4;", "4");
@@ -114,6 +120,7 @@
assertActiveKeys();
}
+ @Test
public void testImportOnDemand() {
assertImportKeyMatch("import java.util.*;", "java.util.*", TYPE_IMPORT_ON_DEMAND_SUBKIND, added(VALID));
assertEval("List<Integer> list = new ArrayList<>();");
--- a/langtools/test/jdk/jshell/FailOverDirectExecutionControlTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/jdk/jshell/FailOverDirectExecutionControlTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -61,7 +61,8 @@
ClassLoader ccl;
ExecutionControlProvider provider;
- Map<Level, List<String>> logged = new HashMap<>();
+ LogTestHandler hndlr;
+ Map<Level, List<String>> logged;
private class LogTestHandler extends Handler {
@@ -95,7 +96,9 @@
public void setUp() {
Logger logger = Logger.getLogger("jdk.jshell.execution");
logger.setLevel(Level.ALL);
- logger.addHandler(new LogTestHandler());
+ hndlr = new LogTestHandler();
+ logger.addHandler(hndlr);
+ logged = new HashMap<>();
Compiler compiler = new Compiler();
Path modDir = Paths.get("mod");
compiler.compile(modDir,
@@ -133,6 +136,8 @@
@Override
public void tearDown() {
super.tearDown();
+ Logger logger = Logger.getLogger("jdk.jshell.execution");
+ logger.removeHandler(hndlr);
Thread.currentThread().setContextClassLoader(ccl);
}
--- a/langtools/test/jdk/jshell/FailOverExecutionControlDyingLaunchTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/jdk/jshell/FailOverExecutionControlDyingLaunchTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -27,7 +27,7 @@
* @summary Test that fail-over works for fail-over ExecutionControl generators.
* @modules jdk.jshell/jdk.jshell.execution
* jdk.jshell/jdk.jshell.spi
- * @build KullaTesting ExecutionControlTestBase
+ * @build KullaTesting ExecutionControlTestBase DyingRemoteAgent
* @run testng FailOverExecutionControlDyingLaunchTest
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/jshell/ForwardReferenceImportTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,392 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test 8173232
+ * @summary Test of forward referencing of snippets (related to import).
+ * @build KullaTesting TestingInputStream
+ * @run testng ForwardReferenceImportTest
+ */
+
+import jdk.jshell.Snippet;
+import jdk.jshell.DeclarationSnippet;
+import org.testng.annotations.Test;
+
+import static jdk.jshell.Snippet.Status.*;
+
+@Test
+public class ForwardReferenceImportTest extends KullaTesting {
+
+ public void testImportDeclare() {
+ Snippet singleImport = importKey(assertEval("import java.util.List;", added(VALID)));
+ Snippet importOnDemand = importKey(assertEval("import java.util.*;", added(VALID)));
+ Snippet singleStaticImport = importKey(assertEval("import static java.lang.Math.abs;", added(VALID)));
+ Snippet staticImportOnDemand = importKey(assertEval("import static java.lang.Math.*;", added(VALID)));
+ assertEval("import java.util.List; //again",
+ ste(MAIN_SNIPPET, VALID, VALID, false, null),
+ ste(singleImport, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
+ assertEval("import java.util.*; //again",
+ ste(MAIN_SNIPPET, VALID, VALID, false, null),
+ ste(importOnDemand, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
+ assertEval("import static java.lang.Math.abs; //again",
+ ste(MAIN_SNIPPET, VALID, VALID, false, null),
+ ste(singleStaticImport, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
+ assertEval("import static java.lang.Math.*; //again",
+ ste(MAIN_SNIPPET, VALID, VALID, false, null),
+ ste(staticImportOnDemand, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
+ assertActiveKeys();
+ }
+
+ public void testForwardSingleImportMethodToMethod() {
+ DeclarationSnippet string = methodKey(assertEval("String string() { return format(\"string\"); }",
+ added(RECOVERABLE_DEFINED)));
+ assertUnresolvedDependencies1(string, RECOVERABLE_DEFINED, "method format(java.lang.String)");
+ assertEvalUnresolvedException("string();", "string", 1, 0);
+ assertEval("import static java.lang.String.format;",
+ added(VALID),
+ ste(string, RECOVERABLE_DEFINED, VALID, false, null));
+ assertEval("string();", "\"string\"");
+
+ assertEval("double format(String s) { return 0; }",
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ added(VALID),
+ ste(string, VALID, RECOVERABLE_DEFINED, false, null));
+ assertEvalUnresolvedException("string();", "string", 0, 1);
+ assertActiveKeys();
+ }
+
+ public void testForwardImportMethodOnDemandToMethod() {
+ DeclarationSnippet string = methodKey(assertEval("String string() { return format(\"string\"); }",
+ added(RECOVERABLE_DEFINED)));
+ assertUnresolvedDependencies1(string, RECOVERABLE_DEFINED, "method format(java.lang.String)");
+ assertEvalUnresolvedException("string();", "string", 1, 0);
+ assertEval("import static java.lang.String.*;",
+ added(VALID),
+ ste(string, RECOVERABLE_DEFINED, VALID, false, null));
+ assertEval("string();", "\"string\"");
+
+ assertEval("double format(String s) { return 0; }",
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ added(VALID),
+ ste(string, VALID, RECOVERABLE_DEFINED, false, null));
+ assertEvalUnresolvedException("string();", "string", 0, 1);
+ assertActiveKeys();
+ }
+
+ public void testForwardSingleImportFieldToMethod() {
+ DeclarationSnippet pi = methodKey(assertEval("double pi() { return PI; }",
+ added(RECOVERABLE_DEFINED)));
+ assertUnresolvedDependencies1(pi, RECOVERABLE_DEFINED, "variable PI");
+ assertEvalUnresolvedException("pi();", "pi", 1, 0);
+ assertEval("import static java.lang.Math.PI;",
+ added(VALID),
+ ste(pi, RECOVERABLE_DEFINED, VALID, false, null));
+ assertEval("Math.abs(pi() - 3.1415) < 0.001;", "true");
+
+ assertEval("String PI;",
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ added(VALID),
+ ste(pi, VALID, RECOVERABLE_DEFINED, false, null));
+ assertEvalUnresolvedException("pi();", "pi", 0, 1);
+ assertActiveKeys();
+ }
+
+ public void testForwardImportFieldOnDemandToMethod() {
+ DeclarationSnippet pi = methodKey(assertEval("double pi() { return PI; }",
+ added(RECOVERABLE_DEFINED)));
+ assertUnresolvedDependencies1(pi, RECOVERABLE_DEFINED, "variable PI");
+ assertEvalUnresolvedException("pi();", "pi", 1, 0);
+ assertEval("import static java.lang.Math.*;",
+ added(VALID),
+ ste(pi, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET));
+ assertEval("Math.abs(pi() - 3.1415) < 0.001;", "true");
+
+ assertEval("String PI;",
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ added(VALID),
+ ste(pi, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET));
+ assertEvalUnresolvedException("pi();", "pi", 0, 1);
+ assertActiveKeys();
+ }
+
+ public void testForwardSingleImportMethodToClass1() {
+ Snippet a = classKey(assertEval("class A { String s = format(\"%d\", 10); }",
+ added(RECOVERABLE_DEFINED)));
+ assertEvalUnresolvedException("new A();", "A", 1, 0);
+ assertEval("import static java.lang.String.format;",
+ added(VALID),
+ ste(a, RECOVERABLE_DEFINED, VALID, false, null));
+ assertEval("new A().s;", "\"10\"");
+ Snippet format = methodKey(assertEval("void format(String s, int d) { }",
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ added(VALID),
+ ste(a, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET)));
+ assertEvalUnresolvedException("new A();", "A", 0, 1);
+ assertActiveKeys();
+ assertDrop(format,
+ ste(format, VALID, DROPPED, true, null),
+ ste(a, RECOVERABLE_DEFINED, VALID, false, format));
+ }
+
+ public void testForwardSingleImportMethodToClass2() {
+ Snippet a = classKey(assertEval("class A { String s() { return format(\"%d\", 10); } }",
+ added(RECOVERABLE_DEFINED)));
+ assertEvalUnresolvedException("new A();", "A", 1, 0);
+ assertEval("import static java.lang.String.format;",
+ added(VALID),
+ ste(a, RECOVERABLE_DEFINED, VALID, false, null));
+ assertEval("new A().s();", "\"10\"");
+ Snippet format = methodKey(assertEval("void format(String s, int d) { }",
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ added(VALID),
+ ste(a, VALID, RECOVERABLE_DEFINED, false, null)));
+ assertEvalUnresolvedException("new A();", "A", 0, 1);
+ assertActiveKeys();
+ assertDrop(format,
+ ste(format, VALID, DROPPED, true, null),
+ ste(a, RECOVERABLE_DEFINED, VALID, false, format));
+ }
+
+ public void testForwardSingleImportClassToClass1() {
+ Snippet a = classKey(assertEval("class A { static List<Integer> list; }",
+ added(RECOVERABLE_NOT_DEFINED)));
+ assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
+ assertEval("import java.util.List;",
+ added(VALID),
+ ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null));
+ assertEval("import java.util.Arrays;", added(VALID));
+ assertEval("A.list = Arrays.asList(1, 2, 3);", "[1, 2, 3]");
+
+ Snippet list = classKey(assertEval("class List {}",
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ added(VALID),
+ ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null)));
+ assertDeclareFail("A.list = Arrays.asList(1, 2, 3);", "compiler.err.already.defined.static.single.import");
+ assertActiveKeys();
+ assertDrop(list,
+ ste(list, VALID, DROPPED, true, null),
+ ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, list));
+ }
+
+ public void testForwardSingleImportClassToClass2() {
+ Snippet clsA = classKey(assertEval("class A extends ArrayList<Integer> { }",
+ added(RECOVERABLE_NOT_DEFINED)));
+ assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
+ assertEval("import java.util.ArrayList;",
+ added(VALID),
+ ste(clsA, RECOVERABLE_NOT_DEFINED, VALID, true, MAIN_SNIPPET));
+ Snippet vara = varKey(assertEval("A a = new A();", "[]"));
+
+ Snippet arraylist = classKey(assertEval("class ArrayList {}",
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ added(VALID),
+ ste(clsA, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET),
+ ste(vara, VALID, RECOVERABLE_NOT_DEFINED, true, clsA)));
+ assertDeclareFail("A a = new A();", "compiler.err.cant.resolve.location",
+ ste(MAIN_SNIPPET, RECOVERABLE_NOT_DEFINED, REJECTED, false, null),
+ ste(vara, RECOVERABLE_NOT_DEFINED, OVERWRITTEN, false, MAIN_SNIPPET));
+ assertActiveKeys();
+ assertDrop(arraylist,
+ ste(arraylist, VALID, DROPPED, true, null),
+ ste(clsA, RECOVERABLE_NOT_DEFINED, VALID, true, arraylist));
+ }
+
+ public void testForwardImportOnDemandMethodToClass1() {
+ Snippet a = classKey(assertEval("class A { String s = format(\"%d\", 10); }",
+ added(RECOVERABLE_DEFINED)));
+ assertEvalUnresolvedException("new A();", "A", 1, 0);
+ assertEval("import static java.lang.String.*;",
+ added(VALID),
+ ste(a, RECOVERABLE_DEFINED, VALID, false, null));
+ assertEval("A x = new A();");
+ assertEval("x.s;", "\"10\"");
+ Snippet format = methodKey(assertEval("void format(String s, int d) { }",
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ added(VALID),
+ ste(a, VALID, RECOVERABLE_DEFINED, false, null)));
+ assertEvalUnresolvedException("new A();", "A", 0, 1);
+ assertActiveKeys();
+ assertDrop(format,
+ ste(format, VALID, DROPPED, true, null),
+ ste(a, RECOVERABLE_DEFINED, VALID, false, format));
+ assertEval("x.s;", "\"10\"");
+ }
+
+ public void testForwardImportOnDemandMethodToClass2() {
+ Snippet a = classKey(assertEval("class A { String s() { return format(\"%d\", 10); } }",
+ added(RECOVERABLE_DEFINED)));
+ assertEvalUnresolvedException("new A();", "A", 1, 0);
+ assertEval("import static java.lang.String.*;",
+ added(VALID),
+ ste(a, RECOVERABLE_DEFINED, VALID, false, null));
+ assertEval("new A().s();", "\"10\"");
+ Snippet format = methodKey(assertEval("void format(String s, int d) { }",
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ added(VALID),
+ ste(a, VALID, RECOVERABLE_DEFINED, false, null)));
+ assertEvalUnresolvedException("new A();", "A", 0, 1);
+ assertActiveKeys();
+ assertDrop(format,
+ ste(format, VALID, DROPPED, true, null),
+ ste(a, RECOVERABLE_DEFINED, VALID, false, format));
+ }
+
+ public void testForwardImportOnDemandClassToClass1() {
+ Snippet a = classKey(assertEval("class A { static List<Integer> list; }",
+ added(RECOVERABLE_NOT_DEFINED)));
+ assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
+ assertEval("import java.util.*;",
+ added(VALID),
+ ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null));
+ assertEval("A.list = Arrays.asList(1, 2, 3);", "[1, 2, 3]");
+
+ Snippet list = classKey(assertEval("class List {}",
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ added(VALID),
+ ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null)));
+ assertDeclareFail("A.list = Arrays.asList(1, 2, 3);", "compiler.err.cant.resolve.location");
+ assertActiveKeys();
+ assertDrop(list,
+ ste(list, VALID, DROPPED, true, null),
+ ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, list));
+ }
+
+ public void testForwardImportOnDemandClassToClass2() {
+ Snippet clsA = classKey(assertEval("class A extends ArrayList<Integer> { }",
+ added(RECOVERABLE_NOT_DEFINED)));
+ assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
+ assertEval("import java.util.*;",
+ added(VALID),
+ ste(clsA, RECOVERABLE_NOT_DEFINED, VALID, true, MAIN_SNIPPET));
+ Snippet vara = varKey(assertEval("A a = new A();", "[]"));
+
+ Snippet arraylist = classKey(assertEval("class ArrayList {}",
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ added(VALID),
+ ste(clsA, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET),
+ ste(vara, VALID, RECOVERABLE_NOT_DEFINED, true, clsA)));
+ assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
+ assertActiveKeys();
+ assertDrop(arraylist,
+ ste(arraylist, VALID, DROPPED, true, null),
+ ste(clsA, RECOVERABLE_NOT_DEFINED, VALID, true, arraylist),
+ ste(vara, RECOVERABLE_NOT_DEFINED, VALID, true, clsA));
+ }
+
+ public void testForwardSingleImportFieldToClass1() {
+ Snippet a = classKey(assertEval("class A { static double pi() { return PI; } }",
+ added(RECOVERABLE_DEFINED)));
+ assertEvalUnresolvedException("new A();", "A", 1, 0);
+ assertEval("import static java.lang.Math.PI;",
+ added(VALID),
+ ste(a, RECOVERABLE_DEFINED, VALID, false, null));
+ assertEval("Math.abs(A.pi() - 3.1415) < 0.001;", "true");
+
+ Snippet list = varKey(assertEval("String PI;",
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ added(VALID),
+ ste(a, VALID, RECOVERABLE_DEFINED, false, null)));
+ assertEvalUnresolvedException("new A();", "A", 0, 1);
+ assertActiveKeys();
+ assertDrop(list,
+ ste(list, VALID, DROPPED, true, null),
+ ste(a, RECOVERABLE_DEFINED, VALID, false, list));
+ }
+
+ public void testForwardSingleImportFieldToClass2() {
+ Snippet a = classKey(assertEval("class A { static double pi = PI; }",
+ added(RECOVERABLE_DEFINED)));
+ assertEvalUnresolvedException("new A();", "A", 1, 0);
+ assertEval("import static java.lang.Math.PI;",
+ added(VALID),
+ ste(a, RECOVERABLE_DEFINED, VALID, true, null));
+ assertEval("Math.abs(A.pi - 3.1415) < 0.001;", "true");
+
+ Snippet list = varKey(assertEval("String PI;",
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ added(VALID),
+ ste(a, VALID, RECOVERABLE_DEFINED, true, null)));
+ assertEvalUnresolvedException("new A();", "A", 0, 1);
+ assertActiveKeys();
+ assertDrop(list,
+ ste(list, VALID, DROPPED, true, null),
+ ste(a, RECOVERABLE_DEFINED, VALID, true, list));
+ }
+
+ public void testForwardImportOnDemandFieldToClass1() {
+ Snippet a = classKey(assertEval("class A { static double pi() { return PI; } }",
+ added(RECOVERABLE_DEFINED)));
+ assertEvalUnresolvedException("new A();", "A", 1, 0);
+ assertEval("import static java.lang.Math.*;",
+ added(VALID),
+ ste(a, RECOVERABLE_DEFINED, VALID, false, null));
+ assertEval("Math.abs(A.pi() - 3.1415) < 0.001;", "true");
+
+ Snippet list = varKey(assertEval("String PI;",
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ added(VALID),
+ ste(a, VALID, RECOVERABLE_DEFINED, false, null)));
+ assertEvalUnresolvedException("new A();", "A", 0, 1);
+ assertActiveKeys();
+ assertDrop(list,
+ ste(list, VALID, DROPPED, true, null),
+ ste(a, RECOVERABLE_DEFINED, VALID, false, list));
+ }
+
+ public void testForwardImportOnDemandFieldToClass2() {
+ Snippet a = classKey(assertEval("class A { static double pi = PI; }",
+ added(RECOVERABLE_DEFINED)));
+ assertEvalUnresolvedException("new A();", "A", 1, 0);
+ assertEval("import static java.lang.Math.*;",
+ added(VALID),
+ ste(a, RECOVERABLE_DEFINED, VALID, true, null));
+ assertEval("Math.abs(A.pi - 3.1415) < 0.001;", "true");
+
+ Snippet list = varKey(assertEval("String PI;",
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ added(VALID),
+ ste(a, VALID, RECOVERABLE_DEFINED, true, null)));
+ assertEvalUnresolvedException("new A();", "A", 0, 1);
+ assertActiveKeys();
+ assertDrop(list,
+ ste(list, VALID, DROPPED, true, null),
+ ste(a, RECOVERABLE_DEFINED, VALID, true, list));
+ assertEval("Math.abs(A.pi - 3.1415) < 0.001;", "true");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/jshell/ForwardReferenceTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,321 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test 8173232
+ * @summary Test of forward referencing of snippets.
+ * @build KullaTesting TestingInputStream
+ * @run testng ForwardReferenceTest
+ */
+
+import java.util.List;
+import jdk.jshell.Snippet;
+import jdk.jshell.MethodSnippet;
+import jdk.jshell.VarSnippet;
+import jdk.jshell.DeclarationSnippet;
+import org.testng.annotations.Test;
+
+import jdk.jshell.SnippetEvent;
+import jdk.jshell.UnresolvedReferenceException;
+import static org.testng.Assert.assertEquals;
+import static jdk.jshell.Snippet.Status.*;
+import static org.testng.Assert.assertTrue;
+
+@Test
+public class ForwardReferenceTest extends KullaTesting {
+
+ public void testOverwriteMethodForwardReferenceClass() {
+ Snippet k1 = methodKey(assertEval("int q(Boo b) { return b.x; }",
+ added(RECOVERABLE_NOT_DEFINED)));
+ assertUnresolvedDependencies1((MethodSnippet) k1, RECOVERABLE_NOT_DEFINED, "class Boo");
+ assertEval("class Boo { int x = 55; }",
+ added(VALID),
+ ste(k1, RECOVERABLE_NOT_DEFINED, VALID, true, null));
+ assertMethodDeclSnippet((MethodSnippet) k1, "q", "(Boo)int", VALID, 0, 0);
+ assertEval("q(new Boo());", "55");
+ assertActiveKeys();
+ }
+
+ public void testOverwriteMethodForwardReferenceClassImport() {
+ MethodSnippet k1 = methodKey(assertEval("int ff(List lis) { return lis.size(); }",
+ added(RECOVERABLE_NOT_DEFINED)));
+ assertUnresolvedDependencies1(k1, RECOVERABLE_NOT_DEFINED, "class List");
+ assertEval("import java.util.*;",
+ added(VALID),
+ ste(k1, RECOVERABLE_NOT_DEFINED, VALID, true, null));
+ assertMethodDeclSnippet(k1, "ff", "(List)int", VALID, 0, 0);
+ assertEval("ff(new ArrayList());", "0");
+ assertActiveKeys();
+ }
+
+ public void testForwardVarToMethod() {
+ DeclarationSnippet t = methodKey(assertEval("int t() { return x; }", added(RECOVERABLE_DEFINED)));
+ assertUnresolvedDependencies1(t, RECOVERABLE_DEFINED, "variable x");
+ assertEvalUnresolvedException("t();", "t", 1, 0);
+ Snippet x = varKey(assertEval("int x = 33;", "33",
+ added(VALID),
+ ste(t, RECOVERABLE_DEFINED, VALID, false, null)));
+ assertEval("t();", "33");
+ assertEval("double x = 0.88;",
+ "0.88", null,
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ ste(MAIN_SNIPPET, VALID, VALID, true, null),
+ ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
+ ste(t, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET));
+ assertEvalUnresolvedException("t();", "t", 0, 1);
+ assertActiveKeys();
+ }
+
+ public void testForwardMethodToMethod() {
+ Snippet t = methodKey(assertEval("int t() { return f(); }", added(RECOVERABLE_DEFINED)));
+ Snippet f = methodKey(assertEval("int f() { return g(); }",
+ added(RECOVERABLE_DEFINED),
+ ste(t, RECOVERABLE_DEFINED, VALID, false, null)));
+ assertUnresolvedDependencies1((DeclarationSnippet) f, RECOVERABLE_DEFINED, "method g()");
+ assertEvalUnresolvedException("t();", "f", 1, 0);
+ Snippet g = methodKey(assertEval("int g() { return 55; }",
+ added(VALID),
+ ste(f, RECOVERABLE_DEFINED, VALID, false, null)));
+ assertEval("t();", "55");
+ assertEval("double g() { return 3.14159; }",
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ ste(MAIN_SNIPPET, VALID, VALID, true, null),
+ ste(g, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
+ ste(f, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET));
+ DeclarationSnippet exsn = assertEvalUnresolvedException("t();", "f", 0, 1);
+ assertTrue(exsn == f, "Identity must not change");
+ assertActiveKeys();
+ }
+
+ public void testForwardClassToMethod() {
+ DeclarationSnippet t = methodKey(assertEval("int t() { return new A().f(); }", added(RECOVERABLE_DEFINED)));
+ assertUnresolvedDependencies1(t, RECOVERABLE_DEFINED, "class A");
+ assertEvalUnresolvedException("t();", "t", 1, 0);
+ Snippet a = classKey(assertEval(
+ "class A {\n" +
+ " int f() { return 10; }\n" +
+ "}",
+ added(VALID),
+ ste(t, RECOVERABLE_DEFINED, VALID, false, null)));
+ assertEval("t();", "10");
+ assertEval(
+ "class A {\n" +
+ " double f() { return 88.0; }\n" +
+ "}",
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ ste(MAIN_SNIPPET, VALID, VALID, true, null),
+ ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
+ ste(t, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET));
+ assertEvalUnresolvedException("t();", "t", 0, 1);
+ assertActiveKeys();
+ }
+
+ public void testForwardVarToClass() {
+ DeclarationSnippet a = classKey(assertEval("class A { int f() { return g; } }", added(RECOVERABLE_DEFINED)));
+ assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "variable g");
+ Snippet g = varKey(assertEval("int g = 10;", "10",
+ added(VALID),
+ ste(a, RECOVERABLE_DEFINED, VALID, false, null)));
+ assertEval("new A().f();", "10");
+ assertEval("double g = 10;", "10.0", null,
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ ste(MAIN_SNIPPET, VALID, VALID, true, null),
+ ste(g, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
+ ste(a, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET));
+ assertUnresolvedDependencies(a, 0);
+ assertActiveKeys();
+ }
+
+ public void testForwardVarToClassGeneric() {
+ DeclarationSnippet a = classKey(assertEval("class A<T> { final T x; A(T v) { this.x = v; } ; T get() { return x; } int core() { return g; } }", added(RECOVERABLE_DEFINED)));
+ assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "variable g");
+
+ List<SnippetEvent> events = assertEval("A<String> as = new A<>(\"hi\");", null,
+ UnresolvedReferenceException.class, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, null);
+ SnippetEvent ste = events.get(0);
+ Snippet assn = ste.snippet();
+ DeclarationSnippet unsn = ((UnresolvedReferenceException) ste.exception()).getSnippet();
+ assertEquals(unsn.name(), "A", "Wrong with unresolved");
+ assertEquals(getState().unresolvedDependencies(unsn).count(), 1, "Wrong size unresolved");
+ assertEquals(getState().diagnostics(unsn).count(), 0L, "Expected no diagnostics");
+
+ Snippet g = varKey(assertEval("int g = 10;", "10",
+ added(VALID),
+ ste(a, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET)));
+ assertEval("A<String> as = new A<>(\"low\");",
+ ste(MAIN_SNIPPET, VALID, VALID, false, null),
+ ste(assn, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
+ assertEval("as.get();", "\"low\"");
+ assertUnresolvedDependencies(a, 0);
+ assertActiveKeys();
+ }
+
+ public void testForwardVarToClassExtendsImplements() {
+ DeclarationSnippet ik = classKey(assertEval("interface I { default int ii() { return 1; } }", added(VALID)));
+ DeclarationSnippet jk = classKey(assertEval("interface J { default int jj() { return 2; } }", added(VALID)));
+ DeclarationSnippet ck = classKey(assertEval("class C { int cc() { return 3; } }", added(VALID)));
+ DeclarationSnippet dk = classKey(assertEval("class D extends C implements I,J { int dd() { return g; } }", added(RECOVERABLE_DEFINED)));
+ DeclarationSnippet ek = classKey(assertEval("class E extends D { int ee() { return 5; } }", added(VALID)));
+ assertUnresolvedDependencies1(dk, RECOVERABLE_DEFINED, "variable g");
+ assertEvalUnresolvedException("new D();", "D", 1, 0);
+ assertEvalUnresolvedException("new E();", "D", 1, 0);
+ VarSnippet g = varKey(assertEval("int g = 10;", "10",
+ added(VALID),
+ ste(dk, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET)));
+ assertEval("E e = new E();");
+ assertDrop(g,
+ ste(g, VALID, DROPPED, true, null),
+ ste(dk, VALID, RECOVERABLE_DEFINED, false, g));
+ assertEvalUnresolvedException("new D();", "D", 1, 0);
+ assertEvalUnresolvedException("new E();", "D", 1, 0);
+ assertEval("e.ee();", "5");
+ assertEvalUnresolvedException("e.dd();", "D", 1, 0);
+ assertEval("e.cc();", "3");
+ assertEval("e.jj();", "2");
+ assertEval("e.ii();", "1");
+ assertActiveKeys();
+ }
+
+ public void testForwardVarToInterface() {
+ DeclarationSnippet i = classKey(assertEval("interface I { default int f() { return x; } }", added(RECOVERABLE_DEFINED)));
+ assertUnresolvedDependencies1(i, RECOVERABLE_DEFINED, "variable x");
+ DeclarationSnippet c = classKey(assertEval("class C implements I { int z() { return 2; } }", added(VALID)));
+ assertEval("C c = new C();");
+ assertEval("c.z();", "2");
+ assertEvalUnresolvedException("c.f()", "I", 1, 0);
+ Snippet g = varKey(assertEval("int x = 55;", "55",
+ added(VALID),
+ ste(i, RECOVERABLE_DEFINED, VALID, false, null)));
+ assertEval("c.f();", "55");
+ assertUnresolvedDependencies(i, 0);
+ assertActiveKeys();
+ }
+
+ public void testForwardVarToEnum() {
+ DeclarationSnippet a = classKey(assertEval("enum E { Q, W, E; float ff() { return fff; } }", added(RECOVERABLE_DEFINED)));
+ assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "variable fff");
+ Snippet g = varKey(assertEval("float fff = 4.5f;", "4.5",
+ added(VALID),
+ ste(a, RECOVERABLE_DEFINED, VALID, false, null)));
+ assertEval("E.Q.ff();", "4.5");
+ assertEval("double fff = 3.3;", "3.3", null,
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ ste(MAIN_SNIPPET, VALID, VALID, true, null),
+ ste(g, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
+ ste(a, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET));
+ assertUnresolvedDependencies(a, 0);
+ assertActiveKeys();
+ }
+
+ public void testForwardMethodToClass() {
+ DeclarationSnippet a = classKey(assertEval("class A { int f() { return g(); } }", added(RECOVERABLE_DEFINED)));
+ assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "method g()");
+ assertEval("A foo() { return null; }");
+ assertEvalUnresolvedException("new A();", "A", 1, 0);
+ Snippet g = methodKey(assertEval("int g() { return 10; }",
+ added(VALID),
+ ste(a, RECOVERABLE_DEFINED, VALID, false, null)));
+ assertEval("new A().f();", "10");
+ assertEval("double g() { return 10; }",
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ ste(MAIN_SNIPPET, VALID, VALID, true, null),
+ ste(g, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
+ ste(a, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET));
+ assertUnresolvedDependencies(a, 0);
+ assertActiveKeys();
+ }
+
+ public void testForwardClassToClass1() {
+ Snippet a = classKey(assertEval("class A { B b = new B(); }", added(RECOVERABLE_NOT_DEFINED)));
+ assertDeclareFail("new A().b;", "compiler.err.cant.resolve.location");
+
+ Snippet b = classKey(assertEval("class B { public String toString() { return \"B\"; } }",
+ added(VALID),
+ ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)));
+ assertEval("new A().b;", "B");
+ assertEval("interface B { }",
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ ste(MAIN_SNIPPET, VALID, VALID, true, null),
+ ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
+ ste(a, VALID, RECOVERABLE_DEFINED, true, MAIN_SNIPPET));
+ assertEvalUnresolvedException("new A().b;", "A", 0, 1);
+ assertActiveKeys();
+ }
+
+ public void testForwardClassToClass2() {
+ Snippet a = classKey(assertEval("class A extends B { }", added(RECOVERABLE_NOT_DEFINED)));
+ assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
+
+ Snippet b = classKey(assertEval("class B { public String toString() { return \"B\"; } }",
+ added(VALID),
+ ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)));
+ assertEval("new A();", "B");
+ assertEval("interface B { }",
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ ste(MAIN_SNIPPET, VALID, VALID, true, null),
+ ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
+ ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET));
+ assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
+ assertActiveKeys();
+ }
+
+ public void testForwardClassToClass3() {
+ Snippet a = classKey(assertEval("interface A extends B { static int f() { return 10; } }", added(RECOVERABLE_NOT_DEFINED)));
+ assertDeclareFail("A.f();", "compiler.err.cant.resolve.location");
+
+ Snippet b = classKey(assertEval("interface B { }",
+ added(VALID),
+ ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)));
+ assertEval("A.f();", "10");
+ assertEval("class B { }",
+ DiagCheck.DIAG_OK,
+ DiagCheck.DIAG_ERROR,
+ ste(MAIN_SNIPPET, VALID, VALID, true, null),
+ ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
+ ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET));
+ assertDeclareFail("A.f();", "compiler.err.cant.resolve.location");
+ assertActiveKeys();
+ }
+
+ public void testForwardVariable() {
+ assertEval("int f() { return x; }", added(RECOVERABLE_DEFINED));
+ assertEvalUnresolvedException("f();", "f", 1, 0);
+ assertActiveKeys();
+ }
+
+ public void testLocalClassInUnresolved() {
+ Snippet f = methodKey(assertEval("void f() { class A {} g(); }", added(RECOVERABLE_DEFINED)));
+ assertEval("void g() {}",
+ added(VALID),
+ ste(f, RECOVERABLE_DEFINED, VALID, false, null));
+ assertEval("f();", "");
+ }
+}
--- a/langtools/test/jdk/jshell/ReplaceTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/jdk/jshell/ReplaceTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -29,18 +29,13 @@
*/
import java.util.Iterator;
-import java.util.List;
import java.util.stream.Stream;
import jdk.jshell.Snippet;
import jdk.jshell.MethodSnippet;
import jdk.jshell.TypeDeclSnippet;
import jdk.jshell.VarSnippet;
-import jdk.jshell.DeclarationSnippet;
import org.testng.annotations.Test;
-import jdk.jshell.SnippetEvent;
-import jdk.jshell.UnresolvedReferenceException;
-import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static jdk.jshell.Snippet.Status.*;
import static jdk.jshell.Snippet.SubKind.*;
@@ -198,267 +193,6 @@
assertActiveKeys();
}
- public void testOverwriteMethodForwardReferenceClass() {
- Snippet k1 = methodKey(assertEval("int q(Boo b) { return b.x; }",
- added(RECOVERABLE_NOT_DEFINED)));
- assertUnresolvedDependencies1((MethodSnippet) k1, RECOVERABLE_NOT_DEFINED, "class Boo");
- assertEval("class Boo { int x = 55; }",
- added(VALID),
- ste(k1, RECOVERABLE_NOT_DEFINED, VALID, true, null));
- assertMethodDeclSnippet((MethodSnippet) k1, "q", "(Boo)int", VALID, 0, 0);
- assertEval("q(new Boo());", "55");
- assertActiveKeys();
- }
-
- public void testOverwriteMethodForwardReferenceClassImport() {
- MethodSnippet k1 = methodKey(assertEval("int ff(List lis) { return lis.size(); }",
- added(RECOVERABLE_NOT_DEFINED)));
- assertUnresolvedDependencies1(k1, RECOVERABLE_NOT_DEFINED, "class List");
- assertEval("import java.util.*;",
- added(VALID),
- ste(k1, RECOVERABLE_NOT_DEFINED, VALID, true, null));
- assertMethodDeclSnippet(k1, "ff", "(List)int", VALID, 0, 0);
- assertEval("ff(new ArrayList());", "0");
- assertActiveKeys();
- }
-
- public void testForwardVarToMethod() {
- DeclarationSnippet t = methodKey(assertEval("int t() { return x; }", added(RECOVERABLE_DEFINED)));
- assertUnresolvedDependencies1(t, RECOVERABLE_DEFINED, "variable x");
- assertEvalUnresolvedException("t();", "t", 1, 0);
- Snippet x = varKey(assertEval("int x = 33;", "33",
- added(VALID),
- ste(t, RECOVERABLE_DEFINED, VALID, false, null)));
- assertEval("t();", "33");
- assertEval("double x = 0.88;",
- "0.88", null,
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- ste(MAIN_SNIPPET, VALID, VALID, true, null),
- ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
- ste(t, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET));
- assertEvalUnresolvedException("t();", "t", 0, 1);
- assertActiveKeys();
- }
-
- public void testForwardMethodToMethod() {
- Snippet t = methodKey(assertEval("int t() { return f(); }", added(RECOVERABLE_DEFINED)));
- Snippet f = methodKey(assertEval("int f() { return g(); }",
- added(RECOVERABLE_DEFINED),
- ste(t, RECOVERABLE_DEFINED, VALID, false, null)));
- assertUnresolvedDependencies1((DeclarationSnippet) f, RECOVERABLE_DEFINED, "method g()");
- assertEvalUnresolvedException("t();", "f", 1, 0);
- Snippet g = methodKey(assertEval("int g() { return 55; }",
- added(VALID),
- ste(f, RECOVERABLE_DEFINED, VALID, false, null)));
- assertEval("t();", "55");
- assertEval("double g() { return 3.14159; }",
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- ste(MAIN_SNIPPET, VALID, VALID, true, null),
- ste(g, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
- ste(f, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET));
- DeclarationSnippet exsn = assertEvalUnresolvedException("t();", "f", 0, 1);
- assertTrue(exsn == f, "Identity must not change");
- assertActiveKeys();
- }
-
- public void testForwardClassToMethod() {
- DeclarationSnippet t = methodKey(assertEval("int t() { return new A().f(); }", added(RECOVERABLE_DEFINED)));
- assertUnresolvedDependencies1(t, RECOVERABLE_DEFINED, "class A");
- assertEvalUnresolvedException("t();", "t", 1, 0);
- Snippet a = classKey(assertEval(
- "class A {\n" +
- " int f() { return 10; }\n" +
- "}",
- added(VALID),
- ste(t, RECOVERABLE_DEFINED, VALID, false, null)));
- assertEval("t();", "10");
- assertEval(
- "class A {\n" +
- " double f() { return 88.0; }\n" +
- "}",
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- ste(MAIN_SNIPPET, VALID, VALID, true, null),
- ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
- ste(t, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET));
- assertEvalUnresolvedException("t();", "t", 0, 1);
- assertActiveKeys();
- }
-
- public void testForwardVarToClass() {
- DeclarationSnippet a = classKey(assertEval("class A { int f() { return g; } }", added(RECOVERABLE_DEFINED)));
- assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "variable g");
- Snippet g = varKey(assertEval("int g = 10;", "10",
- added(VALID),
- ste(a, RECOVERABLE_DEFINED, VALID, false, null)));
- assertEval("new A().f();", "10");
- assertEval("double g = 10;", "10.0", null,
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- ste(MAIN_SNIPPET, VALID, VALID, true, null),
- ste(g, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
- ste(a, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET));
- assertUnresolvedDependencies(a, 0);
- assertActiveKeys();
- }
-
- public void testForwardVarToClassGeneric() {
- DeclarationSnippet a = classKey(assertEval("class A<T> { final T x; A(T v) { this.x = v; } ; T get() { return x; } int core() { return g; } }", added(RECOVERABLE_DEFINED)));
- assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "variable g");
-
- List<SnippetEvent> events = assertEval("A<String> as = new A<>(\"hi\");", null,
- UnresolvedReferenceException.class, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, null);
- SnippetEvent ste = events.get(0);
- Snippet assn = ste.snippet();
- DeclarationSnippet unsn = ((UnresolvedReferenceException) ste.exception()).getSnippet();
- assertEquals(unsn.name(), "A", "Wrong with unresolved");
- assertEquals(getState().unresolvedDependencies(unsn).count(), 1, "Wrong size unresolved");
- assertEquals(getState().diagnostics(unsn).count(), 0L, "Expected no diagnostics");
-
- Snippet g = varKey(assertEval("int g = 10;", "10",
- added(VALID),
- ste(a, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET)));
- assertEval("A<String> as = new A<>(\"low\");",
- ste(MAIN_SNIPPET, VALID, VALID, false, null),
- ste(assn, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
- assertEval("as.get();", "\"low\"");
- assertUnresolvedDependencies(a, 0);
- assertActiveKeys();
- }
-
- public void testForwardVarToClassExtendsImplements() {
- DeclarationSnippet ik = classKey(assertEval("interface I { default int ii() { return 1; } }", added(VALID)));
- DeclarationSnippet jk = classKey(assertEval("interface J { default int jj() { return 2; } }", added(VALID)));
- DeclarationSnippet ck = classKey(assertEval("class C { int cc() { return 3; } }", added(VALID)));
- DeclarationSnippet dk = classKey(assertEval("class D extends C implements I,J { int dd() { return g; } }", added(RECOVERABLE_DEFINED)));
- DeclarationSnippet ek = classKey(assertEval("class E extends D { int ee() { return 5; } }", added(VALID)));
- assertUnresolvedDependencies1(dk, RECOVERABLE_DEFINED, "variable g");
- assertEvalUnresolvedException("new D();", "D", 1, 0);
- assertEvalUnresolvedException("new E();", "D", 1, 0);
- VarSnippet g = varKey(assertEval("int g = 10;", "10",
- added(VALID),
- ste(dk, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET)));
- assertEval("E e = new E();");
- assertDrop(g,
- ste(g, VALID, DROPPED, true, null),
- ste(dk, VALID, RECOVERABLE_DEFINED, false, g));
- assertEvalUnresolvedException("new D();", "D", 1, 0);
- assertEvalUnresolvedException("new E();", "D", 1, 0);
- assertEval("e.ee();", "5");
- assertEvalUnresolvedException("e.dd();", "D", 1, 0);
- assertEval("e.cc();", "3");
- assertEval("e.jj();", "2");
- assertEval("e.ii();", "1");
- assertActiveKeys();
- }
-
- public void testForwardVarToInterface() {
- DeclarationSnippet i = classKey(assertEval("interface I { default int f() { return x; } }", added(RECOVERABLE_DEFINED)));
- assertUnresolvedDependencies1(i, RECOVERABLE_DEFINED, "variable x");
- DeclarationSnippet c = classKey(assertEval("class C implements I { int z() { return 2; } }", added(VALID)));
- assertEval("C c = new C();");
- assertEval("c.z();", "2");
- assertEvalUnresolvedException("c.f()", "I", 1, 0);
- Snippet g = varKey(assertEval("int x = 55;", "55",
- added(VALID),
- ste(i, RECOVERABLE_DEFINED, VALID, false, null)));
- assertEval("c.f();", "55");
- assertUnresolvedDependencies(i, 0);
- assertActiveKeys();
- }
-
- public void testForwardVarToEnum() {
- DeclarationSnippet a = classKey(assertEval("enum E { Q, W, E; float ff() { return fff; } }", added(RECOVERABLE_DEFINED)));
- assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "variable fff");
- Snippet g = varKey(assertEval("float fff = 4.5f;", "4.5",
- added(VALID),
- ste(a, RECOVERABLE_DEFINED, VALID, false, null)));
- assertEval("E.Q.ff();", "4.5");
- assertEval("double fff = 3.3;", "3.3", null,
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- ste(MAIN_SNIPPET, VALID, VALID, true, null),
- ste(g, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
- ste(a, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET));
- assertUnresolvedDependencies(a, 0);
- assertActiveKeys();
- }
-
- public void testForwardMethodToClass() {
- DeclarationSnippet a = classKey(assertEval("class A { int f() { return g(); } }", added(RECOVERABLE_DEFINED)));
- assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "method g()");
- assertEval("A foo() { return null; }");
- assertEvalUnresolvedException("new A();", "A", 1, 0);
- Snippet g = methodKey(assertEval("int g() { return 10; }",
- added(VALID),
- ste(a, RECOVERABLE_DEFINED, VALID, false, null)));
- assertEval("new A().f();", "10");
- assertEval("double g() { return 10; }",
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- ste(MAIN_SNIPPET, VALID, VALID, true, null),
- ste(g, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
- ste(a, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET));
- assertUnresolvedDependencies(a, 0);
- assertActiveKeys();
- }
-
- public void testForwardClassToClass1() {
- Snippet a = classKey(assertEval("class A { B b = new B(); }", added(RECOVERABLE_NOT_DEFINED)));
- assertDeclareFail("new A().b;", "compiler.err.cant.resolve.location");
-
- Snippet b = classKey(assertEval("class B { public String toString() { return \"B\"; } }",
- added(VALID),
- ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)));
- assertEval("new A().b;", "B");
- assertEval("interface B { }",
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- ste(MAIN_SNIPPET, VALID, VALID, true, null),
- ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
- ste(a, VALID, RECOVERABLE_DEFINED, true, MAIN_SNIPPET));
- assertEvalUnresolvedException("new A().b;", "A", 0, 1);
- assertActiveKeys();
- }
-
- public void testForwardClassToClass2() {
- Snippet a = classKey(assertEval("class A extends B { }", added(RECOVERABLE_NOT_DEFINED)));
- assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
-
- Snippet b = classKey(assertEval("class B { public String toString() { return \"B\"; } }",
- added(VALID),
- ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)));
- assertEval("new A();", "B");
- assertEval("interface B { }",
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- ste(MAIN_SNIPPET, VALID, VALID, true, null),
- ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
- ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET));
- assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
- assertActiveKeys();
- }
-
- public void testForwardClassToClass3() {
- Snippet a = classKey(assertEval("interface A extends B { static int f() { return 10; } }", added(RECOVERABLE_NOT_DEFINED)));
- assertDeclareFail("A.f();", "compiler.err.cant.resolve.location");
-
- Snippet b = classKey(assertEval("interface B { }",
- added(VALID),
- ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)));
- assertEval("A.f();", "10");
- assertEval("class B { }",
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- ste(MAIN_SNIPPET, VALID, VALID, true, null),
- ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET),
- ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET));
- assertDeclareFail("A.f();", "compiler.err.cant.resolve.location");
- assertActiveKeys();
- }
-
public void testImportDeclare() {
Snippet singleImport = importKey(assertEval("import java.util.List;", added(VALID)));
Snippet importOnDemand = importKey(assertEval("import java.util.*;", added(VALID)));
@@ -479,20 +213,6 @@
assertActiveKeys();
}
- public void testForwardVariable() {
- assertEval("int f() { return x; }", added(RECOVERABLE_DEFINED));
- assertEvalUnresolvedException("f();", "f", 1, 0);
- assertActiveKeys();
- }
-
- public void testLocalClassInUnresolved() {
- Snippet f = methodKey(assertEval("void f() { class A {} g(); }", added(RECOVERABLE_DEFINED)));
- assertEval("void g() {}",
- added(VALID),
- ste(f, RECOVERABLE_DEFINED, VALID, false, null));
- assertEval("f();", "");
- }
-
@Test(enabled = false) // TODO 8129420
public void testLocalClassEvolve() {
Snippet j = methodKey(assertEval("Object j() { return null; }", added(VALID)));
@@ -507,339 +227,6 @@
assertEval("j();", "Yep");
}
- public void testForwardSingleImportMethodToMethod() {
- DeclarationSnippet string = methodKey(assertEval("String string() { return format(\"string\"); }",
- added(RECOVERABLE_DEFINED)));
- assertUnresolvedDependencies1(string, RECOVERABLE_DEFINED, "method format(java.lang.String)");
- assertEvalUnresolvedException("string();", "string", 1, 0);
- assertEval("import static java.lang.String.format;",
- added(VALID),
- ste(string, RECOVERABLE_DEFINED, VALID, false, null));
- assertEval("string();", "\"string\"");
-
- assertEval("double format(String s) { return 0; }",
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- added(VALID),
- ste(string, VALID, RECOVERABLE_DEFINED, false, null));
- assertEvalUnresolvedException("string();", "string", 0, 1);
- assertActiveKeys();
- }
-
- public void testForwardImportMethodOnDemandToMethod() {
- DeclarationSnippet string = methodKey(assertEval("String string() { return format(\"string\"); }",
- added(RECOVERABLE_DEFINED)));
- assertUnresolvedDependencies1(string, RECOVERABLE_DEFINED, "method format(java.lang.String)");
- assertEvalUnresolvedException("string();", "string", 1, 0);
- assertEval("import static java.lang.String.*;",
- added(VALID),
- ste(string, RECOVERABLE_DEFINED, VALID, false, null));
- assertEval("string();", "\"string\"");
-
- assertEval("double format(String s) { return 0; }",
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- added(VALID),
- ste(string, VALID, RECOVERABLE_DEFINED, false, null));
- assertEvalUnresolvedException("string();", "string", 0, 1);
- assertActiveKeys();
- }
-
- public void testForwardSingleImportFieldToMethod() {
- DeclarationSnippet pi = methodKey(assertEval("double pi() { return PI; }",
- added(RECOVERABLE_DEFINED)));
- assertUnresolvedDependencies1(pi, RECOVERABLE_DEFINED, "variable PI");
- assertEvalUnresolvedException("pi();", "pi", 1, 0);
- assertEval("import static java.lang.Math.PI;",
- added(VALID),
- ste(pi, RECOVERABLE_DEFINED, VALID, false, null));
- assertEval("Math.abs(pi() - 3.1415) < 0.001;", "true");
-
- assertEval("String PI;",
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- added(VALID),
- ste(pi, VALID, RECOVERABLE_DEFINED, false, null));
- assertEvalUnresolvedException("pi();", "pi", 0, 1);
- assertActiveKeys();
- }
-
- public void testForwardImportFieldOnDemandToMethod() {
- DeclarationSnippet pi = methodKey(assertEval("double pi() { return PI; }",
- added(RECOVERABLE_DEFINED)));
- assertUnresolvedDependencies1(pi, RECOVERABLE_DEFINED, "variable PI");
- assertEvalUnresolvedException("pi();", "pi", 1, 0);
- assertEval("import static java.lang.Math.*;",
- added(VALID),
- ste(pi, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET));
- assertEval("Math.abs(pi() - 3.1415) < 0.001;", "true");
-
- assertEval("String PI;",
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- added(VALID),
- ste(pi, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET));
- assertEvalUnresolvedException("pi();", "pi", 0, 1);
- assertActiveKeys();
- }
-
- public void testForwardSingleImportMethodToClass1() {
- Snippet a = classKey(assertEval("class A { String s = format(\"%d\", 10); }",
- added(RECOVERABLE_DEFINED)));
- assertEvalUnresolvedException("new A();", "A", 1, 0);
- assertEval("import static java.lang.String.format;",
- added(VALID),
- ste(a, RECOVERABLE_DEFINED, VALID, false, null));
- assertEval("new A().s;", "\"10\"");
- Snippet format = methodKey(assertEval("void format(String s, int d) { }",
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- added(VALID),
- ste(a, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET)));
- assertEvalUnresolvedException("new A();", "A", 0, 1);
- assertActiveKeys();
- assertDrop(format,
- ste(format, VALID, DROPPED, true, null),
- ste(a, RECOVERABLE_DEFINED, VALID, false, format));
- }
-
- public void testForwardSingleImportMethodToClass2() {
- Snippet a = classKey(assertEval("class A { String s() { return format(\"%d\", 10); } }",
- added(RECOVERABLE_DEFINED)));
- assertEvalUnresolvedException("new A();", "A", 1, 0);
- assertEval("import static java.lang.String.format;",
- added(VALID),
- ste(a, RECOVERABLE_DEFINED, VALID, false, null));
- assertEval("new A().s();", "\"10\"");
- Snippet format = methodKey(assertEval("void format(String s, int d) { }",
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- added(VALID),
- ste(a, VALID, RECOVERABLE_DEFINED, false, null)));
- assertEvalUnresolvedException("new A();", "A", 0, 1);
- assertActiveKeys();
- assertDrop(format,
- ste(format, VALID, DROPPED, true, null),
- ste(a, RECOVERABLE_DEFINED, VALID, false, format));
- }
-
- public void testForwardSingleImportClassToClass1() {
- Snippet a = classKey(assertEval("class A { static List<Integer> list; }",
- added(RECOVERABLE_NOT_DEFINED)));
- assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
- assertEval("import java.util.List;",
- added(VALID),
- ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null));
- assertEval("import java.util.Arrays;", added(VALID));
- assertEval("A.list = Arrays.asList(1, 2, 3);", "[1, 2, 3]");
-
- Snippet list = classKey(assertEval("class List {}",
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- added(VALID),
- ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null)));
- assertDeclareFail("A.list = Arrays.asList(1, 2, 3);", "compiler.err.already.defined.static.single.import");
- assertActiveKeys();
- assertDrop(list,
- ste(list, VALID, DROPPED, true, null),
- ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, list));
- }
-
- public void testForwardSingleImportClassToClass2() {
- Snippet clsA = classKey(assertEval("class A extends ArrayList<Integer> { }",
- added(RECOVERABLE_NOT_DEFINED)));
- assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
- assertEval("import java.util.ArrayList;",
- added(VALID),
- ste(clsA, RECOVERABLE_NOT_DEFINED, VALID, true, MAIN_SNIPPET));
- Snippet vara = varKey(assertEval("A a = new A();", "[]"));
-
- Snippet arraylist = classKey(assertEval("class ArrayList {}",
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- added(VALID),
- ste(clsA, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET),
- ste(vara, VALID, RECOVERABLE_NOT_DEFINED, true, clsA)));
- assertDeclareFail("A a = new A();", "compiler.err.cant.resolve.location",
- ste(MAIN_SNIPPET, RECOVERABLE_NOT_DEFINED, REJECTED, false, null),
- ste(vara, RECOVERABLE_NOT_DEFINED, OVERWRITTEN, false, MAIN_SNIPPET));
- assertActiveKeys();
- assertDrop(arraylist,
- ste(arraylist, VALID, DROPPED, true, null),
- ste(clsA, RECOVERABLE_NOT_DEFINED, VALID, true, arraylist));
- }
-
- public void testForwardImportOnDemandMethodToClass1() {
- Snippet a = classKey(assertEval("class A { String s = format(\"%d\", 10); }",
- added(RECOVERABLE_DEFINED)));
- assertEvalUnresolvedException("new A();", "A", 1, 0);
- assertEval("import static java.lang.String.*;",
- added(VALID),
- ste(a, RECOVERABLE_DEFINED, VALID, false, null));
- assertEval("A x = new A();");
- assertEval("x.s;", "\"10\"");
- Snippet format = methodKey(assertEval("void format(String s, int d) { }",
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- added(VALID),
- ste(a, VALID, RECOVERABLE_DEFINED, false, null)));
- assertEvalUnresolvedException("new A();", "A", 0, 1);
- assertActiveKeys();
- assertDrop(format,
- ste(format, VALID, DROPPED, true, null),
- ste(a, RECOVERABLE_DEFINED, VALID, false, format));
- assertEval("x.s;", "\"10\"");
- }
-
- public void testForwardImportOnDemandMethodToClass2() {
- Snippet a = classKey(assertEval("class A { String s() { return format(\"%d\", 10); } }",
- added(RECOVERABLE_DEFINED)));
- assertEvalUnresolvedException("new A();", "A", 1, 0);
- assertEval("import static java.lang.String.*;",
- added(VALID),
- ste(a, RECOVERABLE_DEFINED, VALID, false, null));
- assertEval("new A().s();", "\"10\"");
- Snippet format = methodKey(assertEval("void format(String s, int d) { }",
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- added(VALID),
- ste(a, VALID, RECOVERABLE_DEFINED, false, null)));
- assertEvalUnresolvedException("new A();", "A", 0, 1);
- assertActiveKeys();
- assertDrop(format,
- ste(format, VALID, DROPPED, true, null),
- ste(a, RECOVERABLE_DEFINED, VALID, false, format));
- }
-
- public void testForwardImportOnDemandClassToClass1() {
- Snippet a = classKey(assertEval("class A { static List<Integer> list; }",
- added(RECOVERABLE_NOT_DEFINED)));
- assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
- assertEval("import java.util.*;",
- added(VALID),
- ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null));
- assertEval("A.list = Arrays.asList(1, 2, 3);", "[1, 2, 3]");
-
- Snippet list = classKey(assertEval("class List {}",
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- added(VALID),
- ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null)));
- assertDeclareFail("A.list = Arrays.asList(1, 2, 3);", "compiler.err.cant.resolve.location");
- assertActiveKeys();
- assertDrop(list,
- ste(list, VALID, DROPPED, true, null),
- ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, list));
- }
-
- public void testForwardImportOnDemandClassToClass2() {
- Snippet clsA = classKey(assertEval("class A extends ArrayList<Integer> { }",
- added(RECOVERABLE_NOT_DEFINED)));
- assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
- assertEval("import java.util.*;",
- added(VALID),
- ste(clsA, RECOVERABLE_NOT_DEFINED, VALID, true, MAIN_SNIPPET));
- Snippet vara = varKey(assertEval("A a = new A();", "[]"));
-
- Snippet arraylist = classKey(assertEval("class ArrayList {}",
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- added(VALID),
- ste(clsA, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET),
- ste(vara, VALID, RECOVERABLE_NOT_DEFINED, true, clsA)));
- assertDeclareFail("new A();", "compiler.err.cant.resolve.location");
- assertActiveKeys();
- assertDrop(arraylist,
- ste(arraylist, VALID, DROPPED, true, null),
- ste(clsA, RECOVERABLE_NOT_DEFINED, VALID, true, arraylist),
- ste(vara, RECOVERABLE_NOT_DEFINED, VALID, true, clsA));
- }
-
- public void testForwardSingleImportFieldToClass1() {
- Snippet a = classKey(assertEval("class A { static double pi() { return PI; } }",
- added(RECOVERABLE_DEFINED)));
- assertEvalUnresolvedException("new A();", "A", 1, 0);
- assertEval("import static java.lang.Math.PI;",
- added(VALID),
- ste(a, RECOVERABLE_DEFINED, VALID, false, null));
- assertEval("Math.abs(A.pi() - 3.1415) < 0.001;", "true");
-
- Snippet list = varKey(assertEval("String PI;",
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- added(VALID),
- ste(a, VALID, RECOVERABLE_DEFINED, false, null)));
- assertEvalUnresolvedException("new A();", "A", 0, 1);
- assertActiveKeys();
- assertDrop(list,
- ste(list, VALID, DROPPED, true, null),
- ste(a, RECOVERABLE_DEFINED, VALID, false, list));
- }
-
- public void testForwardSingleImportFieldToClass2() {
- Snippet a = classKey(assertEval("class A { static double pi = PI; }",
- added(RECOVERABLE_DEFINED)));
- assertEvalUnresolvedException("new A();", "A", 1, 0);
- assertEval("import static java.lang.Math.PI;",
- added(VALID),
- ste(a, RECOVERABLE_DEFINED, VALID, true, null));
- assertEval("Math.abs(A.pi - 3.1415) < 0.001;", "true");
-
- Snippet list = varKey(assertEval("String PI;",
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- added(VALID),
- ste(a, VALID, RECOVERABLE_DEFINED, true, null)));
- assertEvalUnresolvedException("new A();", "A", 0, 1);
- assertActiveKeys();
- assertDrop(list,
- ste(list, VALID, DROPPED, true, null),
- ste(a, RECOVERABLE_DEFINED, VALID, true, list));
- }
-
- public void testForwardImportOnDemandFieldToClass1() {
- Snippet a = classKey(assertEval("class A { static double pi() { return PI; } }",
- added(RECOVERABLE_DEFINED)));
- assertEvalUnresolvedException("new A();", "A", 1, 0);
- assertEval("import static java.lang.Math.*;",
- added(VALID),
- ste(a, RECOVERABLE_DEFINED, VALID, false, null));
- assertEval("Math.abs(A.pi() - 3.1415) < 0.001;", "true");
-
- Snippet list = varKey(assertEval("String PI;",
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- added(VALID),
- ste(a, VALID, RECOVERABLE_DEFINED, false, null)));
- assertEvalUnresolvedException("new A();", "A", 0, 1);
- assertActiveKeys();
- assertDrop(list,
- ste(list, VALID, DROPPED, true, null),
- ste(a, RECOVERABLE_DEFINED, VALID, false, list));
- }
-
- public void testForwardImportOnDemandFieldToClass2() {
- Snippet a = classKey(assertEval("class A { static double pi = PI; }",
- added(RECOVERABLE_DEFINED)));
- assertEvalUnresolvedException("new A();", "A", 1, 0);
- assertEval("import static java.lang.Math.*;",
- added(VALID),
- ste(a, RECOVERABLE_DEFINED, VALID, true, null));
- assertEval("Math.abs(A.pi - 3.1415) < 0.001;", "true");
-
- Snippet list = varKey(assertEval("String PI;",
- DiagCheck.DIAG_OK,
- DiagCheck.DIAG_ERROR,
- added(VALID),
- ste(a, VALID, RECOVERABLE_DEFINED, true, null)));
- assertEvalUnresolvedException("new A();", "A", 0, 1);
- assertActiveKeys();
- assertDrop(list,
- ste(list, VALID, DROPPED, true, null),
- ste(a, RECOVERABLE_DEFINED, VALID, true, list));
- assertEval("Math.abs(A.pi - 3.1415) < 0.001;", "true");
- }
-
public void testReplaceCausesMethodReferenceError() {
Snippet l = classKey(assertEval("interface Logger { public void log(String message); }", added(VALID)));
Snippet v = varKey(assertEval("Logger l = System.out::println;", added(VALID)));
--- a/langtools/test/jdk/jshell/SimpleRegressionTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/jdk/jshell/SimpleRegressionTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -22,7 +22,7 @@
*/
/*
- * @test 8130450 8158906 8154374 8166400 8171892
+ * @test 8130450 8158906 8154374 8166400 8171892 8173807 8173848
* @summary simple regression test
* @build KullaTesting TestingInputStream
* @run testng SimpleRegressionTest
@@ -76,6 +76,15 @@
assertEval("c;", "600");
}
+ public void testLessThanParsing() {
+ assertEval("int x = 3;", "3");
+ assertEval("int y = 4;", "4");
+ assertEval("int z = 5;", "5");
+ assertEval("x < y", "true");
+ assertEval("x < y;", "true");
+ assertEval("x < y && y < z", "true");
+ }
+
public void testNotStmtCannotResolve() {
assertDeclareFail("dfasder;", new ExpectedDiagnostic("compiler.err.cant.resolve.location", 0, 7, 0, -1, -1, Diagnostic.Kind.ERROR));
}
@@ -182,4 +191,36 @@
assertEval("new boolean[2][1][3]",
"boolean[2][][] { boolean[1][] { boolean[3] { false, false, false } }, boolean[1][] { boolean[3] { false, false, false } } }");
}
+
+ public void testStringRepresentation() {
+ assertEval("\"A!\\rB!\"",
+ "\"A!\\rB!\"");
+ assertEval("\"a\\bB\\tc\\nd\\fe\\rf\\\"g'\\\\h\"",
+ "\"a\\bB\\tc\\nd\\fe\\rf\\\"g'\\\\h\"");
+ assertEval("\"\\141\\10B\\11c\\nd\\fe\\15f\\42g\\'\\134h\"",
+ "\"a\\bB\\tc\\nd\\fe\\rf\\\"g'\\\\h\"");
+ assertEval("\"1234567890!@#$%^&*()-_=+qwertQWERT,./<>?;:[]{}\"",
+ "\"1234567890!@#$%^&*()-_=+qwertQWERT,./<>?;:[]{}\"");
+ assertEval("\"AA\\1\\7\\35\\25\"",
+ "\"AA\\001\\007\\035\\025\"");
+ assertEval("\"\"",
+ "\"\"");
+ assertEval("(String)null",
+ "null");
+ }
+
+ public void testCharRepresentation() {
+ for (String s : new String[]{"'A'", "'Z'", "'0'", "'9'",
+ "'a'", "'z'", "'*'", "'%'",
+ "'\\b'", "'\\t'", "'\\n'", "'\\f'", "'\\r'",
+ "'\"'", "'\\\''", "'\\\\'", "'\\007'", "'\\034'",}) {
+ assertEval(s, s);
+ }
+ assertEval("'\\3'",
+ "'\\003'");
+ assertEval("'\\u001D'",
+ "'\\035'");
+ assertEval("\"a\\bb\\tc\\nd\\fe\\rf\\\"g'\\\\h\".charAt(1)",
+ "'\\b'");
+ }
}
--- a/langtools/test/jdk/jshell/StartOptionTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/jdk/jshell/StartOptionTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -22,7 +22,7 @@
*/
/*
- * @test 8151754 8080883 8160089 8170162 8166581 8172102
+ * @test 8151754 8080883 8160089 8170162 8166581 8172102 8171343
* @summary Testing start-up options.
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
@@ -33,7 +33,9 @@
* @run testng StartOptionTest
*/
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
@@ -46,6 +48,7 @@
import org.testng.annotations.Test;
import jdk.jshell.tool.JavaShellToolBuilder;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
@@ -57,12 +60,14 @@
private ByteArrayOutputStream console;
private ByteArrayOutputStream userout;
private ByteArrayOutputStream usererr;
+ private InputStream cmdInStream;
private JavaShellToolBuilder builder() {
return JavaShellToolBuilder
.builder()
.out(new PrintStream(cmdout), new PrintStream(console), new PrintStream(userout))
.err(new PrintStream(cmderr), new PrintStream(usererr))
+ .in(cmdInStream, null)
.persistence(new HashMap<>())
.env(new HashMap<>())
.locale(Locale.ROOT);
@@ -119,6 +124,7 @@
console = new ByteArrayOutputStream();
userout = new ByteArrayOutputStream();
usererr = new ByteArrayOutputStream();
+ cmdInStream = new ByteArrayInputStream("/exit\n".getBytes());
}
protected String writeToFile(String stuff) throws Exception {
@@ -138,6 +144,19 @@
start(s -> {
assertTrue(s.split("\n").length >= 7, "Not enough usage lines: " + s);
assertTrue(s.startsWith("Usage: jshell <options>"), "Unexpect usage start: " + s);
+ assertTrue(s.contains("--show-version"), "Expected help: " + s);
+ assertFalse(s.contains("Welcome"), "Unexpected start: " + s);
+ }, null, null, opt);
+ }
+ }
+
+ public void testHelpExtra() throws Exception {
+ for (String opt : new String[]{"-X", "--help-extra"}) {
+ start(s -> {
+ assertTrue(s.split("\n").length >= 5, "Not enough help-extra lines: " + s);
+ assertTrue(s.contains("--add-exports"), "Expected --add-exports: " + s);
+ assertTrue(s.contains("--execution"), "Expected --add-exports: " + s);
+ assertFalse(s.contains("Welcome"), "Unexpected start: " + s);
}, null, null, opt);
}
}
@@ -201,7 +220,29 @@
}
public void testVersion() throws Exception {
- start(s -> assertTrue(s.startsWith("jshell"), "unexpected version: " + s), null, null, "--version");
+ start(
+ s -> {
+ assertTrue(s.startsWith("jshell"), "unexpected version: " + s);
+ assertFalse(s.contains("Welcome"), "Unexpected start: " + s);
+ },
+ null, null,
+ "--version");
+ }
+
+ public void testShowVersion() throws Exception {
+ runShell("--show-version");
+ check(cmdout,
+ s -> {
+ assertTrue(s.startsWith("jshell"), "unexpected version: " + s);
+ assertTrue(s.contains("Welcome"), "Expected start (but got no welcome): " + s);
+ },
+ "cmdout");
+ check(cmderr, null, "cmderr");
+ check(console,
+ s -> assertTrue(s.trim().startsWith("jshell>"), "Expected prompt, got: " + s),
+ "console");
+ check(userout, null, "userout");
+ check(usererr, null, "usererr");
}
@AfterMethod
@@ -211,5 +252,6 @@
console = null;
userout = null;
usererr = null;
+ cmdInStream = null;
}
}
--- a/langtools/test/jdk/jshell/ToolProviderTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/jdk/jshell/ToolProviderTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -23,16 +23,18 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
import java.util.ServiceLoader;
import java.util.function.Consumer;
import javax.tools.Tool;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
+import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
/*
* @test
- * @bug 8170044
+ * @bug 8170044 8171343
* @summary Test ServiceLoader launching of jshell tool
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
@@ -47,12 +49,14 @@
private ByteArrayOutputStream cmdout;
private ByteArrayOutputStream cmderr;
+ private InputStream cmdInStream;
@BeforeMethod
@Override
public void setUp() {
cmdout = new ByteArrayOutputStream();
cmderr = new ByteArrayOutputStream();
+ cmdInStream = new ByteArrayInputStream("/exit\n".getBytes());
}
@Override
@@ -70,7 +74,7 @@
ServiceLoader<Tool> sl = ServiceLoader.load(Tool.class);
for (Tool provider : sl) {
if (provider.name().equals("jshell")) {
- return provider.run(new ByteArrayInputStream(new byte[0]), cmdout, cmderr, args);
+ return provider.run(cmdInStream, cmdout, cmderr, args);
}
}
throw new AssertionError("Repl tool not found by ServiceLoader: " + sl);
@@ -90,4 +94,16 @@
check(cmderr, s -> s.startsWith("Launching JShell execution engine threw: Failed remote"), "cmderr");
}
}
+
+ @Override
+ public void testShowVersion() throws Exception {
+ start(
+ s -> {
+ assertTrue(s.startsWith("jshell "), "unexpected version: " + s);
+ assertTrue(s.contains("Welcome"), "Expected start (but got no welcome): " + s);
+ assertTrue(s.trim().contains("jshell>"), "Expected prompt, got: " + s);
+ },
+ null, null,
+ "--show-version");
+ }
}
--- a/langtools/test/jdk/jshell/ToolSimpleTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/jdk/jshell/ToolSimpleTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102 8172103 8165405 8173073
+ * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102 8172103 8165405 8173073 8173848
* @summary Simple jshell tool tests
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
@@ -74,6 +74,18 @@
}
@Test
+ public void testLessThan() {
+ test(
+ (a) -> assertCommand(a, "45", "$1 ==> 45"),
+ (a) -> assertCommand(a, "72", "$2 ==> 72"),
+ (a) -> assertCommand(a, "$1 < $2", "$3 ==> true"),
+ (a) -> assertCommand(a, "int a, b", "a ==> 0\n" +
+ "b ==> 0"),
+ (a) -> assertCommand(a, "a < b", "$6 ==> false")
+ );
+ }
+
+ @Test
public void oneLineOfError() {
test(
(a) -> assertCommand(a, "12+", null),
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/DuplicateParamTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,24 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8081820
+ * @summary Validate parameter names uniqueness
+ * @modules jdk.compiler/com.sun.tools.doclint
+ * @build DocLintTester
+ * @run main DocLintTester -Xmsgs:-reference DuplicateParamTest.java
+ * @run main DocLintTester -ref DuplicateParamTest.out DuplicateParamTest.java
+ */
+
+/** . */
+public class DuplicateParamTest {
+
+ /**
+ * Test.
+ *
+ * @param s one
+ * @param s two
+ * @param s three
+ *
+ * @return number
+ */
+ public static int Test(String s) { return s.length(); }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/DuplicateParamTest.out Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,7 @@
+DuplicateParamTest.java:18: warning: @param "s" has already been specified
+ * @param s two
+ ^
+DuplicateParamTest.java:19: warning: @param "s" has already been specified
+ * @param s three
+ ^
+2 warnings
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/DuplicateReturnTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,24 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8081820
+ * @summary Validate return uniqueness
+ * @modules jdk.compiler/com.sun.tools.doclint
+ * @build DocLintTester
+ * @run main DocLintTester -Xmsgs:-reference DuplicateReturnTest.java
+ * @run main DocLintTester -ref DuplicateReturnTest.out DuplicateReturnTest.java
+ */
+
+/** . */
+public class DuplicateReturnTest {
+
+ /**
+ * Test.
+ *
+ * @param s one
+ *
+ * @return one
+ * @return two
+ * @return three
+ */
+ public static int Test(String s) { return s.length(); }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/doclint/DuplicateReturnTest.out Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,7 @@
+DuplicateReturnTest.java:20: warning: @return has already been specified
+ * @return two
+ ^
+DuplicateReturnTest.java:21: warning: @return has already been specified
+ * @return three
+ ^
+2 warnings
--- a/langtools/test/tools/javac/Paths/wcMineField.sh Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/tools/javac/Paths/wcMineField.sh Thu Feb 09 23:15:52 2017 +0100
@@ -26,7 +26,7 @@
#
# @test
# @summary Test classpath wildcards for javac and java -classpath option.
-# @bug 6268383
+# @bug 6268383 8172309
# @run shell/timeout=600 wcMineField.sh
# To run this test manually, simply do ./wcMineField.sh
@@ -186,6 +186,8 @@
Failure "$javac" ${TESTTOOLVMOPTS} -classpath "GooJar/*${PS}." Main1.java
Success "$javac" ${TESTTOOLVMOPTS} -cp "GooJar/SubDir/*" Main1.java
Success "$javac" ${TESTTOOLVMOPTS} -classpath "GooJar/SubDir/*" Main1.java
+Success "$javac" ${TESTTOOLVMOPTS} --class-path "GooJar/SubDir/*" Main1.java
+Success "$javac" ${TESTTOOLVMOPTS} --class-path="GooJar/SubDir/*" Main1.java
#Same with launcher. Should not load jar in subdirectories unless specified
Failure "$java" ${TESTVMOPTS} -classpath "GooJar/*${PS}." Main1
Success "$java" ${TESTVMOPTS} -classpath "GooJar/SubDir/*${PS}." Main1
--- a/langtools/test/tools/javac/diags/examples/DuplicateProvides/module-info.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/tools/javac/diags/examples/DuplicateProvides/module-info.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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,6 +25,6 @@
module DuplicateExports {
exports exported;
- provides exported.Service with impl.ServiceImplementation;
- provides exported.Service with impl.ServiceImplementation;
+ provides exported.Service
+ with impl.ServiceImplementation, impl.ServiceImplementation;
}
--- a/langtools/test/tools/javac/diags/examples/PackageEmptyOrNotFound/PackageEmptyOrNotFound.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// key: compiler.err.package.empty.or.not.found
--- a/langtools/test/tools/javac/diags/examples/PackageEmptyOrNotFound/modulesourcepath/m1x/module-info.java Thu Feb 02 05:26:20 2017 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-module m1x {
- exports p1;
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/PackageEmptyOrNotFoundError/PackageEmptyOrNotFound.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016, 2017, 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.
+ */
+
+// key: compiler.err.package.empty.or.not.found
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/PackageEmptyOrNotFoundError/modulesourcepath/m1x/module-info.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, 2017, 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.
+ */
+
+module m1x {
+ exports p1;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/PackageEmptyOrNotFoundWarning/PackageEmptyOrNotFound.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016, 2017, 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.
+ */
+
+// key: compiler.warn.package.empty.or.not.found
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/PackageEmptyOrNotFoundWarning/modulesourcepath/m1x/module-info.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, 2017, 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.
+ */
+
+module m1x {
+ opens p1;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RepeatedProvidesForService/RepeatedProvides.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+//key: compiler.err.repeated.provides.for.service
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RepeatedProvidesForService/modulesourcepath/m/module-info.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,6 @@
+module m {
+ uses p.I;
+ provides p.I with p.A;
+ provides p.I with p.B;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RepeatedProvidesForService/modulesourcepath/m/p/A.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,3 @@
+package p;
+public class A implements I { }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RepeatedProvidesForService/modulesourcepath/m/p/B.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,3 @@
+package p;
+public class B implements I { }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RepeatedProvidesForService/modulesourcepath/m/p/I.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,3 @@
+package p;
+public interface I { }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/UnexpectedTokenInModuleInfo/module-info.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+// key: compiler.err.expected.module.or.open
+
+weak module m {}
\ No newline at end of file
--- a/langtools/test/tools/javac/file/LimitedImage.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/tools/javac/file/LimitedImage.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -74,6 +74,7 @@
);
//check proper diagnostics when zip/jar FS not present:
+ System.err.println("Test " + testJar + " on classpath");
actualOutput = new JavacTask(tb, Mode.CMDLINE)
.classpath(testJar)
.options("-XDrawDiagnostics")
@@ -84,9 +85,10 @@
.getOutputLines(OutputKind.DIRECT);
if (!expectedOutput.equals(actualOutput)) {
- throw new AssertionError("Unexpected output: " + actualOutput);
+ throw new AssertionError("Unexpected output");
}
+ System.err.println("Test " + testJar + " on sourcepath");
actualOutput = new JavacTask(tb, Mode.CMDLINE)
.sourcepath(testJar)
.options("-XDrawDiagnostics")
@@ -97,9 +99,10 @@
.getOutputLines(OutputKind.DIRECT);
if (!expectedOutput.equals(actualOutput)) {
- throw new AssertionError("Unexpected output: " + actualOutput);
+ throw new AssertionError("Unexpected output");
}
+ System.err.println("Test " + testJar + " on modulepath");
actualOutput = new JavacTask(tb, Mode.CMDLINE)
.options("-XDrawDiagnostics",
"--module-path", testJar.toString())
@@ -110,7 +113,7 @@
.getOutputLines(OutputKind.DIRECT);
if (!expectedOutput.equals(actualOutput)) {
- throw new AssertionError("Unexpected output: " + actualOutput);
+ throw new AssertionError("Unexpected output");
}
expectedOutput = Arrays.asList(
@@ -118,6 +121,7 @@
"1 error"
);
+ System.err.println("Test directory containing " + testJar + " on modulepath");
actualOutput = new JavacTask(tb, Mode.CMDLINE)
.classpath()
.options("-XDrawDiagnostics",
@@ -129,7 +133,7 @@
.getOutputLines(OutputKind.DIRECT);
if (!expectedOutput.equals(actualOutput)) {
- throw new AssertionError("Unexpected output: " + actualOutput);
+ throw new AssertionError("Unexpected output");
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MethodReferenceNoThisTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,31 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8173456
+ * @summary com.sun.tools.javac.util.Assert.error during code compilation
+ * @compile/fail/ref=MethodReferenceNoThisTest.out -XDrawDiagnostics MethodReferenceNoThisTest.java
+ */
+
+import java.util.function.Function;
+
+abstract class MethodReferenceNoThisTest_Base {
+ protected MethodReferenceNoThisTest_Base(Function<MethodReferenceNoThisTest_Base, MethodReferenceNoThisTest_AV> x) {}
+}
+
+abstract class MethodReferenceNoThisTest_AV {
+ MethodReferenceNoThisTest_AV(MethodReferenceNoThisTest_Base b) {
+ }
+}
+
+public class MethodReferenceNoThisTest extends MethodReferenceNoThisTest_Base {
+
+ public MethodReferenceNoThisTest() {
+ super(V::new);
+ }
+
+ private class V extends MethodReferenceNoThisTest_AV {
+
+ V(MethodReferenceNoThisTest_Base b) {
+ super(b);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/MethodReferenceNoThisTest.out Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,2 @@
+MethodReferenceNoThisTest.java:22:15: compiler.err.cant.ref.before.ctor.called: this
+1 error
\ No newline at end of file
--- a/langtools/test/tools/javac/lambda/intersection/IntersectionTargetTypeTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/tools/javac/lambda/intersection/IntersectionTargetTypeTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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,6 @@
* @bug 8002099 8010822
* @summary Add support for intersection types in cast expression
* @modules jdk.compiler/com.sun.tools.javac.util
- * @run main/othervm IntersectionTargetTypeTest
*/
import com.sun.source.util.JavacTask;
--- a/langtools/test/tools/javac/modules/AddLimitMods.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/tools/javac/modules/AddLimitMods.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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
@@ -217,10 +217,10 @@
private static final List<Entry<String[], String>> variants = Arrays.asList(
new SimpleEntry<String[], String>(new String[] {},
- "Test.java:2:7: compiler.err.package.not.visible: javax.annotation, (compiler.misc.not.def.access.does.not.read.from.unnamed: javax.annotation, java.annotations.common)\n"
+ "Test.java:2:7: compiler.err.package.not.visible: javax.annotation, (compiler.misc.not.def.access.does.not.read.from.unnamed: javax.annotation, java.xml.ws.annotation)\n"
+ "Test.java:5:14: compiler.err.package.not.visible: javax.xml.bind, (compiler.misc.not.def.access.does.not.read.from.unnamed: javax.xml.bind, java.xml.bind)\n"
+ "2 errors\n"),
- new SimpleEntry<String[], String>(new String[] {"--add-modules", "java.annotations.common,java.xml.bind"},
+ new SimpleEntry<String[], String>(new String[] {"--add-modules", "java.xml.ws.annotation,java.xml.bind"},
null),
new SimpleEntry<String[], String>(new String[] {"--limit-modules", "java.xml.ws,jdk.compiler"},
null),
--- a/langtools/test/tools/javac/modules/AnnotationProcessing.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/tools/javac/modules/AnnotationProcessing.java Thu Feb 09 23:15:52 2017 +0100
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 8133884 8162711 8133896 8172158 8172262
+ * @bug 8133884 8162711 8133896 8172158 8172262 8173636
* @summary Verify that annotation processing works.
* @library /tools/lib
* @modules
@@ -173,7 +173,7 @@
String[] module2Packages = moduleDef.split("=>");
module2ExpectedEnclosedElements.put(module2Packages[0],
- Arrays.asList(module2Packages[1].split(":")));
+ List.of(module2Packages[1].split(":")));
}
}
@@ -359,7 +359,7 @@
.writeAll()
.getOutput(Task.OutputKind.DIRECT);
- List<String> expected = Arrays.asList("Note: field: m1x");
+ List<String> expected = List.of("Note: field: m1x");
for (Mode mode : new Mode[] {Mode.API, Mode.CMDLINE}) {
List<String> log = new JavacTask(tb, mode)
@@ -424,7 +424,7 @@
.writeAll()
.getOutputLines(Task.OutputKind.STDERR);
- assertEquals(Arrays.asList("module: m1x"), log);
+ assertEquals(List.of("module: m1x"), log);
}
@SupportedAnnotationTypes("*")
@@ -472,8 +472,8 @@
.writeAll()
.getOutputLines(Task.OutputKind.DIRECT);
- List<String> expectedLog = Arrays.asList("Note: AP Invoked",
- "Note: AP Invoked");
+ List<String> expectedLog = List.of("Note: AP Invoked",
+ "Note: AP Invoked");
assertEquals(expectedLog, log);
@@ -600,7 +600,7 @@
JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
try (StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null)) {
- List<String> options = Arrays.asList("-d", scratchClasses.toString());
+ List<String> options = List.of("-d", scratchClasses.toString());
Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(scratchSrc);
CompilationTask task = comp.getTask(null, fm, null, options, null, files);
@@ -939,7 +939,7 @@
.writeAll()
.getOutputLines(OutputKind.STDERR);
- expected = Arrays.asList("");
+ expected = List.of("");
if (!expected.equals(log)) {
throw new AssertionError("Output does not match; output: " + log);
@@ -954,15 +954,17 @@
.writeAll()
.getOutputLines(OutputKind.STDERR);
- expected = Arrays.asList("SelectAnnotationBTestAP",
- "SelectAnnotationBTestAP");
+ expected = List.of("SelectAnnotationBTestAP",
+ "SelectAnnotationBTestAP");
if (!expected.equals(log)) {
throw new AssertionError("Output does not match; output: " + log);
}
log = new JavacTask(tb)
- .options("-processor", SelectAnnotationATestAP.class.getName() + "," + SelectAnnotationBTestAP.class.getName(),
+ .options("-processor", SelectAnnotationATestAP.class.getName() + "," +
+ SelectAnnotationBTestAP.class.getName() + "," +
+ SelectAnnotationAStrictTestAP.class.getName(),
"--module-source-path", src.toString(),
"-m", "m4x")
.outdir(classes)
@@ -970,10 +972,43 @@
.writeAll()
.getOutputLines(OutputKind.STDERR);
- expected = Arrays.asList("SelectAnnotationATestAP",
- "SelectAnnotationBTestAP",
- "SelectAnnotationATestAP",
- "SelectAnnotationBTestAP");
+ expected = List.of("SelectAnnotationATestAP",
+ "SelectAnnotationBTestAP",
+ "SelectAnnotationAStrictTestAP",
+ "SelectAnnotationATestAP",
+ "SelectAnnotationBTestAP",
+ "SelectAnnotationAStrictTestAP");
+
+ if (!expected.equals(log)) {
+ throw new AssertionError("Output does not match; output: " + log);
+ }
+ }
+
+ @Test
+ public void testDisambiguateAnnotationsUnnamedModule(Path base) throws Exception {
+ Path classes = base.resolve("classes");
+
+ Files.createDirectories(classes);
+
+ Path src = base.resolve("src");
+
+ tb.writeJavaFiles(src,
+ "package api; public @interface A {}",
+ "package api; public @interface B {}",
+ "package impl; import api.*; @A @B public class T {}");
+
+ List<String> log = new JavacTask(tb)
+ .options("-processor", SelectAnnotationATestAP.class.getName() + "," +
+ SelectAnnotationBTestAP.class.getName() + "," +
+ SelectAnnotationAStrictTestAP.class.getName())
+ .outdir(classes)
+ .files(findJavaFiles(src))
+ .run()
+ .writeAll()
+ .getOutputLines(OutputKind.STDERR);
+
+ List<String> expected = List.of("SelectAnnotationBTestAP",
+ "SelectAnnotationBTestAP");
if (!expected.equals(log)) {
throw new AssertionError("Output does not match; output: " + log);
@@ -994,7 +1029,9 @@
"package impl; import api.*; @A @B public class T {}");
List<String> log = new JavacTask(tb)
- .options("-processor", SelectAnnotationATestAP.class.getName() + "," + SelectAnnotationBTestAP.class.getName(),
+ .options("-processor", SelectAnnotationATestAP.class.getName() + "," +
+ SelectAnnotationBTestAP.class.getName() + "," +
+ SelectAnnotationAStrictTestAP.class.getName(),
"-source", "8", "-target", "8")
.outdir(classes)
.files(findJavaFiles(src))
@@ -1002,10 +1039,10 @@
.writeAll()
.getOutputLines(OutputKind.STDERR);
- List<String> expected = Arrays.asList("SelectAnnotationATestAP",
- "SelectAnnotationBTestAP",
- "SelectAnnotationATestAP",
- "SelectAnnotationBTestAP");
+ List<String> expected = List.of("SelectAnnotationATestAP",
+ "SelectAnnotationBTestAP",
+ "SelectAnnotationATestAP",
+ "SelectAnnotationBTestAP");
if (!expected.equals(log)) {
throw new AssertionError("Output does not match; output: " + log);
@@ -1036,6 +1073,22 @@
}
+ public static final class SelectAnnotationAStrictTestAP extends AbstractProcessor {
+
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ System.err.println("SelectAnnotationAStrictTestAP");
+
+ return false;
+ }
+
+ @Override
+ public Set<String> getSupportedAnnotationTypes() {
+ return Set.of("m2x/api.A");
+ }
+
+ }
+
private static void writeFile(String content, Path base, String... pathElements) throws IOException {
Path file = resolveFile(base, pathElements);
--- a/langtools/test/tools/javac/modules/EdgeCases.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/tools/javac/modules/EdgeCases.java Thu Feb 09 23:15:52 2017 +0100
@@ -23,13 +23,14 @@
/*
* @test
- * @bug 8154283 8167320 8171098 8172809 8173117
+ * @bug 8154283 8167320 8171098 8172809 8173068 8173117
* @summary tests for multi-module mode compilation
* @library /tools/lib
* @modules
* jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.code
* jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.processing
* jdk.compiler/com.sun.tools.javac.util
* @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask ModuleTestBase
* @run main EdgeCases
@@ -53,8 +54,10 @@
import javax.lang.model.element.Element;
import javax.lang.model.element.ModuleElement;
import javax.lang.model.element.ModuleElement.RequiresDirective;
+import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.ElementFilter;
+import javax.lang.model.util.Elements;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
@@ -64,7 +67,10 @@
//import com.sun.source.util.JavacTask; // conflicts with toolbox.JavacTask
import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.code.Symbol.PackageSymbol;
import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.processing.JavacProcessingEnvironment;
+import com.sun.tools.javac.util.Context;
import toolbox.JarTask;
import toolbox.JavacTask;
@@ -654,4 +660,156 @@
}
}
+ @Test
+ public void testUnnamedPackage(Path base) throws Exception {
+ List<String> out;
+ List<String> expected;
+
+ //-source 8:
+ Path src8 = base.resolve("src8");
+ Files.createDirectories(src8);
+ tb.writeJavaFiles(src8,
+ "package test; public class Test {}");
+ Path classes = base.resolve("classes");
+ tb.createDirectories(classes);
+
+ out = new JavacTask(tb)
+ .options("--source-path", src8.toString(),
+ "-processor", UnnamedPackageProcessor.class.getName(),
+ "-source", "8")
+ .outdir(classes)
+ .files(findJavaFiles(src8))
+ .run()
+ .writeAll()
+ .getOutputLines(OutputKind.STDOUT);
+
+ expected = Arrays.asList("noModule");
+
+ if (!expected.equals(out)) {
+ throw new AssertionError("Unexpected output: " + out);
+ }
+
+ //-source 9, unnamed:
+ Path srcUnnamed = base.resolve("srcUnnamed");
+ Files.createDirectories(srcUnnamed);
+ tb.writeJavaFiles(srcUnnamed,
+ "public class Test {}");
+ Path classesUnnamed = base.resolve("classesUnnamed");
+ tb.createDirectories(classesUnnamed);
+
+ out = new JavacTask(tb)
+ .options("--source-path", srcUnnamed.toString(),
+ "-processor", UnnamedPackageProcessor.class.getName())
+ .outdir(classesUnnamed)
+ .files(findJavaFiles(srcUnnamed))
+ .run()
+ .writeAll()
+ .getOutputLines(OutputKind.STDOUT);
+
+ expected = Arrays.asList("unnamedModule");
+
+ if (!expected.equals(out)) {
+ throw new AssertionError("Unexpected output: " + out);
+ }
+
+ //-source 9, named:
+ Path srcNamed = base.resolve("srcNamed");
+ Files.createDirectories(srcNamed);
+ tb.writeJavaFiles(srcNamed,
+ "module m {}",
+ "public class Test {}");
+ Path classesNamed = base.resolve("classesNamed");
+ tb.createDirectories(classesNamed);
+
+ out = new JavacTask(tb)
+ .options("--source-path", srcNamed.toString(),
+ "-classpath", "",
+ "-processorpath", System.getProperty("test.class.path"),
+ "-processor", UnnamedPackageProcessor.class.getName())
+ .outdir(classesNamed)
+ .files(findJavaFiles(srcNamed))
+ .run()
+ .writeAll()
+ .getOutputLines(OutputKind.STDOUT);
+
+ expected = Arrays.asList("m");
+
+ if (!expected.equals(out)) {
+ throw new AssertionError("Unexpected output: " + out);
+ }
+
+ //-source 9, conflict:
+ Path srcNamed2 = base.resolve("srcNamed2");
+ Path srcNamed2m1 = srcNamed2.resolve("m1x");
+ Files.createDirectories(srcNamed2m1);
+ tb.writeJavaFiles(srcNamed2m1,
+ "module m1x {}",
+ "public class Test {}");
+ Path srcNamed2m2 = srcNamed2.resolve("m2x");
+ Files.createDirectories(srcNamed2m2);
+ tb.writeJavaFiles(srcNamed2m2,
+ "module m2x {}",
+ "public class Test {}");
+ Path classesNamed2 = base.resolve("classesNamed2");
+ tb.createDirectories(classesNamed2);
+
+ out = new JavacTask(tb)
+ .options("--module-source-path", srcNamed2.toString(),
+ "-classpath", "",
+ "-processorpath", System.getProperty("test.class.path"),
+ "-processor", UnnamedPackageProcessor.class.getName(),
+ "-XDshould-stop.ifError=FLOW")
+ .outdir(classesNamed2)
+ .files(findJavaFiles(srcNamed2))
+ .run(Expect.FAIL)
+ .writeAll()
+ .getOutputLines(OutputKind.STDOUT);
+
+ expected = Arrays.asList("null",
+ "m1x: true",
+ "m2x: true");
+
+ if (!expected.equals(out)) {
+ throw new AssertionError("Unexpected output: " + out);
+ }
+ }
+
+ @SupportedAnnotationTypes("*")
+ public static final class UnnamedPackageProcessor extends AbstractProcessor {
+
+ int round = 0;
+
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ if (round++ != 0)
+ return false;
+
+ Elements elements = processingEnv.getElementUtils();
+ PackageElement pe = elements.getPackageElement("");
+
+ if (pe == null) {
+ System.out.println("null");
+ } else {
+ ModuleElement mod = (ModuleElement) pe.getEnclosingElement();
+ if (mod == null) {
+ System.out.println("noModule");
+ } else if (mod.isUnnamed()) {
+ System.out.println("unnamedModule");
+ } else {
+ System.out.println(mod);
+ }
+ }
+
+ ModuleElement m1x = elements.getModuleElement("m1x");
+ ModuleElement m2x = elements.getModuleElement("m2x");
+
+ if (m1x != null && m2x != null) {
+ System.out.println("m1x: " + (elements.getPackageElement(m1x, "") != null));
+ System.out.println("m2x: " + (elements.getPackageElement(m2x, "") != null));
+ }
+
+ return false;
+ }
+
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/modules/MissingModuleTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2017, 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 8172240
+ * @summary javac should not need the transitive closure to compile a module
+ * @library /tools/lib
+ * @modules
+ * jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.processing
+ * @build toolbox.ToolBox toolbox.JavacTask toolbox.ModuleBuilder ModuleTestBase
+ * @run main MissingModuleTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.List;
+
+import toolbox.JavacTask;
+import toolbox.Task;
+import toolbox.Task.Expect;
+
+public class MissingModuleTest extends ModuleTestBase {
+
+ public static void main(String... args) throws Exception {
+ new MissingModuleTest().runTests();
+ }
+
+ @Test
+ public void testMissingNotNeeded(Path base) throws Exception {
+ doTest(base, "m1x", new String[0]);
+ }
+
+ @Test
+ public void testMissingNeededTransitive(Path base) throws Exception {
+ doTest(base, "m2x", "- compiler.err.module.not.found: m2x", "1 error");
+ }
+
+ @Test
+ public void testMissingNeededDirect(Path base) throws Exception {
+ doTest(base, "m3x", "module-info.java:1:24: compiler.err.module.not.found: m3x", "1 error");
+ }
+
+ @Test
+ public void testMultipleErrors(Path base) throws Exception {
+ doTest(base, "m4x", "module-info.java:1:38: compiler.err.module.not.found: m4x", "1 error");
+ }
+
+ private void doTest(Path base, String toDelete, String... errors) throws Exception {
+ //note: avoiding use of java.base, as that gets special handling on some places:
+ Path srcMP = base.resolve("src-mp");
+ Path m1x = srcMP.resolve("m1x");
+ tb.writeJavaFiles(m1x,
+ "module m1x { exports api1; }",
+ "package api1; public interface Api { }");
+ Path m2x = srcMP.resolve("m2x");
+ tb.writeJavaFiles(m2x,
+ "module m2x { requires m1x; exports api2; }",
+ "package api2; public interface Api { }");
+ Path m3x = srcMP.resolve("m3x");
+ tb.writeJavaFiles(m3x,
+ "module m3x { requires transitive m2x; }");
+ Path m4x = srcMP.resolve("m4x");
+ tb.writeJavaFiles(m4x,
+ "module m4x { requires transitive m2x; }");
+ Path m5x = srcMP.resolve("m5x");
+ tb.writeJavaFiles(m5x,
+ "module m5x { requires transitive m4x; }");
+ Path classesMP = base.resolve("classes-mp");
+ tb.createDirectories(classesMP);
+
+ new JavacTask(tb)
+ .options("--module-source-path", srcMP.toString())
+ .outdir(classesMP)
+ .files(findJavaFiles(srcMP))
+ .run()
+ .writeAll();
+
+ tb.cleanDirectory(classesMP.resolve(toDelete));
+ Files.delete(classesMP.resolve(toDelete));
+
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src,
+ "module test { requires m3x; requires m4x; requires m5x; } ");
+ Path classes = base.resolve("classes");
+ tb.createDirectories(classes);
+
+ List<String> log = new JavacTask(tb)
+ .options("--module-path", classesMP.toString(),
+ "-XDrawDiagnostics")
+ .outdir(classes)
+ .files(findJavaFiles(src))
+ .run(errors.length > 0 ? Expect.FAIL : Expect.SUCCESS)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ if (errors.length == 0) {
+ errors = new String[] {""};
+ }
+
+ if (!log.equals(Arrays.asList(errors)))
+ throw new Exception("expected output not found: " + log);
+ }
+
+}
--- a/langtools/test/tools/javac/modules/ModulesAndModuleSourcePathTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/tools/javac/modules/ModulesAndModuleSourcePathTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -22,7 +22,8 @@
*/
/**
- * @test 8165102
+ * @test
+ * @bug 8165102
* @summary incorrect message from javac
* @library /tools/lib
* @modules
--- a/langtools/test/tools/javac/modules/ProvidesTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/tools/javac/modules/ProvidesTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -24,7 +24,7 @@
/**
* @test
* @summary simple tests of module provides
- * @bug 8168854
+ * @bug 8168854 8172807
* @library /tools/lib
* @modules
* jdk.compiler/com.sun.tools.javac.api
@@ -109,21 +109,56 @@
}
@Test
- public void testDuplicateProvides(Path base) throws Exception {
+ public void testDuplicateImplementations1(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
- "module m { provides p1.C1 with p2.C2; provides p1.C1 with p2.C2; }",
+ "module m { exports p1; exports p2; provides p1.C1 with p2.C2, p2.C2; }",
"package p1; public class C1 { }",
"package p2; public class C2 extends p1.C1 { }");
Path classes = base.resolve("classes");
Files.createDirectories(classes);
- new JavacTask(tb)
- .options("-XDrawDiagnostic")
+ List<String> output = new JavacTask(tb)
+ .options("-XDrawDiagnostics")
.outdir(classes)
.files(findJavaFiles(src))
.run(Task.Expect.FAIL)
- .writeAll();
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ List<String> expected = Arrays.asList(
+ "module-info.java:1:65: compiler.err.duplicate.provides: p1.C1, p2.C2",
+ "1 error");
+ if (!output.containsAll(expected)) {
+ throw new Exception("Expected output not found");
+ }
+ }
+
+ @Test
+ public void testDuplicateImplementations2(Path base) throws Exception {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src,
+ "module m { exports p1; provides p1.C1 with p2.C2; provides p1.C1 with p2.C2; }",
+ "package p1; public class C1 { }",
+ "package p2; public class C2 extends p1.C1 { }");
+ Path classes = base.resolve("classes");
+ Files.createDirectories(classes);
+
+ List<String> output = new JavacTask(tb)
+ .options("-XDrawDiagnostics")
+ .outdir(classes)
+ .files(findJavaFiles(src))
+ .run(Task.Expect.FAIL)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ List<String> expected = Arrays.asList(
+ "module-info.java:1:62: compiler.err.repeated.provides.for.service: p1.C1",
+ "module-info.java:1:73: compiler.err.duplicate.provides: p1.C1, p2.C2",
+ "2 errors");
+ if (!output.containsAll(expected)) {
+ throw new Exception("Expected output not found");
+ }
}
@Test
@@ -228,7 +263,7 @@
public void testSeveralImplementations(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
- "module m { provides p.C with p.Impl1; provides p.C with p.Impl2; }",
+ "module m { provides p.C with p.Impl1, p.Impl2; }",
"package p; public class C { }",
"package p; public class Impl1 extends p.C { }",
"package p; public class Impl2 extends p.C { }");
@@ -241,6 +276,30 @@
}
@Test
+ public void testRepeatedProvides(Path base) throws Exception {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src,
+ "module m { exports p; provides p.C with p.Impl1; provides p.C with p.Impl2; }",
+ "package p; public class C { }",
+ "package p; public class Impl1 extends p.C { }",
+ "package p; public class Impl2 extends p.C { }");
+
+ List<String> output = new JavacTask(tb)
+ .options("-XDrawDiagnostics")
+ .outdir(Files.createDirectories(base.resolve("classes")))
+ .files(findJavaFiles(src))
+ .run(Task.Expect.FAIL)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ List<String> expected = Arrays.asList("module-info.java:1:60: compiler.err.repeated.provides.for.service: p.C",
+ "1 error");
+ if (!output.containsAll(expected)) {
+ throw new Exception("Expected output not found");
+ }
+ }
+
+ @Test
public void testOneImplementationsForServices(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
--- a/langtools/test/tools/javac/modules/ReportNonExistentPackageTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/tools/javac/modules/ReportNonExistentPackageTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -105,7 +105,7 @@
}
@Test
- public void testExportPrivateEmptyPackage(Path base) throws Exception {
+ public void testOpensEmptyPackage(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { opens p; }");
@@ -116,15 +116,34 @@
.options("-XDrawDiagnostics")
.outdir(classes)
.files(findJavaFiles(src))
- .run(Task.Expect.FAIL)
+ .run(Task.Expect.SUCCESS)
.writeAll()
.getOutput(Task.OutputKind.DIRECT);
- if (!log.contains("module-info.java:1:18: compiler.err.package.empty.or.not.found: p"))
+ if (!log.contains("module-info.java:1:18: compiler.warn.package.empty.or.not.found: p"))
throw new Exception("expected output not found, actual output: " + log);
}
@Test
- public void testExportPrivateOnlyWithResources(Path base) throws Exception {
+ public void testOpensEmptyPackageSuppressed(Path base) throws Exception {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src,
+ "@SuppressWarnings(\"opens\") module m { opens p; }");
+ Path classes = base.resolve("classes");
+ Files.createDirectories(classes);
+
+ String log = new JavacTask(tb)
+ .options("-XDrawDiagnostics")
+ .outdir(classes)
+ .files(findJavaFiles(src))
+ .run(Task.Expect.SUCCESS)
+ .writeAll()
+ .getOutput(Task.OutputKind.DIRECT);
+ if (!log.equals(""))
+ throw new Exception("expected output not found, actual output: " + log);
+ }
+
+ @Test
+ public void testOpenOnlyWithResources(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"module m { opens p; }");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/modules/UnexpectedTokenInModuleInfoTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2017, 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 8166420
+ * @summary Confusing error message when reading bad module declaration
+ * @library /tools/lib
+ * @modules
+ * jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase
+ * @run main UnexpectedTokenInModuleInfoTest
+ */
+
+import java.nio.file.*;
+import java.util.List;
+import java.util.Arrays;
+
+import toolbox.JavacTask;
+import toolbox.Task;
+
+public class UnexpectedTokenInModuleInfoTest extends ModuleTestBase {
+ public static void main(String... args) throws Exception {
+ UnexpectedTokenInModuleInfoTest t = new UnexpectedTokenInModuleInfoTest();
+ t.runTests();
+ }
+
+ @Test
+ public void testSingleModule(Path base) throws Exception {
+ Path src = base.resolve("src");
+ tb.writeFile(src.resolve("module-info.java"), "weak module m { }");
+
+ List<String> output = new JavacTask(tb)
+ .options("-XDrawDiagnostics")
+ .files(src.resolve("module-info.java"))
+ .run(Task.Expect.FAIL)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ List<String> expected = Arrays.asList("module-info.java:1:1: compiler.err.expected.module.or.open",
+ "1 error");
+ if (!output.containsAll(expected)) {
+ throw new Exception("Expected output not found");
+ }
+ }
+}
\ No newline at end of file
--- a/langtools/test/tools/javac/parser/extend/TrialParserFactory.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/tools/javac/parser/extend/TrialParserFactory.java Thu Feb 09 23:15:52 2017 +0100
@@ -52,4 +52,9 @@
com.sun.tools.javac.parser.Lexer lexer = scannerFactory.newScanner(input, keepDocComments);
return new TrialParser(this, lexer, keepDocComments, keepLineMap, keepEndPos);
}
+
+ @Override
+ public JavacParser newParser(CharSequence input, boolean keepDocComments, boolean keepEndPos, boolean keepLineMap, boolean parseModuleInfo) {
+ return newParser(input, keepDocComments, keepEndPos, keepLineMap);
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/OverwriteInitialInput.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 8067747
+ * @summary Verify the correct Filer behavior w.r.t. initial inputs
+ * (should throw FilerException when overwriting initial inputs).
+ * @library /tools/lib /tools/javac/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.ToolBox toolbox.JavacTask toolbox.Task
+ * @build OverwriteInitialInput JavacTestingAbstractProcessor
+ * @run main OverwriteInitialInput
+ */
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Set;
+
+import javax.annotation.processing.FilerException;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedOptions;
+import javax.lang.model.element.TypeElement;
+import javax.tools.StandardLocation;
+
+import toolbox.JavacTask;
+import toolbox.Task;
+import toolbox.ToolBox;
+
+@SupportedOptions({OverwriteInitialInput.EXPECT_EXCEPTION_OPTION,
+ OverwriteInitialInput.TEST_SOURCE
+ })
+public class OverwriteInitialInput extends JavacTestingAbstractProcessor {
+
+ public static final String EXPECT_EXCEPTION_OPTION = "exception";
+ public static final String TEST_SOURCE = "testSource";
+
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ if (roundEnv.processingOver()) {
+ if (processingEnv.getOptions().containsKey(EXPECT_EXCEPTION_OPTION)) {
+ try (Writer w = processingEnv.getFiler().createSourceFile("Test").openWriter()) {
+ throw new AssertionError("Expected IOException not seen.");
+ } catch (FilerException ex) {
+ //expected
+ } catch (IOException ex) {
+ throw new IllegalStateException(ex);
+ }
+ try (OutputStream out = processingEnv.getFiler().createClassFile("Test").openOutputStream()) {
+ throw new AssertionError("Expected IOException not seen.");
+ } catch (FilerException ex) {
+ //expected
+ } catch (IOException ex) {
+ throw new IllegalStateException(ex);
+ }
+ if (processingEnv.getOptions().containsKey(TEST_SOURCE)) {
+ try (OutputStream out = processingEnv.getFiler().createResource(StandardLocation.SOURCE_OUTPUT, "", "Test.java").openOutputStream()) {
+ throw new AssertionError("Expected IOException not seen.");
+ } catch (FilerException ex) {
+ //expected
+ } catch (IOException ex) {
+ throw new IllegalStateException(ex);
+ }
+ } else {
+ try (OutputStream out = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", "Test2.class").openOutputStream()) {
+ throw new AssertionError("Expected IOException not seen.");
+ } catch (FilerException ex) {
+ //expected
+ } catch (IOException ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+ } else {
+ try (Writer w = processingEnv.getFiler().createSourceFile("Test").openWriter()) {
+ w.append("public class Test {}");
+ } catch (IOException ex) {
+ throw new IllegalStateException(ex);
+ }
+ try (OutputStream out = processingEnv.getFiler().createClassFile("Test2").openOutputStream()) {
+ try (ToolBox.MemoryFileManager mfm = new ToolBox.MemoryFileManager()) {
+ ToolBox tb = new ToolBox();
+ new JavacTask(tb)
+ .sources("public class Test2 {}")
+ .fileManager(mfm)
+ .run()
+ .writeAll();
+
+ out.write(mfm.getFileBytes(StandardLocation.CLASS_OUTPUT, "Test2"));
+ }
+ } catch (IOException ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public static void main(String... args) throws IOException {
+ new OverwriteInitialInput().run();
+ }
+
+ void run() throws IOException {
+ run(Task.Mode.API);
+ run(Task.Mode.CMDLINE);
+ }
+
+ void run(Task.Mode mode) throws IOException {
+ ToolBox tb = new ToolBox();
+ Path path = Paths.get("output");
+ if (Files.isDirectory(path))
+ tb.cleanDirectory(path);
+ Files.deleteIfExists(path);
+ tb.createDirectories(path);
+ Path thisSource = Paths.get(System.getProperty("test.src"), "OverwriteInitialInput.java");
+ new JavacTask(tb, mode).options("-processor", "OverwriteInitialInput",
+ "-d", path.toString(),
+ "-XDaccessInternalAPI=true")
+ .files(thisSource)
+ .run()
+ .writeAll();
+ new JavacTask(tb, mode).options("-processor", "OverwriteInitialInput",
+ "-d", path.toString(),
+ "-A" + EXPECT_EXCEPTION_OPTION,
+ "-A" + TEST_SOURCE,
+ "-XDaccessInternalAPI=true")
+ .files(thisSource, path.resolve("Test.java"))
+ .run()
+ .writeAll();
+ new JavacTask(tb, mode).options("-processor", "OverwriteInitialInput",
+ "-classpath", path.toString(),
+ "-processorpath", System.getProperty("test.class.path"),
+ "-d", path.toString(),
+ "-A" + EXPECT_EXCEPTION_OPTION,
+ "-XDaccessInternalAPI=true")
+ .classes("Test", "Test2")
+ .run()
+ .writeAll();
+ }
+
+}
--- a/langtools/test/tools/javac/processing/messager/6362067/T6362067.out Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/tools/javac/processing/messager/6362067/T6362067.out Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
T6362067.java:19:8: compiler.note.proc.messager: note:elem
T6362067.java:17:1: compiler.note.proc.messager: note:anno
T6362067.java:18:1: compiler.note.proc.messager: note:anno
-T6362067.java:18:1: compiler.note.proc.messager: note:value
+T6362067.java:18:19: compiler.note.proc.messager: note:value
- compiler.note.proc.messager: note:nopos
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/messager/6388543/T6388543.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,101 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 6388543
+ * @summary improve accuracy of source positions for AnnotationValue param of Messager.printMessage
+ * @library /tools/javac/lib
+ * @modules jdk.compiler
+ * @build JavacTestingAbstractProcessor T6388543
+ * @compile/ref=T6388543.out -XDrawDiagnostics -processor T6388543 -proc:only T6388543.java
+ */
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+import java.util.Set;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
+import static javax.tools.Diagnostic.Kind.NOTE;
+
+class Annotated {
+ @A(1)
+ int a1;
+
+ @A(value = 2)
+ int a2;
+
+ @A(value = {3})
+ int a3;
+
+ @A(value = {4, 5})
+ int a4;
+
+ @B(x = @C(x = E.ONE, y = E.TWO), y = @C(x = E.ONE, y = E.TWO))
+ int b;
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface A {
+ int[] value() default 0;
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface B {
+ C x() default @C;
+
+ C y() default @C;
+}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface C {
+ E x() default E.ONE;
+
+ E y() default E.ONE;
+}
+
+enum E {
+ ONE,
+ TWO
+}
+
+public class T6388543 extends JavacTestingAbstractProcessor {
+ public boolean process(Set<? extends TypeElement> annos, RoundEnvironment roundEnv) {
+ if (roundEnv.processingOver()) {
+ return false;
+ }
+ for (Element e : elements.getTypeElement("Annotated").getEnclosedElements()) {
+ for (AnnotationMirror a : e.getAnnotationMirrors()) {
+ for (AnnotationValue v : a.getElementValues().values()) {
+ printValue(e, a, v);
+ }
+ }
+ }
+ return false;
+ }
+
+ private void printValue(Element e, AnnotationMirror a, AnnotationValue v) {
+ messager.printMessage(NOTE, String.format("note:value %s + %s", a, v), e, a, v);
+ v.accept(
+ new SimpleAnnotationValueVisitor<Void, Void>() {
+ @Override
+ public Void visitArray(List<? extends AnnotationValue> values, Void unused) {
+ for (AnnotationValue value : values) {
+ printValue(e, a, value);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visitAnnotation(AnnotationMirror nestedAnnotation, Void unused) {
+ for (AnnotationValue value : nestedAnnotation.getElementValues().values()) {
+ printValue(e, a, value);
+ }
+ return null;
+ }
+ },
+ null);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/messager/6388543/T6388543.out Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,15 @@
+T6388543.java:24:8: compiler.note.proc.messager: note:value @A({1}) + {1}
+T6388543.java:24:8: compiler.note.proc.messager: note:value @A({1}) + 1
+T6388543.java:27:16: compiler.note.proc.messager: note:value @A({2}) + {2}
+T6388543.java:27:16: compiler.note.proc.messager: note:value @A({2}) + 2
+T6388543.java:30:16: compiler.note.proc.messager: note:value @A({3}) + {3}
+T6388543.java:30:17: compiler.note.proc.messager: note:value @A({3}) + 3
+T6388543.java:33:16: compiler.note.proc.messager: note:value @A({4, 5}) + {4, 5}
+T6388543.java:33:17: compiler.note.proc.messager: note:value @A({4, 5}) + 4
+T6388543.java:33:20: compiler.note.proc.messager: note:value @A({4, 5}) + 5
+T6388543.java:36:12: compiler.note.proc.messager: note:value @B(x=@C(x=E.ONE, y=E.TWO), y=@C(x=E.ONE, y=E.TWO)) + @C(x=E.ONE, y=E.TWO)
+T6388543.java:36:20: compiler.note.proc.messager: note:value @B(x=@C(x=E.ONE, y=E.TWO), y=@C(x=E.ONE, y=E.TWO)) + E.ONE
+T6388543.java:36:31: compiler.note.proc.messager: note:value @B(x=@C(x=E.ONE, y=E.TWO), y=@C(x=E.ONE, y=E.TWO)) + E.TWO
+T6388543.java:36:42: compiler.note.proc.messager: note:value @B(x=@C(x=E.ONE, y=E.TWO), y=@C(x=E.ONE, y=E.TWO)) + @C(x=E.ONE, y=E.TWO)
+T6388543.java:36:50: compiler.note.proc.messager: note:value @B(x=@C(x=E.ONE, y=E.TWO), y=@C(x=E.ONE, y=E.TWO)) + E.ONE
+T6388543.java:36:61: compiler.note.proc.messager: note:value @B(x=@C(x=E.ONE, y=E.TWO), y=@C(x=E.ONE, y=E.TWO)) + E.TWO
--- a/langtools/test/tools/javac/processing/model/element/TestPackageElement.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/tools/javac/processing/model/element/TestPackageElement.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2017, 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,16 +23,18 @@
/*
* @test
- * @bug 6449798 6399404
+ * @bug 6449798 6399404 8173776
* @summary Test basic workings of PackageElement
* @author Joseph D. Darcy
* @library /tools/javac/lib
* @modules java.compiler
* jdk.compiler
* @build JavacTestingAbstractProcessor TestPackageElement
- * @compile -processor TestPackageElement -proc:only TestPackageElement.java
+ * @compile -processor TestPackageElement -proc:only TestPackageElement.java
+ * @compile -processor TestPackageElement -proc:only --release 8 TestPackageElement.java
*/
+import java.util.Objects;
import java.util.Set;
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
@@ -67,7 +69,22 @@
PackageElement javaLang = eltUtils.getPackageElement("java.lang");
if (javaLang.isUnnamed())
throw new RuntimeException("Package java.lang is unnamed!");
+
+ testEnclosingElement(javaLang);
}
return true;
}
+
+ void testEnclosingElement(PackageElement javaLang) {
+ SourceVersion version = processingEnv.getSourceVersion();
+ Element enclosing = javaLang.getEnclosingElement();
+ Element expectedEnclosing =
+ (version.compareTo(RELEASE_9) < 0) ? // No modules
+ null :
+ eltUtils.getModuleElement("java.base");
+
+ if (!Objects.equals(enclosing, expectedEnclosing))
+ throw new RuntimeException("Unexpected enclosing element under source version " +
+ version);
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/model/util/printing/module-info.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,18 @@
+/*
+ * @test
+ * @bug 8173609
+ * @summary printing of modules
+ * @compile/ref=module-info.out -Xprint p/P.java module-info.java
+ */
+
+/**
+ * Printing of modules
+ */
+@Deprecated
+module printing {
+ requires static transitive java.base;
+ exports p to m.m1, m.m2;
+ opens p to m.m1, m.m2;
+ uses p.P;
+ provides p.P with p.P.P1, p.P.P2;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/model/util/printing/module-info.out Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,27 @@
+package p;
+
+public class P {
+
+ public static class P1 extends p.P {
+
+ public P1();
+ }
+
+ public static class P2 extends p.P {
+
+ public P2();
+ }
+
+ public P();
+}
+/**
+ * Printing of modules
+ */
+@java.lang.Deprecated
+module printing {
+ requires static transitive java.base;
+ exports p to m.m1, m.m2;
+ opens p to m.m1, m.m2;
+ uses p.P;
+ provides p.P with p.P.P1, p.P.P2;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/model/util/printing/p/P.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,6 @@
+package p;
+
+public class P {
+ public static class P1 extends P {}
+ public static class P2 extends P {}
+}
--- a/langtools/test/tools/javac/tree/JavacTreeScannerTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/tools/javac/tree/JavacTreeScannerTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -41,7 +41,7 @@
* jdk.compiler/com.sun.tools.javac.tree
* jdk.compiler/com.sun.tools.javac.util
* @build AbstractTreeScannerTest JavacTreeScannerTest
- * @run main/othervm JavacTreeScannerTest -q -r .
+ * @run main JavacTreeScannerTest -q -r .
*/
import java.io.*;
--- a/langtools/test/tools/javac/tree/SourceTreeScannerTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/tools/javac/tree/SourceTreeScannerTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -41,7 +41,7 @@
* jdk.compiler/com.sun.tools.javac.tree
* jdk.compiler/com.sun.tools.javac.util
* @build AbstractTreeScannerTest SourceTreeScannerTest
- * @run main/othervm SourceTreeScannerTest -q -r .
+ * @run main SourceTreeScannerTest -q -r .
*/
import java.io.*;
--- a/langtools/test/tools/javac/tree/TreePosTest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/tools/javac/tree/TreePosTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -108,7 +108,7 @@
* jdk.compiler/com.sun.tools.javac.file
* jdk.compiler/com.sun.tools.javac.tree
* jdk.compiler/com.sun.tools.javac.util
- * @run main/othervm TreePosTest -q -r .
+ * @run main TreePosTest -q -r .
*/
public class TreePosTest {
/**
--- a/langtools/test/tools/javac/varargs/7043922/T7043922.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/tools/javac/varargs/7043922/T7043922.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2017, 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
@@ -28,7 +28,6 @@
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.file
* jdk.compiler/com.sun.tools.javac.util
- * @run main/othervm T7043922
*/
import com.sun.source.util.JavacTask;
--- a/langtools/test/tools/javadoc/api/basic/APITest.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/tools/javadoc/api/basic/APITest.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -224,9 +224,11 @@
"jquery/images/ui-icons_222222_256x240.png",
"jquery/images/ui-bg_glass_75_e6e6e6_1x400.png",
"jquery/images/ui-bg_flat_75_ffffff_40x100.png",
+ "member-search-index.js",
"member-search-index.zip",
"overview-tree.html",
"package-list",
+ "package-search-index.js",
"package-search-index.zip",
"pkg/C.html",
"pkg/package-frame.html",
@@ -237,12 +239,13 @@
"script.js",
"search.js",
"stylesheet.css",
+ "type-search-index.js",
"type-search-index.zip"
));
protected static Set<String> noIndexFiles = standardExpectFiles.stream()
.filter(s -> !s.startsWith("jquery") && !s.startsWith("resources") && !s.endsWith("zip")
- && !s.equals("index-all.html") && !s.equals("search.js"))
+ && !s.equals("index-all.html") && !s.equals("search.js") && !s.endsWith("-search-index.js"))
.collect(Collectors.toSet());
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javap/typeAnnotations/AnnotationDefaultNewlineTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013, 2017, 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 8041793
+ * @summary Verify that javap prints newline character after AnnotationDefault value
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.jdeps/com.sun.tools.javap
+ * @build toolbox.ToolBox toolbox.JavacTask toolbox.JavapTask toolbox.Assert
+ * @run main AnnotationDefaultNewlineTest
+ */
+
+import java.util.Collections;
+import java.util.List;
+
+import toolbox.Assert;
+import toolbox.JavacTask;
+import toolbox.JavapTask;
+import toolbox.Task;
+import toolbox.ToolBox;
+
+public class AnnotationDefaultNewlineTest {
+
+ private static final String TestSrc =
+ "public @interface AnnotationDefault { \n" +
+ "public abstract int value() default 1; \n" +
+ "}";
+
+ private static final String ExpectedSubstring =
+ " AnnotationDefault:\n" +
+ " default_value: I#7\n";
+
+ public static void main(String[] args) throws Exception {
+ ToolBox tb = new ToolBox();
+ new JavacTask(tb).sources(TestSrc).run();
+
+ List<String> res = new JavapTask(tb)
+ .options("-v")
+ .classes("AnnotationDefault.class")
+ .run()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ List<String> goldenList = tb.split(ExpectedSubstring, "\n");
+ Boolean found = Collections.indexOfSubList(res, goldenList) > -1;
+
+ Assert.check(found, "expected output not found: " + ExpectedSubstring);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javap/typeAnnotations/InvisibleParameterAnnotationsTest.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @bug 8051768
+ * @summary Verify that javap prints "param" for RuntimeInvisibleParameterAnnotations
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.jdeps/com.sun.tools.javap
+ * @build toolbox.ToolBox toolbox.JavacTask toolbox.JavapTask toolbox.Assert
+ * @run main InvisibleParameterAnnotationsTest
+ */
+
+import toolbox.Assert;
+import toolbox.JavacTask;
+import toolbox.JavapTask;
+import toolbox.Task;
+import toolbox.ToolBox;
+
+import java.util.Collections;
+import java.util.List;
+
+public class InvisibleParameterAnnotationsTest {
+
+ private static final String TestSrc =
+ "import java.lang.annotation.Retention \n;" +
+ "import java.lang.annotation.RetentionPolicy \n;" +
+
+ "public class Sample { \n" +
+
+ "@Retention(RetentionPolicy.CLASS) \n" +
+ "public @interface InvisAnno{} \n" +
+ "@Retention(RetentionPolicy.RUNTIME) \n" +
+ "public @interface VisAnno{} \n" +
+
+ "public void Method(@InvisAnno int arg1,@VisAnno int arg2){};" +
+ "}";
+
+ private static final String ExpectedSubstring =
+ " RuntimeVisibleParameterAnnotations:\n" +
+ " parameter 0:\n" +
+ " parameter 1:\n" +
+ " 0: #16()\n" +
+ " RuntimeInvisibleParameterAnnotations:\n" +
+ " parameter 0:\n" +
+ " 0: #18()\n" +
+ " parameter 1:";
+
+ public static void main(String[] args) throws Exception {
+ ToolBox tb = new ToolBox();
+ new JavacTask(tb).sources(TestSrc).run();
+
+ List<String> res = new JavapTask(tb)
+ .options("-v")
+ .classes("Sample.class")
+ .run()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ List<String> expectedList = tb.split(ExpectedSubstring, "\n");
+ Boolean found = Collections.indexOfSubList(res, expectedList) > -1;
+ Assert.check(found, "expected output not found: " + ExpectedSubstring);
+ }
+}
--- a/langtools/test/tools/jdeps/modules/SplitPackage.java Thu Feb 02 05:26:20 2017 -0800
+++ b/langtools/test/tools/jdeps/modules/SplitPackage.java Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -51,7 +51,7 @@
private static final Path CLASSES_DIR = Paths.get("classes");
private static final String SPLIT_PKG_NAME = "javax.annotation";
- private static final String JAVA_ANNOTATIONS_COMMON = "java.annotations.common";
+ private static final String JAVA_XML_WS_ANNOTATION = "java.xml.ws.annotation";
/**
* Compiles classes used by the test
*/
@@ -64,7 +64,7 @@
@Test
public void runTest() throws Exception {
// split package detected if java.annotation.common is in the root set
- runTest(JAVA_ANNOTATIONS_COMMON, SPLIT_PKG_NAME);
+ runTest(JAVA_XML_WS_ANNOTATION, SPLIT_PKG_NAME);
runTest("ALL-SYSTEM", SPLIT_PKG_NAME);
// default
runTest(null, SPLIT_PKG_NAME);
@@ -98,7 +98,7 @@
throw new RuntimeException(splitPackages.toString());
}
- // java.annotations.common is not observable
+ // java.xml.ws.annotation is not observable
DepsAnalyzer analyzer = jdeps.getDepsAnalyzer();
assertTrue(analyzer.run());
--- a/make/CompileJavaModules.gmk Thu Feb 02 05:26:20 2017 -0800
+++ b/make/CompileJavaModules.gmk Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 2017, 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
@@ -247,6 +247,10 @@
################################################################################
+java.management.rmi_ADD_JAVAC_FLAGS := -Xdoclint:all/protected,-reference '-Xdoclint/package:javax.*'
+
+################################################################################
+
java.prefs_ADD_JAVAC_FLAGS := -Xdoclint:all/protected '-Xdoclint/package:java.*,javax.*'
################################################################################
@@ -450,7 +454,7 @@
################################################################################
-jdk.jvmstat_COPY := aliasmap
+jdk.internal.jvmstat_COPY := aliasmap
################################################################################
--- a/make/Images.gmk Thu Feb 02 05:26:20 2017 -0800
+++ b/make/Images.gmk Thu Feb 09 23:15:52 2017 +0100
@@ -72,6 +72,7 @@
java.compiler \
java.instrument \
java.management \
+ java.management.rmi \
java.naming \
java.prefs \
java.security.jgss \
--- a/make/Javadoc.gmk Thu Feb 02 05:26:20 2017 -0800
+++ b/make/Javadoc.gmk Thu Feb 09 23:15:52 2017 +0100
@@ -26,6 +26,7 @@
include $(SPEC)
include MakeBase.gmk
+include $(JDK_TOPDIR)/make/Tools.gmk
################################################################################
@@ -180,6 +181,8 @@
-tag see \
-tag 'jvms:a:See <cite>The Java™ Virtual Machine Specification</cite>:' \
-tag 'jls:a:See <cite>The Java™ Language Specification</cite>:' \
+ -taglet build.tools.taglet.Incubating \
+ -tagletpath $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
#
DEFAULT_JAVADOC_OPTIONS := -XDignore.symbol.file=true -use -keywords -notimestamp \
@@ -311,7 +314,7 @@
$1_INDEX_FILE := $$(JAVADOC_OUTPUTDIR)/$$($1_OUTPUT_DIRNAME)/index.html
# Rule for actually running javadoc
- $$($1_INDEX_FILE): $$($1_VARDEPS_FILE) $$($1_PACKAGE_DEPS) $$($1_DEPS)
+ $$($1_INDEX_FILE): $(BUILD_TOOLS_JDK) $$($1_VARDEPS_FILE) $$($1_PACKAGE_DEPS) $$($1_DEPS)
$$(call LogWarn, Generating Javadoc from $$(words $$($1_PACKAGES)) package(s) for $$($1_OUTPUT_DIRNAME))
$$(call MakeDir, $$(@D))
ifneq ($$($1_PACKAGES_FILE), )
@@ -740,7 +743,7 @@
################################################################################
-docs-javadoc: $(TARGETS)
+docs-javadoc: $(BUILD_TOOLS_JDK) $(TARGETS)
docs-copy: $(COPY_TARGETS)
--- a/make/common/Modules.gmk Thu Feb 02 05:26:20 2017 -0800
+++ b/make/common/Modules.gmk Thu Feb 09 23:15:52 2017 +0100
@@ -51,6 +51,7 @@
java.instrument \
java.logging \
java.management \
+ java.management.rmi \
java.naming \
java.prefs \
java.rmi \
@@ -58,6 +59,7 @@
java.xml \
jdk.httpserver \
jdk.management \
+ jdk.management.agent \
jdk.net \
jdk.sctp \
jdk.unsupported \
@@ -71,11 +73,11 @@
UPGRADEABLE_MODULES += \
java.activation \
- java.annotations.common \
java.corba \
java.transaction \
java.xml.bind \
java.xml.ws \
+ java.xml.ws.annotation \
#
# Modules explicitly declared as not being upgradeable even though they require
@@ -182,15 +184,12 @@
# Find all module-info.java files for the current build target platform and
# configuration.
-# TODO: The $(firstword call is part of a workaround for using different
-# imported module-info.java in Jake due to a change in format. Remove once
-# new format is standard in JDK 9 and javafx delivers just that.
# Param 1 - Module to find for, set to * for finding all
FindAllModuleInfos = \
$(wildcard \
$(foreach sub, $(SRC_SUBDIRS), \
$(patsubst %,%/$(strip $1)/$(sub)/module-info.java, $(TOP_SRC_DIRS))) \
- $(patsubst %,%/$(strip $1)/module-info.java, $(firstword $(IMPORT_MODULES_SRC))))
+ $(patsubst %,%/$(strip $1)/module-info.java, $(IMPORT_MODULES_SRC)))
# Find module-info.java files in the specific source dir
# Param 1 - Src dir to find module-info.java files in
--- a/make/common/NativeCompilation.gmk Thu Feb 02 05:26:20 2017 -0800
+++ b/make/common/NativeCompilation.gmk Thu Feb 09 23:15:52 2017 +0100
@@ -685,7 +685,7 @@
$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).comp.vardeps)
ifneq ($$($1_PRECOMPILED_HEADER), )
- ifeq ($(USE_PRECOMPILED_HEADER), 1)
+ ifeq ($(USE_PRECOMPILED_HEADER), true)
ifeq ($(TOOLCHAIN_TYPE), microsoft)
$1_PCH_FILE := $$($1_OBJECT_DIR)/$1.pch
$1_GENERATED_PCH_SRC := $$($1_OBJECT_DIR)/$1_pch.cpp
--- a/nashorn/.hgtags Thu Feb 02 05:26:20 2017 -0800
+++ b/nashorn/.hgtags Thu Feb 09 23:15:52 2017 +0100
@@ -387,3 +387,5 @@
2a0437036a64853334e538044eb68d2df70075fa jdk-9+151
ddc52e72757086a75a54371e8e7f56a3f89f1e55 jdk-9+152
19aaaf2d02b7d6986538cd9a8c46901ecb50eebf jdk-9+153
+a84b49cfee63716975535abae2865ffef4dd6474 jdk-9+154
+f9bb37a817b3cd3b758a60f3c68258a6554eb382 jdk-9+155
--- a/nashorn/README Thu Feb 02 05:26:20 2017 -0800
+++ b/nashorn/README Thu Feb 09 23:15:52 2017 +0100
@@ -18,7 +18,7 @@
http://mercurial.selenic.com/wiki/ForestExtension
-and downlaoded using
+and downloaded using
hg clone https://bitbucket.org/gxti/hgforest
@@ -39,7 +39,7 @@
- How to build?
To build Nashorn, you need to install JDK 9. You may use the Nashorn
-forest build (recommended) or down load from java.net. You will need to
+forest build (recommended) or download from java.net. You will need to
set JAVA_HOME environmental variable to point to your JDK installation
directory.
--- a/nashorn/make/BuildNashorn.gmk Thu Feb 02 05:26:20 2017 -0800
+++ b/nashorn/make/BuildNashorn.gmk Thu Feb 09 23:15:52 2017 +0100
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2017, 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
@@ -36,12 +36,10 @@
JDK_CLASSES := $(call PathList, $(strip $(addprefix $(JDK_OUTPUTDIR)/modules/, \
java.base java.logging java.scripting jdk.dynalink)))
-NASHORN_JAR := $(IMAGES_OUTPUTDIR)/nashorn.jar
-
MODULESOURCEPATH := $(NASHORN_TOPDIR)/src/*/share/classes
# Need to use source and target 8 for nasgen to work.
-$(eval $(call SetupJavaCompiler,GENERATE_NEWBYTECODE_DEBUG, \
+$(eval $(call SetupJavaCompiler, GENERATE_NEWBYTECODE_DEBUG, \
JVM := $(JAVA_JAVAC), \
JAVAC := $(NEW_JAVAC), \
FLAGS := -g -source 9 -target 9 --upgrade-module-path "$(JDK_OUTPUTDIR)/modules/" \
@@ -53,11 +51,10 @@
# Name the compilation setup the same as the module, as is done in the global
# CompileJavaModules.gmk, to make dependency checking with other modules work
# seamlessly.
-$(eval $(call SetupJavaCompilation,jdk.scripting.nashorn, \
+$(eval $(call SetupJavaCompilation, jdk.scripting.nashorn, \
SETUP := GENERATE_NEWBYTECODE_DEBUG, \
MODULE := jdk.scripting.nashorn, \
SRC := $(NASHORN_TOPDIR)/src/jdk.scripting.nashorn/share/classes, \
- EXCLUDE_FILES := META-INF/MANIFEST.MF, \
COPY := .properties .js, \
BIN := $(SUPPORT_OUTPUTDIR)/special_classes))
@@ -65,7 +62,7 @@
ASM_SRC := $(JDK_TOPDIR)/src/java.base/share/classes/jdk/internal/org/objectweb/asm
# Build nasgen
-$(eval $(call SetupJavaCompilation,BUILD_NASGEN, \
+$(eval $(call SetupJavaCompilation, BUILD_NASGEN, \
SETUP := GENERATE_OLDBYTECODE, \
SRC := $(NASGEN_SRC) $(ASM_SRC), \
BIN := $(BUILDTOOLS_OUTPUTDIR)/nasgen_classes))
@@ -107,21 +104,7 @@
# Version processing needs to happen after nasgen run since nasgen run deletes it
$(BUILD_VERSION_FILE): $(NASGEN_RUN_FILE)
-
-MANIFEST_ATTRIBUTES := Name: jdk/nashorn/\nImplementation-Title: Oracle Nashorn\nImplementation-Version: $(VERSION_SHORT)
-
-# Create nashorn.jar from the final classes dir
-$(eval $(call SetupJarArchive,BUILD_NASHORN_JAR, \
- DEPENDENCIES := $(NASGEN_RUN_FILE) $(BUILD_VERSION_FILE), \
- SRCS := $(NASHORN_CLASSES_DIR), \
- SUFFIXES := .class .js .properties Factory, \
- MANIFEST := $(NASHORN_TOPDIR)/src/jdk.scripting.nashorn/share/classes/META-INF/MANIFEST.MF, \
- EXTRA_MANIFEST_ATTR := $(MANIFEST_ATTRIBUTES), \
- SKIP_METAINF := true, \
- JAR := $(NASHORN_JAR), \
-))
-
-compile: $(NASHORN_RUN_FILE) $(BUILD_VERSION_FILE)
-all: $(NASHORN_JAR)
+compile: $(NASGEN_RUN_FILE) $(BUILD_VERSION_FILE)
+all: compile
.PHONY: compile all
--- a/nashorn/make/build.xml Thu Feb 02 05:26:20 2017 -0800
+++ b/nashorn/make/build.xml Thu Feb 09 23:15:52 2017 +0100
@@ -394,6 +394,18 @@
</target>
+ <target name="generate-security-config" depends="generate-policy-file, generate-security-properties-file"/>
+
+ <target name="generate-security-properties-file" depends="prepare">
+ <echo file="${build.dir}/nashorn.security.properties">
+
+package.access=sun.misc.,\
+ sun.reflect.,\
+ jdk.nashorn.internal.
+
+ </echo>
+ </target>
+
<target name="generate-policy-file" depends="prepare">
<echo file="${build.dir}/nashorn.policy">
@@ -600,7 +612,7 @@
<target name="test" depends="prepare, javadoc, test-pessimistic, test-optimistic"/>
- <target name="test-optimistic" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
+ <target name="test-optimistic" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-security-config" if="testng.available">
<echo message="Running test suite in OPTIMISTIC mode..."/>
<antcall target="-test-nosecurity" inheritRefs="true">
<param name="optimistic" value="true"/>
@@ -612,7 +624,7 @@
</antcall>
</target>
- <target name="test-pessimistic" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
+ <target name="test-pessimistic" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-security-config" if="testng.available">
<echo message="Running test suite in PESSIMISTIC mode..."/>
<antcall target="-test-nosecurity" inheritRefs="true">
<param name="optimistic" value="false"/>
@@ -655,7 +667,7 @@
</testng>
</target>
- <target name="testmarkdown" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
+ <target name="testmarkdown" depends="jar, check-testng, check-external-tests, compile-test, generate-security-config" if="testng.available">
<fileset id="test.classes" dir="${build.test.classes.dir}">
<include name="**/framework/*Test.class"/>
</fileset>
@@ -673,7 +685,7 @@
</testng>
</target>
- <target name="test262" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
+ <target name="test262" depends="jar, check-testng, check-external-tests, compile-test, generate-security-config" if="testng.available">
<fileset id="test.classes" dir="${build.test.classes.dir}">
<include name="**/framework/*Test.class"/>
</fileset>
@@ -696,7 +708,7 @@
<target name="test262parallel" depends="test262-parallel"/>
- <target name="test262-parallel" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
+ <target name="test262-parallel" depends="jar, check-testng, check-external-tests, compile-test, generate-security-config" if="testng.available">
<!-- use just build.test.classes.dir to avoid referring to TestNG -->
<java classname="${parallel.test.runner}" dir="${basedir}" fork="true" failonerror="true">
<jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -Dbuild.dir=${build.dir}"/>
@@ -714,7 +726,7 @@
<target name="testparallel" depends="test-parallel"/>
- <target name="test-parallel" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
+ <target name="test-parallel" depends="jar, check-testng, check-external-tests, compile-test, generate-security-config" if="testng.available">
<!-- use just build.test.classes.dir to avoid referring to TestNG -->
<java classname="${parallel.test.runner}" dir="${basedir}"
failonerror="true"
--- a/nashorn/make/project.properties Thu Feb 02 05:26:20 2017 -0800
+++ b/nashorn/make/project.properties Thu Feb 09 23:15:52 2017 +0100
@@ -408,7 +408,7 @@
run.test.jvmargs.octane.main=${run.test.jvmargs.common} -XX:TypeProfileLevel=222
# Security manager args - make sure that we run with the nashorn.policy that the build creates
-run.test.jvmsecurityargs=-Xverify:all -Djava.security.manager -Djava.security.policy=${build.dir}/nashorn.policy
+run.test.jvmsecurityargs=-Xverify:all -Djava.security.manager -Djava.security.policy=${build.dir}/nashorn.policy -Djava.security.properties=${build.dir}/nashorn.security.properties
# VM options for script tests with @fork option
test-sys-prop.test.fork.jvm.options=${run.test.jvmargs.main} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -cp ${run.test.classpath}
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocation.java Thu Feb 02 05:26:20 2017 -0800
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocation.java Thu Feb 09 23:15:52 2017 +0100
@@ -395,39 +395,45 @@
}
/**
- * Applies argument filters to both the invocation and the guard (if there
- * is one) with {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)}.
+ * Applies argument filters to both the invocation and the guard
+ * (if it exists and has at least {@code pos + 1} parameters) with
+ * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)}.
* @param pos the position of the first argument being filtered
* @param filters the argument filters
* @return a filtered invocation
*/
public GuardedInvocation filterArguments(final int pos, final MethodHandle... filters) {
- return replaceMethods(MethodHandles.filterArguments(invocation, pos, filters), guard == null ? null :
- MethodHandles.filterArguments(guard, pos, filters));
+ return replaceMethods(MethodHandles.filterArguments(invocation, pos, filters),
+ guard == null || pos >= guard.type().parameterCount() ?
+ guard : MethodHandles.filterArguments(guard, pos, filters));
}
/**
* Makes an invocation that drops arguments in both the invocation and the
- * guard (if there is one) with {@link MethodHandles#dropArguments(MethodHandle, int, List)}.
+ * guard (if it exists and has at least {@code pos} parameters) with
+ * {@link MethodHandles#dropArguments(MethodHandle, int, List)}.
* @param pos the position of the first argument being dropped
* @param valueTypes the types of the values being dropped
* @return an invocation that drops arguments
*/
public GuardedInvocation dropArguments(final int pos, final List<Class<?>> valueTypes) {
- return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes), guard == null ? null :
- MethodHandles.dropArguments(guard, pos, valueTypes));
+ return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes),
+ guard == null || pos > guard.type().parameterCount() ?
+ guard : MethodHandles.dropArguments(guard, pos, valueTypes));
}
/**
* Makes an invocation that drops arguments in both the invocation and the
- * guard (if there is one) with {@link MethodHandles#dropArguments(MethodHandle, int, Class...)}.
+ * guard (if it exists and has at least {@code pos} parameters) with
+ * {@link MethodHandles#dropArguments(MethodHandle, int, Class...)}.
* @param pos the position of the first argument being dropped
* @param valueTypes the types of the values being dropped
* @return an invocation that drops arguments
*/
public GuardedInvocation dropArguments(final int pos, final Class<?>... valueTypes) {
- return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes), guard == null ? null :
- MethodHandles.dropArguments(guard, pos, valueTypes));
+ return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes),
+ guard == null || pos > guard.type().parameterCount() ?
+ guard : MethodHandles.dropArguments(guard, pos, valueTypes));
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/linker/NashornLinkerExporter.java Thu Feb 02 05:26:20 2017 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/linker/NashornLinkerExporter.java Thu Feb 09 23:15:52 2017 +0100
@@ -38,7 +38,7 @@
/**
* This linker exporter is a service provider that exports Nashorn Dynalink
- * linkers to external users. Other languague runtimes that use Dynalink
+ * linkers to external users. Other language runtimes that use Dynalink
* can use the linkers exported by this provider to support tight integration
* of Nashorn objects.
*/
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/WeighNodes.java Thu Feb 02 05:26:20 2017 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/WeighNodes.java Thu Feb 09 23:15:52 2017 +0100
@@ -77,6 +77,7 @@
static final long CALL_WEIGHT = 10;
static final long CATCH_WEIGHT = 10;
static final long COMPARE_WEIGHT = 6;
+ static final long CONST_WEIGHT = 2;
static final long CONTINUE_WEIGHT = 1;
static final long IF_WEIGHT = 2;
static final long LITERAL_WEIGHT = 10;
@@ -185,7 +186,7 @@
@Override
public Node leaveIdentNode(final IdentNode identNode) {
- weight += ACCESS_WEIGHT + identNode.getName().length() * 2;
+ weight += ACCESS_WEIGHT;
return identNode;
}
@@ -210,6 +211,11 @@
@SuppressWarnings("rawtypes")
@Override
public boolean enterLiteralNode(final LiteralNode literalNode) {
+ if (literalNode instanceof LiteralNode.PrimitiveLiteralNode) {
+ weight += CONST_WEIGHT;
+ return false;
+ }
+
weight += LITERAL_WEIGHT;
if (literalNode instanceof ArrayLiteralNode) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java Thu Feb 02 05:26:20 2017 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java Thu Feb 09 23:15:52 2017 +0100
@@ -735,7 +735,7 @@
/**
* Name getter - ECMA Function.name
*
- * @param self self refence
+ * @param self self reference
* @return the name, or undefined if none
*/
public static Object G$name(final Object self) {
@@ -1120,12 +1120,19 @@
assert appliedRequest != null; // Bootstrap.isCallable() returned true for args[1], so it must produce a linkage.
final Class<?> applyFnType = descType.parameterType(0);
- MethodHandle inv = appliedInvocation.getInvocation(); //method handle from apply invocation. the applied function invocation
+ // Invocation and guard handles from apply invocation.
+ MethodHandle inv = appliedInvocation.getInvocation();
+ MethodHandle guard = appliedInvocation.getGuard();
if (isApply && !isFailedApplyToCall) {
if (passesArgs) {
// Make sure that the passed argArray is converted to Object[] the same way NativeFunction.apply() would do it.
inv = MH.filterArguments(inv, 2, NativeFunction.TO_APPLY_ARGS);
+ // Some guards (non-strict functions with non-primitive this) have a this-object parameter, so we
+ // need to apply this transformations to them as well.
+ if (guard.type().parameterCount() > 2) {
+ guard = MH.filterArguments(guard, 2, NativeFunction.TO_APPLY_ARGS);
+ }
} else {
// If the original call site doesn't pass argArray, pass in an empty array
inv = MH.insertArguments(inv, 2, (Object) ScriptRuntime.EMPTY_ARRAY);
@@ -1144,12 +1151,25 @@
if (!passesThis) {
// If the original call site doesn't pass in a thisArg, pass in Global/undefined as needed
- inv = bindImplicitThis(appliedFn, inv);
+ inv = bindImplicitThis(appliedFnNeedsWrappedThis, inv);
+ // guard may have this-parameter that needs to be inserted
+ if (guard.type().parameterCount() > 1) {
+ guard = bindImplicitThis(appliedFnNeedsWrappedThis, guard);
+ }
} else if (appliedFnNeedsWrappedThis) {
// target function needs a wrapped this, so make sure we filter for that
inv = MH.filterArguments(inv, 1, WRAP_THIS);
+ // guard may have this-parameter that needs to be wrapped
+ if (guard.type().parameterCount() > 1) {
+ guard = MH.filterArguments(guard, 1, WRAP_THIS);
+ }
}
+
+ final MethodType guardType = guard.type(); // Needed for combining guards below
+
+ // We need to account for the dropped (apply|call) function argument.
inv = MH.dropArguments(inv, 0, applyFnType);
+ guard = MH.dropArguments(guard, 0, applyFnType);
/*
* Dropargs can only be non-()V in the case of isApply && !isFailedApplyToCall, which
@@ -1160,15 +1180,6 @@
inv = MH.dropArguments(inv, 4 + i, dropArgs.parameterType(i));
}
- MethodHandle guard = appliedInvocation.getGuard();
- // If the guard checks the value of "this" but we aren't passing thisArg, insert the default one
- if (!passesThis && guard.type().parameterCount() > 1) {
- guard = bindImplicitThis(appliedFn, guard);
- }
- final MethodType guardType = guard.type();
-
- // We need to account for the dropped (apply|call) function argument.
- guard = MH.dropArguments(guard, 0, descType.parameterType(0));
// Take the "isApplyFunction" guard, and bind it to this function.
MethodHandle applyFnGuard = MH.insertArguments(IS_APPLY_FUNCTION, 2, this); //TODO replace this with switchpoint
// Adapt the guard to receive all the arguments that the original guard does.
@@ -1244,9 +1255,9 @@
return ScriptObject.adaptHandleToVarArgCallSite(arrayConvertingGuard, descParamCount);
}
- private static MethodHandle bindImplicitThis(final Object fn, final MethodHandle mh) {
+ private static MethodHandle bindImplicitThis(final boolean needsWrappedThis, final MethodHandle mh) {
final MethodHandle bound;
- if (fn instanceof ScriptFunction && ((ScriptFunction) fn).needsWrappedThis()) {
+ if (needsWrappedThis) {
bound = MH.filterArguments(mh, 1, SCRIPTFUNCTION_GLOBALFILTER);
} else {
bound = mh;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java Thu Feb 02 05:26:20 2017 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java Thu Feb 09 23:15:52 2017 +0100
@@ -45,6 +45,7 @@
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
+import jdk.dynalink.beans.BeansLinker;
import jdk.dynalink.beans.StaticClass;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
@@ -56,6 +57,7 @@
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.objects.NativeObject;
import jdk.nashorn.internal.parser.Lexer;
+import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
import jdk.nashorn.internal.runtime.linker.InvokeByName;
@@ -1039,7 +1041,30 @@
return ((JSObject)obj).hasMember(Objects.toString(property));
}
- return false;
+ final Object key = JSType.toPropertyKey(property);
+
+ if (obj instanceof StaticClass) {
+ final Class<?> clazz = ((StaticClass) obj).getRepresentedClass();
+ return BeansLinker.getReadableStaticPropertyNames(clazz).contains(Objects.toString(key))
+ || BeansLinker.getStaticMethodNames(clazz).contains(Objects.toString(key));
+ } else {
+ if (obj instanceof Map && ((Map) obj).containsKey(key)) {
+ return true;
+ }
+
+ final int index = ArrayIndex.getArrayIndex(key);
+ if (index >= 0) {
+ if (obj instanceof List && index < ((List) obj).size()) {
+ return true;
+ }
+ if (obj.getClass().isArray() && index < Array.getLength(obj)) {
+ return true;
+ }
+ }
+
+ return BeansLinker.getReadableInstancePropertyNames(obj.getClass()).contains(Objects.toString(key))
+ || BeansLinker.getInstanceMethodNames(obj.getClass()).contains(Objects.toString(key));
+ }
}
throw typeError("in.with.non.object", rvalType.toString().toLowerCase(Locale.ENGLISH));
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Thu Feb 02 05:26:20 2017 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Thu Feb 09 23:15:52 2017 +0100
@@ -147,9 +147,8 @@
new NashornBeansLinkerServices(linkerServices));
// Bind to the method, drop the original "this" and use original "callee" as this:
- final MethodHandle inv = linkerServices.filterInternalObjects(gi
- .getInvocation() // (method, this, args...)
- .bindTo(method)); // (this, args...)
+ final MethodHandle inv = gi.getInvocation() // (method, this, args...)
+ .bindTo(method); // (this, args...)
final MethodHandle calleeToThis = MH.dropArguments(inv, 1, callType.parameterType(1)); // (callee->this, <drop>, args...)
return gi.replaceMethods(calleeToThis, gi.getGuard());
}
--- a/nashorn/test/script/basic/JDK-8030182_2.js Thu Feb 02 05:26:20 2017 -0800
+++ b/nashorn/test/script/basic/JDK-8030182_2.js Thu Feb 09 23:15:52 2017 +0100
@@ -31,7 +31,7 @@
var str = "";
// large code to force splitting
-for (i = 0; i < 1000; ++i)
+for (i = 0; i < 2000; ++i)
str +="o = new Object()\n";
str +="g()";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8166186.js Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/**
+ * 8166186: ClassCastException with arguments usage
+ *
+ * @test
+ * @run
+ */
+
+function F (arg) {
+ print("F called");
+ Function.prototype.call.apply(G, arguments);
+}
+
+function G (){
+ print("G called");
+ print(this);
+ if (C++ > 5) return;
+ F("argument " + C);
+}
+
+var C = 0;
+
+G();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8166186.js.EXPECTED Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,20 @@
+G called
+[object global]
+F called
+G called
+argument 1
+F called
+G called
+argument 2
+F called
+G called
+argument 3
+F called
+G called
+argument 4
+F called
+G called
+argument 5
+F called
+G called
+argument 6
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8172006.js Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/**
+ * JDK-8172006: Nashorn JavaScript engine fails to call @FunctionalInterface with a java.util.List argument
+ *
+ * @test
+ * @run
+ */
+
+var f = Java.type("jdk.nashorn.test.models.FunctionalInterfaceProvider").getImpl();
+
+var s = "a";
+s += "b";
+var o = { p: 10 };
+var a = [1, 2, 3];
+
+f([ f([]), f([]), f([]), f([]), f([]), f([]), f([]), f([]) ]);
+f([ f([]), f([ f([]), f([f([]), f([]), f([]) ]), f([])]), f([]) ]);
+f([ f([s]), f([o]), f([a]), f([s + "c"]), f([o]), f([a]) ]);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8173480.js Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/**
+ * JDK-8173480: in operator should work on java objects and classes
+ *
+ * @test
+ * @run
+ */
+
+var hash = "hash"; // for testing ConsString keys
+
+var obj = new java.lang.Object();
+Assert.assertTrue("hashCode" in obj);
+Assert.assertTrue(hash + "Code" in obj);
+Assert.assertTrue("class" in obj);
+Assert.assertFalse("x" in obj);
+Assert.assertFalse(1 in obj);
+Assert.assertFalse("1" in obj);
+
+var map = new java.util.HashMap();
+map["k"] = true;
+Assert.assertTrue(map["k"]);
+Assert.assertTrue("k" in map);
+Assert.assertTrue("hashCode" in map);
+Assert.assertTrue(hash + "Code" in map);
+Assert.assertTrue("class" in map);
+Assert.assertFalse("x" in map);
+Assert.assertFalse(1 in map);
+Assert.assertFalse("1" in map);
+
+var list = new java.util.ArrayList();
+list.add(true);
+Assert.assertTrue(list[0]);
+Assert.assertTrue(list["0"]);
+Assert.assertTrue(0 in list);
+Assert.assertTrue("0" in list);
+Assert.assertTrue("hashCode" in list);
+Assert.assertTrue(hash + "Code" in list);
+Assert.assertTrue("class" in list);
+Assert.assertFalse("x" in list);
+Assert.assertFalse(1 in list);
+Assert.assertFalse("1" in list);
+
+var objectArray = new (Java.type("java.lang.Object[]"))(1);
+objectArray[0] = true;
+Assert.assertTrue(objectArray[0]);
+Assert.assertTrue(objectArray["0"]);
+Assert.assertTrue(0 in objectArray);
+Assert.assertTrue("0" in objectArray);
+Assert.assertTrue("hashCode" in objectArray);
+Assert.assertTrue(hash + "Code" in objectArray);
+Assert.assertTrue("class" in objectArray);
+Assert.assertFalse("x" in objectArray);
+Assert.assertFalse(1 in objectArray);
+Assert.assertFalse("1" in objectArray);
+
+var RuntimeClass = Java.type("java.lang.Runtime");
+Assert.assertTrue("getRuntime" in RuntimeClass);
+Assert.assertTrue("runtime" in RuntimeClass);
+Assert.assertTrue("class" in RuntimeClass);
+Assert.assertFalse("hashCode" in RuntimeClass);
+Assert.assertFalse(hash + "Code" in RuntimeClass);
+Assert.assertFalse("x" in RuntimeClass);
+Assert.assertFalse(1 in RuntimeClass);
+Assert.assertFalse("1" in RuntimeClass);
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/src/jdk/nashorn/test/models/FunctionalInterfaceProvider.java Thu Feb 09 23:15:52 2017 +0100
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2017, 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.test.models;
+
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
+import org.testng.Assert;
+
+import java.util.List;
+
+public class FunctionalInterfaceProvider {
+
+ private final static Object RETURN_TOKEN = new Object();
+
+ public static Functional getImpl() {
+ return (l) -> {
+ // Make sure parameters are properly exported
+ for (final Object o : l) {
+ Assert.assertTrue(o == RETURN_TOKEN
+ || o instanceof ScriptObjectMirror
+ || o instanceof String);
+ }
+ return RETURN_TOKEN;
+ };
+ }
+
+ @FunctionalInterface
+ public interface Functional {
+ Object method(List<Object> args);
+ }
+
+}
--- a/test/Makefile Thu Feb 02 05:26:20 2017 -0800
+++ b/test/Makefile Thu Feb 09 23:15:52 2017 +0100
@@ -60,7 +60,12 @@
-include $(TOPDIR)/closed/test/Makefile
ifeq ($(TEST_JOBS), 0)
- JDK_TEST_JOBS=$(JOBS)
+ ifeq ($(shell $(EXPR) $(JOBS) \> 50), 1)
+ # JTReg cannot handle more than 50 in concurrency
+ JDK_TEST_JOBS=50
+ else
+ JDK_TEST_JOBS=$(JOBS)
+ endif
else
JDK_TEST_JOBS=$(TEST_JOBS)
endif
--- a/test/jtreg-ext/requires/VMProps.java Thu Feb 02 05:26:20 2017 -0800
+++ b/test/jtreg-ext/requires/VMProps.java Thu Feb 09 23:15:52 2017 +0100
@@ -33,6 +33,8 @@
import java.util.concurrent.Callable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+
+import sun.hotspot.cpuinfo.CPUInfo;
import sun.hotspot.gc.GC;
import sun.hotspot.WhiteBox;
@@ -62,6 +64,8 @@
map.put("vm.simpleArch", vmArch());
map.put("vm.debug", vmDebug());
map.put("vm.jvmci", vmJvmci());
+ map.put("vm.emulatedClient", vmEmulatedClient());
+ map.put("vm.cpu.features", cpuFeatures());
vmGC(map); // vm.gc.X = true/false
VMProps.dump(map);
@@ -166,6 +170,24 @@
}
/**
+ * @return true if VM runs in emulated-client mode and false otherwise.
+ */
+ protected String vmEmulatedClient() {
+ String vmInfo = System.getProperty("java.vm.info");
+ if (vmInfo == null) {
+ return "false";
+ }
+ return "" + vmInfo.contains(" emulated-client");
+ }
+
+ /**
+ * @return supported CPU features
+ */
+ protected String cpuFeatures() {
+ return CPUInfo.getFeatures().toString();
+ }
+
+ /**
* For all existing GC sets vm.gc.X property.
* Example vm.gc.G1=true means:
* VM supports G1
--- a/test/lib/jdk/test/lib/Platform.java Thu Feb 02 05:26:20 2017 -0800
+++ b/test/lib/jdk/test/lib/Platform.java Thu Feb 09 23:15:52 2017 +0100
@@ -63,6 +63,10 @@
return vmName.contains("Embedded");
}
+ public static boolean isEmulatedClient() {
+ return vmInfo.contains(" emulated-client");
+ }
+
public static boolean isTieredSupported() {
return compiler.contains("Tiered Compilers");
}