This commit is contained in:
Jesper Wilhelmsson 2017-11-07 08:47:47 +01:00
commit 3c76c33dba
313 changed files with 8110 additions and 11952 deletions

View File

@ -454,3 +454,4 @@ e5357aa85dadacc6562175ff74714fecfb4470cf jdk-10+22
b87d7b5d5dedc1185e5929470f945b7378cdb3ad jdk-10+27 b87d7b5d5dedc1185e5929470f945b7378cdb3ad jdk-10+27
92f08900cb3c0d694e5c529a676c1c9e5909193f jdk-10+28 92f08900cb3c0d694e5c529a676c1c9e5909193f jdk-10+28
a6e591e12f122768f675428e1e5a838fd0e9c7ec jdk-10+29 a6e591e12f122768f675428e1e5a838fd0e9c7ec jdk-10+29
8fee80b92e65149f7414250fd5e34b6f35d417b4 jdk-10+30

View File

@ -639,6 +639,14 @@ AC_DEFUN_ONCE([BASIC_SETUP_DEVKIT],
elif test -d "$DEVKIT_ROOT/$host/sys-root"; then elif test -d "$DEVKIT_ROOT/$host/sys-root"; then
SYSROOT="$DEVKIT_ROOT/$host/sys-root" SYSROOT="$DEVKIT_ROOT/$host/sys-root"
fi fi
if test "x$DEVKIT_ROOT" != x; then
DEVKIT_LIB_DIR="$DEVKIT_ROOT/lib"
if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
DEVKIT_LIB_DIR="$DEVKIT_ROOT/lib64"
fi
AC_SUBST(DEVKIT_LIB_DIR)
fi
] ]
) )

View File

@ -1,5 +1,5 @@
SRC# SRC#
# 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. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
@ -203,6 +203,9 @@ FLAGS_SETUP_COMPILER_FLAGS_MISC
JDKOPT_SETUP_DEBUG_SYMBOLS JDKOPT_SETUP_DEBUG_SYMBOLS
JDKOPT_SETUP_CODE_COVERAGE JDKOPT_SETUP_CODE_COVERAGE
# AddressSanitizer
JDKOPT_SETUP_ADDRESS_SANITIZER
# Need toolchain to setup dtrace # Need toolchain to setup dtrace
HOTSPOT_SETUP_DTRACE HOTSPOT_SETUP_DTRACE
HOTSPOT_ENABLE_DISABLE_AOT HOTSPOT_ENABLE_DISABLE_AOT

View File

@ -690,6 +690,7 @@ FREETYPE_LICENSE
FREETYPE_BUNDLE_LIB_PATH FREETYPE_BUNDLE_LIB_PATH
FREETYPE_LIBS FREETYPE_LIBS
FREETYPE_CFLAGS FREETYPE_CFLAGS
FONTCONFIG_CFLAGS
CUPS_CFLAGS CUPS_CFLAGS
X_EXTRA_LIBS X_EXTRA_LIBS
X_LIBS X_LIBS
@ -704,6 +705,7 @@ FIXPATH
BUILD_GTEST BUILD_GTEST
ENABLE_CDS ENABLE_CDS
ENABLE_AOT ENABLE_AOT
ASAN_ENABLED
GCOV_ENABLED GCOV_ENABLED
ZIP_EXTERNAL_DEBUG_SYMBOLS ZIP_EXTERNAL_DEBUG_SYMBOLS
COPY_DEBUG_SYMBOLS COPY_DEBUG_SYMBOLS
@ -958,6 +960,7 @@ CONF_NAME
SPEC SPEC
SDKROOT SDKROOT
XCODEBUILD XCODEBUILD
DEVKIT_LIB_DIR
JVM_VARIANT_MAIN JVM_VARIANT_MAIN
VALID_JVM_VARIANTS VALID_JVM_VARIANTS
JVM_VARIANTS JVM_VARIANTS
@ -1171,6 +1174,7 @@ with_native_debug_symbols
enable_debug_symbols enable_debug_symbols
enable_zip_debug_info enable_zip_debug_info
enable_native_coverage enable_native_coverage
enable_asan
enable_dtrace enable_dtrace
enable_aot enable_aot
enable_cds enable_cds
@ -1181,6 +1185,8 @@ with_msvcp_dll
with_x with_x
with_cups with_cups
with_cups_include with_cups_include
with_fontconfig
with_fontconfig_include
with_freetype with_freetype
with_freetype_include with_freetype_include
with_freetype_lib with_freetype_lib
@ -1976,6 +1982,7 @@ Optional Features:
--enable-native-coverage --enable-native-coverage
enable native compilation with code coverage enable native compilation with code coverage
data[disabled] data[disabled]
--enable-asan enable AddressSanitizer if possible [disabled]
--enable-dtrace[=yes/no/auto] --enable-dtrace[=yes/no/auto]
enable dtrace. Default is auto, where dtrace is enable dtrace. Default is auto, where dtrace is
enabled if all dependencies are present. enabled if all dependencies are present.
@ -2109,6 +2116,10 @@ Optional Packages:
--with-cups specify prefix directory for the cups package --with-cups specify prefix directory for the cups package
(expecting the headers under PATH/include) (expecting the headers under PATH/include)
--with-cups-include specify directory for the cups include files --with-cups-include specify directory for the cups include files
--with-fontconfig specify prefix directory for the fontconfig package
(expecting the headers under PATH/include)
--with-fontconfig-include
specify directory for the fontconfig include files
--with-freetype specify prefix directory for the freetype package --with-freetype specify prefix directory for the freetype package
(expecting the libraries under PATH/lib and the (expecting the libraries under PATH/lib and the
headers under PATH/include) headers under PATH/include)
@ -4166,6 +4177,8 @@ apt_help() {
PKGHANDLER_COMMAND="sudo apt-get install libasound2-dev" ;; PKGHANDLER_COMMAND="sudo apt-get install libasound2-dev" ;;
cups) cups)
PKGHANDLER_COMMAND="sudo apt-get install libcups2-dev" ;; PKGHANDLER_COMMAND="sudo apt-get install libcups2-dev" ;;
fontconfig)
PKGHANDLER_COMMAND="sudo apt-get install libfontconfig1-dev" ;;
freetype) freetype)
PKGHANDLER_COMMAND="sudo apt-get install libfreetype6-dev" ;; PKGHANDLER_COMMAND="sudo apt-get install libfreetype6-dev" ;;
ffi) ffi)
@ -4189,6 +4202,8 @@ yum_help() {
PKGHANDLER_COMMAND="sudo yum install alsa-lib-devel" ;; PKGHANDLER_COMMAND="sudo yum install alsa-lib-devel" ;;
cups) cups)
PKGHANDLER_COMMAND="sudo yum install cups-devel" ;; PKGHANDLER_COMMAND="sudo yum install cups-devel" ;;
fontconfig)
PKGHANDLER_COMMAND="sudo yum install fontconfig-devel" ;;
freetype) freetype)
PKGHANDLER_COMMAND="sudo yum install freetype-devel" ;; PKGHANDLER_COMMAND="sudo yum install freetype-devel" ;;
x11) x11)
@ -4403,6 +4418,12 @@ VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom"
# #
###############################################################################
#
# AddressSanitizer
#
################################################################################ ################################################################################
# #
# Static build support. When enabled will generate static # Static build support. When enabled will generate static
@ -4746,6 +4767,36 @@ VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom"
################################################################################ ################################################################################
#
# 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.
#
################################################################################
# Setup fontconfig
################################################################################
################################################################################ ################################################################################
# Determine which libraries are needed for this configuration # Determine which libraries are needed for this configuration
@ -5115,7 +5166,7 @@ VS_SDK_PLATFORM_NAME_2013=
#CUSTOM_AUTOCONF_INCLUDE #CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks: # Do not change or remove the following line, it is needed for consistency checks:
DATE_WHEN_GENERATED=1509013542 DATE_WHEN_GENERATED=1509128484
############################################################################### ###############################################################################
# #
@ -17273,6 +17324,14 @@ $as_echo "$DEVKIT_ROOT" >&6; }
SYSROOT="$DEVKIT_ROOT/$host/sys-root" SYSROOT="$DEVKIT_ROOT/$host/sys-root"
fi fi
if test "x$DEVKIT_ROOT" != x; then
DEVKIT_LIB_DIR="$DEVKIT_ROOT/lib"
if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
DEVKIT_LIB_DIR="$DEVKIT_ROOT/lib64"
fi
fi
fi fi
@ -54169,6 +54228,49 @@ $as_echo "no" >&6; }
# AddressSanitizer
# Check whether --enable-asan was given.
if test "${enable_asan+set}" = set; then :
enableval=$enable_asan;
fi
ASAN_ENABLED="no"
if test "x$enable_asan" = "xyes"; then
case $TOOLCHAIN_TYPE in
gcc | clang)
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if asan is enabled" >&5
$as_echo_n "checking if asan is enabled... " >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
ASAN_CFLAGS="-fsanitize=address -fno-omit-frame-pointer"
ASAN_LDFLAGS="-fsanitize=address"
JVM_CFLAGS="$JVM_CFLAGS $ASAN_CFLAGS"
JVM_LDFLAGS="$JVM_LDFLAGS $ASAN_LDFLAGS"
CFLAGS_JDKLIB="$CFLAGS_JDKLIB $ASAN_CFLAGS"
CFLAGS_JDKEXE="$CFLAGS_JDKEXE $ASAN_CFLAGS"
CXXFLAGS_JDKLIB="$CXXFLAGS_JDKLIB $ASAN_CFLAGS"
CXXFLAGS_JDKEXE="$CXXFLAGS_JDKEXE $ASAN_CFLAGS"
LDFLAGS_JDKLIB="$LDFLAGS_JDKLIB $ASAN_LDFLAGS"
LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE $ASAN_LDFLAGS"
ASAN_ENABLED="yes"
;;
*)
as_fn_error $? "--enable-asan only works with toolchain type gcc or clang" "$LINENO" 5
;;
esac
elif test "x$enable_asan" = "xno"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if asan is enabled" >&5
$as_echo_n "checking if asan is enabled... " >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
elif test "x$enable_asan" != "x"; then
as_fn_error $? "--enable-asan can only be assigned \"yes\" or \"no\"" "$LINENO" 5
fi
# Need toolchain to setup dtrace # Need toolchain to setup dtrace
# Test for dtrace dependencies # Test for dtrace dependencies
@ -54480,6 +54582,16 @@ $as_echo "yes" >&6; }
NEEDS_LIB_X11=true NEEDS_LIB_X11=true
fi fi
# Check if fontconfig is needed
if test "x$OPENJDK_TARGET_OS" = xwindows || test "x$OPENJDK_TARGET_OS" = xmacosx; then
# No fontconfig support on windows or macosx
NEEDS_LIB_FONTCONFIG=false
else
# All other instances need fontconfig, even if building headless only,
# libawt still needs fontconfig headers.
NEEDS_LIB_FONTCONFIG=true
fi
# Check if cups is needed # Check if cups is needed
if test "x$OPENJDK_TARGET_OS" = xwindows; then if test "x$OPENJDK_TARGET_OS" = xwindows; then
# Windows have a separate print system # Windows have a separate print system
@ -58297,6 +58409,116 @@ done
# Check whether --with-fontconfig was given.
if test "${with_fontconfig+set}" = set; then :
withval=$with_fontconfig;
fi
# Check whether --with-fontconfig-include was given.
if test "${with_fontconfig_include+set}" = set; then :
withval=$with_fontconfig_include;
fi
if test "x$NEEDS_LIB_FONTCONFIG" = xfalse; then
if (test "x${with_fontconfig}" != x && test "x${with_fontconfig}" != xno) || \
(test "x${with_fontconfig_include}" != x && test "x${with_fontconfig_include}" != xno); then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: fontconfig not used, so --with-fontconfig[-*] is ignored" >&5
$as_echo "$as_me: WARNING: fontconfig not used, so --with-fontconfig[-*] is ignored" >&2;}
fi
FONTCONFIG_CFLAGS=
else
FONTCONFIG_FOUND=no
if test "x${with_fontconfig}" = xno || test "x${with_fontconfig_include}" = xno; then
as_fn_error $? "It is not possible to disable the use of fontconfig. Remove the --without-fontconfig option." "$LINENO" 5
fi
if test "x${with_fontconfig}" != x; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fontconfig headers" >&5
$as_echo_n "checking for fontconfig headers... " >&6; }
if test -s "${with_fontconfig}/include/fontconfig/fontconfig.h"; then
FONTCONFIG_CFLAGS="-I${with_fontconfig}/include"
FONTCONFIG_FOUND=yes
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $FONTCONFIG_FOUND" >&5
$as_echo "$FONTCONFIG_FOUND" >&6; }
else
as_fn_error $? "Can't find 'include/fontconfig/fontconfig.h' under ${with_fontconfig} given with the --with-fontconfig option." "$LINENO" 5
fi
fi
if test "x${with_fontconfig_include}" != x; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fontconfig headers" >&5
$as_echo_n "checking for fontconfig headers... " >&6; }
if test -s "${with_fontconfig_include}/fontconfig/fontconfig.h"; then
FONTCONFIG_CFLAGS="-I${with_fontconfig_include}"
FONTCONFIG_FOUND=yes
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $FONTCONFIG_FOUND" >&5
$as_echo "$FONTCONFIG_FOUND" >&6; }
else
as_fn_error $? "Can't find 'fontconfig/fontconfig.h' under ${with_fontconfig_include} given with the --with-fontconfig-include option." "$LINENO" 5
fi
fi
if test "x$FONTCONFIG_FOUND" = xno; then
# Are the fontconfig headers installed in the default /usr/include location?
for ac_header in fontconfig/fontconfig.h
do :
ac_fn_cxx_check_header_mongrel "$LINENO" "fontconfig/fontconfig.h" "ac_cv_header_fontconfig_fontconfig_h" "$ac_includes_default"
if test "x$ac_cv_header_fontconfig_fontconfig_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_FONTCONFIG_FONTCONFIG_H 1
_ACEOF
FONTCONFIG_FOUND=yes
FONTCONFIG_CFLAGS=
DEFAULT_FONTCONFIG=yes
fi
done
fi
if test "x$FONTCONFIG_FOUND" = xno; then
# Print a helpful message on how to acquire the necessary build dependency.
# fontconfig is the help tag: freetype, cups, alsa etc
MISSING_DEPENDENCY=fontconfig
if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
cygwin_help $MISSING_DEPENDENCY
elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
msys_help $MISSING_DEPENDENCY
else
PKGHANDLER_COMMAND=
case $PKGHANDLER in
apt-get)
apt_help $MISSING_DEPENDENCY ;;
yum)
yum_help $MISSING_DEPENDENCY ;;
brew)
brew_help $MISSING_DEPENDENCY ;;
port)
port_help $MISSING_DEPENDENCY ;;
pkgutil)
pkgutil_help $MISSING_DEPENDENCY ;;
pkgadd)
pkgadd_help $MISSING_DEPENDENCY ;;
esac
if test "x$PKGHANDLER_COMMAND" != x; then
HELP_MSG="You might be able to fix this by running '$PKGHANDLER_COMMAND'."
fi
fi
as_fn_error $? "Could not find fontconfig! $HELP_MSG " "$LINENO" 5
fi
fi
# Check whether --with-freetype was given. # Check whether --with-freetype was given.
if test "${with_freetype+set}" = set; then : if test "${with_freetype+set}" = set; then :
withval=$with_freetype; withval=$with_freetype;
@ -65831,6 +66053,7 @@ $as_echo "no, not found at $STLPORT_LIB" >&6; }
# Hotspot setup depends on lib checks. # Hotspot setup depends on lib checks.

View File

@ -113,6 +113,8 @@ apt_help() {
PKGHANDLER_COMMAND="sudo apt-get install libasound2-dev" ;; PKGHANDLER_COMMAND="sudo apt-get install libasound2-dev" ;;
cups) cups)
PKGHANDLER_COMMAND="sudo apt-get install libcups2-dev" ;; PKGHANDLER_COMMAND="sudo apt-get install libcups2-dev" ;;
fontconfig)
PKGHANDLER_COMMAND="sudo apt-get install libfontconfig1-dev" ;;
freetype) freetype)
PKGHANDLER_COMMAND="sudo apt-get install libfreetype6-dev" ;; PKGHANDLER_COMMAND="sudo apt-get install libfreetype6-dev" ;;
ffi) ffi)
@ -136,6 +138,8 @@ yum_help() {
PKGHANDLER_COMMAND="sudo yum install alsa-lib-devel" ;; PKGHANDLER_COMMAND="sudo yum install alsa-lib-devel" ;;
cups) cups)
PKGHANDLER_COMMAND="sudo yum install cups-devel" ;; PKGHANDLER_COMMAND="sudo yum install cups-devel" ;;
fontconfig)
PKGHANDLER_COMMAND="sudo yum install fontconfig-devel" ;;
freetype) freetype)
PKGHANDLER_COMMAND="sudo yum install freetype-devel" ;; PKGHANDLER_COMMAND="sudo yum install freetype-devel" ;;
x11) x11)

View File

@ -399,6 +399,46 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_CODE_COVERAGE],
AC_SUBST(GCOV_ENABLED) AC_SUBST(GCOV_ENABLED)
]) ])
###############################################################################
#
# AddressSanitizer
#
AC_DEFUN_ONCE([JDKOPT_SETUP_ADDRESS_SANITIZER],
[
AC_ARG_ENABLE(asan, [AS_HELP_STRING([--enable-asan],
[enable AddressSanitizer if possible @<:@disabled@:>@])])
ASAN_ENABLED="no"
if test "x$enable_asan" = "xyes"; then
case $TOOLCHAIN_TYPE in
gcc | clang)
AC_MSG_CHECKING([if asan is enabled])
AC_MSG_RESULT([yes])
ASAN_CFLAGS="-fsanitize=address -fno-omit-frame-pointer"
ASAN_LDFLAGS="-fsanitize=address"
JVM_CFLAGS="$JVM_CFLAGS $ASAN_CFLAGS"
JVM_LDFLAGS="$JVM_LDFLAGS $ASAN_LDFLAGS"
CFLAGS_JDKLIB="$CFLAGS_JDKLIB $ASAN_CFLAGS"
CFLAGS_JDKEXE="$CFLAGS_JDKEXE $ASAN_CFLAGS"
CXXFLAGS_JDKLIB="$CXXFLAGS_JDKLIB $ASAN_CFLAGS"
CXXFLAGS_JDKEXE="$CXXFLAGS_JDKEXE $ASAN_CFLAGS"
LDFLAGS_JDKLIB="$LDFLAGS_JDKLIB $ASAN_LDFLAGS"
LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE $ASAN_LDFLAGS"
ASAN_ENABLED="yes"
;;
*)
AC_MSG_ERROR([--enable-asan only works with toolchain type gcc or clang])
;;
esac
elif test "x$enable_asan" = "xno"; then
AC_MSG_CHECKING([if asan is enabled])
AC_MSG_RESULT([no])
elif test "x$enable_asan" != "x"; then
AC_MSG_ERROR([--enable-asan can only be assigned "yes" or "no"])
fi
AC_SUBST(ASAN_ENABLED)
])
################################################################################ ################################################################################
# #
# Static build support. When enabled will generate static # Static build support. When enabled will generate static

View File

@ -0,0 +1,85 @@
#
# 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.
#
################################################################################
# Setup fontconfig
################################################################################
AC_DEFUN_ONCE([LIB_SETUP_FONTCONFIG],
[
AC_ARG_WITH(fontconfig, [AS_HELP_STRING([--with-fontconfig],
[specify prefix directory for the fontconfig package
(expecting the headers under PATH/include)])])
AC_ARG_WITH(fontconfig-include, [AS_HELP_STRING([--with-fontconfig-include],
[specify directory for the fontconfig include files])])
if test "x$NEEDS_LIB_FONTCONFIG" = xfalse; then
if (test "x${with_fontconfig}" != x && test "x${with_fontconfig}" != xno) || \
(test "x${with_fontconfig_include}" != x && test "x${with_fontconfig_include}" != xno); then
AC_MSG_WARN([[fontconfig not used, so --with-fontconfig[-*] is ignored]])
fi
FONTCONFIG_CFLAGS=
else
FONTCONFIG_FOUND=no
if test "x${with_fontconfig}" = xno || test "x${with_fontconfig_include}" = xno; then
AC_MSG_ERROR([It is not possible to disable the use of fontconfig. Remove the --without-fontconfig option.])
fi
if test "x${with_fontconfig}" != x; then
AC_MSG_CHECKING([for fontconfig headers])
if test -s "${with_fontconfig}/include/fontconfig/fontconfig.h"; then
FONTCONFIG_CFLAGS="-I${with_fontconfig}/include"
FONTCONFIG_FOUND=yes
AC_MSG_RESULT([$FONTCONFIG_FOUND])
else
AC_MSG_ERROR([Can't find 'include/fontconfig/fontconfig.h' under ${with_fontconfig} given with the --with-fontconfig option.])
fi
fi
if test "x${with_fontconfig_include}" != x; then
AC_MSG_CHECKING([for fontconfig headers])
if test -s "${with_fontconfig_include}/fontconfig/fontconfig.h"; then
FONTCONFIG_CFLAGS="-I${with_fontconfig_include}"
FONTCONFIG_FOUND=yes
AC_MSG_RESULT([$FONTCONFIG_FOUND])
else
AC_MSG_ERROR([Can't find 'fontconfig/fontconfig.h' under ${with_fontconfig_include} given with the --with-fontconfig-include option.])
fi
fi
if test "x$FONTCONFIG_FOUND" = xno; then
# Are the fontconfig headers installed in the default /usr/include location?
AC_CHECK_HEADERS([fontconfig/fontconfig.h], [
FONTCONFIG_FOUND=yes
FONTCONFIG_CFLAGS=
DEFAULT_FONTCONFIG=yes
])
fi
if test "x$FONTCONFIG_FOUND" = xno; then
HELP_MSG_MISSING_DEPENDENCY([fontconfig])
AC_MSG_ERROR([Could not find fontconfig! $HELP_MSG ])
fi
fi
AC_SUBST(FONTCONFIG_CFLAGS)
])

View File

@ -31,6 +31,7 @@ m4_include([lib-ffi.m4])
m4_include([lib-freetype.m4]) m4_include([lib-freetype.m4])
m4_include([lib-std.m4]) m4_include([lib-std.m4])
m4_include([lib-x11.m4]) m4_include([lib-x11.m4])
m4_include([lib-fontconfig.m4])
################################################################################ ################################################################################
# Determine which libraries are needed for this configuration # Determine which libraries are needed for this configuration
@ -47,6 +48,16 @@ AC_DEFUN_ONCE([LIB_DETERMINE_DEPENDENCIES],
NEEDS_LIB_X11=true NEEDS_LIB_X11=true
fi fi
# Check if fontconfig is needed
if test "x$OPENJDK_TARGET_OS" = xwindows || test "x$OPENJDK_TARGET_OS" = xmacosx; then
# No fontconfig support on windows or macosx
NEEDS_LIB_FONTCONFIG=false
else
# All other instances need fontconfig, even if building headless only,
# libawt still needs fontconfig headers.
NEEDS_LIB_FONTCONFIG=true
fi
# Check if cups is needed # Check if cups is needed
if test "x$OPENJDK_TARGET_OS" = xwindows; then if test "x$OPENJDK_TARGET_OS" = xwindows; then
# Windows have a separate print system # Windows have a separate print system
@ -83,6 +94,7 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES],
LIB_SETUP_STD_LIBS LIB_SETUP_STD_LIBS
LIB_SETUP_X11 LIB_SETUP_X11
LIB_SETUP_CUPS LIB_SETUP_CUPS
LIB_SETUP_FONTCONFIG
LIB_SETUP_FREETYPE LIB_SETUP_FREETYPE
LIB_SETUP_ALSA LIB_SETUP_ALSA
LIB_SETUP_LIBFFI LIB_SETUP_LIBFFI

View File

@ -311,6 +311,16 @@ UNLIMITED_CRYPTO=@UNLIMITED_CRYPTO@
GCOV_ENABLED=@GCOV_ENABLED@ GCOV_ENABLED=@GCOV_ENABLED@
# AddressSanitizer
export ASAN_ENABLED:=@ASAN_ENABLED@
export DEVKIT_LIB_DIR:=@DEVKIT_LIB_DIR@
ifeq ($(ASAN_ENABLED), yes)
export ASAN_OPTIONS="handle_segv=0 detect_leaks=0"
ifneq ($(DEVKIT_LIB_DIR),)
export LD_LIBRARY_PATH:=$(LD_LIBRARY_PATH):$(DEVKIT_LIB_DIR)
endif
endif
# Necessary additional compiler flags to compile X11 # Necessary additional compiler flags to compile X11
X_CFLAGS:=@X_CFLAGS@ X_CFLAGS:=@X_CFLAGS@
X_LIBS:=@X_LIBS@ X_LIBS:=@X_LIBS@

View File

@ -317,6 +317,7 @@ ifeq ($(findstring $(OPENJDK_TARGET_OS),windows macosx),)
LIBAWT_XAWT_CFLAGS += -DXAWT -DXAWT_HACK \ LIBAWT_XAWT_CFLAGS += -DXAWT -DXAWT_HACK \
-DPACKAGE_PATH=\"$(PACKAGE_PATH)\" \ -DPACKAGE_PATH=\"$(PACKAGE_PATH)\" \
$(FONTCONFIG_CFLAGS) \
$(CUPS_CFLAGS) $(CUPS_CFLAGS)
ifeq ($(OPENJDK_TARGET_OS), solaris) ifeq ($(OPENJDK_TARGET_OS), solaris)
@ -555,6 +556,7 @@ ifeq ($(findstring $(OPENJDK_TARGET_OS), windows macosx),)
-DHEADLESS=true \ -DHEADLESS=true \
-DPACKAGE_PATH=\"$(PACKAGE_PATH)\" \ -DPACKAGE_PATH=\"$(PACKAGE_PATH)\" \
$(CUPS_CFLAGS) \ $(CUPS_CFLAGS) \
$(FONTCONFIG_CFLAGS) \
$(X_CFLAGS) \ $(X_CFLAGS) \
$(LIBAWT_HEADLESS_CFLAGS), \ $(LIBAWT_HEADLESS_CFLAGS), \
DISABLED_WARNINGS_xlc := 1506-356, \ DISABLED_WARNINGS_xlc := 1506-356, \

View File

@ -698,7 +698,7 @@ public final class FilePermission extends Permission implements Serializable {
if (p2.equals(EMPTY_PATH)) { if (p2.equals(EMPTY_PATH)) {
return 0; return 0;
} else if (p2.getName(0).equals(DOTDOT_PATH)) { } else if (p2.getName(0).equals(DOTDOT_PATH)) {
// "." contains p2 iif p2 has no "..". Since a // "." contains p2 iff p2 has no "..". Since
// a normalized path can only have 0 or more // a normalized path can only have 0 or more
// ".." at the beginning. We only need to look // ".." at the beginning. We only need to look
// at the head. // at the head.
@ -711,7 +711,7 @@ public final class FilePermission extends Permission implements Serializable {
} else if (p2.equals(EMPTY_PATH)) { } else if (p2.equals(EMPTY_PATH)) {
int c1 = p1.getNameCount(); int c1 = p1.getNameCount();
if (!p1.getName(c1 - 1).equals(DOTDOT_PATH)) { if (!p1.getName(c1 - 1).equals(DOTDOT_PATH)) {
// "." is inside p1 iif p1 is 1 or more "..". // "." is inside p1 iff p1 is 1 or more "..".
// For the same reason above, we only need to // For the same reason above, we only need to
// look at the tail. // look at the tail.
return -1; return -1;

View File

@ -57,8 +57,6 @@ import java.util.stream.Stream;
import jdk.internal.loader.BuiltinClassLoader; import jdk.internal.loader.BuiltinClassLoader;
import jdk.internal.loader.BootLoader; import jdk.internal.loader.BootLoader;
import jdk.internal.loader.ClassLoaders; import jdk.internal.loader.ClassLoaders;
import jdk.internal.misc.JavaLangAccess;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.module.IllegalAccessLogger; import jdk.internal.module.IllegalAccessLogger;
import jdk.internal.module.ModuleLoaderMap; import jdk.internal.module.ModuleLoaderMap;
import jdk.internal.module.ServicesCatalog; import jdk.internal.module.ServicesCatalog;
@ -68,6 +66,7 @@ import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ClassReader; import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection; import jdk.internal.reflect.Reflection;
@ -1432,7 +1431,7 @@ public final class Module implements AnnotatedElement {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
+ ClassWriter.COMPUTE_FRAMES); + ClassWriter.COMPUTE_FRAMES);
ClassVisitor cv = new ClassVisitor(Opcodes.ASM5, cw) { ClassVisitor cv = new ClassVisitor(Opcodes.ASM6, cw) {
@Override @Override
public void visit(int version, public void visit(int version,
int access, int access,
@ -1458,6 +1457,11 @@ public final class Module implements AnnotatedElement {
public void visitAttribute(Attribute attr) { public void visitAttribute(Attribute attr) {
// drop non-annotation attributes // drop non-annotation attributes
} }
@Override
public ModuleVisitor visitModule(String name, int flags, String version) {
// drop Module attribute
return null;
}
}; };
ClassReader cr = new ClassReader(in); ClassReader cr = new ClassReader(in);

View File

@ -1937,7 +1937,7 @@ public final class System {
// initialization. So make sure the "props" is available at the // initialization. So make sure the "props" is available at the
// very beginning of the initialization and all system properties to // very beginning of the initialization and all system properties to
// be put into it directly. // be put into it directly.
props = new Properties(); props = new Properties(84);
initProperties(props); // initialized by the VM initProperties(props); // initialized by the VM
// There are certain system configurations that may be controlled by // There are certain system configurations that may be controlled by

View File

@ -765,7 +765,7 @@ public abstract class MethodHandle {
* In every other case, all conversions are applied <em>pairwise</em>, * In every other case, all conversions are applied <em>pairwise</em>,
* which means that each argument or return value is converted to * which means that each argument or return value is converted to
* exactly one argument or return value (or no return value). * exactly one argument or return value (or no return value).
* The applied conversions are defined by consulting the * The applied conversions are defined by consulting
* the corresponding component types of the old and new * the corresponding component types of the old and new
* method handle types. * method handle types.
* <p> * <p>

View File

@ -194,7 +194,7 @@ public final class StringConcatFactory {
static { static {
// In case we need to double-back onto the StringConcatFactory during this // In case we need to double-back onto the StringConcatFactory during this
// static initialization, make sure we have the reasonable defaults to complete // static initialization, make sure we have the reasonable defaults to complete
// the static initialization properly. After that, actual users would use the // the static initialization properly. After that, actual users would use
// the proper values we have read from the properties. // the proper values we have read from the properties.
STRATEGY = DEFAULT_STRATEGY; STRATEGY = DEFAULT_STRATEGY;
// CACHE_ENABLE = false; // implied // CACHE_ENABLE = false; // implied

View File

@ -205,7 +205,7 @@ import static java.lang.invoke.MethodHandleStatics.newInternalError;
* and {@code double} on 32-bit platforms. * and {@code double} on 32-bit platforms.
* *
* <p>Access modes will override any memory ordering effects specified at * <p>Access modes will override any memory ordering effects specified at
* the declaration site of a variable. For example, a VarHandle accessing a * the declaration site of a variable. For example, a VarHandle accessing
* a field using the {@code get} access mode will access the field as * a field using the {@code get} access mode will access the field as
* specified <em>by its access mode</em> even if that field is declared * specified <em>by its access mode</em> even if that field is declared
* {@code volatile}. When mixed access is performed extreme care should be * {@code volatile}. When mixed access is performed extreme care should be
@ -423,7 +423,7 @@ import static java.lang.invoke.MethodHandleStatics.newInternalError;
* {@link java.lang.invoke.MethodHandles#varHandleInvoker}. * {@link java.lang.invoke.MethodHandles#varHandleInvoker}.
* *
* <h1>Interoperation between VarHandles and Java generics</h1> * <h1>Interoperation between VarHandles and Java generics</h1>
* A VarHandle can be obtained for a variable, such as a a field, which is * A VarHandle can be obtained for a variable, such as a field, which is
* declared with Java generic types. As with the Core Reflection API, the * declared with Java generic types. As with the Core Reflection API, the
* VarHandle's variable type will be constructed from the erasure of the * VarHandle's variable type will be constructed from the erasure of the
* source-level type. When a VarHandle access mode method is invoked, the * source-level type. When a VarHandle access mode method is invoked, the

View File

@ -988,7 +988,7 @@ class DatagramSocket implements java.io.Closeable {
/** /**
* Sets the SO_RCVBUF option to the specified value for this * Sets the SO_RCVBUF option to the specified value for this
* {@code DatagramSocket}. The SO_RCVBUF option is used by the * {@code DatagramSocket}. The SO_RCVBUF option is used by
* the network implementation as a hint to size the underlying * the network implementation as a hint to size the underlying
* network I/O buffers. The SO_RCVBUF setting may also be used * network I/O buffers. The SO_RCVBUF setting may also be used
* by the network implementation to determine the maximum size * by the network implementation to determine the maximum size

View File

@ -143,7 +143,7 @@ class Inet4Address extends InetAddress {
/** /**
* Prior to 1.4 an InetAddress was created with a family * Prior to 1.4 an InetAddress was created with a family
* based on the platform AF_INET value (usually 2). * based on the platform AF_INET value (usually 2).
* For compatibility reasons we must therefore write the * For compatibility reasons we must therefore write
* the InetAddress with this family. * the InetAddress with this family.
*/ */
inet.holder().family = 2; inet.holder().family = 2;

View File

@ -333,7 +333,7 @@ public abstract class SocketImpl implements SocketOptions {
* latency, and low latency above short connection time, then it could * latency, and low latency above short connection time, then it could
* invoke this method with the values {@code (0, 1, 2)}. * invoke this method with the values {@code (0, 1, 2)}.
* *
* By default, this method does nothing, unless it is overridden in a * By default, this method does nothing, unless it is overridden in
* a sub-class. * a sub-class.
* *
* @param connectionTime * @param connectionTime

View File

@ -657,7 +657,7 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts {
/** /**
* Sends the Bind request to the SOCKS proxy. In the SOCKS protocol, bind * Sends the Bind request to the SOCKS proxy. In the SOCKS protocol, bind
* means "accept incoming connection from", so the SocketAddress is the * means "accept incoming connection from", so the SocketAddress is
* the one of the host we do accept connection from. * the one of the host we do accept connection from.
* *
* @param saddr the Socket address of the remote host. * @param saddr the Socket address of the remote host.

View File

@ -785,7 +785,7 @@ public abstract class URLConnection {
* required to make the connection. By default, this method * required to make the connection. By default, this method
* returns {@code java.security.AllPermission}. Subclasses * returns {@code java.security.AllPermission}. Subclasses
* should override this method and return the permission * should override this method and return the permission
* that best represents the permission required to make a * that best represents the permission required to make
* a connection to the URL. For example, a {@code URLConnection} * a connection to the URL. For example, a {@code URLConnection}
* representing a {@code file:} URL would return a * representing a {@code file:} URL would return a
* {@code java.io.FilePermission} object. * {@code java.io.FilePermission} object.

View File

@ -165,7 +165,7 @@ public abstract class AsynchronousFileChannel
* <tr> * <tr>
* <th scope="row" > {@link StandardOpenOption#DELETE_ON_CLOSE DELETE_ON_CLOSE} </th> * <th scope="row" > {@link StandardOpenOption#DELETE_ON_CLOSE DELETE_ON_CLOSE} </th>
* <td> When this option is present then the implementation makes a * <td> When this option is present then the implementation makes a
* <em>best effort</em> attempt to delete the file when closed by the * <em>best effort</em> attempt to delete the file when closed by
* the {@link #close close} method. If the {@code close} method is not * the {@link #close close} method. If the {@code close} method is not
* invoked then a <em>best effort</em> attempt is made to delete the file * invoked then a <em>best effort</em> attempt is made to delete the file
* when the Java virtual machine terminates. </td> * when the Java virtual machine terminates. </td>

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -368,6 +368,10 @@ public final class Channels {
@Override @Override
public int read(ByteBuffer dst) throws IOException { public int read(ByteBuffer dst) throws IOException {
if (!isOpen()) {
throw new ClosedChannelException();
}
int len = dst.remaining(); int len = dst.remaining();
int totalRead = 0; int totalRead = 0;
int bytesRead = 0; int bytesRead = 0;
@ -442,6 +446,10 @@ public final class Channels {
@Override @Override
public int write(ByteBuffer src) throws IOException { public int write(ByteBuffer src) throws IOException {
if (!isOpen()) {
throw new ClosedChannelException();
}
int len = src.remaining(); int len = src.remaining();
int totalWritten = 0; int totalWritten = 0;
synchronized (writeLock) { synchronized (writeLock) {

View File

@ -216,7 +216,7 @@ public abstract class FileChannel
* <tr> * <tr>
* <th scope="row" > {@link StandardOpenOption#DELETE_ON_CLOSE DELETE_ON_CLOSE} </th> * <th scope="row" > {@link StandardOpenOption#DELETE_ON_CLOSE DELETE_ON_CLOSE} </th>
* <td> When this option is present then the implementation makes a * <td> When this option is present then the implementation makes a
* <em>best effort</em> attempt to delete the file when closed by the * <em>best effort</em> attempt to delete the file when closed by
* the {@link #close close} method. If the {@code close} method is not * the {@link #close close} method. If the {@code close} method is not
* invoked then a <em>best effort</em> attempt is made to delete the file * invoked then a <em>best effort</em> attempt is made to delete the file
* when the Java virtual machine terminates. </td> * when the Java virtual machine terminates. </td>

View File

@ -2401,7 +2401,7 @@ public final class Files {
* *
* <p> Note that the result of this method is immediately outdated. If this * <p> Note that the result of this method is immediately outdated. If this
* method indicates the file exists then there is no guarantee that a * method indicates the file exists then there is no guarantee that a
* subsequence access will succeed. Care should be taken when using this * subsequent access will succeed. Care should be taken when using this
* method in security sensitive applications. * method in security sensitive applications.
* *
* @param path * @param path
@ -2458,7 +2458,7 @@ public final class Files {
* or not then both methods return {@code false}. As with the {@code exists} * or not then both methods return {@code false}. As with the {@code exists}
* method, the result of this method is immediately outdated. If this * method, the result of this method is immediately outdated. If this
* method indicates the file does exist then there is no guarantee that a * method indicates the file does exist then there is no guarantee that a
* subsequence attempt to create the file will succeed. Care should be taken * subsequent attempt to create the file will succeed. Care should be taken
* when using this method in security sensitive applications. * when using this method in security sensitive applications.
* *
* @param path * @param path
@ -3301,7 +3301,7 @@ public final class Files {
} }
/** /**
* Writes bytes to a file. The {@code options} parameter specifies how the * Writes bytes to a file. The {@code options} parameter specifies how
* the file is created or opened. If no options are present then this method * the file is created or opened. If no options are present then this method
* works as if the {@link StandardOpenOption#CREATE CREATE}, {@link * works as if the {@link StandardOpenOption#CREATE CREATE}, {@link
* StandardOpenOption#TRUNCATE_EXISTING TRUNCATE_EXISTING}, and {@link * StandardOpenOption#TRUNCATE_EXISTING TRUNCATE_EXISTING}, and {@link

View File

@ -84,7 +84,7 @@ import sun.security.util.Debug;
* exists (e.g., so-called <i>community parameters</i> in DSA), there are two * exists (e.g., so-called <i>community parameters</i> in DSA), there are two
* {@link #initialize(java.security.spec.AlgorithmParameterSpec) * {@link #initialize(java.security.spec.AlgorithmParameterSpec)
* initialize} methods that have an {@code AlgorithmParameterSpec} * initialize} methods that have an {@code AlgorithmParameterSpec}
* argument. One also has a {@code SecureRandom} argument, while the * argument. One also has a {@code SecureRandom} argument, while
* the other uses the {@code SecureRandom} * the other uses the {@code SecureRandom}
* implementation of the highest-priority installed provider as the source * implementation of the highest-priority installed provider as the source
* of randomness. (If none of the installed providers supply an implementation * of randomness. (If none of the installed providers supply an implementation

View File

@ -4775,7 +4775,7 @@ public final class DateTimeFormatterBuilder {
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
/** /**
* Prints or parses a localized pattern from a localized field. * Prints or parses a localized pattern from a localized field.
* The specific formatter and parameters is not selected until the * The specific formatter and parameters is not selected until
* the field is to be printed or parsed. * the field is to be printed or parsed.
* The locale is needed to select the proper WeekFields from which * The locale is needed to select the proper WeekFields from which
* the field for day-of-week, week-of-month, or week-of-year is selected. * the field for day-of-week, week-of-month, or week-of-year is selected.

View File

@ -311,7 +311,7 @@ public final class WeekFields implements Serializable {
* the new month or year. * the new month or year.
* <p> * <p>
* WeekFields instances are singletons; for each unique combination * WeekFields instances are singletons; for each unique combination
* of {@code firstDayOfWeek} and {@code minimalDaysInFirstWeek} the * of {@code firstDayOfWeek} and {@code minimalDaysInFirstWeek}
* the same instance will be returned. * the same instance will be returned.
* *
* @param firstDayOfWeek the first day of the week, not null * @param firstDayOfWeek the first day of the week, not null

View File

@ -56,7 +56,7 @@ import java.nio.charset.StandardCharsets;
* base64 alphabet.</p></li> * base64 alphabet.</p></li>
* *
* <li><a id="mime"><b>MIME</b></a> * <li><a id="mime"><b>MIME</b></a>
* <p> Uses the "The Base64 Alphabet" as specified in Table 1 of * <p> Uses "The Base64 Alphabet" as specified in Table 1 of
* RFC 2045 for encoding and decoding operation. The encoded output * RFC 2045 for encoding and decoding operation. The encoded output
* must be represented in lines of no more than 76 characters each * must be represented in lines of no more than 76 characters each
* and uses a carriage return {@code '\r'} followed immediately by * and uses a carriage return {@code '\r'} followed immediately by

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,6 +26,7 @@ package java.util;
import java.util.function.DoubleConsumer; import java.util.function.DoubleConsumer;
import java.util.stream.Collector; import java.util.stream.Collector;
import java.util.stream.DoubleStream;
/** /**
* A state object for collecting statistics such as count, min, max, sum, and * A state object for collecting statistics such as count, min, max, sum, and
@ -69,12 +70,65 @@ public class DoubleSummaryStatistics implements DoubleConsumer {
private double max = Double.NEGATIVE_INFINITY; private double max = Double.NEGATIVE_INFINITY;
/** /**
* Construct an empty instance with zero count, zero sum, * Constructs an empty instance with zero count, zero sum,
* {@code Double.POSITIVE_INFINITY} min, {@code Double.NEGATIVE_INFINITY} * {@code Double.POSITIVE_INFINITY} min, {@code Double.NEGATIVE_INFINITY}
* max and zero average. * max and zero average.
*/ */
public DoubleSummaryStatistics() { } public DoubleSummaryStatistics() { }
/**
* Constructs a non-empty instance with the specified {@code count},
* {@code min}, {@code max}, and {@code sum}.
*
* <p>If {@code count} is zero then the remaining arguments are ignored and
* an empty instance is constructed.
*
* <p>If the arguments are inconsistent then an {@code IllegalArgumentException}
* is thrown. The necessary consistent argument conditions are:
* <ul>
* <li>{@code count >= 0}</li>
* <li>{@code (min <= max && !isNaN(sum)) || (isNaN(min) && isNaN(max) && isNaN(sum))}</li>
* </ul>
* @apiNote
* The enforcement of argument correctness means that the retrieved set of
* recorded values obtained from a {@code DoubleSummaryStatistics} source
* instance may not be a legal set of arguments for this constructor due to
* arithmetic overflow of the source's recorded count of values.
* The consistent argument conditions are not sufficient to prevent the
* creation of an internally inconsistent instance. An example of such a
* state would be an instance with: {@code count} = 2, {@code min} = 1,
* {@code max} = 2, and {@code sum} = 0.
*
* @param count the count of values
* @param min the minimum value
* @param max the maximum value
* @param sum the sum of all values
* @throws IllegalArgumentException if the arguments are inconsistent
* @since 10
*/
public DoubleSummaryStatistics(long count, double min, double max, double sum)
throws IllegalArgumentException {
if (count < 0L) {
throw new IllegalArgumentException("Negative count value");
} else if (count > 0L) {
if (min > max)
throw new IllegalArgumentException("Minimum greater than maximum");
// All NaN or non NaN
var ncount = DoubleStream.of(min, max, sum).filter(Double::isNaN).count();
if (ncount > 0 && ncount < 3)
throw new IllegalArgumentException("Some, not all, of the minimum, maximum, or sum is NaN");
this.count = count;
this.sum = sum;
this.simpleSum = sum;
this.sumCompensation = 0.0d;
this.min = min;
this.max = max;
}
// Use default field values if count == 0
}
/** /**
* Records another value into the summary information. * Records another value into the summary information.
* *

View File

@ -43,13 +43,13 @@ public class EventObject implements java.io.Serializable {
/** /**
* The object on which the Event initially occurred. * The object on which the Event initially occurred.
*/ */
protected transient Object source; protected transient Object source;
/** /**
* Constructs a prototypical Event. * Constructs a prototypical Event.
* *
* @param source The object on which the Event initially occurred. * @param source the object on which the Event initially occurred
* @exception IllegalArgumentException if source is null. * @throws IllegalArgumentException if source is null
*/ */
public EventObject(Object source) { public EventObject(Object source) {
if (source == null) if (source == null)
@ -61,7 +61,7 @@ public class EventObject implements java.io.Serializable {
/** /**
* The object on which the Event initially occurred. * The object on which the Event initially occurred.
* *
* @return The object on which the Event initially occurred. * @return the object on which the Event initially occurred
*/ */
public Object getSource() { public Object getSource() {
return source; return source;
@ -70,7 +70,7 @@ public class EventObject implements java.io.Serializable {
/** /**
* Returns a String representation of this EventObject. * Returns a String representation of this EventObject.
* *
* @return A a String representation of this EventObject. * @return a String representation of this EventObject
*/ */
public String toString() { public String toString() {
return getClass().getName() + "[source=" + source + "]"; return getClass().getName() + "[source=" + source + "]";

View File

@ -26,7 +26,7 @@
package java.util; package java.util;
/** /**
* FomattableFlags are passed to the {@link Formattable#formatTo * FormattableFlags are passed to the {@link Formattable#formatTo
* Formattable.formatTo()} method and modify the output format for {@linkplain * Formattable.formatTo()} method and modify the output format for {@linkplain
* Formattable Formattables}. Implementations of {@link Formattable} are * Formattable Formattables}. Implementations of {@link Formattable} are
* responsible for interpreting and validating any flags. * responsible for interpreting and validating any flags.

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -69,12 +69,57 @@ public class IntSummaryStatistics implements IntConsumer {
private int max = Integer.MIN_VALUE; private int max = Integer.MIN_VALUE;
/** /**
* Construct an empty instance with zero count, zero sum, * Constructs an empty instance with zero count, zero sum,
* {@code Integer.MAX_VALUE} min, {@code Integer.MIN_VALUE} max and zero * {@code Integer.MAX_VALUE} min, {@code Integer.MIN_VALUE} max and zero
* average. * average.
*/ */
public IntSummaryStatistics() { } public IntSummaryStatistics() { }
/**
* Constructs a non-empty instance with the specified {@code count},
* {@code min}, {@code max}, and {@code sum}.
*
* <p>If {@code count} is zero then the remaining arguments are ignored and
* an empty instance is constructed.
*
* <p>If the arguments are inconsistent then an {@code IllegalArgumentException}
* is thrown. The necessary consistent argument conditions are:
* <ul>
* <li>{@code count >= 0}</li>
* <li>{@code min <= max}</li>
* </ul>
* @apiNote
* The enforcement of argument correctness means that the retrieved set of
* recorded values obtained from a {@code IntSummaryStatistics} source
* instance may not be a legal set of arguments for this constructor due to
* arithmetic overflow of the source's recorded count of values.
* The consistent argument conditions are not sufficient to prevent the
* creation of an internally inconsistent instance. An example of such a
* state would be an instance with: {@code count} = 2, {@code min} = 1,
* {@code max} = 2, and {@code sum} = 0.
*
* @param count the count of values
* @param min the minimum value
* @param max the maximum value
* @param sum the sum of all values
* @throws IllegalArgumentException if the arguments are inconsistent
* @since 10
*/
public IntSummaryStatistics(long count, int min, int max, long sum)
throws IllegalArgumentException {
if (count < 0L) {
throw new IllegalArgumentException("Negative count value");
} else if (count > 0L) {
if (min > max) throw new IllegalArgumentException("Minimum greater than maximum");
this.count = count;
this.sum = sum;
this.min = min;
this.max = max;
}
// Use default field values if count == 0
}
/** /**
* Records a new value into the summary information * Records a new value into the summary information
* *

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -70,12 +70,57 @@ public class LongSummaryStatistics implements LongConsumer, IntConsumer {
private long max = Long.MIN_VALUE; private long max = Long.MIN_VALUE;
/** /**
* Construct an empty instance with zero count, zero sum, * Constructs an empty instance with zero count, zero sum,
* {@code Long.MAX_VALUE} min, {@code Long.MIN_VALUE} max and zero * {@code Long.MAX_VALUE} min, {@code Long.MIN_VALUE} max and zero
* average. * average.
*/ */
public LongSummaryStatistics() { } public LongSummaryStatistics() { }
/**
* Constructs a non-empty instance with the specified {@code count},
* {@code min}, {@code max}, and {@code sum}.
*
* <p>If {@code count} is zero then the remaining arguments are ignored and
* an empty instance is constructed.
*
* <p>If the arguments are inconsistent then an {@code IllegalArgumentException}
* is thrown. The necessary consistent argument conditions are:
* <ul>
* <li>{@code count >= 0}</li>
* <li>{@code min <= max}</li>
* </ul>
* @apiNote
* The enforcement of argument correctness means that the retrieved set of
* recorded values obtained from a {@code LongSummaryStatistics} source
* instance may not be a legal set of arguments for this constructor due to
* arithmetic overflow of the source's recorded count of values.
* The consistent argument conditions are not sufficient to prevent the
* creation of an internally inconsistent instance. An example of such a
* state would be an instance with: {@code count} = 2, {@code min} = 1,
* {@code max} = 2, and {@code sum} = 0.
*
* @param count the count of values
* @param min the minimum value
* @param max the maximum value
* @param sum the sum of all values
* @throws IllegalArgumentException if the arguments are inconsistent
* @since 10
*/
public LongSummaryStatistics(long count, long min, long max, long sum)
throws IllegalArgumentException {
if (count < 0L) {
throw new IllegalArgumentException("Negative count value");
} else if (count > 0L) {
if (min > max) throw new IllegalArgumentException("Minimum greater than maximum");
this.count = count;
this.sum = sum;
this.min = min;
this.max = max;
}
// Use default field values if count == 0
}
/** /**
* Records a new {@code int} value into the summary information. * Records a new {@code int} value into the summary information.
* *

View File

@ -122,6 +122,10 @@ import jdk.internal.util.xml.PropertiesDefaultHandler;
* <p>This class is thread-safe: multiple threads can share a single * <p>This class is thread-safe: multiple threads can share a single
* {@code Properties} object without the need for external synchronization. * {@code Properties} object without the need for external synchronization.
* *
* @apiNote
* The {@code Properties} class does not inherit the concept of a load factor
* from its superclass, {@code Hashtable}.
*
* @author Arthur van Hoff * @author Arthur van Hoff
* @author Michael McCloskey * @author Michael McCloskey
* @author Xueming Shen * @author Xueming Shen
@ -148,25 +152,49 @@ class Properties extends Hashtable<Object,Object> {
* simple read operations. Writes and bulk operations remain synchronized, * simple read operations. Writes and bulk operations remain synchronized,
* as in Hashtable. * as in Hashtable.
*/ */
private transient ConcurrentHashMap<Object, Object> map = private transient ConcurrentHashMap<Object, Object> map;
new ConcurrentHashMap<>(8);
/** /**
* Creates an empty property list with no default values. * Creates an empty property list with no default values.
*
* @implNote The initial capacity of a {@code Properties} object created
* with this constructor is unspecified.
*/ */
public Properties() { public Properties() {
this(null); this(null, 8);
}
/**
* Creates an empty property list with no default values, and with an
* initial size accommodating the specified number of elements without the
* need to dynamically resize.
*
* @param initialCapacity the {@code Properties} will be sized to
* accommodate this many elements
* @throws IllegalArgumentException if the initial capacity is less than
* zero.
*/
public Properties(int initialCapacity) {
this(null, initialCapacity);
} }
/** /**
* Creates an empty property list with the specified defaults. * Creates an empty property list with the specified defaults.
* *
* @implNote The initial capacity of a {@code Properties} object created
* with this constructor is unspecified.
*
* @param defaults the defaults. * @param defaults the defaults.
*/ */
public Properties(Properties defaults) { public Properties(Properties defaults) {
this(defaults, 8);
}
private Properties(Properties defaults, int initialCapacity) {
// use package-private constructor to // use package-private constructor to
// initialize unused fields with dummy values // initialize unused fields with dummy values
super((Void) null); super((Void) null);
map = new ConcurrentHashMap<>(initialCapacity);
this.defaults = defaults; this.defaults = defaults;
} }

View File

@ -2743,7 +2743,7 @@ public abstract class ResourceBundle {
* of multiple subtags separated by underscore, generate candidate * of multiple subtags separated by underscore, generate candidate
* <code>Locale</code>s by omitting the variant subtags one by one, then * <code>Locale</code>s by omitting the variant subtags one by one, then
* insert them after every occurrence of <code> Locale</code>s with the * insert them after every occurrence of <code> Locale</code>s with the
* full variant value in the original list. For example, if the * full variant value in the original list. For example, if
* the variant consists of two subtags <em>V1</em> and <em>V2</em>: * the variant consists of two subtags <em>V1</em> and <em>V2</em>:
* *
* <ul> * <ul>

View File

@ -238,7 +238,7 @@ public final class BootstrapLogger implements Logger, PlatformLogger.Bridge,
// This way we could simply do things like: // This way we could simply do things like:
// push((logger) -> logger.log(level, msg)); // push((logger) -> logger.log(level, msg));
// Unfortunately, if we come to here it means we are in the bootsraping // Unfortunately, if we come to here it means we are in the bootsraping
// phase where using lambdas is not safe yet - so we have to use a // phase where using lambdas is not safe yet - so we have to use
// a data object instead... // a data object instead...
// //
static final class LogEvent { static final class LogEvent {

View File

@ -1,765 +0,0 @@
/*
* 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. 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.module;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleDescriptor.Builder;
import java.lang.module.ModuleDescriptor.Requires;
import java.lang.module.ModuleDescriptor.Exports;
import java.lang.module.ModuleDescriptor.Opens;
import java.lang.module.ModuleDescriptor.Provides;
import java.lang.module.ModuleDescriptor.Version;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import jdk.internal.misc.JavaLangModuleAccess;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ByteVector;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Label;
import static jdk.internal.module.ClassFileConstants.*;
/**
* Provides ASM implementations of {@code Attribute} to read and write the
* class file attributes in a module-info class file.
*/
public final class ClassFileAttributes {
private ClassFileAttributes() { }
/**
* Module_attribute {
* // See lang-vm.html for details.
* }
*/
public static class ModuleAttribute extends Attribute {
private static final JavaLangModuleAccess JLMA
= SharedSecrets.getJavaLangModuleAccess();
private ModuleDescriptor descriptor;
private Version replacementVersion;
public ModuleAttribute(ModuleDescriptor descriptor) {
super(MODULE);
this.descriptor = descriptor;
}
public ModuleAttribute(Version v) {
super(MODULE);
this.replacementVersion = v;
}
public ModuleAttribute() {
super(MODULE);
}
@Override
protected Attribute read(ClassReader cr,
int off,
int len,
char[] buf,
int codeOff,
Label[] labels)
{
// module_name (CONSTANT_Module_info)
String mn = cr.readModule(off, buf);
off += 2;
// module_flags
int module_flags = cr.readUnsignedShort(off);
off += 2;
Set<ModuleDescriptor.Modifier> modifiers = new HashSet<>();
if ((module_flags & ACC_OPEN) != 0)
modifiers.add(ModuleDescriptor.Modifier.OPEN);
if ((module_flags & ACC_SYNTHETIC) != 0)
modifiers.add(ModuleDescriptor.Modifier.SYNTHETIC);
if ((module_flags & ACC_MANDATED) != 0)
modifiers.add(ModuleDescriptor.Modifier.MANDATED);
Builder builder = JLMA.newModuleBuilder(mn, false, modifiers);
// module_version
String module_version = cr.readUTF8(off, buf);
off += 2;
if (replacementVersion != null) {
builder.version(replacementVersion);
} else if (module_version != null) {
builder.version(module_version);
}
// requires_count and requires[requires_count]
int requires_count = cr.readUnsignedShort(off);
off += 2;
for (int i=0; i<requires_count; i++) {
// CONSTANT_Module_info
String dn = cr.readModule(off, buf);
off += 2;
// requires_flags
int requires_flags = cr.readUnsignedShort(off);
off += 2;
Set<Requires.Modifier> mods;
if (requires_flags == 0) {
mods = Collections.emptySet();
} else {
mods = new HashSet<>();
if ((requires_flags & ACC_TRANSITIVE) != 0)
mods.add(Requires.Modifier.TRANSITIVE);
if ((requires_flags & ACC_STATIC_PHASE) != 0)
mods.add(Requires.Modifier.STATIC);
if ((requires_flags & ACC_SYNTHETIC) != 0)
mods.add(Requires.Modifier.SYNTHETIC);
if ((requires_flags & ACC_MANDATED) != 0)
mods.add(Requires.Modifier.MANDATED);
}
// requires_version
String requires_version = cr.readUTF8(off, buf);
off += 2;
if (requires_version == null) {
builder.requires(mods, dn);
} else {
JLMA.requires(builder, mods, dn, requires_version);
}
}
// exports_count and exports[exports_count]
int exports_count = cr.readUnsignedShort(off);
off += 2;
if (exports_count > 0) {
for (int i=0; i<exports_count; i++) {
// CONSTANT_Package_info
String pkg = cr.readPackage(off, buf).replace('/', '.');
off += 2;
int exports_flags = cr.readUnsignedShort(off);
off += 2;
Set<Exports.Modifier> mods;
if (exports_flags == 0) {
mods = Collections.emptySet();
} else {
mods = new HashSet<>();
if ((exports_flags & ACC_SYNTHETIC) != 0)
mods.add(Exports.Modifier.SYNTHETIC);
if ((exports_flags & ACC_MANDATED) != 0)
mods.add(Exports.Modifier.MANDATED);
}
int exports_to_count = cr.readUnsignedShort(off);
off += 2;
if (exports_to_count > 0) {
Set<String> targets = new HashSet<>();
for (int j=0; j<exports_to_count; j++) {
String t = cr.readModule(off, buf);
off += 2;
targets.add(t);
}
builder.exports(mods, pkg, targets);
} else {
builder.exports(mods, pkg);
}
}
}
// opens_count and opens[opens_count]
int open_count = cr.readUnsignedShort(off);
off += 2;
if (open_count > 0) {
for (int i=0; i<open_count; i++) {
// CONSTANT_Package_info
String pkg = cr.readPackage(off, buf).replace('/', '.');
off += 2;
int opens_flags = cr.readUnsignedShort(off);
off += 2;
Set<Opens.Modifier> mods;
if (opens_flags == 0) {
mods = Collections.emptySet();
} else {
mods = new HashSet<>();
if ((opens_flags & ACC_SYNTHETIC) != 0)
mods.add(Opens.Modifier.SYNTHETIC);
if ((opens_flags & ACC_MANDATED) != 0)
mods.add(Opens.Modifier.MANDATED);
}
int opens_to_count = cr.readUnsignedShort(off);
off += 2;
if (opens_to_count > 0) {
Set<String> targets = new HashSet<>();
for (int j=0; j<opens_to_count; j++) {
String t = cr.readModule(off, buf);
off += 2;
targets.add(t);
}
builder.opens(mods, pkg, targets);
} else {
builder.opens(mods, pkg);
}
}
}
// uses_count and uses_index[uses_count]
int uses_count = cr.readUnsignedShort(off);
off += 2;
if (uses_count > 0) {
for (int i=0; i<uses_count; i++) {
String sn = cr.readClass(off, buf).replace('/', '.');
builder.uses(sn);
off += 2;
}
}
// provides_count and provides[provides_count]
int provides_count = cr.readUnsignedShort(off);
off += 2;
if (provides_count > 0) {
for (int i=0; i<provides_count; i++) {
String service = cr.readClass(off, buf).replace('/', '.');
off += 2;
int with_count = cr.readUnsignedShort(off);
off += 2;
List<String> providers = new ArrayList<>();
for (int j=0; j<with_count; j++) {
String cn = cr.readClass(off, buf).replace('/', '.');
off += 2;
providers.add(cn);
}
builder.provides(service, providers);
}
}
return new ModuleAttribute(builder.build());
}
@Override
protected ByteVector write(ClassWriter cw,
byte[] code,
int len,
int maxStack,
int maxLocals)
{
assert descriptor != null;
ByteVector attr = new ByteVector();
// module_name
String mn = descriptor.name();
int module_name_index = cw.newModule(mn);
attr.putShort(module_name_index);
// module_flags
Set<ModuleDescriptor.Modifier> modifiers = descriptor.modifiers();
int module_flags = 0;
if (modifiers.contains(ModuleDescriptor.Modifier.OPEN))
module_flags |= ACC_OPEN;
if (modifiers.contains(ModuleDescriptor.Modifier.SYNTHETIC))
module_flags |= ACC_SYNTHETIC;
if (modifiers.contains(ModuleDescriptor.Modifier.MANDATED))
module_flags |= ACC_MANDATED;
attr.putShort(module_flags);
// module_version
String vs = descriptor.rawVersion().orElse(null);
if (vs == null) {
attr.putShort(0);
} else {
int module_version_index = cw.newUTF8(vs);
attr.putShort(module_version_index);
}
// requires_count
attr.putShort(descriptor.requires().size());
// requires[requires_count]
for (Requires r : descriptor.requires()) {
int requires_index = cw.newModule(r.name());
attr.putShort(requires_index);
int requires_flags = 0;
if (r.modifiers().contains(Requires.Modifier.TRANSITIVE))
requires_flags |= ACC_TRANSITIVE;
if (r.modifiers().contains(Requires.Modifier.STATIC))
requires_flags |= ACC_STATIC_PHASE;
if (r.modifiers().contains(Requires.Modifier.SYNTHETIC))
requires_flags |= ACC_SYNTHETIC;
if (r.modifiers().contains(Requires.Modifier.MANDATED))
requires_flags |= ACC_MANDATED;
attr.putShort(requires_flags);
int requires_version_index;
vs = r.rawCompiledVersion().orElse(null);
if (vs == null) {
requires_version_index = 0;
} else {
requires_version_index = cw.newUTF8(vs);
}
attr.putShort(requires_version_index);
}
// exports_count and exports[exports_count];
attr.putShort(descriptor.exports().size());
for (Exports e : descriptor.exports()) {
String pkg = e.source().replace('.', '/');
attr.putShort(cw.newPackage(pkg));
int exports_flags = 0;
if (e.modifiers().contains(Exports.Modifier.SYNTHETIC))
exports_flags |= ACC_SYNTHETIC;
if (e.modifiers().contains(Exports.Modifier.MANDATED))
exports_flags |= ACC_MANDATED;
attr.putShort(exports_flags);
if (e.isQualified()) {
Set<String> ts = e.targets();
attr.putShort(ts.size());
ts.forEach(target -> attr.putShort(cw.newModule(target)));
} else {
attr.putShort(0);
}
}
// opens_counts and opens[opens_counts]
attr.putShort(descriptor.opens().size());
for (Opens obj : descriptor.opens()) {
String pkg = obj.source().replace('.', '/');
attr.putShort(cw.newPackage(pkg));
int opens_flags = 0;
if (obj.modifiers().contains(Opens.Modifier.SYNTHETIC))
opens_flags |= ACC_SYNTHETIC;
if (obj.modifiers().contains(Opens.Modifier.MANDATED))
opens_flags |= ACC_MANDATED;
attr.putShort(opens_flags);
if (obj.isQualified()) {
Set<String> ts = obj.targets();
attr.putShort(ts.size());
ts.forEach(target -> attr.putShort(cw.newModule(target)));
} else {
attr.putShort(0);
}
}
// uses_count and uses_index[uses_count]
if (descriptor.uses().isEmpty()) {
attr.putShort(0);
} else {
attr.putShort(descriptor.uses().size());
for (String s : descriptor.uses()) {
String service = s.replace('.', '/');
int index = cw.newClass(service);
attr.putShort(index);
}
}
// provides_count and provides[provides_count]
if (descriptor.provides().isEmpty()) {
attr.putShort(0);
} else {
attr.putShort(descriptor.provides().size());
for (Provides p : descriptor.provides()) {
String service = p.service().replace('.', '/');
attr.putShort(cw.newClass(service));
int with_count = p.providers().size();
attr.putShort(with_count);
for (String provider : p.providers()) {
attr.putShort(cw.newClass(provider.replace('.', '/')));
}
}
}
return attr;
}
}
/**
* ModulePackages attribute.
*
* <pre> {@code
*
* ModulePackages_attribute {
* // index to CONSTANT_utf8_info structure in constant pool representing
* // the string "ModulePackages"
* u2 attribute_name_index;
* u4 attribute_length;
*
* // the number of entries in the packages table
* u2 packages_count;
* { // index to CONSTANT_Package_info structure with the package name
* u2 package_index
* } packages[package_count];
*
* }</pre>
*/
public static class ModulePackagesAttribute extends Attribute {
private final Set<String> packages;
public ModulePackagesAttribute(Set<String> packages) {
super(MODULE_PACKAGES);
this.packages = packages;
}
public ModulePackagesAttribute() {
this(null);
}
@Override
protected Attribute read(ClassReader cr,
int off,
int len,
char[] buf,
int codeOff,
Label[] labels)
{
// package count
int package_count = cr.readUnsignedShort(off);
off += 2;
// packages
Set<String> packages = new HashSet<>();
for (int i=0; i<package_count; i++) {
String pkg = cr.readPackage(off, buf).replace('/', '.');
packages.add(pkg);
off += 2;
}
return new ModulePackagesAttribute(packages);
}
@Override
protected ByteVector write(ClassWriter cw,
byte[] code,
int len,
int maxStack,
int maxLocals)
{
assert packages != null;
ByteVector attr = new ByteVector();
// package_count
attr.putShort(packages.size());
// packages
packages.stream()
.map(p -> p.replace('.', '/'))
.forEach(p -> attr.putShort(cw.newPackage(p)));
return attr;
}
}
/**
* ModuleMainClass attribute.
*
* <pre> {@code
*
* MainClass_attribute {
* // index to CONSTANT_utf8_info structure in constant pool representing
* // the string "ModuleMainClass"
* u2 attribute_name_index;
* u4 attribute_length;
*
* // index to CONSTANT_Class_info structure with the main class name
* u2 main_class_index;
* }
*
* } </pre>
*/
public static class ModuleMainClassAttribute extends Attribute {
private final String mainClass;
public ModuleMainClassAttribute(String mainClass) {
super(MODULE_MAIN_CLASS);
this.mainClass = mainClass;
}
public ModuleMainClassAttribute() {
this(null);
}
@Override
protected Attribute read(ClassReader cr,
int off,
int len,
char[] buf,
int codeOff,
Label[] labels)
{
String value = cr.readClass(off, buf).replace('/', '.');
return new ModuleMainClassAttribute(value);
}
@Override
protected ByteVector write(ClassWriter cw,
byte[] code,
int len,
int maxStack,
int maxLocals)
{
ByteVector attr = new ByteVector();
int index = cw.newClass(mainClass.replace('.', '/'));
attr.putShort(index);
return attr;
}
}
/**
* ModuleTarget attribute.
*
* <pre> {@code
*
* TargetPlatform_attribute {
* // index to CONSTANT_utf8_info structure in constant pool representing
* // the string "ModuleTarget"
* u2 attribute_name_index;
* u4 attribute_length;
*
* // index to CONSTANT_utf8_info structure with the target platform
* u2 target_platform_index;
* }
*
* } </pre>
*/
public static class ModuleTargetAttribute extends Attribute {
private final String targetPlatform;
public ModuleTargetAttribute(String targetPlatform) {
super(MODULE_TARGET);
this.targetPlatform = targetPlatform;
}
public ModuleTargetAttribute() {
this(null);
}
public String targetPlatform() {
return targetPlatform;
}
@Override
protected Attribute read(ClassReader cr,
int off,
int len,
char[] buf,
int codeOff,
Label[] labels)
{
String targetPlatform = null;
int target_platform_index = cr.readUnsignedShort(off);
if (target_platform_index != 0)
targetPlatform = cr.readUTF8(off, buf);
off += 2;
return new ModuleTargetAttribute(targetPlatform);
}
@Override
protected ByteVector write(ClassWriter cw,
byte[] code,
int len,
int maxStack,
int maxLocals)
{
ByteVector attr = new ByteVector();
int target_platform_index = 0;
if (targetPlatform != null && targetPlatform.length() > 0)
target_platform_index = cw.newUTF8(targetPlatform);
attr.putShort(target_platform_index);
return attr;
}
}
/**
* ModuleHashes attribute.
*
* <pre> {@code
*
* ModuleHashes_attribute {
* // index to CONSTANT_utf8_info structure in constant pool representing
* // the string "ModuleHashes"
* u2 attribute_name_index;
* u4 attribute_length;
*
* // index to CONSTANT_utf8_info structure with algorithm name
* u2 algorithm_index;
*
* // the number of entries in the hashes table
* u2 hashes_count;
* { u2 module_name_index (index to CONSTANT_Module_info structure)
* u2 hash_length;
* u1 hash[hash_length];
* } hashes[hashes_count];
*
* } </pre>
*/
static class ModuleHashesAttribute extends Attribute {
private final ModuleHashes hashes;
ModuleHashesAttribute(ModuleHashes hashes) {
super(MODULE_HASHES);
this.hashes = hashes;
}
ModuleHashesAttribute() {
this(null);
}
@Override
protected Attribute read(ClassReader cr,
int off,
int len,
char[] buf,
int codeOff,
Label[] labels)
{
String algorithm = cr.readUTF8(off, buf);
off += 2;
int hashes_count = cr.readUnsignedShort(off);
off += 2;
Map<String, byte[]> map = new HashMap<>();
for (int i=0; i<hashes_count; i++) {
String mn = cr.readModule(off, buf);
off += 2;
int hash_length = cr.readUnsignedShort(off);
off += 2;
byte[] hash = new byte[hash_length];
for (int j=0; j<hash_length; j++) {
hash[j] = (byte) (0xff & cr.readByte(off+j));
}
off += hash_length;
map.put(mn, hash);
}
ModuleHashes hashes = new ModuleHashes(algorithm, map);
return new ModuleHashesAttribute(hashes);
}
@Override
protected ByteVector write(ClassWriter cw,
byte[] code,
int len,
int maxStack,
int maxLocals)
{
ByteVector attr = new ByteVector();
int index = cw.newUTF8(hashes.algorithm());
attr.putShort(index);
Set<String> names = hashes.names();
attr.putShort(names.size());
for (String mn : names) {
byte[] hash = hashes.hashFor(mn);
assert hash != null;
attr.putShort(cw.newModule(mn));
attr.putShort(hash.length);
for (byte b: hash) {
attr.putByte(b);
}
}
return attr;
}
}
/**
* ModuleResolution_attribute {
* u2 attribute_name_index; // "ModuleResolution"
* u4 attribute_length; // 2
* u2 resolution_flags;
*
* The value of the resolution_flags item is a mask of flags used to denote
* properties of module resolution. The flags are as follows:
*
* // Optional
* 0x0001 (DO_NOT_RESOLVE_BY_DEFAULT)
*
* // At most one of:
* 0x0002 (WARN_DEPRECATED)
* 0x0004 (WARN_DEPRECATED_FOR_REMOVAL)
* 0x0008 (WARN_INCUBATING)
*/
static class ModuleResolutionAttribute extends Attribute {
private final int value;
ModuleResolutionAttribute() {
super(MODULE_RESOLUTION);
value = 0;
}
ModuleResolutionAttribute(int value) {
super(MODULE_RESOLUTION);
this.value = value;
}
@Override
protected Attribute read(ClassReader cr,
int off,
int len,
char[] buf,
int codeOff,
Label[] labels)
{
int flags = cr.readUnsignedShort(off);
return new ModuleResolutionAttribute(flags);
}
@Override
protected ByteVector write(ClassWriter cw,
byte[] code,
int len,
int maxStack,
int maxLocals)
{
ByteVector attr = new ByteVector();
attr.putShort(value);
return attr;
}
}
}

View File

@ -31,18 +31,18 @@ import java.io.OutputStream;
import java.lang.module.ModuleDescriptor.Version; import java.lang.module.ModuleDescriptor.Version;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import jdk.internal.org.objectweb.asm.Attribute; import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ClassReader; import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.commons.ModuleHashesAttribute;
import static jdk.internal.module.ClassFileAttributes.*; import jdk.internal.org.objectweb.asm.commons.ModuleResolutionAttribute;
import jdk.internal.org.objectweb.asm.commons.ModuleTargetAttribute;
/** /**
* Utility class to extend a module-info.class with additional attributes. * Utility class to extend a module-info.class with additional attributes.
@ -132,43 +132,6 @@ public final class ModuleInfoExtender {
return this; return this;
} }
/**
* A ClassVisitor that supports adding class file attributes. If an
* attribute already exists then the first occurrence of the attribute
* is replaced.
*/
private static class AttributeAddingClassVisitor extends ClassVisitor {
private Map<String, Attribute> attrs = new HashMap<>();
AttributeAddingClassVisitor(int api, ClassVisitor cv) {
super(api, cv);
}
void addAttribute(Attribute attr) {
attrs.put(attr.type, attr);
}
@Override
public void visitAttribute(Attribute attr) {
String name = attr.type;
Attribute replacement = attrs.get(name);
if (replacement != null) {
attr = replacement;
attrs.remove(name);
}
super.visitAttribute(attr);
}
/**
* Adds any remaining attributes that weren't replaced to the
* class file.
*/
void finish() {
attrs.values().forEach(a -> super.visitAttribute(a));
attrs.clear();
}
}
/** /**
* Outputs the modified module-info.class to the given output stream. * Outputs the modified module-info.class to the given output stream.
* Once this method has been called then the Extender object should * Once this method has been called then the Extender object should
@ -185,38 +148,86 @@ public final class ModuleInfoExtender {
* be discarded. * be discarded.
*/ */
public byte[] toByteArray() throws IOException { public byte[] toByteArray() throws IOException {
ClassWriter cw ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
= new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES); + ClassWriter.COMPUTE_FRAMES);
AttributeAddingClassVisitor cv
= new AttributeAddingClassVisitor(Opcodes.ASM5, cw);
ClassReader cr = new ClassReader(in); ClassReader cr = new ClassReader(in);
if (packages != null) ClassVisitor cv = new ClassVisitor(Opcodes.ASM6, cw) {
cv.addAttribute(new ModulePackagesAttribute(packages)); @Override
if (mainClass != null) public ModuleVisitor visitModule(String name, int flags, String version) {
cv.addAttribute(new ModuleMainClassAttribute(mainClass)); Version v = ModuleInfoExtender.this.version;
if (targetPlatform != null) String vs = (v != null) ? v.toString() : version;
cv.addAttribute(new ModuleTargetAttribute(targetPlatform)); ModuleVisitor mv = super.visitModule(name, flags, vs);
if (hashes != null)
cv.addAttribute(new ModuleHashesAttribute(hashes)); // ModuleMainClass attribute
if (moduleResolution != null) if (mainClass != null) {
cv.addAttribute(new ModuleResolutionAttribute(moduleResolution.value())); mv.visitMainClass(mainClass.replace('.', '/'));
}
// ModulePackages attribute
if (packages != null) {
packages.forEach(pn -> mv.visitPackage(pn.replace('.', '/')));
}
return new ModuleVisitor(Opcodes.ASM6, mv) {
public void visitMainClass(String existingMainClass) {
// skip main class if there is a new value
if (mainClass == null) {
super.visitMainClass(existingMainClass);
}
}
public void visitPackage(String existingPackage) {
// skip packages if there is a new set of packages
if (packages == null) {
super.visitPackage(existingPackage);
}
}
};
}
@Override
public void visitAttribute(Attribute attr) {
String name = attr.type;
// drop existing attributes if there are replacements
if (name.equals(ClassFileConstants.MODULE_TARGET)
&& targetPlatform != null)
return;
if (name.equals(ClassFileConstants.MODULE_RESOLUTION)
&& moduleResolution != null)
return;
if (name.equals(ClassFileConstants.MODULE_HASHES)
&& hashes != null)
return;
super.visitAttribute(attr);
}
};
List<Attribute> attrs = new ArrayList<>(); List<Attribute> attrs = new ArrayList<>();
// prototypes of attributes that should be parsed
attrs.add(new ModuleAttribute(version));
attrs.add(new ModulePackagesAttribute());
attrs.add(new ModuleMainClassAttribute());
attrs.add(new ModuleTargetAttribute()); attrs.add(new ModuleTargetAttribute());
attrs.add(new ModuleResolutionAttribute());
attrs.add(new ModuleHashesAttribute()); attrs.add(new ModuleHashesAttribute());
cr.accept(cv, attrs.toArray(new Attribute[0]), 0); cr.accept(cv, attrs.toArray(new Attribute[0]), 0);
// add any attributes that didn't replace previous attributes // add ModuleTarget, ModuleResolution and ModuleHashes attributes
cv.finish(); if (targetPlatform != null) {
cw.visitAttribute(new ModuleTargetAttribute(targetPlatform));
}
if (moduleResolution != null) {
int flags = moduleResolution.value();
cw.visitAttribute(new ModuleResolutionAttribute(flags));
}
if (hashes != null) {
String algorithm = hashes.algorithm();
List<String> names = new ArrayList<>();
List<byte[]> values = new ArrayList<>();
for (String name : hashes.names()) {
names.add(name);
values.add(hashes.hashFor(name));
}
cw.visitAttribute(new ModuleHashesAttribute(algorithm, names, values));
}
return cw.toByteArray(); return cw.toByteArray();
} }

View File

@ -28,13 +28,14 @@ import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleDescriptor;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Map;
import java.util.stream.Stream; import java.util.stream.Stream;
import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.commons.ModuleTargetAttribute;
import static jdk.internal.module.ClassFileAttributes.*; import static jdk.internal.org.objectweb.asm.Opcodes.*;
import static jdk.internal.module.ClassFileConstants.ACC_MODULE;
/** /**
* Utility class to write a ModuleDescriptor as a module-info.class. * Utility class to write a ModuleDescriptor as a module-info.class.
@ -42,6 +43,35 @@ import static jdk.internal.module.ClassFileConstants.ACC_MODULE;
public final class ModuleInfoWriter { public final class ModuleInfoWriter {
private static final Map<ModuleDescriptor.Modifier, Integer>
MODULE_MODS_TO_FLAGS = Map.of(
ModuleDescriptor.Modifier.OPEN, ACC_OPEN,
ModuleDescriptor.Modifier.SYNTHETIC, ACC_SYNTHETIC,
ModuleDescriptor.Modifier.MANDATED, ACC_MANDATED
);
private static final Map<ModuleDescriptor.Requires.Modifier, Integer>
REQUIRES_MODS_TO_FLAGS = Map.of(
ModuleDescriptor.Requires.Modifier.TRANSITIVE, ACC_TRANSITIVE,
ModuleDescriptor.Requires.Modifier.STATIC, ACC_STATIC_PHASE,
ModuleDescriptor.Requires.Modifier.SYNTHETIC, ACC_SYNTHETIC,
ModuleDescriptor.Requires.Modifier.MANDATED, ACC_MANDATED
);
private static final Map<ModuleDescriptor.Exports.Modifier, Integer>
EXPORTS_MODS_TO_FLAGS = Map.of(
ModuleDescriptor.Exports.Modifier.SYNTHETIC, ACC_SYNTHETIC,
ModuleDescriptor.Exports.Modifier.MANDATED, ACC_MANDATED
);
private static final Map<ModuleDescriptor.Opens.Modifier, Integer>
OPENS_MODS_TO_FLAGS = Map.of(
ModuleDescriptor.Opens.Modifier.SYNTHETIC, ACC_SYNTHETIC,
ModuleDescriptor.Opens.Modifier.MANDATED, ACC_MANDATED
);
private static final String[] EMPTY_STRING_ARRAY = new String[0];
private ModuleInfoWriter() { } private ModuleInfoWriter() { }
/** /**
@ -50,24 +80,75 @@ public final class ModuleInfoWriter {
*/ */
private static byte[] toModuleInfo(ModuleDescriptor md, ModuleTarget target) { private static byte[] toModuleInfo(ModuleDescriptor md, ModuleTarget target) {
ClassWriter cw = new ClassWriter(0); ClassWriter cw = new ClassWriter(0);
cw.visit(Opcodes.V1_9, ACC_MODULE, "module-info", null, null, null); cw.visit(Opcodes.V9, ACC_MODULE, "module-info", null, null, null);
cw.visitAttribute(new ModuleAttribute(md));
// for tests: write the ModulePackages attribute when there are packages int moduleFlags = md.modifiers().stream()
// that aren't exported or open .map(MODULE_MODS_TO_FLAGS::get)
.reduce(0, (x, y) -> (x | y));
String vs = md.rawVersion().orElse(null);
ModuleVisitor mv = cw.visitModule(md.name(), moduleFlags, vs);
// requires
for (ModuleDescriptor.Requires r : md.requires()) {
int flags = r.modifiers().stream()
.map(REQUIRES_MODS_TO_FLAGS::get)
.reduce(0, (x, y) -> (x | y));
vs = r.rawCompiledVersion().orElse(null);
mv.visitRequire(r.name(), flags, vs);
}
// exports
for (ModuleDescriptor.Exports e : md.exports()) {
int flags = e.modifiers().stream()
.map(EXPORTS_MODS_TO_FLAGS::get)
.reduce(0, (x, y) -> (x | y));
String[] targets = e.targets().toArray(EMPTY_STRING_ARRAY);
mv.visitExport(e.source().replace('.', '/'), flags, targets);
}
// opens
for (ModuleDescriptor.Opens opens : md.opens()) {
int flags = opens.modifiers().stream()
.map(OPENS_MODS_TO_FLAGS::get)
.reduce(0, (x, y) -> (x | y));
String[] targets = opens.targets().toArray(EMPTY_STRING_ARRAY);
mv.visitOpen(opens.source().replace('.', '/'), flags, targets);
}
// uses
md.uses().stream().map(sn -> sn.replace('.', '/')).forEach(mv::visitUse);
// provides
for (ModuleDescriptor.Provides p : md.provides()) {
mv.visitProvide(p.service().replace('.', '/'),
p.providers()
.stream()
.map(pn -> pn.replace('.', '/'))
.toArray(String[]::new));
}
// add the ModulePackages attribute when there are packages that aren't
// exported or open
Stream<String> exported = md.exports().stream() Stream<String> exported = md.exports().stream()
.map(ModuleDescriptor.Exports::source); .map(ModuleDescriptor.Exports::source);
Stream<String> open = md.opens().stream() Stream<String> open = md.opens().stream()
.map(ModuleDescriptor.Opens::source); .map(ModuleDescriptor.Opens::source);
long exportedOrOpen = Stream.concat(exported, open).distinct().count(); long exportedOrOpen = Stream.concat(exported, open).distinct().count();
if (md.packages().size() > exportedOrOpen) if (md.packages().size() > exportedOrOpen) {
cw.visitAttribute(new ModulePackagesAttribute(md.packages())); md.packages().stream()
.map(pn -> pn.replace('.', '/'))
.forEach(mv::visitPackage);
}
// write ModuleMainClass if the module has a main class // ModuleMainClass attribute
md.mainClass().ifPresent(mc -> cw.visitAttribute(new ModuleMainClassAttribute(mc))); md.mainClass()
.map(mc -> mc.replace('.', '/'))
.ifPresent(mv::visitMainClass);
// write ModuleTarget if there is a target platform mv.visitEnd();
if (target != null) {
// write ModuleTarget attribute if there is a target platform
if (target != null && target.targetPlatform().length() > 0) {
cw.visitAttribute(new ModuleTargetAttribute(target.targetPlatform())); cw.visitAttribute(new ModuleTargetAttribute(target.targetPlatform()));
} }

View File

@ -70,7 +70,7 @@ public abstract class AnnotationVisitor {
/** /**
* The ASM API version implemented by this visitor. The value of this field * The ASM API version implemented by this visitor. The value of this field
* must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/ */
protected final int api; protected final int api;
@ -85,7 +85,7 @@ public abstract class AnnotationVisitor {
* *
* @param api * @param api
* the ASM API version implemented by this visitor. Must be one * the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/ */
public AnnotationVisitor(final int api) { public AnnotationVisitor(final int api) {
this(api, null); this(api, null);
@ -96,13 +96,13 @@ public abstract class AnnotationVisitor {
* *
* @param api * @param api
* the ASM API version implemented by this visitor. Must be one * the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param av * @param av
* the annotation visitor to which this visitor must delegate * the annotation visitor to which this visitor must delegate
* method calls. May be null. * method calls. May be null.
*/ */
public AnnotationVisitor(final int api, final AnnotationVisitor av) { public AnnotationVisitor(final int api, final AnnotationVisitor av) {
if (api != Opcodes.ASM4 && api != Opcodes.ASM5) { if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
this.api = api; this.api = api;
@ -118,7 +118,7 @@ public abstract class AnnotationVisitor {
* the actual value, whose type must be {@link Byte}, * the actual value, whose type must be {@link Byte},
* {@link Boolean}, {@link Character}, {@link Short}, * {@link Boolean}, {@link Character}, {@link Short},
* {@link Integer} , {@link Long}, {@link Float}, {@link Double}, * {@link Integer} , {@link Long}, {@link Float}, {@link Double},
* {@link String} or {@link Type} or OBJECT or ARRAY sort. This * {@link String} or {@link Type} of OBJECT or ARRAY sort. This
* value can also be an array of byte, boolean, short, char, int, * value can also be an array of byte, boolean, short, char, int,
* long, float or double values (this is equivalent to using * long, float or double values (this is equivalent to using
* {@link #visitArray visitArray} and visiting each array element * {@link #visitArray visitArray} and visiting each array element

View File

@ -133,7 +133,7 @@ final class AnnotationWriter extends AnnotationVisitor {
*/ */
AnnotationWriter(final ClassWriter cw, final boolean named, AnnotationWriter(final ClassWriter cw, final boolean named,
final ByteVector bv, final ByteVector parent, final int offset) { final ByteVector bv, final ByteVector parent, final int offset) {
super(Opcodes.ASM5); super(Opcodes.ASM6);
this.cw = cw; this.cw = cw;
this.named = named; this.named = named;
this.bv = bv; this.bv = bv;

View File

@ -72,31 +72,6 @@ import java.io.InputStream;
*/ */
public class ClassReader { public class ClassReader {
/**
* True to enable signatures support.
*/
static final boolean SIGNATURES = true;
/**
* True to enable annotations support.
*/
static final boolean ANNOTATIONS = true;
/**
* True to enable stack map frames support.
*/
static final boolean FRAMES = true;
/**
* True to enable bytecode writing support.
*/
static final boolean WRITER = true;
/**
* True to enable JSR_W and GOTO_W support.
*/
static final boolean RESIZE = true;
/** /**
* Flag to skip method code. If this class is set <code>CODE</code> * Flag to skip method code. If this class is set <code>CODE</code>
* attribute won't be visited. This can be used, for example, to retrieve * attribute won't be visited. This can be used, for example, to retrieve
@ -133,6 +108,21 @@ public class ClassReader {
*/ */
public static final int EXPAND_FRAMES = 8; public static final int EXPAND_FRAMES = 8;
/**
* Flag to expand the ASM pseudo instructions into an equivalent sequence of
* standard bytecode instructions. When resolving a forward jump it may
* happen that the signed 2 bytes offset reserved for it is not sufficient
* to store the bytecode offset. In this case the jump instruction is
* replaced with a temporary ASM pseudo instruction using an unsigned 2
* bytes offset (see Label#resolve). This internal flag is used to re-read
* classes containing such instructions, in order to replace them with
* standard instructions. In addition, when this flag is used, GOTO_W and
* JSR_W are <i>not</i> converted into GOTO and JSR, to make sure that
* infinite loops where a GOTO_W is replaced with a GOTO in ClassReader and
* converted back to a GOTO_W in ClassWriter cannot occur.
*/
static final int EXPAND_ASM_INSNS = 256;
/** /**
* The class to be parsed. <i>The content of this array must not be * The class to be parsed. <i>The content of this array must not be
* modified. This field is intended for {@link Attribute} sub classes, and * modified. This field is intended for {@link Attribute} sub classes, and
@ -195,7 +185,7 @@ public class ClassReader {
public ClassReader(final byte[] b, final int off, final int len) { public ClassReader(final byte[] b, final int off, final int len) {
this.b = b; this.b = b;
// checks the class version // checks the class version
if (readShort(off + 6) > Opcodes.V1_9) { if (readShort(off + 6) > Opcodes.V9) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
// parses the constant pool // parses the constant pool
@ -234,6 +224,8 @@ public class ClassReader {
// case ClassWriter.CLASS: // case ClassWriter.CLASS:
// case ClassWriter.STR: // case ClassWriter.STR:
// case ClassWriter.MTYPE // case ClassWriter.MTYPE
// case ClassWriter.PACKAGE:
// case ClassWriter.MODULE:
default: default:
size = 3; size = 3;
break; break;
@ -377,7 +369,9 @@ public class ClassReader {
break; break;
// case ClassWriter.STR: // case ClassWriter.STR:
// case ClassWriter.CLASS: // case ClassWriter.CLASS:
// case ClassWriter.MTYPE // case ClassWriter.MTYPE:
// case ClassWriter.MODULE:
// case ClassWriter.PACKAGE:
default: default:
item.set(tag, readUTF8(index, buf), null, null); item.set(tag, readUTF8(index, buf), null, null);
break; break;
@ -584,11 +578,14 @@ public class ClassReader {
String enclosingOwner = null; String enclosingOwner = null;
String enclosingName = null; String enclosingName = null;
String enclosingDesc = null; String enclosingDesc = null;
String moduleMainClass = null;
int anns = 0; int anns = 0;
int ianns = 0; int ianns = 0;
int tanns = 0; int tanns = 0;
int itanns = 0; int itanns = 0;
int innerClasses = 0; int innerClasses = 0;
int module = 0;
int packages = 0;
Attribute attributes = null; Attribute attributes = null;
u = getAttributes(); u = getAttributes();
@ -607,13 +604,11 @@ public class ClassReader {
enclosingName = readUTF8(items[item], c); enclosingName = readUTF8(items[item], c);
enclosingDesc = readUTF8(items[item] + 2, c); enclosingDesc = readUTF8(items[item] + 2, c);
} }
} else if (SIGNATURES && "Signature".equals(attrName)) { } else if ("Signature".equals(attrName)) {
signature = readUTF8(u + 8, c); signature = readUTF8(u + 8, c);
} else if (ANNOTATIONS } else if ("RuntimeVisibleAnnotations".equals(attrName)) {
&& "RuntimeVisibleAnnotations".equals(attrName)) {
anns = u + 8; anns = u + 8;
} else if (ANNOTATIONS } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {
&& "RuntimeVisibleTypeAnnotations".equals(attrName)) {
tanns = u + 8; tanns = u + 8;
} else if ("Deprecated".equals(attrName)) { } else if ("Deprecated".equals(attrName)) {
access |= Opcodes.ACC_DEPRECATED; access |= Opcodes.ACC_DEPRECATED;
@ -623,12 +618,16 @@ public class ClassReader {
} else if ("SourceDebugExtension".equals(attrName)) { } else if ("SourceDebugExtension".equals(attrName)) {
int len = readInt(u + 4); int len = readInt(u + 4);
sourceDebug = readUTF(u + 8, len, new char[len]); sourceDebug = readUTF(u + 8, len, new char[len]);
} else if (ANNOTATIONS } else if ("RuntimeInvisibleAnnotations".equals(attrName)) {
&& "RuntimeInvisibleAnnotations".equals(attrName)) {
ianns = u + 8; ianns = u + 8;
} else if (ANNOTATIONS } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {
&& "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
itanns = u + 8; itanns = u + 8;
} else if ("Module".equals(attrName)) {
module = u + 8;
} else if ("ModuleMainClass".equals(attrName)) {
moduleMainClass = readClass(u + 8, c);
} else if ("ModulePackages".equals(attrName)) {
packages = u + 10;
} else if ("BootstrapMethods".equals(attrName)) { } else if ("BootstrapMethods".equals(attrName)) {
int[] bootstrapMethods = new int[readUnsignedShort(u + 8)]; int[] bootstrapMethods = new int[readUnsignedShort(u + 8)];
for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) { for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) {
@ -657,6 +656,12 @@ public class ClassReader {
classVisitor.visitSource(sourceFile, sourceDebug); classVisitor.visitSource(sourceFile, sourceDebug);
} }
// visits the module info and associated attributes
if (module != 0) {
readModule(classVisitor, context, module,
moduleMainClass, packages);
}
// visits the outer class // visits the outer class
if (enclosingOwner != null) { if (enclosingOwner != null) {
classVisitor.visitOuterClass(enclosingOwner, enclosingName, classVisitor.visitOuterClass(enclosingOwner, enclosingName,
@ -664,19 +669,19 @@ public class ClassReader {
} }
// visits the class annotations and type annotations // visits the class annotations and type annotations
if (ANNOTATIONS && anns != 0) { if (anns != 0) {
for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
classVisitor.visitAnnotation(readUTF8(v, c), true)); classVisitor.visitAnnotation(readUTF8(v, c), true));
} }
} }
if (ANNOTATIONS && ianns != 0) { if (ianns != 0) {
for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
classVisitor.visitAnnotation(readUTF8(v, c), false)); classVisitor.visitAnnotation(readUTF8(v, c), false));
} }
} }
if (ANNOTATIONS && tanns != 0) { if (tanns != 0) {
for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v); v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
@ -684,7 +689,7 @@ public class ClassReader {
context.typePath, readUTF8(v, c), true)); context.typePath, readUTF8(v, c), true));
} }
} }
if (ANNOTATIONS && itanns != 0) { if (itanns != 0) {
for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v); v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
@ -726,6 +731,120 @@ public class ClassReader {
classVisitor.visitEnd(); classVisitor.visitEnd();
} }
/**
* Reads the module attribute and visit it.
*
* @param classVisitor
* the current class visitor
* @param context
* information about the class being parsed.
* @param u
* start offset of the module attribute in the class file.
* @param mainClass
* name of the main class of a module or null.
* @param packages
* start offset of the concealed package attribute.
*/
private void readModule(final ClassVisitor classVisitor,
final Context context, int u,
final String mainClass, int packages) {
char[] buffer = context.buffer;
// reads module name, flags and version
String name = readModule(u, buffer);
int flags = readUnsignedShort(u + 2);
String version = readUTF8(u + 4, buffer);
u += 6;
ModuleVisitor mv = classVisitor.visitModule(name, flags, version);
if (mv == null) {
return;
}
// module attributes (main class, packages)
if (mainClass != null) {
mv.visitMainClass(mainClass);
}
if (packages != 0) {
for (int i = readUnsignedShort(packages - 2); i > 0; --i) {
String packaze = readPackage(packages, buffer);
mv.visitPackage(packaze);
packages += 2;
}
}
// reads requires
u += 2;
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
String module = readModule(u, buffer);
int access = readUnsignedShort(u + 2);
String requireVersion = readUTF8(u + 4, buffer);
mv.visitRequire(module, access, requireVersion);
u += 6;
}
// reads exports
u += 2;
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
String export = readPackage(u, buffer);
int access = readUnsignedShort(u + 2);
int exportToCount = readUnsignedShort(u + 4);
u += 6;
String[] tos = null;
if (exportToCount != 0) {
tos = new String[exportToCount];
for (int j = 0; j < tos.length; ++j) {
tos[j] = readModule(u, buffer);
u += 2;
}
}
mv.visitExport(export, access, tos);
}
// reads opens
u += 2;
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
String open = readPackage(u, buffer);
int access = readUnsignedShort(u + 2);
int openToCount = readUnsignedShort(u + 4);
u += 6;
String[] tos = null;
if (openToCount != 0) {
tos = new String[openToCount];
for (int j = 0; j < tos.length; ++j) {
tos[j] = readModule(u, buffer);
u += 2;
}
}
mv.visitOpen(open, access, tos);
}
// read uses
u += 2;
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
mv.visitUse(readClass(u, buffer));
u += 2;
}
// read provides
u += 2;
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
String service = readClass(u, buffer);
int provideWithCount = readUnsignedShort(u + 2);
u += 4;
String[] withs = new String[provideWithCount];
for (int j = 0; j < withs.length; ++j) {
withs[j] = readClass(u, buffer);
u += 2;
}
mv.visitProvide(service, withs);
}
mv.visitEnd();
}
/** /**
* Reads a field and makes the given visitor visit it. * Reads a field and makes the given visitor visit it.
* *
@ -762,24 +881,20 @@ public class ClassReader {
if ("ConstantValue".equals(attrName)) { if ("ConstantValue".equals(attrName)) {
int item = readUnsignedShort(u + 8); int item = readUnsignedShort(u + 8);
value = item == 0 ? null : readConst(item, c); value = item == 0 ? null : readConst(item, c);
} else if (SIGNATURES && "Signature".equals(attrName)) { } else if ("Signature".equals(attrName)) {
signature = readUTF8(u + 8, c); signature = readUTF8(u + 8, c);
} else if ("Deprecated".equals(attrName)) { } else if ("Deprecated".equals(attrName)) {
access |= Opcodes.ACC_DEPRECATED; access |= Opcodes.ACC_DEPRECATED;
} else if ("Synthetic".equals(attrName)) { } else if ("Synthetic".equals(attrName)) {
access |= Opcodes.ACC_SYNTHETIC access |= Opcodes.ACC_SYNTHETIC
| ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
} else if (ANNOTATIONS } else if ("RuntimeVisibleAnnotations".equals(attrName)) {
&& "RuntimeVisibleAnnotations".equals(attrName)) {
anns = u + 8; anns = u + 8;
} else if (ANNOTATIONS } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {
&& "RuntimeVisibleTypeAnnotations".equals(attrName)) {
tanns = u + 8; tanns = u + 8;
} else if (ANNOTATIONS } else if ("RuntimeInvisibleAnnotations".equals(attrName)) {
&& "RuntimeInvisibleAnnotations".equals(attrName)) {
ianns = u + 8; ianns = u + 8;
} else if (ANNOTATIONS } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {
&& "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
itanns = u + 8; itanns = u + 8;
} else { } else {
Attribute attr = readAttribute(context.attrs, attrName, u + 8, Attribute attr = readAttribute(context.attrs, attrName, u + 8,
@ -801,19 +916,19 @@ public class ClassReader {
} }
// visits the field annotations and type annotations // visits the field annotations and type annotations
if (ANNOTATIONS && anns != 0) { if (anns != 0) {
for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
fv.visitAnnotation(readUTF8(v, c), true)); fv.visitAnnotation(readUTF8(v, c), true));
} }
} }
if (ANNOTATIONS && ianns != 0) { if (ianns != 0) {
for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
fv.visitAnnotation(readUTF8(v, c), false)); fv.visitAnnotation(readUTF8(v, c), false));
} }
} }
if (ANNOTATIONS && tanns != 0) { if (tanns != 0) {
for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v); v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
@ -821,7 +936,7 @@ public class ClassReader {
context.typePath, readUTF8(v, c), true)); context.typePath, readUTF8(v, c), true));
} }
} }
if (ANNOTATIONS && itanns != 0) { if (itanns != 0) {
for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v); v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
@ -895,32 +1010,26 @@ public class ClassReader {
exceptions[j] = readClass(exception, c); exceptions[j] = readClass(exception, c);
exception += 2; exception += 2;
} }
} else if (SIGNATURES && "Signature".equals(attrName)) { } else if ("Signature".equals(attrName)) {
signature = readUTF8(u + 8, c); signature = readUTF8(u + 8, c);
} else if ("Deprecated".equals(attrName)) { } else if ("Deprecated".equals(attrName)) {
context.access |= Opcodes.ACC_DEPRECATED; context.access |= Opcodes.ACC_DEPRECATED;
} else if (ANNOTATIONS } else if ("RuntimeVisibleAnnotations".equals(attrName)) {
&& "RuntimeVisibleAnnotations".equals(attrName)) {
anns = u + 8; anns = u + 8;
} else if (ANNOTATIONS } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {
&& "RuntimeVisibleTypeAnnotations".equals(attrName)) {
tanns = u + 8; tanns = u + 8;
} else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) { } else if ("AnnotationDefault".equals(attrName)) {
dann = u + 8; dann = u + 8;
} else if ("Synthetic".equals(attrName)) { } else if ("Synthetic".equals(attrName)) {
context.access |= Opcodes.ACC_SYNTHETIC context.access |= Opcodes.ACC_SYNTHETIC
| ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
} else if (ANNOTATIONS } else if ("RuntimeInvisibleAnnotations".equals(attrName)) {
&& "RuntimeInvisibleAnnotations".equals(attrName)) {
ianns = u + 8; ianns = u + 8;
} else if (ANNOTATIONS } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {
&& "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
itanns = u + 8; itanns = u + 8;
} else if (ANNOTATIONS } else if ("RuntimeVisibleParameterAnnotations".equals(attrName)) {
&& "RuntimeVisibleParameterAnnotations".equals(attrName)) {
mpanns = u + 8; mpanns = u + 8;
} else if (ANNOTATIONS } else if ("RuntimeInvisibleParameterAnnotations".equals(attrName)) {
&& "RuntimeInvisibleParameterAnnotations".equals(attrName)) {
impanns = u + 8; impanns = u + 8;
} else if ("MethodParameters".equals(attrName)) { } else if ("MethodParameters".equals(attrName)) {
methodParameters = u + 8; methodParameters = u + 8;
@ -953,7 +1062,7 @@ public class ClassReader {
* access, name and descriptor can have been changed, this is not * access, name and descriptor can have been changed, this is not
* important since they are not copied as is from the reader). * important since they are not copied as is from the reader).
*/ */
if (WRITER && mv instanceof MethodWriter) { if (mv instanceof MethodWriter) {
MethodWriter mw = (MethodWriter) mv; MethodWriter mw = (MethodWriter) mv;
if (mw.cw.cr == this && signature == mw.signature) { if (mw.cw.cr == this && signature == mw.signature) {
boolean sameExceptions = false; boolean sameExceptions = false;
@ -990,26 +1099,26 @@ public class ClassReader {
} }
// visits the method annotations // visits the method annotations
if (ANNOTATIONS && dann != 0) { if (dann != 0) {
AnnotationVisitor dv = mv.visitAnnotationDefault(); AnnotationVisitor dv = mv.visitAnnotationDefault();
readAnnotationValue(dann, c, null, dv); readAnnotationValue(dann, c, null, dv);
if (dv != null) { if (dv != null) {
dv.visitEnd(); dv.visitEnd();
} }
} }
if (ANNOTATIONS && anns != 0) { if (anns != 0) {
for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
mv.visitAnnotation(readUTF8(v, c), true)); mv.visitAnnotation(readUTF8(v, c), true));
} }
} }
if (ANNOTATIONS && ianns != 0) { if (ianns != 0) {
for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
mv.visitAnnotation(readUTF8(v, c), false)); mv.visitAnnotation(readUTF8(v, c), false));
} }
} }
if (ANNOTATIONS && tanns != 0) { if (tanns != 0) {
for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v); v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
@ -1017,7 +1126,7 @@ public class ClassReader {
context.typePath, readUTF8(v, c), true)); context.typePath, readUTF8(v, c), true));
} }
} }
if (ANNOTATIONS && itanns != 0) { if (itanns != 0) {
for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v); v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
@ -1025,10 +1134,10 @@ public class ClassReader {
context.typePath, readUTF8(v, c), false)); context.typePath, readUTF8(v, c), false));
} }
} }
if (ANNOTATIONS && mpanns != 0) { if (mpanns != 0) {
readParameterAnnotations(mv, context, mpanns, true); readParameterAnnotations(mv, context, mpanns, true);
} }
if (ANNOTATIONS && impanns != 0) { if (impanns != 0) {
readParameterAnnotations(mv, context, impanns, false); readParameterAnnotations(mv, context, impanns, false);
} }
@ -1075,7 +1184,7 @@ public class ClassReader {
int codeStart = u; int codeStart = u;
int codeEnd = u + codeLength; int codeEnd = u + codeLength;
Label[] labels = context.labels = new Label[codeLength + 2]; Label[] labels = context.labels = new Label[codeLength + 2];
readLabel(codeLength + 1, labels); createLabel(codeLength + 1, labels);
while (u < codeEnd) { while (u < codeEnd) {
int offset = u - codeStart; int offset = u - codeStart;
int opcode = b[u] & 0xFF; int opcode = b[u] & 0xFF;
@ -1085,11 +1194,16 @@ public class ClassReader {
u += 1; u += 1;
break; break;
case ClassWriter.LABEL_INSN: case ClassWriter.LABEL_INSN:
readLabel(offset + readShort(u + 1), labels); createLabel(offset + readShort(u + 1), labels);
u += 3;
break;
case ClassWriter.ASM_LABEL_INSN:
createLabel(offset + readUnsignedShort(u + 1), labels);
u += 3; u += 3;
break; break;
case ClassWriter.LABELW_INSN: case ClassWriter.LABELW_INSN:
readLabel(offset + readInt(u + 1), labels); case ClassWriter.ASM_LABELW_INSN:
createLabel(offset + readInt(u + 1), labels);
u += 5; u += 5;
break; break;
case ClassWriter.WIDE_INSN: case ClassWriter.WIDE_INSN:
@ -1104,9 +1218,9 @@ public class ClassReader {
// skips 0 to 3 padding bytes // skips 0 to 3 padding bytes
u = u + 4 - (offset & 3); u = u + 4 - (offset & 3);
// reads instruction // reads instruction
readLabel(offset + readInt(u), labels); createLabel(offset + readInt(u), labels);
for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) { for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) {
readLabel(offset + readInt(u + 12), labels); createLabel(offset + readInt(u + 12), labels);
u += 4; u += 4;
} }
u += 12; u += 12;
@ -1115,9 +1229,9 @@ public class ClassReader {
// skips 0 to 3 padding bytes // skips 0 to 3 padding bytes
u = u + 4 - (offset & 3); u = u + 4 - (offset & 3);
// reads instruction // reads instruction
readLabel(offset + readInt(u), labels); createLabel(offset + readInt(u), labels);
for (int i = readInt(u + 4); i > 0; --i) { for (int i = readInt(u + 4); i > 0; --i) {
readLabel(offset + readInt(u + 12), labels); createLabel(offset + readInt(u + 12), labels);
u += 8; u += 8;
} }
u += 8; u += 8;
@ -1147,9 +1261,9 @@ public class ClassReader {
// reads the try catch entries to find the labels, and also visits them // reads the try catch entries to find the labels, and also visits them
for (int i = readUnsignedShort(u); i > 0; --i) { for (int i = readUnsignedShort(u); i > 0; --i) {
Label start = readLabel(readUnsignedShort(u + 2), labels); Label start = createLabel(readUnsignedShort(u + 2), labels);
Label end = readLabel(readUnsignedShort(u + 4), labels); Label end = createLabel(readUnsignedShort(u + 4), labels);
Label handler = readLabel(readUnsignedShort(u + 6), labels); Label handler = createLabel(readUnsignedShort(u + 6), labels);
String type = readUTF8(items[readUnsignedShort(u + 8)], c); String type = readUTF8(items[readUnsignedShort(u + 8)], c);
mv.visitTryCatchBlock(start, end, handler, type); mv.visitTryCatchBlock(start, end, handler, type);
u += 8; u += 8;
@ -1180,13 +1294,9 @@ public class ClassReader {
varTable = u + 8; varTable = u + 8;
for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) { for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
int label = readUnsignedShort(v + 10); int label = readUnsignedShort(v + 10);
if (labels[label] == null) { createDebugLabel(label, labels);
readLabel(label, labels).status |= Label.DEBUG;
}
label += readUnsignedShort(v + 12); label += readUnsignedShort(v + 12);
if (labels[label] == null) { createDebugLabel(label, labels);
readLabel(label, labels).status |= Label.DEBUG;
}
v += 10; v += 10;
} }
} }
@ -1196,9 +1306,7 @@ public class ClassReader {
if ((context.flags & SKIP_DEBUG) == 0) { if ((context.flags & SKIP_DEBUG) == 0) {
for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) { for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
int label = readUnsignedShort(v + 10); int label = readUnsignedShort(v + 10);
if (labels[label] == null) { createDebugLabel(label, labels);
readLabel(label, labels).status |= Label.DEBUG;
}
Label l = labels[label]; Label l = labels[label];
while (l.line > 0) { while (l.line > 0) {
if (l.next == null) { if (l.next == null) {
@ -1210,17 +1318,15 @@ public class ClassReader {
v += 4; v += 4;
} }
} }
} else if (ANNOTATIONS } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {
&& "RuntimeVisibleTypeAnnotations".equals(attrName)) {
tanns = readTypeAnnotations(mv, context, u + 8, true); tanns = readTypeAnnotations(mv, context, u + 8, true);
ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1 ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1
: readUnsignedShort(tanns[0] + 1); : readUnsignedShort(tanns[0] + 1);
} else if (ANNOTATIONS } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {
&& "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
itanns = readTypeAnnotations(mv, context, u + 8, false); itanns = readTypeAnnotations(mv, context, u + 8, false);
nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1 nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1
: readUnsignedShort(itanns[0] + 1); : readUnsignedShort(itanns[0] + 1);
} else if (FRAMES && "StackMapTable".equals(attrName)) { } else if ("StackMapTable".equals(attrName)) {
if ((context.flags & SKIP_FRAMES) == 0) { if ((context.flags & SKIP_FRAMES) == 0) {
stackMap = u + 10; stackMap = u + 10;
stackMapSize = readInt(u + 4); stackMapSize = readInt(u + 4);
@ -1244,7 +1350,7 @@ public class ClassReader {
* this by parsing the stack map table without a full decoding * this by parsing the stack map table without a full decoding
* (see below). * (see below).
*/ */
} else if (FRAMES && "StackMap".equals(attrName)) { } else if ("StackMap".equals(attrName)) {
if ((context.flags & SKIP_FRAMES) == 0) { if ((context.flags & SKIP_FRAMES) == 0) {
zip = false; zip = false;
stackMap = u + 10; stackMap = u + 10;
@ -1273,7 +1379,7 @@ public class ClassReader {
u += 2; u += 2;
// generates the first (implicit) stack map frame // generates the first (implicit) stack map frame
if (FRAMES && stackMap != 0) { if (stackMap != 0) {
/* /*
* for the first explicit frame the offset is not offset_delta + 1 * for the first explicit frame the offset is not offset_delta + 1
* but only offset_delta; setting the implicit frame offset to -1 * but only offset_delta; setting the implicit frame offset to -1
@ -1306,14 +1412,31 @@ public class ClassReader {
int v = readUnsignedShort(i + 1); int v = readUnsignedShort(i + 1);
if (v >= 0 && v < codeLength) { if (v >= 0 && v < codeLength) {
if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) { if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) {
readLabel(v, labels); createLabel(v, labels);
} }
} }
} }
} }
} }
if ((context.flags & EXPAND_ASM_INSNS) != 0
&& (context.flags & EXPAND_FRAMES) != 0) {
// Expanding the ASM pseudo instructions can introduce F_INSERT
// frames, even if the method does not currently have any frame.
// Also these inserted frames must be computed by simulating the
// effect of the bytecode instructions one by one, starting from the
// first one and the last existing frame (or the implicit first
// one). Finally, due to the way MethodWriter computes this (with
// the compute = INSERTED_FRAMES option), MethodWriter needs to know
// maxLocals before the first instruction is visited. For all these
// reasons we always visit the implicit first frame in this case
// (passing only maxLocals - the rest can be and is computed in
// MethodWriter).
mv.visitFrame(Opcodes.F_NEW, maxLocals, null, 0, null);
}
// visits the instructions // visits the instructions
int opcodeDelta = (context.flags & EXPAND_ASM_INSNS) == 0 ? -33 : 0;
boolean insertFrame = false;
u = codeStart; u = codeStart;
while (u < codeEnd) { while (u < codeEnd) {
int offset = u - codeStart; int offset = u - codeStart;
@ -1334,7 +1457,7 @@ public class ClassReader {
} }
// visits the frame for this offset, if any // visits the frame for this offset, if any
while (FRAMES && frame != null while (frame != null
&& (frame.offset == offset || frame.offset == -1)) { && (frame.offset == offset || frame.offset == -1)) {
// if there is a frame for this offset, makes the visitor visit // if there is a frame for this offset, makes the visitor visit
// it, and reads the next frame if there is one. // it, and reads the next frame if there is one.
@ -1346,6 +1469,9 @@ public class ClassReader {
mv.visitFrame(frame.mode, frame.localDiff, frame.local, mv.visitFrame(frame.mode, frame.localDiff, frame.local,
frame.stackCount, frame.stack); frame.stackCount, frame.stack);
} }
// if there is already a frame for this offset, there is no
// need to insert a new one.
insertFrame = false;
} }
if (frameCount > 0) { if (frameCount > 0) {
stackMap = readFrame(stackMap, zip, unzip, frame); stackMap = readFrame(stackMap, zip, unzip, frame);
@ -1354,6 +1480,13 @@ public class ClassReader {
frame = null; frame = null;
} }
} }
// inserts a frame for this offset, if requested by setting
// insertFrame to true during the previous iteration. The actual
// frame content will be computed in MethodWriter.
if (insertFrame) {
mv.visitFrame(ClassWriter.F_INSERT, 0, null, 0, null);
insertFrame = false;
}
// visits the instruction at this offset // visits the instruction at this offset
int opcode = b[u] & 0xFF; int opcode = b[u] & 0xFF;
@ -1378,9 +1511,47 @@ public class ClassReader {
u += 3; u += 3;
break; break;
case ClassWriter.LABELW_INSN: case ClassWriter.LABELW_INSN:
mv.visitJumpInsn(opcode - 33, labels[offset + readInt(u + 1)]); mv.visitJumpInsn(opcode + opcodeDelta, labels[offset
+ readInt(u + 1)]);
u += 5; u += 5;
break; break;
case ClassWriter.ASM_LABEL_INSN: {
// changes temporary opcodes 202 to 217 (inclusive), 218
// and 219 to IFEQ ... JSR (inclusive), IFNULL and
// IFNONNULL
opcode = opcode < 218 ? opcode - 49 : opcode - 20;
Label target = labels[offset + readUnsignedShort(u + 1)];
// replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
// <l> with IFNOTxxx <L> GOTO_W <l> L:..., where IFNOTxxx is
// the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
// and where <L> designates the instruction just after
// the GOTO_W.
if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) {
mv.visitJumpInsn(opcode + 33, target);
} else {
opcode = opcode <= 166 ? ((opcode + 1) ^ 1) - 1
: opcode ^ 1;
Label endif = createLabel(offset + 3, labels);
mv.visitJumpInsn(opcode, endif);
mv.visitJumpInsn(200, target); // GOTO_W
// endif designates the instruction just after GOTO_W,
// and is visited as part of the next instruction. Since
// it is a jump target, we need to insert a frame here.
insertFrame = true;
}
u += 3;
break;
}
case ClassWriter.ASM_LABELW_INSN: {
// replaces the pseudo GOTO_W instruction with a real one.
mv.visitJumpInsn(200, labels[offset + readInt(u + 1)]);
// The instruction just after is a jump target (because pseudo
// GOTO_W are used in patterns IFNOTxxx <L> GOTO_W <l> L:...,
// see MethodWriter), so we need to insert a frame here.
insertFrame = true;
u += 5;
break;
}
case ClassWriter.WIDE_INSN: case ClassWriter.WIDE_INSN:
opcode = b[u + 1] & 0xFF; opcode = b[u + 1] & 0xFF;
if (opcode == Opcodes.IINC) { if (opcode == Opcodes.IINC) {
@ -1636,8 +1807,8 @@ public class ClassReader {
for (int j = readUnsignedShort(u + 1); j > 0; --j) { for (int j = readUnsignedShort(u + 1); j > 0; --j) {
int start = readUnsignedShort(u + 3); int start = readUnsignedShort(u + 3);
int length = readUnsignedShort(u + 5); int length = readUnsignedShort(u + 5);
readLabel(start, context.labels); createLabel(start, context.labels);
readLabel(start + length, context.labels); createLabel(start + length, context.labels);
u += 6; u += 6;
} }
u += 3; u += 3;
@ -1716,8 +1887,8 @@ public class ClassReader {
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
int start = readUnsignedShort(u); int start = readUnsignedShort(u);
int length = readUnsignedShort(u + 2); int length = readUnsignedShort(u + 2);
context.start[i] = readLabel(start, context.labels); context.start[i] = createLabel(start, context.labels);
context.end[i] = readLabel(start + length, context.labels); context.end[i] = createLabel(start + length, context.labels);
context.index[i] = readUnsignedShort(u + 4); context.index[i] = readUnsignedShort(u + 4);
u += 6; u += 6;
} }
@ -2137,7 +2308,7 @@ public class ClassReader {
} }
} }
frame.offset += delta + 1; frame.offset += delta + 1;
readLabel(frame.offset, labels); createLabel(frame.offset, labels);
return stackMap; return stackMap;
} }
@ -2190,7 +2361,7 @@ public class ClassReader {
v += 2; v += 2;
break; break;
default: // Uninitialized default: // Uninitialized
frame[index] = readLabel(readUnsignedShort(v), labels); frame[index] = createLabel(readUnsignedShort(v), labels);
v += 2; v += 2;
} }
return v; return v;
@ -2216,6 +2387,39 @@ public class ClassReader {
return labels[offset]; return labels[offset];
} }
/**
* Creates a label without the Label.DEBUG flag set, for the given offset.
* The label is created with a call to {@link #readLabel} and its
* Label.DEBUG flag is cleared.
*
* @param offset
* a bytecode offset in a method.
* @param labels
* the already created labels, indexed by their offset.
* @return a Label without the Label.DEBUG flag set.
*/
private Label createLabel(int offset, Label[] labels) {
Label label = readLabel(offset, labels);
label.status &= ~Label.DEBUG;
return label;
}
/**
* Creates a label with the Label.DEBUG flag set, if there is no already
* existing label for the given offset (otherwise does nothing). The label
* is created with a call to {@link #readLabel}.
*
* @param offset
* a bytecode offset in a method.
* @param labels
* the already created labels, indexed by their offset.
*/
private void createDebugLabel(int offset, Label[] labels) {
if (labels[offset] == null) {
readLabel(offset, labels).status |= Label.DEBUG;
}
}
/** /**
* Returns the start index of the attribute_info structure of this class. * Returns the start index of the attribute_info structure of this class.
* *
@ -2470,6 +2674,20 @@ public class ClassReader {
return new String(buf, 0, strLen); return new String(buf, 0, strLen);
} }
/**
* Read a stringish constant item (CONSTANT_Class, CONSTANT_String,
* CONSTANT_MethodType, CONSTANT_Module or CONSTANT_Package
* @param index
* @param buf
* @return
*/
private String readStringish(final int index, final char[] buf) {
// computes the start index of the item in b
// and reads the CONSTANT_Utf8 item designated by
// the first two bytes of this item
return readUTF8(items[readUnsignedShort(index)], buf);
}
/** /**
* Reads a class constant pool item in {@link #b b}. <i>This method is * Reads a class constant pool item in {@link #b b}. <i>This method is
* intended for {@link Attribute} sub classes, and is normally not needed by * intended for {@link Attribute} sub classes, and is normally not needed by
@ -2484,44 +2702,41 @@ public class ClassReader {
* @return the String corresponding to the specified class item. * @return the String corresponding to the specified class item.
*/ */
public String readClass(final int index, final char[] buf) { public String readClass(final int index, final char[] buf) {
// computes the start index of the CONSTANT_Class item in b return readStringish(index, buf);
// and reads the CONSTANT_Utf8 item designated by
// the first two bytes of this CONSTANT_Class item
return readUTF8(items[readUnsignedShort(index)], buf);
} }
/** /**
* Reads a CONSTANT_Module_info item in {@code b}. This method is intended * Reads a module constant pool item in {@link #b b}. <i>This method is
* for {@link Attribute} sub classes, and is normally not needed by class * intended for {@link Attribute} sub classes, and is normally not needed by
* generators or adapters.</i> * class generators or adapters.</i>
* *
* @param index * @param index
* the start index of an unsigned short value in {@link #b b}, * the start index of an unsigned short value in {@link #b b},
* whose value is the index of a module constant pool item. * whose value is the index of a module constant pool item.
* @param buf * @param buf
* buffer to be used to read the item. This buffer must be * buffer to be used to read the item. This buffer must be
* sufficiently large. It is not automatically resized. * sufficiently large. It is not automatically resized.
* @return the String corresponding to the specified module item. * @return the String corresponding to the specified module item.
*/ */
public String readModule(int index, char[] buf) { public String readModule(final int index, final char[] buf) {
return readUTF8(items[readUnsignedShort(index)], buf); return readStringish(index, buf);
} }
/** /**
* Reads a CONSTANT_Package_info item in {@code b}. This method is * Reads a module constant pool item in {@link #b b}. <i>This method is
* intended for {@link Attribute} sub slasses, and is normally not needed * intended for {@link Attribute} sub classes, and is normally not needed by
* by class generators or adapters.</i> * class generators or adapters.</i>
* *
* @param index * @param index
* the start index of an unsigned short value in {@link #b b}, * the start index of an unsigned short value in {@link #b b},
* whose value is the index of a package constant pool item. * whose value is the index of a module constant pool item.
* @param buf * @param buf
* buffer to be used to read the item. This buffer must be * buffer to be used to read the item. This buffer must be
* sufficiently large. It is not automatically resized. * sufficiently large. It is not automatically resized.
* @return the String corresponding to the specified package item. * @return the String corresponding to the specified module item.
*/ */
public String readPackage(int index, char[] buf) { public String readPackage(final int index, final char[] buf) {
return readUTF8(items[readUnsignedShort(index)], buf); return readStringish(index, buf);
} }
/** /**
@ -2550,8 +2765,6 @@ public class ClassReader {
case ClassWriter.DOUBLE: case ClassWriter.DOUBLE:
return Double.longBitsToDouble(readLong(index)); return Double.longBitsToDouble(readLong(index));
case ClassWriter.CLASS: case ClassWriter.CLASS:
case ClassWriter.MODULE:
case ClassWriter.PACKAGE:
return Type.getObjectType(readUTF8(index, buf)); return Type.getObjectType(readUTF8(index, buf));
case ClassWriter.STR: case ClassWriter.STR:
return readUTF8(index, buf); return readUTF8(index, buf);

View File

@ -61,7 +61,7 @@ package jdk.internal.org.objectweb.asm;
/** /**
* A visitor to visit a Java class. The methods of this class must be called in * A visitor to visit a Java class. The methods of this class must be called in
* the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [ * the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
* <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> | * <tt>visitModule</tt> ][ <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
* <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* ( * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* (
* <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt> )* * <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt> )*
* <tt>visitEnd</tt>. * <tt>visitEnd</tt>.
@ -72,7 +72,7 @@ public abstract class ClassVisitor {
/** /**
* The ASM API version implemented by this visitor. The value of this field * The ASM API version implemented by this visitor. The value of this field
* must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/ */
protected final int api; protected final int api;
@ -87,7 +87,7 @@ public abstract class ClassVisitor {
* *
* @param api * @param api
* the ASM API version implemented by this visitor. Must be one * the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/ */
public ClassVisitor(final int api) { public ClassVisitor(final int api) {
this(api, null); this(api, null);
@ -98,13 +98,13 @@ public abstract class ClassVisitor {
* *
* @param api * @param api
* the ASM API version implemented by this visitor. Must be one * the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param cv * @param cv
* the class visitor to which this visitor must delegate method * the class visitor to which this visitor must delegate method
* calls. May be null. * calls. May be null.
*/ */
public ClassVisitor(final int api, final ClassVisitor cv) { public ClassVisitor(final int api, final ClassVisitor cv) {
if (api != Opcodes.ASM4 && api != Opcodes.ASM5) { if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
this.api = api; this.api = api;
@ -160,6 +160,28 @@ public abstract class ClassVisitor {
} }
} }
/**
* Visit the module corresponding to the class.
* @param name
* module name
* @param access
* module flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC}
* and {@code ACC_MANDATED}.
* @param version
* module version or null.
* @return a visitor to visit the module values, or <tt>null</tt> if
* this visitor is not interested in visiting this module.
*/
public ModuleVisitor visitModule(String name, int access, String version) {
if (api < Opcodes.ASM6) {
throw new RuntimeException();
}
if (cv != null) {
return cv.visitModule(name, access, version);
}
return null;
}
/** /**
* Visits the enclosing class of the class. This method must be called only * Visits the enclosing class of the class. This method must be called only
* if the class has an enclosing class. * if the class has an enclosing class.

View File

@ -87,8 +87,8 @@ public class ClassWriter extends ClassVisitor {
* {@link MethodVisitor#visitFrame} method are ignored, and the stack map * {@link MethodVisitor#visitFrame} method are ignored, and the stack map
* frames are recomputed from the methods bytecode. The arguments of the * frames are recomputed from the methods bytecode. The arguments of the
* {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and * {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and
* recomputed from the bytecode. In other words, computeFrames implies * recomputed from the bytecode. In other words, COMPUTE_FRAMES implies
* computeMaxs. * COMPUTE_MAXS.
* *
* @see #ClassWriter(int) * @see #ClassWriter(int)
*/ */
@ -196,6 +196,27 @@ public class ClassWriter extends ClassVisitor {
*/ */
static final int WIDE_INSN = 17; static final int WIDE_INSN = 17;
/**
* The type of the ASM pseudo instructions with an unsigned 2 bytes offset
* label (see Label#resolve).
*/
static final int ASM_LABEL_INSN = 18;
/**
* The type of the ASM pseudo instructions with a 4 bytes offset label.
*/
static final int ASM_LABELW_INSN = 19;
/**
* Represents a frame inserted between already existing frames. This kind of
* frame can only be used if the frame content can be computed from the
* previous existing frame and from the instructions between this existing
* frame and the inserted one, without any knowledge of the type hierarchy.
* This kind of frame is only used when an unconditional jump is inserted in
* a method while expanding an ASM pseudo instruction (see ClassReader).
*/
static final int F_INSERT = 256;
/** /**
* The instruction types of all JVM opcodes. * The instruction types of all JVM opcodes.
*/ */
@ -284,7 +305,7 @@ public class ClassWriter extends ClassVisitor {
/** /**
* The base value for all CONSTANT_MethodHandle constant pool items. * The base value for all CONSTANT_MethodHandle constant pool items.
* Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9 * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9
* different items. * different items (from 21 to 29).
*/ */
static final int HANDLE_BASE = 20; static final int HANDLE_BASE = 20;
@ -433,6 +454,11 @@ public class ClassWriter extends ClassVisitor {
*/ */
private ByteVector sourceDebug; private ByteVector sourceDebug;
/**
* The module attribute of this class.
*/
private ModuleWriter moduleWriter;
/** /**
* The constant pool item that contains the name of the enclosing class of * The constant pool item that contains the name of the enclosing class of
* this class. * this class.
@ -523,25 +549,19 @@ public class ClassWriter extends ClassVisitor {
MethodWriter lastMethod; MethodWriter lastMethod;
/** /**
* <tt>true</tt> if the maximum stack size and number of local variables * Indicates what must be automatically computed.
* must be automatically computed. *
* @see MethodWriter#compute
*/ */
private boolean computeMaxs; private int compute;
/** /**
* <tt>true</tt> if the stack map frames must be recomputed from scratch. * <tt>true</tt> if some methods have wide forward jumps using ASM pseudo
* instructions, which need to be expanded into sequences of standard
* bytecode instructions. In this case the class is re-read and re-written
* with a ClassReader -> ClassWriter chain to perform this transformation.
*/ */
private boolean computeFrames; boolean hasAsmInsns;
/**
* <tt>true</tt> if the stack map tables of this class are invalid. The
* {@link MethodWriter#resizeInstructions} method cannot transform existing
* stack map tables, and so produces potentially invalid classes when it is
* executed. In this case the class is reread and rewritten with the
* {@link #COMPUTE_FRAMES} option (the resizeInstructions method can resize
* stack map tables when this option is used).
*/
boolean invalidFrames;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Static initializer // Static initializer
@ -552,11 +572,11 @@ public class ClassWriter extends ClassVisitor {
*/ */
static { static {
int i; int i;
byte[] b = new byte[220]; byte[] b = new byte[221];
String s = "AAAAAAAAAAAAAAAABCLMMDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD" String s = "AAAAAAAAAAAAAAAABCLMMDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD"
+ "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAJJJJJJJJJJJJJJJJDOPAA" + "AAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAJJJJJJJJJJJJJJJJDOPAA"
+ "AAAAGGGGGGGHIFBFAAFFAARQJJKKJJJJJJJJJJJJJJJJJJ"; + "AAAAGGGGGGGHIFBFAAFFAARQJJKKSSSSSSSSSSSSSSSSSST";
for (i = 0; i < b.length; ++i) { for (i = 0; i < b.length; ++i) {
b[i] = (byte) (s.charAt(i) - 'A'); b[i] = (byte) (s.charAt(i) - 'A');
} }
@ -610,8 +630,9 @@ public class ClassWriter extends ClassVisitor {
// // temporary opcodes used internally by ASM - see Label and // // temporary opcodes used internally by ASM - see Label and
// MethodWriter // MethodWriter
// for (i = 202; i < 220; ++i) { // for (i = 202; i < 220; ++i) {
// b[i] = LABEL_INSN; // b[i] = ASM_LABEL_INSN;
// } // }
// b[220] = ASM_LABELW_INSN;
// //
// // LDC(_W) instructions // // LDC(_W) instructions
// b[Constants.LDC] = LDC_INSN; // b[Constants.LDC] = LDC_INSN;
@ -644,7 +665,7 @@ public class ClassWriter extends ClassVisitor {
* {@link #COMPUTE_FRAMES}. * {@link #COMPUTE_FRAMES}.
*/ */
public ClassWriter(final int flags) { public ClassWriter(final int flags) {
super(Opcodes.ASM5); super(Opcodes.ASM6);
index = 1; index = 1;
pool = new ByteVector(); pool = new ByteVector();
items = new Item[256]; items = new Item[256];
@ -653,8 +674,9 @@ public class ClassWriter extends ClassVisitor {
key2 = new Item(); key2 = new Item();
key3 = new Item(); key3 = new Item();
key4 = new Item(); key4 = new Item();
this.computeMaxs = (flags & COMPUTE_MAXS) != 0; this.compute = (flags & COMPUTE_FRAMES) != 0 ? MethodWriter.FRAMES
this.computeFrames = (flags & COMPUTE_FRAMES) != 0; : ((flags & COMPUTE_MAXS) != 0 ? MethodWriter.MAXS
: MethodWriter.NOTHING);
} }
/** /**
@ -684,9 +706,9 @@ public class ClassWriter extends ClassVisitor {
* @param flags * @param flags
* option flags that can be used to modify the default behavior * option flags that can be used to modify the default behavior
* of this class. <i>These option flags do not affect methods * of this class. <i>These option flags do not affect methods
* that are copied as is in the new class. This means that the * that are copied as is in the new class. This means that
* maximum stack size nor the stack frames will be computed for * neither the maximum stack size nor the stack frames will be
* these methods</i>. See {@link #COMPUTE_MAXS}, * computed for these methods</i>. See {@link #COMPUTE_MAXS},
* {@link #COMPUTE_FRAMES}. * {@link #COMPUTE_FRAMES}.
*/ */
public ClassWriter(final ClassReader classReader, final int flags) { public ClassWriter(final ClassReader classReader, final int flags) {
@ -705,9 +727,9 @@ public class ClassWriter extends ClassVisitor {
final String[] interfaces) { final String[] interfaces) {
this.version = version; this.version = version;
this.access = access; this.access = access;
this.name = (name == null) ? 0 : newClass(name); this.name = newClass(name);
thisName = name; thisName = name;
if (ClassReader.SIGNATURES && signature != null) { if (signature != null) {
this.signature = newUTF8(signature); this.signature = newUTF8(signature);
} }
this.superName = superName == null ? 0 : newClass(superName); this.superName = superName == null ? 0 : newClass(superName);
@ -731,6 +753,14 @@ public class ClassWriter extends ClassVisitor {
} }
} }
@Override
public final ModuleVisitor visitModule(final String name,
final int access, final String version) {
return moduleWriter = new ModuleWriter(this,
newModule(name), access,
version == null ? 0 : newUTF8(version));
}
@Override @Override
public final void visitOuterClass(final String owner, final String name, public final void visitOuterClass(final String owner, final String name,
final String desc) { final String desc) {
@ -743,9 +773,6 @@ public class ClassWriter extends ClassVisitor {
@Override @Override
public final AnnotationVisitor visitAnnotation(final String desc, public final AnnotationVisitor visitAnnotation(final String desc,
final boolean visible) { final boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
ByteVector bv = new ByteVector(); ByteVector bv = new ByteVector();
// write type, and reserve space for values count // write type, and reserve space for values count
bv.putShort(newUTF8(desc)).putShort(0); bv.putShort(newUTF8(desc)).putShort(0);
@ -763,9 +790,6 @@ public class ClassWriter extends ClassVisitor {
@Override @Override
public final AnnotationVisitor visitTypeAnnotation(int typeRef, public final AnnotationVisitor visitTypeAnnotation(int typeRef,
TypePath typePath, final String desc, final boolean visible) { TypePath typePath, final String desc, final boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
ByteVector bv = new ByteVector(); ByteVector bv = new ByteVector();
// write target_type and target_info // write target_type and target_info
AnnotationWriter.putTarget(typeRef, typePath, bv); AnnotationWriter.putTarget(typeRef, typePath, bv);
@ -805,7 +829,7 @@ public class ClassWriter extends ClassVisitor {
// and equality tests). If so we store the index of this inner class // and equality tests). If so we store the index of this inner class
// entry (plus one) in intVal. This hack allows duplicate detection in // entry (plus one) in intVal. This hack allows duplicate detection in
// O(1) time. // O(1) time.
Item nameItem = newClassItem(name); Item nameItem = newStringishItem(CLASS, name);
if (nameItem.intVal == 0) { if (nameItem.intVal == 0) {
++innerClassesCount; ++innerClassesCount;
innerClasses.putShort(nameItem.index); innerClasses.putShort(nameItem.index);
@ -830,7 +854,7 @@ public class ClassWriter extends ClassVisitor {
public final MethodVisitor visitMethod(final int access, final String name, public final MethodVisitor visitMethod(final int access, final String name,
final String desc, final String signature, final String[] exceptions) { final String desc, final String signature, final String[] exceptions) {
return new MethodWriter(this, access, name, desc, signature, return new MethodWriter(this, access, name, desc, signature,
exceptions, computeMaxs, computeFrames); exceptions, compute);
} }
@Override @Override
@ -874,7 +898,7 @@ public class ClassWriter extends ClassVisitor {
size += 8 + bootstrapMethods.length; size += 8 + bootstrapMethods.length;
newUTF8("BootstrapMethods"); newUTF8("BootstrapMethods");
} }
if (ClassReader.SIGNATURES && signature != 0) { if (signature != 0) {
++attributeCount; ++attributeCount;
size += 8; size += 8;
newUTF8("Signature"); newUTF8("Signature");
@ -912,26 +936,31 @@ public class ClassWriter extends ClassVisitor {
size += 8 + innerClasses.length; size += 8 + innerClasses.length;
newUTF8("InnerClasses"); newUTF8("InnerClasses");
} }
if (ClassReader.ANNOTATIONS && anns != null) { if (anns != null) {
++attributeCount; ++attributeCount;
size += 8 + anns.getSize(); size += 8 + anns.getSize();
newUTF8("RuntimeVisibleAnnotations"); newUTF8("RuntimeVisibleAnnotations");
} }
if (ClassReader.ANNOTATIONS && ianns != null) { if (ianns != null) {
++attributeCount; ++attributeCount;
size += 8 + ianns.getSize(); size += 8 + ianns.getSize();
newUTF8("RuntimeInvisibleAnnotations"); newUTF8("RuntimeInvisibleAnnotations");
} }
if (ClassReader.ANNOTATIONS && tanns != null) { if (tanns != null) {
++attributeCount; ++attributeCount;
size += 8 + tanns.getSize(); size += 8 + tanns.getSize();
newUTF8("RuntimeVisibleTypeAnnotations"); newUTF8("RuntimeVisibleTypeAnnotations");
} }
if (ClassReader.ANNOTATIONS && itanns != null) { if (itanns != null) {
++attributeCount; ++attributeCount;
size += 8 + itanns.getSize(); size += 8 + itanns.getSize();
newUTF8("RuntimeInvisibleTypeAnnotations"); newUTF8("RuntimeInvisibleTypeAnnotations");
} }
if (moduleWriter != null) {
attributeCount += 1 + moduleWriter.attributeCount;
size += 6 + moduleWriter.size + moduleWriter.attributesSize;
newUTF8("Module");
}
if (attrs != null) { if (attrs != null) {
attributeCount += attrs.getCount(); attributeCount += attrs.getCount();
size += attrs.getSize(this, null, 0, -1, -1); size += attrs.getSize(this, null, 0, -1, -1);
@ -968,7 +997,7 @@ public class ClassWriter extends ClassVisitor {
bootstrapMethodsCount); bootstrapMethodsCount);
out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length); out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length);
} }
if (ClassReader.SIGNATURES && signature != 0) { if (signature != 0) {
out.putShort(newUTF8("Signature")).putInt(2).putShort(signature); out.putShort(newUTF8("Signature")).putInt(2).putShort(signature);
} }
if (sourceFile != 0) { if (sourceFile != 0) {
@ -979,6 +1008,11 @@ public class ClassWriter extends ClassVisitor {
out.putShort(newUTF8("SourceDebugExtension")).putInt(len); out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
out.putByteArray(sourceDebug.data, 0, len); out.putByteArray(sourceDebug.data, 0, len);
} }
if (moduleWriter != null) {
out.putShort(newUTF8("Module"));
moduleWriter.put(out);
moduleWriter.putAttributes(out);
}
if (enclosingMethodOwner != 0) { if (enclosingMethodOwner != 0) {
out.putShort(newUTF8("EnclosingMethod")).putInt(4); out.putShort(newUTF8("EnclosingMethod")).putInt(4);
out.putShort(enclosingMethodOwner).putShort(enclosingMethod); out.putShort(enclosingMethodOwner).putShort(enclosingMethod);
@ -997,41 +1031,46 @@ public class ClassWriter extends ClassVisitor {
out.putInt(innerClasses.length + 2).putShort(innerClassesCount); out.putInt(innerClasses.length + 2).putShort(innerClassesCount);
out.putByteArray(innerClasses.data, 0, innerClasses.length); out.putByteArray(innerClasses.data, 0, innerClasses.length);
} }
if (ClassReader.ANNOTATIONS && anns != null) { if (anns != null) {
out.putShort(newUTF8("RuntimeVisibleAnnotations")); out.putShort(newUTF8("RuntimeVisibleAnnotations"));
anns.put(out); anns.put(out);
} }
if (ClassReader.ANNOTATIONS && ianns != null) { if (ianns != null) {
out.putShort(newUTF8("RuntimeInvisibleAnnotations")); out.putShort(newUTF8("RuntimeInvisibleAnnotations"));
ianns.put(out); ianns.put(out);
} }
if (ClassReader.ANNOTATIONS && tanns != null) { if (tanns != null) {
out.putShort(newUTF8("RuntimeVisibleTypeAnnotations")); out.putShort(newUTF8("RuntimeVisibleTypeAnnotations"));
tanns.put(out); tanns.put(out);
} }
if (ClassReader.ANNOTATIONS && itanns != null) { if (itanns != null) {
out.putShort(newUTF8("RuntimeInvisibleTypeAnnotations")); out.putShort(newUTF8("RuntimeInvisibleTypeAnnotations"));
itanns.put(out); itanns.put(out);
} }
if (attrs != null) { if (attrs != null) {
attrs.put(this, null, 0, -1, -1, out); attrs.put(this, null, 0, -1, -1, out);
} }
if (invalidFrames) { if (hasAsmInsns) {
boolean hasFrames = false;
mb = firstMethod;
while (mb != null) {
hasFrames |= mb.frameCount > 0;
mb = (MethodWriter) mb.mv;
}
anns = null; anns = null;
ianns = null; ianns = null;
attrs = null; attrs = null;
innerClassesCount = 0; moduleWriter = null;
innerClasses = null;
bootstrapMethodsCount = 0;
bootstrapMethods = null;
firstField = null; firstField = null;
lastField = null; lastField = null;
firstMethod = null; firstMethod = null;
lastMethod = null; lastMethod = null;
computeMaxs = false; compute =
computeFrames = true; hasFrames ? MethodWriter.INSERTED_FRAMES : MethodWriter.NOTHING;
invalidFrames = false; hasAsmInsns = false;
new ClassReader(out.data).accept(this, ClassReader.SKIP_FRAMES); new ClassReader(out.data).accept(this,
(hasFrames ? ClassReader.EXPAND_FRAMES : 0)
| ClassReader.EXPAND_ASM_INSNS);
return toByteArray(); return toByteArray();
} }
return out.data; return out.data;
@ -1078,16 +1117,16 @@ public class ClassWriter extends ClassVisitor {
double val = ((Double) cst).doubleValue(); double val = ((Double) cst).doubleValue();
return newDouble(val); return newDouble(val);
} else if (cst instanceof String) { } else if (cst instanceof String) {
return newString((String) cst); return newStringishItem(STR, (String) cst);
} else if (cst instanceof Type) { } else if (cst instanceof Type) {
Type t = (Type) cst; Type t = (Type) cst;
int s = t.getSort(); int s = t.getSort();
if (s == Type.OBJECT) { if (s == Type.OBJECT) {
return newClassItem(t.getInternalName()); return newStringishItem(CLASS, t.getInternalName());
} else if (s == Type.METHOD) { } else if (s == Type.METHOD) {
return newMethodTypeItem(t.getDescriptor()); return newStringishItem(MTYPE, t.getDescriptor());
} else { // s == primitive type or array } else { // s == primitive type or array
return newClassItem(t.getDescriptor()); return newStringishItem(CLASS, t.getDescriptor());
} }
} else if (cst instanceof Handle) { } else if (cst instanceof Handle) {
Handle h = (Handle) cst; Handle h = (Handle) cst;
@ -1136,20 +1175,21 @@ public class ClassWriter extends ClassVisitor {
} }
/** /**
* Adds a class reference to the constant pool of the class being build. * Adds a string reference, a class reference, a method type, a module
* or a package to the constant pool of the class being build.
* Does nothing if the constant pool already contains a similar item. * Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
* *
* @param type
* a type among STR, CLASS, MTYPE, MODULE or PACKAGE
* @param value * @param value
* the internal name of the class. * string value of the reference.
* @return a new or already existing class reference item. * @return a new or already existing reference item.
*/ */
Item newClassItem(final String value) { Item newStringishItem(final int type, final String value) {
key2.set(CLASS, value, null, null); key2.set(type, value, null, null);
Item result = get(key2); Item result = get(key2);
if (result == null) { if (result == null) {
pool.put12(CLASS, newUTF8(value)); pool.put12(type, newUTF8(value));
result = new Item(index++, key2); result = new Item(index++, key2);
put(result); put(result);
} }
@ -1167,72 +1207,7 @@ public class ClassWriter extends ClassVisitor {
* @return the index of a new or already existing class reference item. * @return the index of a new or already existing class reference item.
*/ */
public int newClass(final String value) { public int newClass(final String value) {
return newClassItem(value).index; return newStringishItem(CLASS, value).index;
}
/**
* Adds a module name to the constant pool.
*
* Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param value
* the module name
* @return the index of a new or already existing module reference item.
*/
public int newModule(String value) {
key2.set(MODULE, value, null, null);
Item result = get(key2);
if (result == null) {
pool.put12(MODULE, newUTF8(value));
result = new Item(index++, key2);
put(result);
}
return result.index;
}
/**
* Adds a package name to the constant pool.
*
* Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param value
* the internal name of the package.
* @return the index of a new or already existing package reference item.
*/
public int newPackage(String value) {
key2.set(PACKAGE, value, null, null);
Item result = get(key2);
if (result == null) {
pool.put12(PACKAGE, newUTF8(value));
result = new Item(index++, key2);
put(result);
}
return result.index;
}
/**
* Adds a method type reference to the constant pool of the class being
* build. Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param methodDesc
* method descriptor of the method type.
* @return a new or already existing method type reference item.
*/
Item newMethodTypeItem(final String methodDesc) {
key2.set(MTYPE, methodDesc, null, null);
Item result = get(key2);
if (result == null) {
pool.put12(MTYPE, newUTF8(methodDesc));
result = new Item(index++, key2);
put(result);
}
return result;
} }
/** /**
@ -1247,7 +1222,37 @@ public class ClassWriter extends ClassVisitor {
* item. * item.
*/ */
public int newMethodType(final String methodDesc) { public int newMethodType(final String methodDesc) {
return newMethodTypeItem(methodDesc).index; return newStringishItem(MTYPE, methodDesc).index;
}
/**
* Adds a module reference to the constant pool of the class being
* build. Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param moduleName
* name of the module.
* @return the index of a new or already existing module reference
* item.
*/
public int newModule(final String moduleName) {
return newStringishItem(MODULE, moduleName).index;
}
/**
* Adds a package reference to the constant pool of the class being
* build. Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
*
* @param packageName
* name of the package in its internal form.
* @return the index of a new or already existing module reference
* item.
*/
public int newPackage(final String packageName) {
return newStringishItem(PACKAGE, packageName).index;
} }
/** /**
@ -1628,25 +1633,6 @@ public class ClassWriter extends ClassVisitor {
return result; return result;
} }
/**
* Adds a string to the constant pool of the class being build. Does nothing
* if the constant pool already contains a similar item.
*
* @param value
* the String value.
* @return a new or already existing string item.
*/
private Item newString(final String value) {
key2.set(STR, value, null, null);
Item result = get(key2);
if (result == null) {
pool.put12(STR, newUTF8(value));
result = new Item(index++, key2);
put(result);
}
return result;
}
/** /**
* Adds a name and type to the constant pool of the class being build. Does * Adds a name and type to the constant pool of the class being build. Does
* nothing if the constant pool already contains a similar item. <i>This * nothing if the constant pool already contains a similar item. <i>This

View File

@ -0,0 +1,85 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This 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:
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package jdk.internal.org.objectweb.asm;
/**
* Information about the input stack map frame at the "current" instruction of a
* method. This is implemented as a Frame subclass for a "basic block"
* containing only one instruction.
*
* @author Eric Bruneton
*/
class CurrentFrame extends Frame {
/**
* Sets this CurrentFrame to the input stack map frame of the next "current"
* instruction, i.e. the instruction just after the given one. It is assumed
* that the value of this object when this method is called is the stack map
* frame status just before the given instruction is executed.
*/
@Override
void execute(int opcode, int arg, ClassWriter cw, Item item) {
super.execute(opcode, arg, cw, item);
Frame successor = new Frame();
merge(cw, successor, 0);
set(successor);
owner.inputStackTop = 0;
}
}

View File

@ -69,7 +69,7 @@ public abstract class FieldVisitor {
/** /**
* The ASM API version implemented by this visitor. The value of this field * The ASM API version implemented by this visitor. The value of this field
* must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/ */
protected final int api; protected final int api;
@ -84,7 +84,7 @@ public abstract class FieldVisitor {
* *
* @param api * @param api
* the ASM API version implemented by this visitor. Must be one * the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/ */
public FieldVisitor(final int api) { public FieldVisitor(final int api) {
this(api, null); this(api, null);
@ -95,13 +95,13 @@ public abstract class FieldVisitor {
* *
* @param api * @param api
* the ASM API version implemented by this visitor. Must be one * the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param fv * @param fv
* the field visitor to which this visitor must delegate method * the field visitor to which this visitor must delegate method
* calls. May be null. * calls. May be null.
*/ */
public FieldVisitor(final int api, final FieldVisitor fv) { public FieldVisitor(final int api, final FieldVisitor fv) {
if (api != Opcodes.ASM4 && api != Opcodes.ASM5) { if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
this.api = api; this.api = api;

View File

@ -147,7 +147,7 @@ final class FieldWriter extends FieldVisitor {
*/ */
FieldWriter(final ClassWriter cw, final int access, final String name, FieldWriter(final ClassWriter cw, final int access, final String name,
final String desc, final String signature, final Object value) { final String desc, final String signature, final Object value) {
super(Opcodes.ASM5); super(Opcodes.ASM6);
if (cw.firstField == null) { if (cw.firstField == null) {
cw.firstField = this; cw.firstField = this;
} else { } else {
@ -158,7 +158,7 @@ final class FieldWriter extends FieldVisitor {
this.access = access; this.access = access;
this.name = cw.newUTF8(name); this.name = cw.newUTF8(name);
this.desc = cw.newUTF8(desc); this.desc = cw.newUTF8(desc);
if (ClassReader.SIGNATURES && signature != null) { if (signature != null) {
this.signature = cw.newUTF8(signature); this.signature = cw.newUTF8(signature);
} }
if (value != null) { if (value != null) {
@ -173,9 +173,6 @@ final class FieldWriter extends FieldVisitor {
@Override @Override
public AnnotationVisitor visitAnnotation(final String desc, public AnnotationVisitor visitAnnotation(final String desc,
final boolean visible) { final boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
ByteVector bv = new ByteVector(); ByteVector bv = new ByteVector();
// write type, and reserve space for values count // write type, and reserve space for values count
bv.putShort(cw.newUTF8(desc)).putShort(0); bv.putShort(cw.newUTF8(desc)).putShort(0);
@ -193,9 +190,6 @@ final class FieldWriter extends FieldVisitor {
@Override @Override
public AnnotationVisitor visitTypeAnnotation(final int typeRef, public AnnotationVisitor visitTypeAnnotation(final int typeRef,
final TypePath typePath, final String desc, final boolean visible) { final TypePath typePath, final String desc, final boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
ByteVector bv = new ByteVector(); ByteVector bv = new ByteVector();
// write target_type and target_info // write target_type and target_info
AnnotationWriter.putTarget(typeRef, typePath, bv); AnnotationWriter.putTarget(typeRef, typePath, bv);
@ -249,23 +243,23 @@ final class FieldWriter extends FieldVisitor {
cw.newUTF8("Deprecated"); cw.newUTF8("Deprecated");
size += 6; size += 6;
} }
if (ClassReader.SIGNATURES && signature != 0) { if (signature != 0) {
cw.newUTF8("Signature"); cw.newUTF8("Signature");
size += 8; size += 8;
} }
if (ClassReader.ANNOTATIONS && anns != null) { if (anns != null) {
cw.newUTF8("RuntimeVisibleAnnotations"); cw.newUTF8("RuntimeVisibleAnnotations");
size += 8 + anns.getSize(); size += 8 + anns.getSize();
} }
if (ClassReader.ANNOTATIONS && ianns != null) { if (ianns != null) {
cw.newUTF8("RuntimeInvisibleAnnotations"); cw.newUTF8("RuntimeInvisibleAnnotations");
size += 8 + ianns.getSize(); size += 8 + ianns.getSize();
} }
if (ClassReader.ANNOTATIONS && tanns != null) { if (tanns != null) {
cw.newUTF8("RuntimeVisibleTypeAnnotations"); cw.newUTF8("RuntimeVisibleTypeAnnotations");
size += 8 + tanns.getSize(); size += 8 + tanns.getSize();
} }
if (ClassReader.ANNOTATIONS && itanns != null) { if (itanns != null) {
cw.newUTF8("RuntimeInvisibleTypeAnnotations"); cw.newUTF8("RuntimeInvisibleTypeAnnotations");
size += 8 + itanns.getSize(); size += 8 + itanns.getSize();
} }
@ -299,19 +293,19 @@ final class FieldWriter extends FieldVisitor {
if ((access & Opcodes.ACC_DEPRECATED) != 0) { if ((access & Opcodes.ACC_DEPRECATED) != 0) {
++attributeCount; ++attributeCount;
} }
if (ClassReader.SIGNATURES && signature != 0) { if (signature != 0) {
++attributeCount; ++attributeCount;
} }
if (ClassReader.ANNOTATIONS && anns != null) { if (anns != null) {
++attributeCount; ++attributeCount;
} }
if (ClassReader.ANNOTATIONS && ianns != null) { if (ianns != null) {
++attributeCount; ++attributeCount;
} }
if (ClassReader.ANNOTATIONS && tanns != null) { if (tanns != null) {
++attributeCount; ++attributeCount;
} }
if (ClassReader.ANNOTATIONS && itanns != null) { if (itanns != null) {
++attributeCount; ++attributeCount;
} }
if (attrs != null) { if (attrs != null) {
@ -331,23 +325,23 @@ final class FieldWriter extends FieldVisitor {
if ((access & Opcodes.ACC_DEPRECATED) != 0) { if ((access & Opcodes.ACC_DEPRECATED) != 0) {
out.putShort(cw.newUTF8("Deprecated")).putInt(0); out.putShort(cw.newUTF8("Deprecated")).putInt(0);
} }
if (ClassReader.SIGNATURES && signature != 0) { if (signature != 0) {
out.putShort(cw.newUTF8("Signature")); out.putShort(cw.newUTF8("Signature"));
out.putInt(2).putShort(signature); out.putInt(2).putShort(signature);
} }
if (ClassReader.ANNOTATIONS && anns != null) { if (anns != null) {
out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
anns.put(out); anns.put(out);
} }
if (ClassReader.ANNOTATIONS && ianns != null) { if (ianns != null) {
out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
ianns.put(out); ianns.put(out);
} }
if (ClassReader.ANNOTATIONS && tanns != null) { if (tanns != null) {
out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations")); out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
tanns.put(out); tanns.put(out);
} }
if (ClassReader.ANNOTATIONS && itanns != null) { if (itanns != null) {
out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations")); out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
itanns.put(out); itanns.put(out);
} }

View File

@ -63,7 +63,7 @@ package jdk.internal.org.objectweb.asm;
* *
* @author Eric Bruneton * @author Eric Bruneton
*/ */
final class Frame { class Frame {
/* /*
* Frames are computed in a two steps process: during the visit of each * Frames are computed in a two steps process: during the visit of each
@ -525,7 +525,7 @@ final class Frame {
* When the stack map frames are completely computed, this field is the * When the stack map frames are completely computed, this field is the
* actual number of types in {@link #outputStack}. * actual number of types in {@link #outputStack}.
*/ */
private int outputStackTop; int outputStackTop;
/** /**
* Number of types that are initialized in the basic block. * Number of types that are initialized in the basic block.
@ -549,6 +549,110 @@ final class Frame {
*/ */
private int[] initializations; private int[] initializations;
/**
* Sets this frame to the given value.
*
* @param cw
* the ClassWriter to which this label belongs.
* @param nLocal
* the number of local variables.
* @param local
* the local variable types. Primitive types are represented by
* {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
* {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
* {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
* {@link Opcodes#UNINITIALIZED_THIS} (long and double are
* represented by a single element). Reference types are
* represented by String objects (representing internal names),
* and uninitialized types by Label objects (this label
* designates the NEW instruction that created this uninitialized
* value).
* @param nStack
* the number of operand stack elements.
* @param stack
* the operand stack types (same format as the "local" array).
*/
final void set(ClassWriter cw, final int nLocal, final Object[] local,
final int nStack, final Object[] stack) {
int i = convert(cw, nLocal, local, inputLocals);
while (i < local.length) {
inputLocals[i++] = TOP;
}
int nStackTop = 0;
for (int j = 0; j < nStack; ++j) {
if (stack[j] == Opcodes.LONG || stack[j] == Opcodes.DOUBLE) {
++nStackTop;
}
}
inputStack = new int[nStack + nStackTop];
convert(cw, nStack, stack, inputStack);
outputStackTop = 0;
initializationCount = 0;
}
/**
* Converts types from the MethodWriter.visitFrame() format to the Frame
* format.
*
* @param cw
* the ClassWriter to which this label belongs.
* @param nInput
* the number of types to convert.
* @param input
* the types to convert. Primitive types are represented by
* {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
* {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
* {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
* {@link Opcodes#UNINITIALIZED_THIS} (long and double are
* represented by a single element). Reference types are
* represented by String objects (representing internal names),
* and uninitialized types by Label objects (this label
* designates the NEW instruction that created this uninitialized
* value).
* @param output
* where to store the converted types.
* @return the number of output elements.
*/
private static int convert(ClassWriter cw, int nInput, Object[] input,
int[] output) {
int i = 0;
for (int j = 0; j < nInput; ++j) {
if (input[j] instanceof Integer) {
output[i++] = BASE | ((Integer) input[j]).intValue();
if (input[j] == Opcodes.LONG || input[j] == Opcodes.DOUBLE) {
output[i++] = TOP;
}
} else if (input[j] instanceof String) {
output[i++] = type(cw, Type.getObjectType((String) input[j])
.getDescriptor());
} else {
output[i++] = UNINITIALIZED
| cw.addUninitializedType("",
((Label) input[j]).position);
}
}
return i;
}
/**
* Sets this frame to the value of the given frame. WARNING: after this
* method is called the two frames share the same data structures. It is
* recommended to discard the given frame f to avoid unexpected side
* effects.
*
* @param f
* The new frame value.
*/
final void set(final Frame f) {
inputLocals = f.inputLocals;
inputStack = f.inputStack;
outputLocals = f.outputLocals;
outputStack = f.outputStack;
outputStackTop = f.outputStackTop;
initializationCount = f.initializationCount;
initializations = f.initializations;
}
/** /**
* Returns the output frame local variable type at the given index. * Returns the output frame local variable type at the given index.
* *
@ -614,7 +718,7 @@ final class Frame {
} }
// pushes the type on the output stack // pushes the type on the output stack
outputStack[outputStackTop++] = type; outputStack[outputStackTop++] = type;
// updates the maximun height reached by the output stack, if needed // updates the maximum height reached by the output stack, if needed
int top = owner.inputStackTop + outputStackTop; int top = owner.inputStackTop + outputStackTop;
if (top > owner.outputStackMax) { if (top > owner.outputStackMax) {
owner.outputStackMax = top; owner.outputStackMax = top;
@ -650,7 +754,7 @@ final class Frame {
* a type descriptor. * a type descriptor.
* @return the int encoding of the given type. * @return the int encoding of the given type.
*/ */
private static int type(final ClassWriter cw, final String desc) { static int type(final ClassWriter cw, final String desc) {
String t; String t;
int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0; int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
switch (desc.charAt(index)) { switch (desc.charAt(index)) {
@ -838,7 +942,7 @@ final class Frame {
* @param maxLocals * @param maxLocals
* the maximum number of local variables of this method. * the maximum number of local variables of this method.
*/ */
void initInputFrame(final ClassWriter cw, final int access, final void initInputFrame(final ClassWriter cw, final int access,
final Type[] args, final int maxLocals) { final Type[] args, final int maxLocals) {
inputLocals = new int[maxLocals]; inputLocals = new int[maxLocals];
inputStack = new int[0]; inputStack = new int[0];
@ -981,7 +1085,7 @@ final class Frame {
case Opcodes.AALOAD: case Opcodes.AALOAD:
pop(1); pop(1);
t1 = pop(); t1 = pop();
push(ELEMENT_OF + t1); push(t1 == NULL ? t1 : ELEMENT_OF + t1);
break; break;
case Opcodes.ISTORE: case Opcodes.ISTORE:
case Opcodes.FSTORE: case Opcodes.FSTORE:
@ -1312,7 +1416,7 @@ final class Frame {
* @return <tt>true</tt> if the input frame of the given label has been * @return <tt>true</tt> if the input frame of the given label has been
* changed by this operation. * changed by this operation.
*/ */
boolean merge(final ClassWriter cw, final Frame frame, final int edge) { final boolean merge(final ClassWriter cw, final Frame frame, final int edge) {
boolean changed = false; boolean changed = false;
int i, s, dim, kind, t; int i, s, dim, kind, t;

View File

@ -80,6 +80,7 @@ final class Item {
* {@link ClassWriter#STR}, {@link ClassWriter#CLASS}, * {@link ClassWriter#STR}, {@link ClassWriter#CLASS},
* {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD}, * {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},
* {@link ClassWriter#METH}, {@link ClassWriter#IMETH}, * {@link ClassWriter#METH}, {@link ClassWriter#IMETH},
* {@link ClassWriter#MODULE}, {@link ClassWriter#PACKAGE},
* {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}. * {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}.
* *
* MethodHandle constant 9 variations are stored using a range of 9 values * MethodHandle constant 9 variations are stored using a range of 9 values
@ -239,12 +240,12 @@ final class Item {
this.strVal3 = strVal3; this.strVal3 = strVal3;
switch (type) { switch (type) {
case ClassWriter.CLASS: case ClassWriter.CLASS:
case ClassWriter.MODULE:
case ClassWriter.PACKAGE:
this.intVal = 0; // intVal of a class must be zero, see visitInnerClass this.intVal = 0; // intVal of a class must be zero, see visitInnerClass
case ClassWriter.UTF8: case ClassWriter.UTF8:
case ClassWriter.STR: case ClassWriter.STR:
case ClassWriter.MTYPE: case ClassWriter.MTYPE:
case ClassWriter.MODULE:
case ClassWriter.PACKAGE:
case ClassWriter.TYPE_NORMAL: case ClassWriter.TYPE_NORMAL:
hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()); hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
return; return;

View File

@ -389,13 +389,12 @@ public class Label {
* the position of this label in the bytecode. * the position of this label in the bytecode.
* @param data * @param data
* the bytecode of the method. * the bytecode of the method.
* @return <tt>true</tt> if a blank that was left for this label was to * @return <tt>true</tt> if a blank that was left for this label was too
* small to store the offset. In such a case the corresponding jump * small to store the offset. In such a case the corresponding jump
* instruction is replaced with a pseudo instruction (using unused * instruction is replaced with a pseudo instruction (using unused
* opcodes) using an unsigned two bytes offset. These pseudo * opcodes) using an unsigned two bytes offset. These pseudo
* instructions will need to be replaced with true instructions with * instructions will be replaced with standard bytecode instructions
* wider offsets (4 bytes instead of 2). This is done in * with wider offsets (4 bytes instead of 2), in ClassReader.
* {@link MethodWriter#resizeInstructions}.
* @throws IllegalArgumentException * @throws IllegalArgumentException
* if this label has already been resolved, or if it has not * if this label has already been resolved, or if it has not
* been created by the given code writer. * been created by the given code writer.
@ -454,7 +453,7 @@ public class Label {
* @return the first label of the series to which this label belongs. * @return the first label of the series to which this label belongs.
*/ */
Label getFirst() { Label getFirst() {
return !ClassReader.FRAMES || frame == null ? this : frame.owner; return frame == null ? this : frame.owner;
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------

View File

@ -86,7 +86,7 @@ public abstract class MethodVisitor {
/** /**
* The ASM API version implemented by this visitor. The value of this field * The ASM API version implemented by this visitor. The value of this field
* must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/ */
protected final int api; protected final int api;
@ -101,7 +101,7 @@ public abstract class MethodVisitor {
* *
* @param api * @param api
* the ASM API version implemented by this visitor. Must be one * the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/ */
public MethodVisitor(final int api) { public MethodVisitor(final int api) {
this(api, null); this(api, null);
@ -112,13 +112,13 @@ public abstract class MethodVisitor {
* *
* @param api * @param api
* the ASM API version implemented by this visitor. Must be one * the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param mv * @param mv
* the method visitor to which this visitor must delegate method * the method visitor to which this visitor must delegate method
* calls. May be null. * calls. May be null.
*/ */
public MethodVisitor(final int api, final MethodVisitor mv) { public MethodVisitor(final int api, final MethodVisitor mv) {
if (api != Opcodes.ASM4 && api != Opcodes.ASM5) { if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
this.api = api; this.api = api;

View File

@ -0,0 +1,219 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This 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:
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package jdk.internal.org.objectweb.asm;
/**
* A visitor to visit a Java module. The methods of this class must be called in
* the following order: <tt>visitMainClass</tt> | ( <tt>visitPackage</tt> |
* <tt>visitRequire</tt> | <tt>visitExport</tt> | <tt>visitOpen</tt> |
* <tt>visitUse</tt> | <tt>visitProvide</tt> )* <tt>visitEnd</tt>.
*
* The methods {@link #visitRequire(String, int, String)}, {@link #visitExport(String, int, String...)},
* {@link #visitOpen(String, int, String...)} and {@link #visitPackage(String)}
* take as parameter a package name or a module name. Unlike the other names which are internal names
* (names separated by slash), module and package names are qualified names (names separated by dot).
*
* @author Remi Forax
*/
public abstract class ModuleVisitor {
/**
* The ASM API version implemented by this visitor. The value of this field
* must be {@link Opcodes#ASM6}.
*/
protected final int api;
/**
* The module visitor to which this visitor must delegate method calls. May
* be null.
*/
protected ModuleVisitor mv;
/**
* Constructs a new {@link ModuleVisitor}.
*
* @param api
* the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}.
*/
public ModuleVisitor(final int api) {
this(api, null);
}
/**
* Constructs a new {@link ModuleVisitor}.
*
* @param api
* the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}.
* @param mv
* the module visitor to which this visitor must delegate method
* calls. May be null.
*/
public ModuleVisitor(final int api, final ModuleVisitor mv) {
if (api != Opcodes.ASM6) {
throw new IllegalArgumentException();
}
this.api = api;
this.mv = mv;
}
/**
* Visit the main class of the current module.
*
* @param mainClass the internal name of the main class of the current module.
*/
public void visitMainClass(String mainClass) {
if (mv != null) {
mv.visitMainClass(mainClass);
}
}
/**
* Visit a package of the current module.
*
* @param packaze the qualified name of a package.
*/
public void visitPackage(String packaze) {
if (mv != null) {
mv.visitPackage(packaze);
}
}
/**
* Visits a dependence of the current module.
*
* @param module the qualified name of the dependence.
* @param access the access flag of the dependence among
* ACC_TRANSITIVE, ACC_STATIC_PHASE, ACC_SYNTHETIC
* and ACC_MANDATED.
* @param version the module version at compile time or null.
*/
public void visitRequire(String module, int access, String version) {
if (mv != null) {
mv.visitRequire(module, access, version);
}
}
/**
* Visit an exported package of the current module.
*
* @param packaze the qualified name of the exported package.
* @param access the access flag of the exported package,
* valid values are among {@code ACC_SYNTHETIC} and
* {@code ACC_MANDATED}.
* @param modules the qualified names of the modules that can access to
* the public classes of the exported package or
* <tt>null</tt>.
*/
public void visitExport(String packaze, int access, String... modules) {
if (mv != null) {
mv.visitExport(packaze, access, modules);
}
}
/**
* Visit an open package of the current module.
*
* @param packaze the qualified name of the opened package.
* @param access the access flag of the opened package,
* valid values are among {@code ACC_SYNTHETIC} and
* {@code ACC_MANDATED}.
* @param modules the qualified names of the modules that can use deep
* reflection to the classes of the open package or
* <tt>null</tt>.
*/
public void visitOpen(String packaze, int access, String... modules) {
if (mv != null) {
mv.visitOpen(packaze, access, modules);
}
}
/**
* Visit a service used by the current module.
* The name must be the internal name of an interface or a class.
*
* @param service the internal name of the service.
*/
public void visitUse(String service) {
if (mv != null) {
mv.visitUse(service);
}
}
/**
* Visit an implementation of a service.
*
* @param service the internal name of the service
* @param providers the internal names of the implementations
* of the service (there is at least one provider).
*/
public void visitProvide(String service, String... providers) {
if (mv != null) {
mv.visitProvide(service, providers);
}
}
/**
* Visits the end of the module. This method, which is the last one to be
* called, is used to inform the visitor that everything have been visited.
*/
public void visitEnd() {
if (mv != null) {
mv.visitEnd();
}
}
}

View File

@ -0,0 +1,322 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This 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:
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package jdk.internal.org.objectweb.asm;
/**
* @author Remi Forax
*/
final class ModuleWriter extends ModuleVisitor {
/**
* The class writer to which this Module attribute must be added.
*/
private final ClassWriter cw;
/**
* size in byte of the Module attribute.
*/
int size;
/**
* Number of attributes associated with the current module
* (Version, ConcealPackages, etc)
*/
int attributeCount;
/**
* Size in bytes of the attributes associated with the current module
*/
int attributesSize;
/**
* module name index in the constant pool
*/
private final int name;
/**
* module access flags
*/
private final int access;
/**
* module version index in the constant pool or 0
*/
private final int version;
/**
* module main class index in the constant pool or 0
*/
private int mainClass;
/**
* number of packages
*/
private int packageCount;
/**
* The packages in bytecode form. This byte vector only contains
* the items themselves, the number of items is store in packageCount
*/
private ByteVector packages;
/**
* number of requires items
*/
private int requireCount;
/**
* The requires items in bytecode form. This byte vector only contains
* the items themselves, the number of items is store in requireCount
*/
private ByteVector requires;
/**
* number of exports items
*/
private int exportCount;
/**
* The exports items in bytecode form. This byte vector only contains
* the items themselves, the number of items is store in exportCount
*/
private ByteVector exports;
/**
* number of opens items
*/
private int openCount;
/**
* The opens items in bytecode form. This byte vector only contains
* the items themselves, the number of items is store in openCount
*/
private ByteVector opens;
/**
* number of uses items
*/
private int useCount;
/**
* The uses items in bytecode form. This byte vector only contains
* the items themselves, the number of items is store in useCount
*/
private ByteVector uses;
/**
* number of provides items
*/
private int provideCount;
/**
* The uses provides in bytecode form. This byte vector only contains
* the items themselves, the number of items is store in provideCount
*/
private ByteVector provides;
ModuleWriter(final ClassWriter cw, final int name,
final int access, final int version) {
super(Opcodes.ASM6);
this.cw = cw;
this.size = 16; // name + access + version + 5 counts
this.name = name;
this.access = access;
this.version = version;
}
@Override
public void visitMainClass(String mainClass) {
if (this.mainClass == 0) { // protect against several calls to visitMainClass
cw.newUTF8("ModuleMainClass");
attributeCount++;
attributesSize += 8;
}
this.mainClass = cw.newClass(mainClass);
}
@Override
public void visitPackage(String packaze) {
if (packages == null) {
// protect against several calls to visitPackage
cw.newUTF8("ModulePackages");
packages = new ByteVector();
attributeCount++;
attributesSize += 8;
}
packages.putShort(cw.newPackage(packaze));
packageCount++;
attributesSize += 2;
}
@Override
public void visitRequire(String module, int access, String version) {
if (requires == null) {
requires = new ByteVector();
}
requires.putShort(cw.newModule(module))
.putShort(access)
.putShort(version == null? 0: cw.newUTF8(version));
requireCount++;
size += 6;
}
@Override
public void visitExport(String packaze, int access, String... modules) {
if (exports == null) {
exports = new ByteVector();
}
exports.putShort(cw.newPackage(packaze)).putShort(access);
if (modules == null) {
exports.putShort(0);
size += 6;
} else {
exports.putShort(modules.length);
for(String module: modules) {
exports.putShort(cw.newModule(module));
}
size += 6 + 2 * modules.length;
}
exportCount++;
}
@Override
public void visitOpen(String packaze, int access, String... modules) {
if (opens == null) {
opens = new ByteVector();
}
opens.putShort(cw.newPackage(packaze)).putShort(access);
if (modules == null) {
opens.putShort(0);
size += 6;
} else {
opens.putShort(modules.length);
for(String module: modules) {
opens.putShort(cw.newModule(module));
}
size += 6 + 2 * modules.length;
}
openCount++;
}
@Override
public void visitUse(String service) {
if (uses == null) {
uses = new ByteVector();
}
uses.putShort(cw.newClass(service));
useCount++;
size += 2;
}
@Override
public void visitProvide(String service, String... providers) {
if (provides == null) {
provides = new ByteVector();
}
provides.putShort(cw.newClass(service));
provides.putShort(providers.length);
for(String provider: providers) {
provides.putShort(cw.newClass(provider));
}
provideCount++;
size += 4 + 2 * providers.length;
}
@Override
public void visitEnd() {
// empty
}
void putAttributes(ByteVector out) {
if (mainClass != 0) {
out.putShort(cw.newUTF8("ModuleMainClass")).putInt(2).putShort(mainClass);
}
if (packages != null) {
out.putShort(cw.newUTF8("ModulePackages"))
.putInt(2 + 2 * packageCount)
.putShort(packageCount)
.putByteArray(packages.data, 0, packages.length);
}
}
void put(ByteVector out) {
out.putInt(size);
out.putShort(name).putShort(access).putShort(version);
out.putShort(requireCount);
if (requires != null) {
out.putByteArray(requires.data, 0, requires.length);
}
out.putShort(exportCount);
if (exports != null) {
out.putByteArray(exports.data, 0, exports.length);
}
out.putShort(openCount);
if (opens != null) {
out.putByteArray(opens.data, 0, opens.length);
}
out.putShort(useCount);
if (uses != null) {
out.putByteArray(uses.data, 0, uses.length);
}
out.putShort(provideCount);
if (provides != null) {
out.putByteArray(provides.data, 0, provides.length);
}
}
}

View File

@ -70,13 +70,13 @@ package jdk.internal.org.objectweb.asm;
* @author Eric Bruneton * @author Eric Bruneton
* @author Eugene Kuleshov * @author Eugene Kuleshov
*/ */
@SuppressWarnings("deprecation") // for Integer(int) constructor
public interface Opcodes { public interface Opcodes {
// ASM API versions // ASM API versions
int ASM4 = 4 << 16 | 0 << 8 | 0; int ASM4 = 4 << 16 | 0 << 8 | 0;
int ASM5 = 5 << 16 | 0 << 8 | 0; int ASM5 = 5 << 16 | 0 << 8 | 0;
int ASM6 = 6 << 16 | 0 << 8 | 0;
// versions // versions
@ -88,7 +88,7 @@ public interface Opcodes {
int V1_6 = 0 << 16 | 50; int V1_6 = 0 << 16 | 50;
int V1_7 = 0 << 16 | 51; int V1_7 = 0 << 16 | 51;
int V1_8 = 0 << 16 | 52; int V1_8 = 0 << 16 | 52;
int V1_9 = 0 << 16 | 53; int V9 = 0 << 16 | 53;
// access flags // access flags
@ -99,18 +99,23 @@ public interface Opcodes {
int ACC_FINAL = 0x0010; // class, field, method, parameter int ACC_FINAL = 0x0010; // class, field, method, parameter
int ACC_SUPER = 0x0020; // class int ACC_SUPER = 0x0020; // class
int ACC_SYNCHRONIZED = 0x0020; // method int ACC_SYNCHRONIZED = 0x0020; // method
int ACC_OPEN = 0x0020; // module
int ACC_TRANSITIVE = 0x0020; // module requires
int ACC_VOLATILE = 0x0040; // field int ACC_VOLATILE = 0x0040; // field
int ACC_BRIDGE = 0x0040; // method int ACC_BRIDGE = 0x0040; // method
int ACC_STATIC_PHASE = 0x0040; // module requires
int ACC_VARARGS = 0x0080; // method int ACC_VARARGS = 0x0080; // method
int ACC_TRANSIENT = 0x0080; // field int ACC_TRANSIENT = 0x0080; // field
int ACC_NATIVE = 0x0100; // method int ACC_NATIVE = 0x0100; // method
int ACC_INTERFACE = 0x0200; // class int ACC_INTERFACE = 0x0200; // class
int ACC_ABSTRACT = 0x0400; // class, method int ACC_ABSTRACT = 0x0400; // class, method
int ACC_STRICT = 0x0800; // method int ACC_STRICT = 0x0800; // method
int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter, module *
int ACC_ANNOTATION = 0x2000; // class int ACC_ANNOTATION = 0x2000; // class
int ACC_ENUM = 0x4000; // class(?) field inner int ACC_ENUM = 0x4000; // class(?) field inner
int ACC_MANDATED = 0x8000; // parameter int ACC_MANDATED = 0x8000; // parameter, module, module *
int ACC_MODULE = 0x8000; // class
// ASM specific pseudo access flags // ASM specific pseudo access flags
@ -177,15 +182,17 @@ public interface Opcodes {
*/ */
int F_SAME1 = 4; int F_SAME1 = 4;
// For reference comparison purposes, construct new instances // Do not try to change the following code to use auto-boxing,
// instead of using valueOf() or autoboxing. // these values are compared by reference and not by value
Integer TOP = new Integer(0); // The constructor of Integer was deprecated in 9
Integer INTEGER = new Integer(1); // but we are stuck with it by backward compatibility
Integer FLOAT = new Integer(2); @SuppressWarnings("deprecation") Integer TOP = new Integer(0);
Integer DOUBLE = new Integer(3); @SuppressWarnings("deprecation") Integer INTEGER = new Integer(1);
Integer LONG = new Integer(4); @SuppressWarnings("deprecation") Integer FLOAT = new Integer(2);
Integer NULL = new Integer(5); @SuppressWarnings("deprecation") Integer DOUBLE = new Integer(3);
Integer UNINITIALIZED_THIS = new Integer(6); @SuppressWarnings("deprecation") Integer LONG = new Integer(4);
@SuppressWarnings("deprecation") Integer NULL = new Integer(5);
@SuppressWarnings("deprecation") Integer UNINITIALIZED_THIS = new Integer(6);
// opcodes // visit method (- = idem) // opcodes // visit method (- = idem)

View File

@ -406,7 +406,16 @@ public class Type {
*/ */
public static Type getReturnType(final String methodDescriptor) { public static Type getReturnType(final String methodDescriptor) {
char[] buf = methodDescriptor.toCharArray(); char[] buf = methodDescriptor.toCharArray();
return getType(buf, methodDescriptor.indexOf(')') + 1); int off = 1;
while (true) {
char car = buf[off++];
if (car == ')') {
return getType(buf, off);
} else if (car == 'L') {
while (buf[off++] != ';') {
}
}
}
} }
/** /**

View File

@ -112,7 +112,7 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes
* *
* @param api * @param api
* the ASM API version implemented by this visitor. Must be one * the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param mv * @param mv
* the method visitor to which this adapter delegates calls. * the method visitor to which this adapter delegates calls.
* @param access * @param access

View File

@ -170,7 +170,7 @@ public class AnalyzerAdapter extends MethodVisitor {
*/ */
public AnalyzerAdapter(final String owner, final int access, public AnalyzerAdapter(final String owner, final int access,
final String name, final String desc, final MethodVisitor mv) { final String name, final String desc, final MethodVisitor mv) {
this(Opcodes.ASM5, owner, access, name, desc, mv); this(Opcodes.ASM6, owner, access, name, desc, mv);
if (getClass() != AnalyzerAdapter.class) { if (getClass() != AnalyzerAdapter.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -181,7 +181,7 @@ public class AnalyzerAdapter extends MethodVisitor {
* *
* @param api * @param api
* the ASM API version implemented by this visitor. Must be one * the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param owner * @param owner
* the owner's class name. * the owner's class name.
* @param access * @param access
@ -690,6 +690,8 @@ public class AnalyzerAdapter extends MethodVisitor {
t1 = pop(); t1 = pop();
if (t1 instanceof String) { if (t1 instanceof String) {
pushDesc(((String) t1).substring(1)); pushDesc(((String) t1).substring(1));
} else if (t1 == Opcodes.NULL) {
push(t1);
} else { } else {
push("java/lang/Object"); push("java/lang/Object");
} }

View File

@ -73,7 +73,7 @@ public class AnnotationRemapper extends AnnotationVisitor {
public AnnotationRemapper(final AnnotationVisitor av, public AnnotationRemapper(final AnnotationVisitor av,
final Remapper remapper) { final Remapper remapper) {
this(Opcodes.ASM5, av, remapper); this(Opcodes.ASM6, av, remapper);
} }
protected AnnotationRemapper(final int api, final AnnotationVisitor av, protected AnnotationRemapper(final int api, final AnnotationVisitor av,

View File

@ -59,10 +59,14 @@
package jdk.internal.org.objectweb.asm.commons; package jdk.internal.org.objectweb.asm.commons;
import java.util.List;
import jdk.internal.org.objectweb.asm.AnnotationVisitor; import jdk.internal.org.objectweb.asm.AnnotationVisitor;
import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.FieldVisitor; import jdk.internal.org.objectweb.asm.FieldVisitor;
import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.TypePath; import jdk.internal.org.objectweb.asm.TypePath;
@ -78,7 +82,7 @@ public class ClassRemapper extends ClassVisitor {
protected String className; protected String className;
public ClassRemapper(final ClassVisitor cv, final Remapper remapper) { public ClassRemapper(final ClassVisitor cv, final Remapper remapper) {
this(Opcodes.ASM5, cv, remapper); this(Opcodes.ASM6, cv, remapper);
} }
protected ClassRemapper(final int api, final ClassVisitor cv, protected ClassRemapper(final int api, final ClassVisitor cv,
@ -96,6 +100,12 @@ public class ClassRemapper extends ClassVisitor {
interfaces == null ? null : remapper.mapTypes(interfaces)); interfaces == null ? null : remapper.mapTypes(interfaces));
} }
@Override
public ModuleVisitor visitModule(String name, int flags, String version) {
ModuleVisitor mv = super.visitModule(remapper.mapModuleName(name), flags, version);
return mv == null ? null : createModuleRemapper(mv);
}
@Override @Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) { public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc), AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
@ -111,6 +121,18 @@ public class ClassRemapper extends ClassVisitor {
return av == null ? null : createAnnotationRemapper(av); return av == null ? null : createAnnotationRemapper(av);
} }
@Override
public void visitAttribute(Attribute attr) {
if (attr instanceof ModuleHashesAttribute) {
ModuleHashesAttribute hashesAttr = new ModuleHashesAttribute();
List<String> modules = hashesAttr.modules;
for(int i = 0; i < modules.size(); i++) {
modules.set(i, remapper.mapModuleName(modules.get(i)));
}
}
super.visitAttribute(attr);
}
@Override @Override
public FieldVisitor visitField(int access, String name, String desc, public FieldVisitor visitField(int access, String name, String desc,
String signature, Object value) { String signature, Object value) {
@ -158,4 +180,8 @@ public class ClassRemapper extends ClassVisitor {
protected AnnotationVisitor createAnnotationRemapper(AnnotationVisitor av) { protected AnnotationVisitor createAnnotationRemapper(AnnotationVisitor av) {
return new AnnotationRemapper(av, remapper); return new AnnotationRemapper(av, remapper);
} }
protected ModuleVisitor createModuleRemapper(ModuleVisitor mv) {
return new ModuleRemapper(mv, remapper);
}
} }

View File

@ -75,7 +75,7 @@ public class CodeSizeEvaluator extends MethodVisitor implements Opcodes {
private int maxSize; private int maxSize;
public CodeSizeEvaluator(final MethodVisitor mv) { public CodeSizeEvaluator(final MethodVisitor mv) {
this(Opcodes.ASM5, mv); this(Opcodes.ASM6, mv);
} }
protected CodeSizeEvaluator(final int api, final MethodVisitor mv) { protected CodeSizeEvaluator(final int api, final MethodVisitor mv) {

View File

@ -74,7 +74,7 @@ public class FieldRemapper extends FieldVisitor {
private final Remapper remapper; private final Remapper remapper;
public FieldRemapper(final FieldVisitor fv, final Remapper remapper) { public FieldRemapper(final FieldVisitor fv, final Remapper remapper) {
this(Opcodes.ASM5, fv, remapper); this(Opcodes.ASM6, fv, remapper);
} }
protected FieldRemapper(final int api, final FieldVisitor fv, protected FieldRemapper(final int api, final FieldVisitor fv,

View File

@ -289,7 +289,7 @@ public class GeneratorAdapter extends LocalVariablesSorter {
*/ */
public GeneratorAdapter(final MethodVisitor mv, final int access, public GeneratorAdapter(final MethodVisitor mv, final int access,
final String name, final String desc) { final String name, final String desc) {
this(Opcodes.ASM5, mv, access, name, desc); this(Opcodes.ASM6, mv, access, name, desc);
if (getClass() != GeneratorAdapter.class) { if (getClass() != GeneratorAdapter.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -300,7 +300,7 @@ public class GeneratorAdapter extends LocalVariablesSorter {
* *
* @param api * @param api
* the ASM API version implemented by this visitor. Must be one * the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param mv * @param mv
* the method visitor to which this adapter delegates calls. * the method visitor to which this adapter delegates calls.
* @param access * @param access

View File

@ -86,7 +86,7 @@ public class InstructionAdapter extends MethodVisitor {
* If a subclass calls this constructor. * If a subclass calls this constructor.
*/ */
public InstructionAdapter(final MethodVisitor mv) { public InstructionAdapter(final MethodVisitor mv) {
this(Opcodes.ASM5, mv); this(Opcodes.ASM6, mv);
if (getClass() != InstructionAdapter.class) { if (getClass() != InstructionAdapter.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -97,7 +97,7 @@ public class InstructionAdapter extends MethodVisitor {
* *
* @param api * @param api
* the ASM API version implemented by this visitor. Must be one * the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param mv * @param mv
* the method visitor to which this adapter delegates calls. * the method visitor to which this adapter delegates calls.
*/ */

View File

@ -142,7 +142,7 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes {
public JSRInlinerAdapter(final MethodVisitor mv, final int access, public JSRInlinerAdapter(final MethodVisitor mv, final int access,
final String name, final String desc, final String signature, final String name, final String desc, final String signature,
final String[] exceptions) { final String[] exceptions) {
this(Opcodes.ASM5, mv, access, name, desc, signature, exceptions); this(Opcodes.ASM6, mv, access, name, desc, signature, exceptions);
if (getClass() != JSRInlinerAdapter.class) { if (getClass() != JSRInlinerAdapter.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -153,7 +153,7 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes {
* *
* @param api * @param api
* the ASM API version implemented by this visitor. Must be one * the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param mv * @param mv
* the <code>MethodVisitor</code> to send the resulting inlined * the <code>MethodVisitor</code> to send the resulting inlined
* method code to (use <code>null</code> for none). * method code to (use <code>null</code> for none).

View File

@ -120,7 +120,7 @@ public class LocalVariablesSorter extends MethodVisitor {
*/ */
public LocalVariablesSorter(final int access, final String desc, public LocalVariablesSorter(final int access, final String desc,
final MethodVisitor mv) { final MethodVisitor mv) {
this(Opcodes.ASM5, access, desc, mv); this(Opcodes.ASM6, access, desc, mv);
if (getClass() != LocalVariablesSorter.class) { if (getClass() != LocalVariablesSorter.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -131,7 +131,7 @@ public class LocalVariablesSorter extends MethodVisitor {
* *
* @param api * @param api
* the ASM API version implemented by this visitor. Must be one * the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param access * @param access
* access flags of the adapted method. * access flags of the adapted method.
* @param desc * @param desc

View File

@ -76,7 +76,7 @@ public class MethodRemapper extends MethodVisitor {
protected final Remapper remapper; protected final Remapper remapper;
public MethodRemapper(final MethodVisitor mv, final Remapper remapper) { public MethodRemapper(final MethodVisitor mv, final Remapper remapper) {
this(Opcodes.ASM5, mv, remapper); this(Opcodes.ASM6, mv, remapper);
} }
protected MethodRemapper(final int api, final MethodVisitor mv, protected MethodRemapper(final int api, final MethodVisitor mv,
@ -122,18 +122,20 @@ public class MethodRemapper extends MethodVisitor {
} }
private Object[] remapEntries(int n, Object[] entries) { private Object[] remapEntries(int n, Object[] entries) {
for (int i = 0; i < n; i++) { if (entries != null) {
if (entries[i] instanceof String) { for (int i = 0; i < n; i++) {
Object[] newEntries = new Object[n]; if (entries[i] instanceof String) {
if (i > 0) { Object[] newEntries = new Object[n];
System.arraycopy(entries, 0, newEntries, 0, i); if (i > 0) {
System.arraycopy(entries, 0, newEntries, 0, i);
}
do {
Object t = entries[i];
newEntries[i++] = t instanceof String ? remapper
.mapType((String) t) : t;
} while (i < n);
return newEntries;
} }
do {
Object t = entries[i];
newEntries[i++] = t instanceof String ? remapper
.mapType((String) t) : t;
} while (i < n);
return newEntries;
} }
} }
return entries; return entries;

View File

@ -0,0 +1,155 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This 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:
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package jdk.internal.org.objectweb.asm.commons;
import java.util.ArrayList;
import java.util.List;
import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ByteVector;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Label;
/**
* ModuleHashes attribute.
* This attribute is specific to the OpenJDK and may change in the future.
*
* @author Remi Forax
*/
public final class ModuleHashesAttribute extends Attribute {
public String algorithm;
public List<String> modules;
public List<byte[]> hashes;
/**
* Creates an attribute with a hashing algorithm, a list of module names,
* and a list of the same length of hashes.
* @param algorithm the hashing algorithm name.
* @param modules a list of module name
* @param hashes a list of hash, one for each module name.
*/
public ModuleHashesAttribute(final String algorithm,
final List<String> modules, final List<byte[]> hashes) {
super("ModuleHashes");
this.algorithm = algorithm;
this.modules = modules;
this.hashes = hashes;
}
/**
* Creates an empty attribute that can be used as prototype
* to be passed as argument of the method
* {@link ClassReader#accept(org.objectweb.asm.ClassVisitor, Attribute[], int)}.
*/
public ModuleHashesAttribute() {
this(null, null, null);
}
@Override
protected Attribute read(ClassReader cr, int off, int len, char[] buf,
int codeOff, Label[] labels) {
String hashAlgorithm = cr.readUTF8(off, buf);
int count = cr.readUnsignedShort(off + 2);
ArrayList<String> modules = new ArrayList<String>(count);
ArrayList<byte[]> hashes = new ArrayList<byte[]>(count);
off += 4;
for (int i = 0; i < count; i++) {
String module = cr.readModule(off, buf);
int hashLength = cr.readUnsignedShort(off + 2);
off += 4;
byte[] hash = new byte[hashLength];
for (int j = 0; j < hashLength; j++) {
hash[j] = (byte) (cr.readByte(off + j) & 0xff);
}
off += hashLength;
modules.add(module);
hashes.add(hash);
}
return new ModuleHashesAttribute(hashAlgorithm, modules, hashes);
}
@Override
protected ByteVector write(ClassWriter cw, byte[] code, int len,
int maxStack, int maxLocals) {
ByteVector v = new ByteVector();
int index = cw.newUTF8(algorithm);
v.putShort(index);
int count = (modules == null)? 0: modules.size();
v.putShort(count);
for(int i = 0; i < count; i++) {
String module = modules.get(i);
v.putShort(cw.newModule(module));
byte[] hash = hashes.get(i);
v.putShort(hash.length);
for(byte b: hash) {
v.putByte(b);
}
}
return v;
}
}

View File

@ -0,0 +1,135 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This 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:
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package jdk.internal.org.objectweb.asm.commons;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
/**
* A {@link ModuleVisitor} adapter for type remapping.
*
* @author Remi Forax
*/
public class ModuleRemapper extends ModuleVisitor {
private final Remapper remapper;
public ModuleRemapper(final ModuleVisitor mv, final Remapper remapper) {
this(Opcodes.ASM6, mv, remapper);
}
protected ModuleRemapper(final int api, final ModuleVisitor mv,
final Remapper remapper) {
super(api, mv);
this.remapper = remapper;
}
@Override
public void visitMainClass(String mainClass) {
super.visitMainClass(remapper.mapType(mainClass));
}
@Override
public void visitPackage(String packaze) {
super.visitPackage(remapper.mapPackageName(packaze));
}
@Override
public void visitRequire(String module, int access, String version) {
super.visitRequire(remapper.mapModuleName(module), access, version);
}
@Override
public void visitExport(String packaze, int access, String... modules) {
String[] newModules = null;
if (modules != null) {
newModules = new String[modules.length];
for (int i = 0 ; i < modules.length; i++) {
newModules[i] = remapper.mapModuleName(modules[i]);
}
}
super.visitExport(remapper.mapPackageName(packaze), access, newModules);
}
@Override
public void visitOpen(String packaze, int access, String... modules) {
String[] newModules = null;
if (modules != null) {
newModules = new String[modules.length];
for (int i = 0 ; i < modules.length; i++) {
newModules[i] = remapper.mapModuleName(modules[i]);
}
}
super.visitOpen(remapper.mapPackageName(packaze), access, newModules);
}
@Override
public void visitUse(String service) {
super.visitUse(remapper.mapType(service));
}
@Override
public void visitProvide(String service, String... providers) {
String[] newProviders = new String[providers.length];
for (int i = 0 ; i < providers.length; i++) {
newProviders[i] = remapper.mapType(providers[i]);
}
super.visitProvide(remapper.mapType(service), newProviders);
}
}

View File

@ -0,0 +1,135 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This 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:
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package jdk.internal.org.objectweb.asm.commons;
import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ByteVector;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Label;
/**
* ModuleResolution_attribute.
* This attribute is specific to the OpenJDK and may change in the future.
*
* @author Remi Forax
*/
public final class ModuleResolutionAttribute extends Attribute {
/**
* Resolution state of a module meaning that the module is not available
* from the class-path by default.
*/
public static final int RESOLUTION_DO_NOT_RESOLVE_BY_DEFAULT = 1;
/**
* Resolution state of a module meaning the module is marked as deprecated.
*/
public static final int RESOLUTION_WARN_DEPRECATED = 2;
/**
* Resolution state of a module meaning the module is marked as deprecated
* and will be removed in a future release.
*/
public static final int RESOLUTION_WARN_DEPRECATED_FOR_REMOVAL = 4;
/**
* Resolution state of a module meaning the module is not yet standardized,
* so in incubating mode.
*/
public static final int RESOLUTION_WARN_INCUBATING = 8;
public int resolution;
/**
* Creates an attribute with a resolution state value.
* @param resolution the resolution state among
* {@link #RESOLUTION_WARN_DEPRECATED},
* {@link #RESOLUTION_WARN_DEPRECATED_FOR_REMOVAL}, and
* {@link #RESOLUTION_WARN_INCUBATING}.
*/
public ModuleResolutionAttribute(final int resolution) {
super("ModuleResolution");
this.resolution = resolution;
}
/**
* Creates an empty attribute that can be used as prototype
* to be passed as argument of the method
* {@link ClassReader#accept(org.objectweb.asm.ClassVisitor, Attribute[], int)}.
*/
public ModuleResolutionAttribute() {
this(0);
}
@Override
protected Attribute read(ClassReader cr, int off, int len, char[] buf,
int codeOff, Label[] labels) {
int resolution = cr.readUnsignedShort(off);
return new ModuleResolutionAttribute(resolution);
}
@Override
protected ByteVector write(ClassWriter cw, byte[] code, int len,
int maxStack, int maxLocals) {
ByteVector v = new ByteVector();
v.putShort(resolution);
return v;
}
}

View File

@ -0,0 +1,110 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This 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:
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package jdk.internal.org.objectweb.asm.commons;
import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ByteVector;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Label;
/**
* ModuleTarget attribute.
* This attribute is specific to the OpenJDK and may change in the future.
*
* @author Remi Forax
*/
public final class ModuleTargetAttribute extends Attribute {
public String platform;
/**
* Creates an attribute with a platform name.
* @param platform the platform name on which the module can run.
*/
public ModuleTargetAttribute(final String platform) {
super("ModuleTarget");
this.platform = platform;
}
/**
* Creates an empty attribute that can be used as prototype
* to be passed as argument of the method
* {@link ClassReader#accept(org.objectweb.asm.ClassVisitor, Attribute[], int)}.
*/
public ModuleTargetAttribute() {
this(null);
}
@Override
protected Attribute read(ClassReader cr, int off, int len, char[] buf,
int codeOff, Label[] labels) {
String platform = cr.readUTF8(off, buf);
return new ModuleTargetAttribute(platform);
}
@Override
protected ByteVector write(ClassWriter cw, byte[] code, int len,
int maxStack, int maxLocals) {
ByteVector v = new ByteVector();
int index = (platform == null)? 0: cw.newUTF8(platform);
v.putShort(index);
return v;
}
}

View File

@ -254,6 +254,28 @@ public abstract class Remapper {
return name; return name;
} }
/**
* Map package name to the new name. Subclasses can override.
*
* @param name name of the package
* @return new name of the package
*/
public String mapPackageName(String name) {
String fakeName = map(name + ".FakeClassName");
int index;
return fakeName == null || (index = fakeName.lastIndexOf('.')) == -1 ? name: fakeName.substring(0, index);
}
/**
* Map module name to the new name. Subclasses can override.
*
* @param name name of the module
* @return new name of the module
*/
public String mapModuleName(String name) {
return name;
}
/** /**
* Map type name to the new name. Subclasses can override. * Map type name to the new name. Subclasses can override.
* *

View File

@ -75,7 +75,7 @@ public class RemappingAnnotationAdapter extends AnnotationVisitor {
public RemappingAnnotationAdapter(final AnnotationVisitor av, public RemappingAnnotationAdapter(final AnnotationVisitor av,
final Remapper remapper) { final Remapper remapper) {
this(Opcodes.ASM5, av, remapper); this(Opcodes.ASM6, av, remapper);
} }
protected RemappingAnnotationAdapter(final int api, protected RemappingAnnotationAdapter(final int api,

View File

@ -63,6 +63,7 @@ import jdk.internal.org.objectweb.asm.AnnotationVisitor;
import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.FieldVisitor; import jdk.internal.org.objectweb.asm.FieldVisitor;
import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.TypePath; import jdk.internal.org.objectweb.asm.TypePath;
@ -80,7 +81,7 @@ public class RemappingClassAdapter extends ClassVisitor {
protected String className; protected String className;
public RemappingClassAdapter(final ClassVisitor cv, final Remapper remapper) { public RemappingClassAdapter(final ClassVisitor cv, final Remapper remapper) {
this(Opcodes.ASM5, cv, remapper); this(Opcodes.ASM6, cv, remapper);
} }
protected RemappingClassAdapter(final int api, final ClassVisitor cv, protected RemappingClassAdapter(final int api, final ClassVisitor cv,
@ -98,6 +99,11 @@ public class RemappingClassAdapter extends ClassVisitor {
interfaces == null ? null : remapper.mapTypes(interfaces)); interfaces == null ? null : remapper.mapTypes(interfaces));
} }
@Override
public ModuleVisitor visitModule(String name, int flags, String version) {
throw new RuntimeException("RemappingClassAdapter is deprecated, use ClassRemapper instead");
}
@Override @Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) { public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc), AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),

View File

@ -76,7 +76,7 @@ public class RemappingFieldAdapter extends FieldVisitor {
private final Remapper remapper; private final Remapper remapper;
public RemappingFieldAdapter(final FieldVisitor fv, final Remapper remapper) { public RemappingFieldAdapter(final FieldVisitor fv, final Remapper remapper) {
this(Opcodes.ASM5, fv, remapper); this(Opcodes.ASM6, fv, remapper);
} }
protected RemappingFieldAdapter(final int api, final FieldVisitor fv, protected RemappingFieldAdapter(final int api, final FieldVisitor fv,

View File

@ -79,7 +79,7 @@ public class RemappingMethodAdapter extends LocalVariablesSorter {
public RemappingMethodAdapter(final int access, final String desc, public RemappingMethodAdapter(final int access, final String desc,
final MethodVisitor mv, final Remapper remapper) { final MethodVisitor mv, final Remapper remapper) {
this(Opcodes.ASM5, access, desc, mv, remapper); this(Opcodes.ASM6, access, desc, mv, remapper);
} }
protected RemappingMethodAdapter(final int api, final int access, protected RemappingMethodAdapter(final int api, final int access,
@ -125,18 +125,20 @@ public class RemappingMethodAdapter extends LocalVariablesSorter {
} }
private Object[] remapEntries(int n, Object[] entries) { private Object[] remapEntries(int n, Object[] entries) {
for (int i = 0; i < n; i++) { if (entries != null) {
if (entries[i] instanceof String) { for (int i = 0; i < n; i++) {
Object[] newEntries = new Object[n]; if (entries[i] instanceof String) {
if (i > 0) { Object[] newEntries = new Object[n];
System.arraycopy(entries, 0, newEntries, 0, i); if (i > 0) {
System.arraycopy(entries, 0, newEntries, 0, i);
}
do {
Object t = entries[i];
newEntries[i++] = t instanceof String ? remapper
.mapType((String) t) : t;
} while (i < n);
return newEntries;
} }
do {
Object t = entries[i];
newEntries[i++] = t instanceof String ? remapper
.mapType((String) t) : t;
} while (i < n);
return newEntries;
} }
} }
return entries; return entries;

View File

@ -79,7 +79,7 @@ public class RemappingSignatureAdapter extends SignatureVisitor {
public RemappingSignatureAdapter(final SignatureVisitor v, public RemappingSignatureAdapter(final SignatureVisitor v,
final Remapper remapper) { final Remapper remapper) {
this(Opcodes.ASM5, v, remapper); this(Opcodes.ASM6, v, remapper);
} }
protected RemappingSignatureAdapter(final int api, protected RemappingSignatureAdapter(final int api,

View File

@ -80,7 +80,7 @@ import jdk.internal.org.objectweb.asm.Opcodes;
* ClassWriter cw = new ClassWriter(...); * ClassWriter cw = new ClassWriter(...);
* ClassVisitor sv = new SerialVersionUIDAdder(cw); * ClassVisitor sv = new SerialVersionUIDAdder(cw);
* ClassVisitor ca = new MyClassAdapter(sv); * ClassVisitor ca = new MyClassAdapter(sv);
* new ClassReader(originalClass).accept(ca, false); * new ClassReader(orginalClass).accept(ca, false);
* </pre> * </pre>
* *
* The SVUID algorithm can be found <a href= * The SVUID algorithm can be found <a href=
@ -199,7 +199,7 @@ public class SerialVersionUIDAdder extends ClassVisitor {
* If a subclass calls this constructor. * If a subclass calls this constructor.
*/ */
public SerialVersionUIDAdder(final ClassVisitor cv) { public SerialVersionUIDAdder(final ClassVisitor cv) {
this(Opcodes.ASM5, cv); this(Opcodes.ASM6, cv);
if (getClass() != SerialVersionUIDAdder.class) { if (getClass() != SerialVersionUIDAdder.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -210,7 +210,7 @@ public class SerialVersionUIDAdder extends ClassVisitor {
* *
* @param api * @param api
* the ASM API version implemented by this visitor. Must be one * the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param cv * @param cv
* a {@link ClassVisitor} to which this visitor will delegate * a {@link ClassVisitor} to which this visitor will delegate
* calls. * calls.

View File

@ -78,7 +78,7 @@ public class SignatureRemapper extends SignatureVisitor {
private Stack<String> classNames = new Stack<String>(); private Stack<String> classNames = new Stack<String>();
public SignatureRemapper(final SignatureVisitor v, final Remapper remapper) { public SignatureRemapper(final SignatureVisitor v, final Remapper remapper) {
this(Opcodes.ASM5, v, remapper); this(Opcodes.ASM6, v, remapper);
} }
protected SignatureRemapper(final int api, final SignatureVisitor v, protected SignatureRemapper(final int api, final SignatureVisitor v,

View File

@ -78,7 +78,7 @@ public class StaticInitMerger extends ClassVisitor {
private int counter; private int counter;
public StaticInitMerger(final String prefix, final ClassVisitor cv) { public StaticInitMerger(final String prefix, final ClassVisitor cv) {
this(Opcodes.ASM5, prefix, cv); this(Opcodes.ASM6, prefix, cv);
} }
protected StaticInitMerger(final int api, final String prefix, protected StaticInitMerger(final int api, final String prefix,

View File

@ -86,7 +86,7 @@ public class TryCatchBlockSorter extends MethodNode {
public TryCatchBlockSorter(final MethodVisitor mv, final int access, public TryCatchBlockSorter(final MethodVisitor mv, final int access,
final String name, final String desc, final String signature, final String name, final String desc, final String signature,
final String[] exceptions) { final String[] exceptions) {
this(Opcodes.ASM5, mv, access, name, desc, signature, exceptions); this(Opcodes.ASM6, mv, access, name, desc, signature, exceptions);
} }
protected TryCatchBlockSorter(final int api, final MethodVisitor mv, protected TryCatchBlockSorter(final int api, final MethodVisitor mv,

View File

@ -102,7 +102,7 @@ public abstract class SignatureVisitor {
/** /**
* The ASM API version implemented by this visitor. The value of this field * The ASM API version implemented by this visitor. The value of this field
* must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/ */
protected final int api; protected final int api;
@ -111,10 +111,10 @@ public abstract class SignatureVisitor {
* *
* @param api * @param api
* the ASM API version implemented by this visitor. Must be one * the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/ */
public SignatureVisitor(final int api) { public SignatureVisitor(final int api) {
if (api != Opcodes.ASM4 && api != Opcodes.ASM5) { if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
this.api = api; this.api = api;

View File

@ -95,7 +95,7 @@ public class SignatureWriter extends SignatureVisitor {
* Constructs a new {@link SignatureWriter} object. * Constructs a new {@link SignatureWriter} object.
*/ */
public SignatureWriter() { public SignatureWriter() {
super(Opcodes.ASM5); super(Opcodes.ASM6);
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------

View File

@ -65,7 +65,7 @@ import jdk.internal.org.objectweb.asm.AnnotationVisitor;
import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Opcodes;
/** /**
* A node that represents an annotationn. * A node that represents an annotation.
* *
* @author Eric Bruneton * @author Eric Bruneton
*/ */
@ -81,8 +81,8 @@ public class AnnotationNode extends AnnotationVisitor {
* as two consecutive elements in the list. The name is a {@link String}, * as two consecutive elements in the list. The name is a {@link String},
* and the value may be a {@link Byte}, {@link Boolean}, {@link Character}, * and the value may be a {@link Byte}, {@link Boolean}, {@link Character},
* {@link Short}, {@link Integer}, {@link Long}, {@link Float}, * {@link Short}, {@link Integer}, {@link Long}, {@link Float},
* {@link Double}, {@link String} or {@link jdk.internal.org.objectweb.asm.Type}, or an * {@link Double}, {@link String} or {@link jdk.internal.org.objectweb.asm.Type}, or a
* two elements String array (for enumeration values), a * two elements String array (for enumeration values), an
* {@link AnnotationNode}, or a {@link List} of values of one of the * {@link AnnotationNode}, or a {@link List} of values of one of the
* preceding types. The list may be <tt>null</tt> if there is no name value * preceding types. The list may be <tt>null</tt> if there is no name value
* pair. * pair.
@ -100,7 +100,7 @@ public class AnnotationNode extends AnnotationVisitor {
* If a subclass calls this constructor. * If a subclass calls this constructor.
*/ */
public AnnotationNode(final String desc) { public AnnotationNode(final String desc) {
this(Opcodes.ASM5, desc); this(Opcodes.ASM6, desc);
if (getClass() != AnnotationNode.class) { if (getClass() != AnnotationNode.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -111,7 +111,7 @@ public class AnnotationNode extends AnnotationVisitor {
* *
* @param api * @param api
* the ASM API version implemented by this visitor. Must be one * the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param desc * @param desc
* the class descriptor of the annotation class. * the class descriptor of the annotation class.
*/ */
@ -127,7 +127,7 @@ public class AnnotationNode extends AnnotationVisitor {
* where the visited values must be stored. * where the visited values must be stored.
*/ */
AnnotationNode(final List<Object> values) { AnnotationNode(final List<Object> values) {
super(Opcodes.ASM5); super(Opcodes.ASM6);
this.values = values; this.values = values;
} }
@ -143,7 +143,65 @@ public class AnnotationNode extends AnnotationVisitor {
if (this.desc != null) { if (this.desc != null) {
values.add(name); values.add(name);
} }
values.add(value); if (value instanceof byte[]) {
byte[] v = (byte[]) value;
ArrayList<Byte> l = new ArrayList<Byte>(v.length);
for (byte b : v) {
l.add(b);
}
values.add(l);
} else if (value instanceof boolean[]) {
boolean[] v = (boolean[]) value;
ArrayList<Boolean> l = new ArrayList<Boolean>(v.length);
for (boolean b : v) {
l.add(b);
}
values.add(l);
} else if (value instanceof short[]) {
short[] v = (short[]) value;
ArrayList<Short> l = new ArrayList<Short>(v.length);
for (short s : v) {
l.add(s);
}
values.add(l);
} else if (value instanceof char[]) {
char[] v = (char[]) value;
ArrayList<Character> l = new ArrayList<Character>(v.length);
for (char c : v) {
l.add(c);
}
values.add(l);
} else if (value instanceof int[]) {
int[] v = (int[]) value;
ArrayList<Integer> l = new ArrayList<Integer>(v.length);
for (int i : v) {
l.add(i);
}
values.add(l);
} else if (value instanceof long[]) {
long[] v = (long[]) value;
ArrayList<Long> l = new ArrayList<Long>(v.length);
for (long lng : v) {
l.add(lng);
}
values.add(l);
} else if (value instanceof float[]) {
float[] v = (float[]) value;
ArrayList<Float> l = new ArrayList<Float>(v.length);
for (float f : v) {
l.add(f);
}
values.add(l);
} else if (value instanceof double[]) {
double[] v = (double[]) value;
ArrayList<Double> l = new ArrayList<Double>(v.length);
for (double d : v) {
l.add(d);
}
values.add(l);
} else {
values.add(value);
}
} }
@Override @Override
@ -200,8 +258,8 @@ public class AnnotationNode extends AnnotationVisitor {
* versions of the ASM API than the given version. * versions of the ASM API than the given version.
* *
* @param api * @param api
* an ASM API version. Must be one of {@link Opcodes#ASM4} or * an ASM API version. Must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5}. * {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/ */
public void check(final int api) { public void check(final int api) {
// nothing to do // nothing to do

View File

@ -67,6 +67,7 @@ import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.FieldVisitor; import jdk.internal.org.objectweb.asm.FieldVisitor;
import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.TypePath; import jdk.internal.org.objectweb.asm.TypePath;
@ -126,6 +127,11 @@ public class ClassNode extends ClassVisitor {
*/ */
public String sourceDebug; public String sourceDebug;
/**
* Module information. May be <tt>null</tt>.
*/
public ModuleNode module;
/** /**
* The internal name of the enclosing class of the class. May be * The internal name of the enclosing class of the class. May be
* <tt>null</tt>. * <tt>null</tt>.
@ -221,7 +227,7 @@ public class ClassNode extends ClassVisitor {
* If a subclass calls this constructor. * If a subclass calls this constructor.
*/ */
public ClassNode() { public ClassNode() {
this(Opcodes.ASM5); this(Opcodes.ASM6);
if (getClass() != ClassNode.class) { if (getClass() != ClassNode.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -232,7 +238,7 @@ public class ClassNode extends ClassVisitor {
* *
* @param api * @param api
* the ASM API version implemented by this visitor. Must be one * the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/ */
public ClassNode(final int api) { public ClassNode(final int api) {
super(api); super(api);
@ -266,6 +272,12 @@ public class ClassNode extends ClassVisitor {
sourceDebug = debug; sourceDebug = debug;
} }
@Override
public ModuleVisitor visitModule(final String name, final int access,
final String version) {
return module = new ModuleNode(name, access, version);
}
@Override @Override
public void visitOuterClass(final String owner, final String name, public void visitOuterClass(final String owner, final String name,
final String desc) { final String desc) {
@ -358,11 +370,16 @@ public class ClassNode extends ClassVisitor {
* API than the given version. * API than the given version.
* *
* @param api * @param api
* an ASM API version. Must be one of {@link Opcodes#ASM4} or * an ASM API version. Must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5}. * {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/ */
public void check(final int api) { public void check(final int api) {
if (api == Opcodes.ASM4) { if (api < Opcodes.ASM6) {
if (module != null) {
throw new RuntimeException();
}
}
if (api < Opcodes.ASM5) {
if (visibleTypeAnnotations != null if (visibleTypeAnnotations != null
&& visibleTypeAnnotations.size() > 0) { && visibleTypeAnnotations.size() > 0) {
throw new RuntimeException(); throw new RuntimeException();
@ -371,12 +388,31 @@ public class ClassNode extends ClassVisitor {
&& invisibleTypeAnnotations.size() > 0) { && invisibleTypeAnnotations.size() > 0) {
throw new RuntimeException(); throw new RuntimeException();
} }
for (FieldNode f : fields) { }
f.check(api); // checks attributes
} int i, n;
for (MethodNode m : methods) { n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
m.check(api); for (i = 0; i < n; ++i) {
} visibleAnnotations.get(i).check(api);
}
n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
for (i = 0; i < n; ++i) {
invisibleAnnotations.get(i).check(api);
}
n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
for (i = 0; i < n; ++i) {
visibleTypeAnnotations.get(i).check(api);
}
n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
.size();
for (i = 0; i < n; ++i) {
invisibleTypeAnnotations.get(i).check(api);
}
for (FieldNode f : fields) {
f.check(api);
}
for (MethodNode m : methods) {
m.check(api);
} }
} }
@ -395,6 +431,10 @@ public class ClassNode extends ClassVisitor {
if (sourceFile != null || sourceDebug != null) { if (sourceFile != null || sourceDebug != null) {
cv.visitSource(sourceFile, sourceDebug); cv.visitSource(sourceFile, sourceDebug);
} }
// visits module
if (module != null) {
module.accept(cv);
}
// visits outer class // visits outer class
if (outerClass != null) { if (outerClass != null) {
cv.visitOuterClass(outerClass, outerMethod, outerMethodDesc); cv.visitOuterClass(outerClass, outerMethod, outerMethodDesc);

View File

@ -173,7 +173,7 @@ public class FieldNode extends FieldVisitor {
*/ */
public FieldNode(final int access, final String name, final String desc, public FieldNode(final int access, final String name, final String desc,
final String signature, final Object value) { final String signature, final Object value) {
this(Opcodes.ASM5, access, name, desc, signature, value); this(Opcodes.ASM6, access, name, desc, signature, value);
if (getClass() != FieldNode.class) { if (getClass() != FieldNode.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -276,8 +276,8 @@ public class FieldNode extends FieldVisitor {
* API than the given version. * API than the given version.
* *
* @param api * @param api
* an ASM API version. Must be one of {@link Opcodes#ASM4} or * an ASM API version. Must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5}. * {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/ */
public void check(final int api) { public void check(final int api) {
if (api == Opcodes.ASM4) { if (api == Opcodes.ASM4) {

View File

@ -634,14 +634,28 @@ public class InsnList {
} }
public void add(Object o) { public void add(Object o) {
InsnList.this.insertBefore(next, (AbstractInsnNode) o); if (next != null) {
InsnList.this.insertBefore(next, (AbstractInsnNode) o);
} else if (prev != null) {
InsnList.this.insert(prev, (AbstractInsnNode) o);
} else {
InsnList.this.add((AbstractInsnNode) o);
}
prev = (AbstractInsnNode) o; prev = (AbstractInsnNode) o;
remove = null; remove = null;
} }
public void set(Object o) { public void set(Object o) {
InsnList.this.set(next.prev, (AbstractInsnNode) o); if (remove != null) {
prev = (AbstractInsnNode) o; InsnList.this.set(remove, (AbstractInsnNode) o);
if (remove == prev) {
prev = (AbstractInsnNode) o;
} else {
next = (AbstractInsnNode) o;
}
} else {
throw new IllegalStateException();
}
} }
} }
} }

View File

@ -122,7 +122,7 @@ public class LocalVariableAnnotationNode extends TypeAnnotationNode {
*/ */
public LocalVariableAnnotationNode(int typeRef, TypePath typePath, public LocalVariableAnnotationNode(int typeRef, TypePath typePath,
LabelNode[] start, LabelNode[] end, int[] index, String desc) { LabelNode[] start, LabelNode[] end, int[] index, String desc) {
this(Opcodes.ASM5, typeRef, typePath, start, end, index, desc); this(Opcodes.ASM6, typeRef, typePath, start, end, index, desc);
} }
/** /**
@ -130,7 +130,7 @@ public class LocalVariableAnnotationNode extends TypeAnnotationNode {
* *
* @param api * @param api
* the ASM API version implemented by this visitor. Must be one * the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param typeRef * @param typeRef
* a reference to the annotated type. See {@link TypeReference}. * a reference to the annotated type. See {@link TypeReference}.
* @param start * @param start
@ -181,6 +181,6 @@ public class LocalVariableAnnotationNode extends TypeAnnotationNode {
index[i] = this.index.get(i); index[i] = this.index.get(i);
} }
accept(mv.visitLocalVariableAnnotation(typeRef, typePath, start, end, accept(mv.visitLocalVariableAnnotation(typeRef, typePath, start, end,
index, desc, true)); index, desc, visible));
} }
} }

View File

@ -249,7 +249,7 @@ public class MethodNode extends MethodVisitor {
* If a subclass calls this constructor. * If a subclass calls this constructor.
*/ */
public MethodNode() { public MethodNode() {
this(Opcodes.ASM5); this(Opcodes.ASM6);
if (getClass() != MethodNode.class) { if (getClass() != MethodNode.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -260,7 +260,7 @@ public class MethodNode extends MethodVisitor {
* *
* @param api * @param api
* the ASM API version implemented by this visitor. Must be one * the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/ */
public MethodNode(final int api) { public MethodNode(final int api) {
super(api); super(api);
@ -291,7 +291,7 @@ public class MethodNode extends MethodVisitor {
*/ */
public MethodNode(final int access, final String name, final String desc, public MethodNode(final int access, final String name, final String desc,
final String signature, final String[] exceptions) { final String signature, final String[] exceptions) {
this(Opcodes.ASM5, access, name, desc, signature, exceptions); this(Opcodes.ASM6, access, name, desc, signature, exceptions);
if (getClass() != MethodNode.class) { if (getClass() != MethodNode.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -302,7 +302,7 @@ public class MethodNode extends MethodVisitor {
* *
* @param api * @param api
* the ASM API version implemented by this visitor. Must be one * the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param access * @param access
* the method's access flags (see {@link Opcodes}). This * the method's access flags (see {@link Opcodes}). This
* parameter also indicates if the method is synthetic and/or * parameter also indicates if the method is synthetic and/or
@ -688,8 +688,8 @@ public class MethodNode extends MethodVisitor {
* versions of the ASM API than the given version. * versions of the ASM API than the given version.
* *
* @param api * @param api
* an ASM API version. Must be one of {@link Opcodes#ASM4} or * an ASM API version. Must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5}. * {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/ */
public void check(final int api) { public void check(final int api) {
if (api == Opcodes.ASM4) { if (api == Opcodes.ASM4) {

View File

@ -0,0 +1,111 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This 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:
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package jdk.internal.org.objectweb.asm.tree;
import java.util.List;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
/**
* A node that represents an exported package with its name and the module that can access to it.
*
* @author Remi Forax
*/
public class ModuleExportNode {
/**
* The package name.
*/
public String packaze;
/**
* The access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}).
* Valid values are {@code ACC_SYNTHETIC} and {@code ACC_MANDATED}.
*/
public int access;
/**
* A list of modules that can access to this exported package.
* May be <tt>null</tt>.
*/
public List<String> modules;
/**
* Constructs a new {@link ModuleExportNode}.
*
* @param packaze
* the parameter's name.
* @param modules
* a list of modules that can access to this exported package.
*/
public ModuleExportNode(final String packaze, final int access, final List<String> modules) {
this.packaze = packaze;
this.access = access;
this.modules = modules;
}
/**
* Makes the given module visitor visit this export declaration.
*
* @param mv
* a module visitor.
*/
public void accept(final ModuleVisitor mv) {
mv.visitExport(packaze, access, (modules == null) ? null : modules.toArray(new String[0]));
}
}

View File

@ -0,0 +1,280 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This 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:
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package jdk.internal.org.objectweb.asm.tree;
import java.util.ArrayList;
import java.util.List;
import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
/**
* A node that represents a module declaration.
*
* @author Remi Forax
*/
public class ModuleNode extends ModuleVisitor {
/**
* Module name
*/
public String name;
/**
* Module access flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC}
* and {@code ACC_MANDATED}.
*/
public int access;
/**
* Version of the module.
* May be <tt>null</tt>.
*/
public String version;
/**
* Name of the main class in internal form
* May be <tt>null</tt>.
*/
public String mainClass;
/**
* A list of packages that are declared by the current module.
* May be <tt>null</tt>.
*/
public List<String> packages;
/**
* A list of modules can are required by the current module.
* May be <tt>null</tt>.
*/
public List<ModuleRequireNode> requires;
/**
* A list of packages that are exported by the current module.
* May be <tt>null</tt>.
*/
public List<ModuleExportNode> exports;
/**
* A list of packages that are opened by the current module.
* May be <tt>null</tt>.
*/
public List<ModuleOpenNode> opens;
/**
* A list of classes in their internal forms that are used
* as a service by the current module. May be <tt>null</tt>.
*/
public List<String> uses;
/**
* A list of services along with their implementations provided
* by the current module. May be <tt>null</tt>.
*/
public List<ModuleProvideNode> provides;
public ModuleNode(final String name, final int access,
final String version) {
super(Opcodes.ASM6);
this.name = name;
this.access = access;
this.version = version;
}
public ModuleNode(final int api,
final String name,
final int access,
final String version,
final List<ModuleRequireNode> requires,
final List<ModuleExportNode> exports,
final List<ModuleOpenNode> opens,
final List<String> uses,
final List<ModuleProvideNode> provides) {
super(api);
this.name = name;
this.access = access;
this.version = version;
this.requires = requires;
this.exports = exports;
this.opens = opens;
this.uses = uses;
this.provides = provides;
if (getClass() != ModuleNode.class) {
throw new IllegalStateException();
}
}
@Override
public void visitMainClass(String mainClass) {
this.mainClass = mainClass;
}
@Override
public void visitPackage(String packaze) {
if (packages == null) {
packages = new ArrayList<String>(5);
}
packages.add(packaze);
}
@Override
public void visitRequire(String module, int access, String version) {
if (requires == null) {
requires = new ArrayList<ModuleRequireNode>(5);
}
requires.add(new ModuleRequireNode(module, access, version));
}
@Override
public void visitExport(String packaze, int access, String... modules) {
if (exports == null) {
exports = new ArrayList<ModuleExportNode>(5);
}
List<String> moduleList = null;
if (modules != null) {
moduleList = new ArrayList<String>(modules.length);
for (int i = 0; i < modules.length; i++) {
moduleList.add(modules[i]);
}
}
exports.add(new ModuleExportNode(packaze, access, moduleList));
}
@Override
public void visitOpen(String packaze, int access, String... modules) {
if (opens == null) {
opens = new ArrayList<ModuleOpenNode>(5);
}
List<String> moduleList = null;
if (modules != null) {
moduleList = new ArrayList<String>(modules.length);
for (int i = 0; i < modules.length; i++) {
moduleList.add(modules[i]);
}
}
opens.add(new ModuleOpenNode(packaze, access, moduleList));
}
@Override
public void visitUse(String service) {
if (uses == null) {
uses = new ArrayList<String>(5);
}
uses.add(service);
}
@Override
public void visitProvide(String service, String... providers) {
if (provides == null) {
provides = new ArrayList<ModuleProvideNode>(5);
}
ArrayList<String> providerList =
new ArrayList<String>(providers.length);
for (int i = 0; i < providers.length; i++) {
providerList.add(providers[i]);
}
provides.add(new ModuleProvideNode(service, providerList));
}
@Override
public void visitEnd() {
}
public void accept(final ClassVisitor cv) {
ModuleVisitor mv = cv.visitModule(name, access, version);
if (mv == null) {
return;
}
if (mainClass != null) {
mv.visitMainClass(mainClass);
}
if (packages != null) {
for (int i = 0; i < packages.size(); i++) {
mv.visitPackage(packages.get(i));
}
}
if (requires != null) {
for (int i = 0; i < requires.size(); i++) {
requires.get(i).accept(mv);
}
}
if (exports != null) {
for (int i = 0; i < exports.size(); i++) {
exports.get(i).accept(mv);
}
}
if (opens != null) {
for (int i = 0; i < opens.size(); i++) {
opens.get(i).accept(mv);
}
}
if (uses != null) {
for (int i = 0; i < uses.size(); i++) {
mv.visitUse(uses.get(i));
}
}
if (provides != null) {
for (int i = 0; i < provides.size(); i++) {
provides.get(i).accept(mv);
}
}
}
}

View File

@ -0,0 +1,111 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This 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:
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package jdk.internal.org.objectweb.asm.tree;
import java.util.List;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
/**
* A node that represents an opened package with its name and the module that can access to it.
*
* @author Remi Forax
*/
public class ModuleOpenNode {
/**
* The package name.
*/
public String packaze;
/**
* The access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}).
* Valid values are {@code ACC_SYNTHETIC} and {@code ACC_MANDATED}.
*/
public int access;
/**
* A list of modules that can access to this exported package.
* May be <tt>null</tt>.
*/
public List<String> modules;
/**
* Constructs a new {@link ModuleOpenNode}.
*
* @param packaze
* the parameter's name.
* @param modules
* a list of modules that can access to this open package.
*/
public ModuleOpenNode(final String packaze, final int access, final List<String> modules) {
this.packaze = packaze;
this.access = access;
this.modules = modules;
}
/**
* Makes the given module visitor visit this open declaration.
*
* @param mv
* a module visitor.
*/
public void accept(final ModuleVisitor mv) {
mv.visitExport(packaze, access, (modules == null) ? null : modules.toArray(new String[0]));
}
}

View File

@ -0,0 +1,103 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This 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:
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package jdk.internal.org.objectweb.asm.tree;
import java.util.List;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
/**
* A node that represents a service and its implementation provided by the current module.
*
* @author Remi Forax
*/
public class ModuleProvideNode {
/**
* The service name (in its internal form).
*/
public String service;
/**
* The service provider names (in their internal form).
*/
public List<String> providers;
/**
* Constructs a new {@link ModuleProvideNode}.
*
* @param service
* the service name (in its internal form).
* @param providers
* the service provider names (in their internal form).
*/
public ModuleProvideNode(final String service, final List<String> providers) {
this.service = service;
this.providers = providers;
}
/**
* Makes the given module visitor visit this require declaration.
*
* @param mv
* a module visitor.
*/
public void accept(final ModuleVisitor mv) {
mv.visitProvide(service, providers.toArray(new String[0]));
}
}

View File

@ -0,0 +1,116 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This 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:
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package jdk.internal.org.objectweb.asm.tree;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
/**
* A node that represents a required module with its name and access of a module descriptor.
*
* @author Remi Forax
*/
public class ModuleRequireNode {
/**
* The name of the required module.
*/
public String module;
/**
* The access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}).
* Valid values are <tt>ACC_TRANSITIVE</tt>, <tt>ACC_STATIC_PHASE</tt>,
* <tt>ACC_SYNTHETIC</tt> and <tt>ACC_MANDATED</tt>.
*/
public int access;
/**
* Version at compile time of the required module or null.
*/
public String version;
/**
* Constructs a new {@link ModuleRequireNode}.
*
* @param module
* the name of the required module.
* @param access
* The access flags. Valid values are
* <tt>ACC_TRANSITIVE</tt>, <tt>ACC_STATIC_PHASE</tt>,
* <tt>ACC_SYNTHETIC</tt> and <tt>ACC_MANDATED</tt>
* (see {@link jdk.internal.org.objectweb.asm.Opcodes}).
* @param version
* Version of the required module at compile time,
* null if not defined.
*/
public ModuleRequireNode(final String module, final int access,
final String version) {
this.module = module;
this.access = access;
this.version = version;
}
/**
* Makes the given module visitor visit this require directive.
*
* @param mv
* a module visitor.
*/
public void accept(final ModuleVisitor mv) {
mv.visitRequire(module, access, version);
}
}

View File

@ -99,7 +99,7 @@ public class TypeAnnotationNode extends AnnotationNode {
*/ */
public TypeAnnotationNode(final int typeRef, final TypePath typePath, public TypeAnnotationNode(final int typeRef, final TypePath typePath,
final String desc) { final String desc) {
this(Opcodes.ASM5, typeRef, typePath, desc); this(Opcodes.ASM6, typeRef, typePath, desc);
if (getClass() != TypeAnnotationNode.class) { if (getClass() != TypeAnnotationNode.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -110,7 +110,7 @@ public class TypeAnnotationNode extends AnnotationNode {
* *
* @param api * @param api
* the ASM API version implemented by this visitor. Must be one * the ASM API version implemented by this visitor. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param typeRef * @param typeRef
* a reference to the annotated type. See {@link TypeReference}. * a reference to the annotated type. See {@link TypeReference}.
* @param typePath * @param typePath

View File

@ -82,7 +82,7 @@ public class BasicInterpreter extends Interpreter<BasicValue> implements
Opcodes { Opcodes {
public BasicInterpreter() { public BasicInterpreter() {
super(ASM5); super(ASM6);
} }
protected BasicInterpreter(final int api) { protected BasicInterpreter(final int api) {

View File

@ -76,7 +76,7 @@ import jdk.internal.org.objectweb.asm.tree.MethodInsnNode;
public class BasicVerifier extends BasicInterpreter { public class BasicVerifier extends BasicInterpreter {
public BasicVerifier() { public BasicVerifier() {
super(ASM5); super(ASM6);
} }
protected BasicVerifier(final int api) { protected BasicVerifier(final int api) {

View File

@ -136,7 +136,7 @@ public class SimpleVerifier extends BasicVerifier {
public SimpleVerifier(final Type currentClass, public SimpleVerifier(final Type currentClass,
final Type currentSuperClass, final Type currentSuperClass,
final List<Type> currentClassInterfaces, final boolean isInterface) { final List<Type> currentClassInterfaces, final boolean isInterface) {
this(ASM5, currentClass, currentSuperClass, currentClassInterfaces, this(ASM6, currentClass, currentSuperClass, currentClassInterfaces,
isInterface); isInterface);
} }

View File

@ -79,7 +79,7 @@ public class SourceInterpreter extends Interpreter<SourceValue> implements
Opcodes { Opcodes {
public SourceInterpreter() { public SourceInterpreter() {
super(ASM5); super(ASM6);
} }
protected SourceInterpreter(final int api) { protected SourceInterpreter(final int api) {

Some files were not shown because too many files have changed in this diff Show More