This commit is contained in:
Dmitry Fazunenko 2016-03-24 15:51:31 +04:00
commit 0f687b0bd5
2531 changed files with 142841 additions and 28019 deletions

View File

@ -352,3 +352,4 @@ db483b34fa7148d257a429acddbde9c13687dcae jdk-9+105
1c076468bf7dad5b8f2ee5dcf66e2279caa3e208 jdk-9+107
257b579d813201682931d6b42f0445ffe5b4210d jdk-9+108
c870cb782aca71093d2584376f27f0cfbfec0e3a jdk-9+109
4a95f4b1bd8bfce85dc02a593896749feab96c34 jdk-9+110

View File

@ -352,3 +352,4 @@ be58b02c11f90b88c67e4d0e2cb5e4cf2d9b3c57 jdk-9+105
4d65eba233a8730f913734a6804910b842d2cb54 jdk-9+107
c7be2a78c31b3b6132f2f5e9e4b3d3bb1c20245c jdk-9+108
1787bdaabb2b6f4193406e25a50cb0419ea8e8f3 jdk-9+109
925be13b3740d07a5958ccb5ab3c0ae1baba7055 jdk-9+110

View File

@ -843,6 +843,8 @@ AC_DEFUN_ONCE([BASIC_SETUP_OUTPUT_DIR],
AC_CONFIG_FILES([$OUTPUT_ROOT/hotspot-spec.gmk:$AUTOCONF_DIR/hotspot-spec.gmk.in])
# The bootcycle-spec.gmk file contains support for boot cycle builds.
AC_CONFIG_FILES([$OUTPUT_ROOT/bootcycle-spec.gmk:$AUTOCONF_DIR/bootcycle-spec.gmk.in])
# The buildjdk-spec.gmk file contains support for building a buildjdk when cross compiling.
AC_CONFIG_FILES([$OUTPUT_ROOT/buildjdk-spec.gmk:$AUTOCONF_DIR/buildjdk-spec.gmk.in])
# The compare.sh is used to compare the build output to other builds.
AC_CONFIG_FILES([$OUTPUT_ROOT/compare.sh:$AUTOCONF_DIR/compare.sh.in])
# The generated Makefile knows where the spec.gmk is and where the source is.

View File

@ -304,6 +304,18 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK],
# When compiling code to be executed by the Boot JDK, force jdk8 compatibility.
BOOT_JDK_SOURCETARGET="-source 8 -target 8"
AC_SUBST(BOOT_JDK_SOURCETARGET)
ADD_JVM_ARG_IF_OK([-Xpatch:], dummy, [$JAVA])
AC_MSG_CHECKING([if Boot JDK supports modules])
if test "x$JVM_ARG_OK" = "xtrue"; then
AC_MSG_RESULT([yes])
BOOT_JDK_MODULAR="true"
else
AC_MSG_RESULT([no])
BOOT_JDK_MODULAR="false"
fi
AC_SUBST(BOOT_JDK_MODULAR)
AC_SUBST(JAVAC_FLAGS)
# Check if the boot jdk is 32 or 64 bit
@ -397,3 +409,100 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS],
done
AC_SUBST(JAVA_TOOL_FLAGS_SMALL)
])
# BUILD_JDK: the location of the latest JDK that can run
# on the host system and supports the target class file version
# generated in this JDK build. This variable should only be
# used after the launchers are built.
#
# Execute the check given as argument, and verify the result.
# If the JDK was previously found, do nothing.
# $1 A command line (typically autoconf macro) to execute
AC_DEFUN([BOOTJDK_CHECK_BUILD_JDK],
[
if test "x$BUILD_JDK_FOUND" = xno; then
# Execute the test
$1
# If previous step claimed to have found a JDK, check it to see if it seems to be valid.
if test "x$BUILD_JDK_FOUND" = xmaybe; then
# Do we have a bin/java?
if test ! -x "$BUILD_JDK/bin/java"; then
AC_MSG_NOTICE([Potential Build JDK found at $BUILD_JDK did not contain bin/java; ignoring])
BUILD_JDK_FOUND=no
elif test ! -x "$BUILD_JDK/bin/jlink"; then
AC_MSG_NOTICE([Potential Build JDK found at $BUILD_JDK did not contain bin/jlink; ignoring])
BUILD_JDK_FOUND=no
elif test ! -x "$BUILD_JDK/bin/javac"; then
# Do we have a bin/javac?
AC_MSG_NOTICE([Potential Build JDK found at $BUILD_JDK did not contain bin/javac; ignoring])
AC_MSG_NOTICE([(This might be a JRE instead of an JDK)])
BUILD_JDK_FOUND=no
else
# Oh, this is looking good! We probably have found a proper JDK. Is it the correct version?
BUILD_JDK_VERSION=`"$BUILD_JDK/bin/java" -version 2>&1 | head -n 1`
# Extra M4 quote needed to protect [] in grep expression.
[FOUND_CORRECT_VERSION=`echo $BUILD_JDK_VERSION | grep '\"1\.[9]\.'`]
if test "x$FOUND_CORRECT_VERSION" = x; then
AC_MSG_NOTICE([Potential Boot JDK found at $BUILD_JDK is incorrect JDK version ($BUILD_JDK_VERSION); ignoring])
AC_MSG_NOTICE([(Your Build JDK must be version 9)])
BUILD_JDK_FOUND=no
else
# We're done!
BUILD_JDK_FOUND=yes
BASIC_FIXUP_PATH(BUILD_JDK)
AC_MSG_CHECKING([for Build JDK])
AC_MSG_RESULT([$BUILD_JDK])
AC_MSG_CHECKING([Build JDK version])
BUILD_JDK_VERSION=`"$BUILD_JDK/bin/java" -version 2>&1 | $TR '\n\r' ' '`
AC_MSG_RESULT([$BUILD_JDK_VERSION])
fi # end check jdk version
fi # end check java
fi # end check build jdk found
fi
])
# By default the BUILD_JDK is the JDK_OUTPUTDIR. If the target architecture
# is different than the host system doing the build (e.g. cross-compilation),
# a special BUILD_JDK is built as part of the build process. An external
# prebuilt BUILD_JDK can also be supplied.
AC_DEFUN([BOOTJDK_SETUP_BUILD_JDK],
[
AC_ARG_WITH(build-jdk, [AS_HELP_STRING([--with-build-jdk],
[path to JDK of same version as is being built@<:@the newly built JDK@:>@])])
CREATE_BUILDJDK_FOR_HOST=false
BUILD_JDK_FOUND="no"
if test "x$with_build_jdk" != "x"; then
BOOTJDK_CHECK_BUILD_JDK([
if test "x$with_build_jdk" != x; then
BUILD_JDK=$with_build_jdk
BUILD_JDK_FOUND=maybe
AC_MSG_NOTICE([Found potential Build JDK using configure arguments])
fi])
else
if test "x$COMPILE_TYPE" = "xcross"; then
BUILD_JDK="\$(BUILDJDK_OUTPUTDIR)/jdk"
BUILD_JDK_FOUND=yes
CREATE_BUILDJDK=true
AC_MSG_CHECKING([for Build JDK])
AC_MSG_RESULT([yes, will build it for the host platform])
else
BUILD_JDK="\$(JDK_OUTPUTDIR)"
BUILD_JDK_FOUND=yes
AC_MSG_CHECKING([for Build JDK])
AC_MSG_RESULT([yes, will use output dir])
fi
fi
if test "x$BUILD_JDK_FOUND" != "xyes"; then
AC_MSG_CHECKING([for Build JDK])
AC_MSG_RESULT([no])
AC_MSG_ERROR([Could not find a suitable Build JDK])
fi
AC_SUBST(CREATE_BUILDJDK)
AC_SUBST(BUILD_JDK)
])

View File

@ -25,6 +25,8 @@
# Support for building boot cycle builds
BOOT_JDK_MODULAR := true
# First include the real base spec.gmk file
include @SPEC@

View File

@ -0,0 +1,148 @@
#
# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. 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 spec file is used to compile a BUILD_JDK while cross compiling. The
# BUILD_JDK runs on the build/host platform and is of the same version as
# the main build.
# First include the real base spec.gmk file
include @SPEC@
CC := @BUILD_CC@
CXX := @BUILD_CXX@
LD := @BUILD_LD@
AS := @BUILD_AS@
NM := @BUILD_NM@
AR := @BUILD_AR@
OBJCOPY := @BUILD_OBJCOPY@
STRIP := @BUILD_STRIP@
SYSROOT_CFLAGS := @BUILD_SYSROOT_CFLAGS@
SYSROOT_LDFLAGS := @BUILD_SYSROOT_LDFLAGS@
# These directories should not be moved to BUILDJDK_OUTPUTDIR
HOTSPOT_OUTPUTDIR := $(patsubst $(BUILD_OUTPUT)%,$(BUILDJDK_OUTPUTDIR)%,$(HOTSPOT_OUTPUTDIR))
HOTSPOT_DIST := $(patsubst $(BUILD_OUTPUT)%,$(BUILDJDK_OUTPUTDIR)%,$(HOTSPOT_DIST))
SUPPORT_OUTPUTDIR := $(patsubst $(BUILD_OUTPUT)%,$(BUILDJDK_OUTPUTDIR)%,$(SUPPORT_OUTPUTDIR))
JDK_OUTPUTDIR := $(patsubst $(BUILD_OUTPUT)%,$(BUILDJDK_OUTPUTDIR)%,$(JDK_OUTPUTDIR))
OPENJDK_BUILD_CPU_LEGACY := @OPENJDK_BUILD_CPU_LEGACY@
OPENJDK_BUILD_CPU_LEGACY_LIB := @OPENJDK_BUILD_CPU_LEGACY_LIB@
OPENJDK_BUILD_CPU_LIBDIR := @OPENJDK_BUILD_CPU_LIBDIR@
OPENJDK_TARGET_CPU_LIBDIR := @OPENJDK_BUILD_CPU_LIBDIR@
OPENJDK_TARGET_CPU := @OPENJDK_BUILD_CPU@
OPENJDK_TARGET_CPU_ARCH := @OPENJDK_BUILD_CPU_ARCH@
OPENJDK_TARGET_CPU_BITS := @OPENJDK_BUILD_CPU_BITS@
OPENJDK_TARGET_CPU_ENDIAN := @OPENJDK_BUILD_CPU_ENDIAN@
OPENJDK_TARGET_CPU_LEGACY := @OPENJDK_BUILD_CPU_LEGACY@
CFLAGS_JDKLIB := @OPENJDK_BUILD_CFLAGS_JDKLIB@
CXXFLAGS_JDKLIB := @OPENJDK_BUILD_CXXFLAGS_JDKLIB@
LDFLAGS_JDKLIB := @OPENJDK_BUILD_LDFLAGS_JDKLIB@
CFLAGS_JDKEXE := @OPENJDK_BUILD_CFLAGS_JDKEXE@
CXXFLAGS_JDKEXE := @OPENJDK_BUILD_CXXFLAGS_JDKEXE@
LDFLAGS_JDKEXE := @OPENJDK_BUILD_LDFLAGS_JDKEXE@
OPENJDK_TARGET_CPU_JLI_CFLAGS := @OPENJDK_BUILD_CPU_JLI_CFLAGS@
# The compiler for the build platform is likely not warning compatible with the official
# compiler.
WARNINGS_AS_ERRORS := false
DISABLE_WARNING_PREFIX := @BUILD_CC_DISABLE_WARNING_PREFIX@
# Save speed and disk space by not enabling debug symbols for the buildjdk
ENABLE_DEBUG_SYMBOLS := false
####################################################
#
# Legacy Hotspot support
# Legacy setting: OPT or DBG
VARIANT := OPT
# Legacy setting: true or false
FASTDEBUG := false
# Legacy setting: debugging the class files?
DEBUG_CLASSFILES := false
# Some users still set EXTRA_*FLAGS on the make command line. Must
# make sure to override that when building buildjdk.
override EXTRA_CFLAGS :=
override EXTRA_CXXFLAGS :=
override EXTRA_LDFLAGS :=
# The HOSTCC/HOSTCXX is Hotspot terminology for the BUILD_CC/BUILD_CXX, i.e. the
# compiler that produces code that can be run on the build platform.
HOSTCC := $(BUILD_CC)
HOSTCXX := $(BUILD_CXX)
# Old name for OPENJDK_TARGET_OS (aix,bsd,hpux,linux,macosx,solaris,windows etc)
PLATFORM := $(OPENJDK_BUILD_OS)
# 32 or 64 bit
ARCH_DATA_MODEL := $(OPENJDK_BUILD_CPU_BITS)
ALT_BOOTDIR := $(BOOT_JDK)
# Yet another name for arch used for an extra subdir below the jvm lib.
# Uses i386 and amd64, instead of x86 and x86_64.
LIBARCH := @OPENJDK_BUILD_CPU_LEGACY_LIB@
# Set the cpu architecture. Some users still set ARCH on the make command line. Must
# make sure to override that when building buildjdk.
override ARCH := $(OPENJDK_BUILD_CPU_ARCH)
# Legacy setting for building for a 64 bit machine.
# If yes then this expands to _LP64 := 1
ifeq ($(OPENJDK_BUILD_CPU_BITS), 64)
_LP64 := 1
endif
ALT_OUTPUTDIR := $(HOTSPOT_OUTPUTDIR)
ALT_EXPORT_PATH := $(HOTSPOT_DIST)
JVM_INTERPRETER := @JVM_INTERPRETER@
ifeq ($(JVM_INTERPRETER), cpp)
CC_INTERP=true
endif
HOTSPOT_MAKE_ARGS := product docs export_product
# Control wether Hotspot runs Queens test after building
TEST_IN_BUILD := false
USE_PRECOMPILED_HEADER := @USE_PRECOMPILED_HEADER@
# Hotspot expects the variable FULL_DEBUG_SYMBOLS=1/0 to control debug symbols
# creation.
FULL_DEBUG_SYMBOLS := 0
ZIP_DEBUGINFO_FILES := 0
# Disable stripping
STRIP_POLICY := none
JVM_VARIANTS := server
JVM_VARIANT_SERVER := true
JVM_VARIANT_CLIENT := false
JVM_VARIANT_MINIMAL1 := false
JVM_VARIANT_KERNEL := false
JVM_VARIANT_ZERO := false
JVM_VARIANT_ZEROSHARK := false
JVM_VARIANT_CORE := false
# Sneak this in via the spec.gmk file, since we don't want to mess around too much with the Hotspot make files.
# This is needed to get the LOG setting to work properly.
include $(SRC_ROOT)/make/common/MakeBase.gmk

View File

@ -134,6 +134,7 @@ BASIC_SETUP_DEFAULT_MAKE_TARGET
# We need build & target for this.
JDKOPT_SETUP_JDK_OPTIONS
JDKOPT_SETUP_JLINK_OPTIONS
HOTSPOT_SETUP_HOTSPOT_OPTIONS
JDKVER_SETUP_JDK_VERSION_NUMBERS
@ -144,6 +145,7 @@ JDKVER_SETUP_JDK_VERSION_NUMBERS
###############################################################################
BOOTJDK_SETUP_BOOT_JDK
BOOTJDK_SETUP_BUILD_JDK
###############################################################################
#
@ -155,6 +157,8 @@ SRCDIRS_SETUP_TOPDIRS
SRCDIRS_SETUP_ALTERNATIVE_TOPDIRS
SRCDIRS_SETUP_OUTPUT_DIRS
SRCDIRS_SETUP_IMPORT_MODULES
###############################################################################
#
# Setup the toolchain (compilers etc), i.e. tools used to compile and process

View File

@ -689,9 +689,6 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK],
;;
esac
# Setup LP64
COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK $ADD_LP64"
# Set some common defines. These works for all compilers, but assume
# -D is universally accepted.
@ -722,7 +719,12 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK],
COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D$OPENJDK_TARGET_OS_UPPERCASE"
# Setup target CPU
COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -DARCH='\"$OPENJDK_TARGET_CPU_LEGACY\"' -D$OPENJDK_TARGET_CPU_LEGACY"
OPENJDK_TARGET_CCXXFLAGS_JDK="$OPENJDK_TARGET_CCXXFLAGS_JDK \
$ADD_LP64 \
-DARCH='\"$OPENJDK_TARGET_CPU_LEGACY\"' -D$OPENJDK_TARGET_CPU_LEGACY"
OPENJDK_BUILD_CCXXFLAGS_JDK="$OPENJDK_BUILD_CCXXFLAGS_JDK \
$OPENJDK_BUILD_ADD_LP64 \
-DARCH='\"$OPENJDK_BUILD_CPU_LEGACY\"' -D$OPENJDK_BUILD_CPU_LEGACY"
# Setup debug/release defines
if test "x$DEBUG_LEVEL" = xrelease; then
@ -766,17 +768,35 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK],
-I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/libjava"
# The shared libraries are compiled using the picflag.
CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA"
CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA"
CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \
$CFLAGS_JDK $EXTRA_CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA"
CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \
$CXXFLAGS_JDK $EXTRA_CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA"
# Executable flags
CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK"
CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK"
CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \
$CFLAGS_JDK $EXTRA_CFLAGS_JDK"
CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \
$CXXFLAGS_JDK $EXTRA_CXXFLAGS_JDK"
# The corresponding flags for building for the build platform. This is still an
# approximation, we only need something that runs on this machine when cross
# compiling the product.
OPENJDK_BUILD_CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK \
$PICFLAG $CFLAGS_JDKLIB_EXTRA"
OPENJDK_BUILD_CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK \
$PICFLAG $CXXFLAGS_JDKLIB_EXTRA"
OPENJDK_BUILD_CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK"
OPENJDK_BUILD_CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_BUILD_CCXXFLAGS_JDK"
AC_SUBST(CFLAGS_JDKLIB)
AC_SUBST(CFLAGS_JDKEXE)
AC_SUBST(CXXFLAGS_JDKLIB)
AC_SUBST(CXXFLAGS_JDKEXE)
AC_SUBST(OPENJDK_BUILD_CFLAGS_JDKLIB)
AC_SUBST(OPENJDK_BUILD_CFLAGS_JDKEXE)
AC_SUBST(OPENJDK_BUILD_CXXFLAGS_JDKLIB)
AC_SUBST(OPENJDK_BUILD_CXXFLAGS_JDKEXE)
# Flags for compiling test libraries
CFLAGS_TESTLIB="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA"
@ -872,6 +892,9 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK],
LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE -Wl,--allow-shlib-undefined"
fi
OPENJDK_BUILD_LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE}"
LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE} ${EXTRA_LDFLAGS_JDK}"
# Customize LDFLAGS for libs
LDFLAGS_JDKLIB="${LDFLAGS_JDK}"
@ -882,30 +905,39 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK],
JDKLIB_LIBS=""
else
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} \
-L${OUTPUT_ROOT}/support/modules_libs/java.base${OPENJDK_TARGET_CPU_LIBDIR}"
-L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)"
# On some platforms (mac) the linker warns about non existing -L dirs.
# Add server first if available. Linking aginst client does not always produce the same results.
# Only add client dir if client is being built. Add minimal (note not minimal1) if only building minimal1.
# Default to server for other variants.
if test "x$JVM_VARIANT_SERVER" = xtrue; then
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${OUTPUT_ROOT}/support/modules_libs/java.base${OPENJDK_TARGET_CPU_LIBDIR}/server"
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server"
elif test "x$JVM_VARIANT_CLIENT" = xtrue; then
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${OUTPUT_ROOT}/support/modules_libs/java.base${OPENJDK_TARGET_CPU_LIBDIR}/client"
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/client"
elif test "x$JVM_VARIANT_MINIMAL1" = xtrue; then
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${OUTPUT_ROOT}/support/modules_libs/java.base${OPENJDK_TARGET_CPU_LIBDIR}/minimal"
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/minimal"
else
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${OUTPUT_ROOT}/support/modules_libs/java.base${OPENJDK_TARGET_CPU_LIBDIR}/server"
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server"
fi
JDKLIB_LIBS="-ljava -ljvm"
if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
JDKLIB_LIBS="$JDKLIB_LIBS -lc"
fi
# When building a buildjdk, it's always only the server variant
OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} \
-L\$(SUPPORT_OUTPUTDIR)/modules_libs/java.base\$(OPENJDK_TARGET_CPU_LIBDIR)/server"
fi
OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} ${LDFLAGS_JDKLIB}"
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} ${EXTRA_LDFLAGS_JDK}"
AC_SUBST(LDFLAGS_JDKLIB)
AC_SUBST(LDFLAGS_JDKEXE)
AC_SUBST(OPENJDK_BUILD_LDFLAGS_JDKLIB)
AC_SUBST(OPENJDK_BUILD_LDFLAGS_JDKEXE)
AC_SUBST(JDKLIB_LIBS)
AC_SUBST(JDKEXE_LIBS)
AC_SUBST(LDFLAGS_CXX_JDK)
@ -1075,5 +1107,6 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_MISC],
;;
esac
AC_SUBST(DISABLE_WARNING_PREFIX)
AC_SUBST(BUILD_CC_DISABLE_WARNING_PREFIX)
AC_SUBST(CFLAGS_WARNINGS_ARE_ERRORS)
])

File diff suppressed because it is too large Load Diff

View File

@ -405,3 +405,31 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_STATIC_BUILD],
AC_SUBST(STATIC_BUILD)
])
################################################################################
#
# jlink options.
# We always keep packaged modules in JDK image.
#
AC_DEFUN_ONCE([JDKOPT_SETUP_JLINK_OPTIONS],
[
AC_ARG_ENABLE([keep-packaged-modules], [AS_HELP_STRING([--disable-keep-packaged-modules],
[Do not keep packaged modules in jdk image @<:@enable@:>@])])
if test "x$enable_keep_packaged_modules" = "xyes"; then
AC_MSG_CHECKING([if packaged modules are kept])
AC_MSG_RESULT([yes])
JLINK_KEEP_PACKAGED_MODULES=true
elif test "x$enable_keep_packaged_modules" = "xno"; then
AC_MSG_CHECKING([if packaged modules are kept])
AC_MSG_RESULT([no])
JLINK_KEEP_PACKAGED_MODULES=false
elif test "x$enable_keep_packaged_modules" = "x"; then
AC_MSG_RESULT([yes (default)])
JLINK_KEEP_PACKAGED_MODULES=true
else
AC_MSG_ERROR([--enable-keep-packaged-modules accepts no argument])
fi
AC_SUBST(JLINK_KEEP_PACKAGED_MODULES)
])

View File

@ -304,6 +304,37 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS],
fi
AC_SUBST(OPENJDK_TARGET_CPU_LIBDIR)
# Now do the same for OPENJDK_BUILD_CPU...
# Also store the legacy naming of the cpu.
# Ie i586 and amd64 instead of x86 and x86_64
OPENJDK_BUILD_CPU_LEGACY="$OPENJDK_BUILD_CPU"
if test "x$OPENJDK_BUILD_CPU" = xx86; then
OPENJDK_BUILD_CPU_LEGACY="i586"
elif test "x$OPENJDK_BUILD_OS" != xmacosx && test "x$OPENJDK_BUILD_CPU" = xx86_64; then
# On all platforms except MacOSX replace x86_64 with amd64.
OPENJDK_BUILD_CPU_LEGACY="amd64"
fi
AC_SUBST(OPENJDK_BUILD_CPU_LEGACY)
# And the second legacy naming of the cpu.
# Ie i386 and amd64 instead of x86 and x86_64.
OPENJDK_BUILD_CPU_LEGACY_LIB="$OPENJDK_BUILD_CPU"
if test "x$OPENJDK_BUILD_CPU" = xx86; then
OPENJDK_BUILD_CPU_LEGACY_LIB="i386"
elif test "x$OPENJDK_BUILD_CPU" = xx86_64; then
OPENJDK_BUILD_CPU_LEGACY_LIB="amd64"
fi
AC_SUBST(OPENJDK_BUILD_CPU_LEGACY_LIB)
# This is the name of the cpu (but using i386 and amd64 instead of
# x86 and x86_64, respectively), preceeded by a /, to be used when
# locating libraries. On macosx, it's empty, though.
OPENJDK_BUILD_CPU_LIBDIR="/$OPENJDK_BUILD_CPU_LEGACY_LIB"
if test "x$OPENJDK_BUILD_OS" = xmacosx; then
OPENJDK_BUILD_CPU_LIBDIR=""
fi
AC_SUBST(OPENJDK_BUILD_CPU_LIBDIR)
# OPENJDK_TARGET_CPU_ISADIR is normally empty. On 64-bit Solaris systems, it is set to
# /amd64 or /sparcv9. This string is appended to some library paths, like this:
# /usr/lib${OPENJDK_TARGET_CPU_ISADIR}/libexample.so
@ -346,6 +377,24 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS],
fi
AC_SUBST(OPENJDK_TARGET_CPU_JLI_CFLAGS)
OPENJDK_BUILD_CPU_JLI="$OPENJDK_BUILD_CPU"
if test "x$OPENJDK_BUILD_CPU" = xx86; then
OPENJDK_BUILD_CPU_JLI="i386"
elif test "x$OPENJDK_BUILD_OS" != xmacosx && test "x$OPENJDK_BUILD_CPU" = xx86_64; then
# On all platforms except macosx, we replace x86_64 with amd64.
OPENJDK_BUILD_CPU_JLI="amd64"
fi
# Now setup the -D flags for building libjli.
OPENJDK_BUILD_CPU_JLI_CFLAGS="-DLIBARCHNAME='\"$OPENJDK_BUILD_CPU_JLI\"'"
if test "x$OPENJDK_BUILD_OS" = xsolaris; then
if test "x$OPENJDK_BUILD_CPU_ARCH" = xsparc; then
OPENJDK_BUILD_CPU_JLI_CFLAGS="$OPENJDK_BUILD_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"sparc\"' -DLIBARCH64NAME='\"sparcv9\"'"
elif test "x$OPENJDK_BUILD_CPU_ARCH" = xx86; then
OPENJDK_BUILD_CPU_JLI_CFLAGS="$OPENJDK_BUILD_CPU_JLI_CFLAGS -DLIBARCH32NAME='\"i386\"' -DLIBARCH64NAME='\"amd64\"'"
fi
fi
AC_SUBST(OPENJDK_BUILD_CPU_JLI_CFLAGS)
if test "x$OPENJDK_TARGET_OS" = xmacosx; then
OPENJDK_TARGET_OS_EXPORT_DIR=macosx
else
@ -362,6 +411,11 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS],
fi
fi
AC_SUBST(LP64,$A_LP64)
if test "x$OPENJDK_BUILD_CPU_BITS" = x64; then
if test "x$OPENJDK_BUILD_OS" = xlinux || test "x$OPENJDK_BUILD_OS" = xmacosx; then
OPENJDK_BUILD_ADD_LP64="-D_LP64=1"
fi
fi
if test "x$COMPILE_TYPE" = "xcross"; then
# FIXME: ... or should this include reduced builds..?

View File

@ -84,3 +84,56 @@ AC_DEFUN_ONCE([SRCDIRS_SETUP_OUTPUT_DIRS],
JDK_OUTPUTDIR="$OUTPUT_ROOT/jdk"
])
################################################################################
# Define a mechanism for importing extra prebuilt modules
#
AC_DEFUN_ONCE([SRCDIRS_SETUP_IMPORT_MODULES],
[
AC_ARG_WITH(import-modules, [AS_HELP_STRING([--with-import-modules],
[import a set of prebuilt modules either as a zip file or an exploded directory])])
if test "x$with_import_modules" != x \
&& test "x$with_import_modules" != "xno"; then
if test -d "$with_import_modules"; then
IMPORT_MODULES_TOPDIR="$with_import_modules"
BASIC_FIXUP_PATH([IMPORT_MODULES_TOPDIR])
elif test -e "$with_import_modules"; then
IMPORT_MODULES_TOPDIR="$CONFIGURESUPPORT_OUTPUTDIR/import-modules"
$RM -rf "$IMPORT_MODULES_TOPDIR"
$MKDIR -p "$IMPORT_MODULES_TOPDIR"
if ! $UNZIP -q "$with_import_modules" -d "$IMPORT_MODULES_TOPDIR"; then
AC_MSG_ERROR([--with-import-modules="$with_import_modules" must point to a dir or a zip file])
fi
else
AC_MSG_ERROR([--with-import-modules="$with_import_modules" must point to a dir or a zip file])
fi
fi
if test -d "$IMPORT_MODULES_TOPDIR/modules"; then
IMPORT_MODULES_CLASSES="$IMPORT_MODULES_TOPDIR/modules"
fi
if test -d "$IMPORT_MODULES_TOPDIR/modules_cmds"; then
IMPORT_MODULES_CMDS="$IMPORT_MODULES_TOPDIR/modules_cmds"
fi
if test -d "$IMPORT_MODULES_TOPDIR/modules_libs"; then
IMPORT_MODULES_LIBS="$IMPORT_MODULES_TOPDIR/modules_libs"
fi
if test -d "$IMPORT_MODULES_TOPDIR/modules_conf"; then
IMPORT_MODULES_CONF="$IMPORT_MODULES_TOPDIR/modules_conf"
fi
if test -d "$IMPORT_MODULES_TOPDIR/modules_src"; then
IMPORT_MODULES_SRC="$IMPORT_MODULES_TOPDIR/modules_src"
fi
if test -d "$IMPORT_MODULES_TOPDIR/make"; then
IMPORT_MODULES_MAKE="$IMPORT_MODULES_TOPDIR/make"
fi
AC_SUBST(IMPORT_MODULES_CLASSES)
AC_SUBST(IMPORT_MODULES_CMDS)
AC_SUBST(IMPORT_MODULES_LIBS)
AC_SUBST(IMPORT_MODULES_CONF)
AC_SUBST(IMPORT_MODULES_SRC)
AC_SUBST(IMPORT_MODULES_MAKE)
])

View File

@ -130,6 +130,14 @@ JAXP_TOPDIR:=@JAXP_TOPDIR@
JAXWS_TOPDIR:=@JAXWS_TOPDIR@
HOTSPOT_TOPDIR:=@HOTSPOT_TOPDIR@
NASHORN_TOPDIR:=@NASHORN_TOPDIR@
IMPORT_MODULES_CLASSES:=@IMPORT_MODULES_CLASSES@
IMPORT_MODULES_CMDS:=@IMPORT_MODULES_CMDS@
IMPORT_MODULES_LIBS:=@IMPORT_MODULES_LIBS@
IMPORT_MODULES_CONF:=@IMPORT_MODULES_CONF@
IMPORT_MODULES_SRC:=@IMPORT_MODULES_SRC@
IMPORT_MODULES_MAKE:=@IMPORT_MODULES_MAKE@
COPYRIGHT_YEAR:=@COPYRIGHT_YEAR@
# New (JEP-223) version information
@ -246,6 +254,7 @@ TESTMAKE_OUTPUTDIR=$(BUILD_OUTPUT)/test-make
MAKESUPPORT_OUTPUTDIR=$(BUILD_OUTPUT)/make-support
# This does not get overridden in a bootcycle build
CONFIGURESUPPORT_OUTPUTDIR:=@CONFIGURESUPPORT_OUTPUTDIR@
BUILDJDK_OUTPUTDIR=$(BUILD_OUTPUT)/buildjdk
HOTSPOT_DIST=@HOTSPOT_DIST@
@ -255,6 +264,9 @@ BUILD_HOTSPOT=@BUILD_HOTSPOT@
# it in sync.
BOOT_JDK:=@BOOT_JDK@
BUILD_JDK:=@BUILD_JDK@
CREATE_BUILDJDK:=@CREATE_BUILDJDK@
# When compiling Java source to be run by the boot jdk
# use these extra flags, eg -source 6 -target 6
BOOT_JDK_SOURCETARGET:=@BOOT_JDK_SOURCETARGET@
@ -405,6 +417,8 @@ BUILD_LDCXX:=@FIXPATH@ @BUILD_LDCXX@
BUILD_AS:=@FIXPATH@ @BUILD_AS@
BUILD_AR:=@FIXPATH@ @BUILD_AR@
BUILD_NM:=@FIXPATH@ @BUILD_NM@
BUILD_OBJCOPY:=@BUILD_OBJCOPY@
BUILD_STRIP:=@BUILD_STRIP@
BUILD_SYSROOT_CFLAGS:=@BUILD_SYSROOT_CFLAGS@
BUILD_SYSROOT_LDFLAGS:=@BUILD_SYSROOT_LDFLAGS@
@ -502,12 +516,40 @@ SJAVAC_SERVER_JAVA=@FIXPATH@ @FIXPATH_DETACH_FLAG@ $(SJAVAC_SERVER_JAVA_CMD) \
# overriding that value by using ?=.
JAVAC_FLAGS?=@JAVAC_FLAGS@
BUILD_JAVA_FLAGS:=-Xms64M -Xmx1100M
BUILD_JAVA=@FIXPATH@ $(BUILD_JDK)/bin/java $(BUILD_JAVA_FLAGS)
# Use ?= as this can be overridden from bootcycle-spec.gmk
BOOT_JDK_MODULAR ?= @BOOT_JDK_MODULAR@
ifeq ($(BOOT_JDK_MODULAR), true)
INTERIM_OVERRIDE_MODULES_ARGS = -Xpatch:$(BUILDTOOLS_OUTPUTDIR)/override_modules
INTERIM_LANGTOOLS_ARGS = $(INTERIM_OVERRIDE_MODULES_ARGS)
JAVAC_MAIN_CLASS = -m jdk.compiler/com.sun.tools.javac.Main
JAVADOC_MAIN_CLASS = -m jdk.javadoc/jdk.javadoc.internal.tool.Main
else
INTERIM_OVERRIDE_MODULES := java.compiler jdk.compiler \
jdk.jdeps jdk.javadoc jdk.rmic
INTERIM_OVERRIDE_MODULES_ARGS = \
-Xbootclasspath/p:$(call PathList, \
$(addprefix $(BUILDTOOLS_OUTPUTDIR)/override_modules/, \
$(INTERIM_OVERRIDE_MODULES)))
INTERIM_LANGTOOLS_ARGS = $(INTERIM_OVERRIDE_MODULES_ARGS) \
-cp $(BUILDTOOLS_OUTPUTDIR)/override_modules/jdk.compiler
JAVAC_MAIN_CLASS = com.sun.tools.javac.Main
JAVADOC_MAIN_CLASS = jdk.javadoc.internal.tool.Main
endif
# You run the new javac using the boot jdk with $(BOOT_JDK)/bin/java $(NEW_JAVAC) ...
# Use = assignment to be able to override in bootcycle-spec.gmk
INTERIM_LANGTOOLS_JAR = $(BUILDTOOLS_OUTPUTDIR)/interim_langtools.jar
INTERIM_LANGTOOLS_ARGS = "-Xbootclasspath/p:$(INTERIM_LANGTOOLS_JAR)" -cp $(INTERIM_LANGTOOLS_JAR)
NEW_JAVAC = $(INTERIM_LANGTOOLS_ARGS) com.sun.tools.javac.Main
NEW_JAVADOC = $(INTERIM_LANGTOOLS_ARGS) jdk.javadoc.internal.tool.Main
NEW_JAVAC = $(INTERIM_LANGTOOLS_ARGS) $(JAVAC_MAIN_CLASS)
NEW_JAVADOC = $(INTERIM_LANGTOOLS_ARGS) $(JAVADOC_MAIN_CLASS)
# JLink/Jmod are run using the BUILD_JDK, which is normally the jdk output dir.
JLINK_KEEP_PACKAGED_MODULES:=@JLINK_KEEP_PACKAGED_MODULES@
JLINK = @FIXPATH@ $(BUILD_JDK)/bin/jlink $(JAVA_TOOL_FLAGS_SMALL)
JMOD = @FIXPATH@ $(BUILD_JDK)/bin/jmod $(JAVA_TOOL_FLAGS_SMALL)
# Base flags for RC
# Guarding this against resetting value. Legacy make files include spec multiple

View File

@ -797,6 +797,10 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_BUILD_COMPILERS],
BASIC_FIXUP_EXECUTABLE(BUILD_NM)
BASIC_PATH_PROGS(BUILD_AR, ar gcc-ar)
BASIC_FIXUP_EXECUTABLE(BUILD_AR)
BASIC_PATH_PROGS(BUILD_OBJCOPY, objcopy)
BASIC_FIXUP_EXECUTABLE(BUILD_OBJCOPY)
BASIC_PATH_PROGS(BUILD_STRIP, strip)
BASIC_FIXUP_EXECUTABLE(BUILD_STRIP)
# Assume the C compiler is the assembler
BUILD_AS="$BUILD_CC -c"
# Just like for the target compiler, use the compiler as linker
@ -813,6 +817,8 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_BUILD_COMPILERS],
BUILD_LDCXX="$LDCXX"
BUILD_NM="$NM"
BUILD_AS="$AS"
BUILD_OBJCOPY="$OBJCOPY"
BUILD_STRIP="$STRIP"
BUILD_SYSROOT_CFLAGS="$SYSROOT_CFLAGS"
BUILD_SYSROOT_LDFLAGS="$SYSROOT_LDFLAGS"
BUILD_AR="$AR"

View File

@ -290,9 +290,9 @@ compare_general_files() {
GENERAL_FILES=$(cd $THIS_DIR && $FIND . -type f ! -name "*.so" ! -name "*.jar" \
! -name "*.zip" ! -name "*.debuginfo" ! -name "*.dylib" ! -name "jexec" \
! -name "*.jimage" ! -name "ct.sym" ! -name "*.diz" ! -name "*.dll" \
! -name "modules" ! -name "ct.sym" ! -name "*.diz" ! -name "*.dll" \
! -name "*.cpl" ! -name "*.pdb" ! -name "*.exp" ! -name "*.ilk" \
! -name "*.lib" ! -name "*.war" ! -name "JavaControlPanel" \
! -name "*.lib" ! -name "*.war" ! -name "JavaControlPanel" ! -name "*.jmod" \
! -name "*.obj" ! -name "*.o" ! -name "JavaControlPanelHelper" \
! -name "JavaUpdater" ! -name "JavaWSApplicationStub" \
! -name "jspawnhelper" ! -name "JavawsLauncher" ! -name "*.a" \
@ -389,13 +389,13 @@ compare_zip_file() {
$RM -rf $THIS_UNZIPDIR $OTHER_UNZIPDIR
$MKDIR -p $THIS_UNZIPDIR
$MKDIR -p $OTHER_UNZIPDIR
if [ "$TYPE" = "jimage" ]
if [ "$TYPE" = "jar" || "$TYPE" = "war" || "$TYPE" = "zip" || "$TYPE" = "jmod"]
then
(cd $THIS_UNZIPDIR && $JIMAGE extract $THIS_ZIP)
(cd $OTHER_UNZIPDIR && $JIMAGE extract $OTHER_ZIP)
else
(cd $THIS_UNZIPDIR && $UNARCHIVE $THIS_ZIP)
(cd $OTHER_UNZIPDIR && $UNARCHIVE $OTHER_ZIP)
else
(cd $THIS_UNZIPDIR && $JIMAGE extract $THIS_ZIP)
(cd $OTHER_UNZIPDIR && $JIMAGE extract $OTHER_ZIP)
fi
# Find all archives inside and unzip them as well to compare the contents rather than
@ -526,7 +526,7 @@ compare_all_jar_files() {
# TODO filter?
ZIPS=$(cd $THIS_DIR && $FIND . -type f -name "*.jar" -o -name "*.war" \
-o -name "*.jimage" | $SORT | $FILTER)
-o -name "modules" -o -name "*.jmod" | $SORT | $FILTER)
if [ -n "$ZIPS" ]; then
echo Jar files...

View File

@ -421,10 +421,10 @@ var getJibProfilesDependencies = function (input, common) {
jtreg: {
server: "javare",
revision: "4.1",
build_number: "b12",
revision: "4.2",
build_number: "b01",
checksum_file: "MD5_VALUES",
file: "jtreg_bin-4.1.zip",
file: "jtreg_bin-4.2.zip",
environment_name: "JT_HOME"
},

View File

@ -352,3 +352,4 @@ e385e95e6101711d5c63e7b1a827e99b6ec7a1cc jdk-9+104
49202432b69445164a42be7cbdf74ed5fce98157 jdk-9+107
84f2862a25eb3232ff36c376b4e2bf2a83dfced3 jdk-9+108
b75afa17aefe480c23c616a6a2497063312f7189 jdk-9+109
9666775734fb6028ee86df9972626b3667b6a318 jdk-9+110

View File

@ -47,7 +47,7 @@ $(eval $(call SetupJavaCompilation,BUILD_IDLJ, \
BIN := $(BUILDTOOLS_OUTPUTDIR)/idlj_classes, \
COPY := .prp, \
INCLUDES := com/sun/tools/corba/se/idl, \
EXCLUDE_FILES := ResourceBundleUtil.java))
EXCLUDE_FILES := ResourceBundleUtil.java module-info.java))
# Force the language to english for predictable source code generation.
TOOL_IDLJ_CMD := $(JAVA) -cp $(BUILDTOOLS_OUTPUTDIR)/idlj_classes \

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
module java.corba {
requires public java.desktop;
requires public java.rmi;
requires java.logging;
requires java.naming;
requires java.transaction;
exports javax.activity;
exports javax.rmi;
exports javax.rmi.CORBA;
exports org.omg.CORBA;
exports org.omg.CORBA.DynAnyPackage;
exports org.omg.CORBA.ORBPackage;
exports org.omg.CORBA.TypeCodePackage;
exports org.omg.CORBA.portable;
exports org.omg.CORBA_2_3;
exports org.omg.CORBA_2_3.portable;
exports org.omg.CosNaming;
exports org.omg.CosNaming.NamingContextExtPackage;
exports org.omg.CosNaming.NamingContextPackage;
exports org.omg.Dynamic;
exports org.omg.DynamicAny;
exports org.omg.DynamicAny.DynAnyFactoryPackage;
exports org.omg.DynamicAny.DynAnyPackage;
exports org.omg.IOP;
exports org.omg.IOP.CodecFactoryPackage;
exports org.omg.IOP.CodecPackage;
exports org.omg.Messaging;
exports org.omg.PortableInterceptor;
exports org.omg.PortableInterceptor.ORBInitInfoPackage;
exports org.omg.PortableServer;
exports org.omg.PortableServer.CurrentPackage;
exports org.omg.PortableServer.POAManagerPackage;
exports org.omg.PortableServer.POAPackage;
exports org.omg.PortableServer.ServantLocatorPackage;
exports org.omg.PortableServer.portable;
exports org.omg.SendingContext;
exports org.omg.stub.java.rmi;
exports com.sun.corba.se.impl.util to
jdk.rmic;
exports com.sun.jndi.cosnaming to
java.naming;
exports com.sun.jndi.url.corbaname to
java.naming;
exports com.sun.jndi.url.iiop to
java.naming;
exports com.sun.jndi.url.iiopname to
java.naming;
provides javax.naming.spi.InitialContextFactory
with com.sun.jndi.cosnaming.CNCtxFactory;
}

View File

@ -512,3 +512,4 @@ c5f55130b1b69510d9a6f4a3105b58e21cd7ffe1 jdk-9+103
c5146d4da417f76edfc43097d2e2ced042a65b4e jdk-9+107
934f6793f5f7dca44f69b4559d525fa64b31840d jdk-9+108
7e7e50ac4faf19899fc811569e32cfa478759ebb jdk-9+109
2f5d1578b24060ea06bd1f340a124db95d1475b2 jdk-9+110

View File

@ -91,7 +91,7 @@ else ifeq ($(OPENJDK_TARGET_OS), windows)
ifeq ($(OPENJDK_TARGET_CPU), x86_64)
SA_CXXFLAGS += -DWIN64
else
SA_CXXFLAGS += -RTC1 -ZI
SA_CXXFLAGS += -RTC1
SA_LDFLAGS += -SAFESEH
endif
endif

View File

@ -167,3 +167,15 @@
JVM_TotalMemory;
JVM_UnloadLibrary;
JVM_Yield;
# Module related API's
JVM_AddModuleExports;
JVM_AddModuleExportsToAll;
JVM_AddModuleExportsToAllUnnamed;
JVM_AddModulePackage;
JVM_AddReadsModule;
JVM_CanReadModule;
JVM_DefineModule;
JVM_IsExportedToModule;
JVM_SetBootLoaderUnnamedModule;
JVM_GetModuleByPackageName;

View File

@ -45,6 +45,7 @@ BUILD_HOTSPOT_JTREG_NATIVE_SRC := \
$(HOTSPOT_TOPDIR)/test/runtime/jni/8025979 \
$(HOTSPOT_TOPDIR)/test/runtime/jni/8033445 \
$(HOTSPOT_TOPDIR)/test/runtime/jni/ToStringInInterfaceTest \
$(HOTSPOT_TOPDIR)/test/runtime/modules/getModuleJNI \
$(HOTSPOT_TOPDIR)/test/runtime/SameObject \
$(HOTSPOT_TOPDIR)/test/compiler/floatingpoint/ \
$(HOTSPOT_TOPDIR)/test/compiler/calls \

View File

@ -849,8 +849,8 @@ class StubGenerator: public StubCodeGenerator {
__ bind(L1);
if (direction == copy_forwards) {
__ add(s, s, 2 * wordSize);
__ add(d, d, 2 * wordSize);
__ add(s, s, bias);
__ add(d, d, bias);
}
__ tbz(count, 1, L2);

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
module jdk.hotspot.agent {
requires java.datatransfer;
requires java.desktop;
requires java.rmi;
requires java.scripting;
requires jdk.jcmd;
requires jdk.jdi;
// RMI needs to serialize types in this package
exports sun.jvm.hotspot.debugger.remote to java.rmi;
provides com.sun.jdi.connect.Connector with sun.jvm.hotspot.jdi.SACoreAttachingConnector;
provides com.sun.jdi.connect.Connector with sun.jvm.hotspot.jdi.SADebugServerAttachingConnector;
provides com.sun.jdi.connect.Connector with sun.jvm.hotspot.jdi.SAPIDAttachingConnector;
provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.JStack;
provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.JInfo;
provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.ClassLoaderStats;
provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.FinalizerInfo;
provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.HeapDumper;
provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.HeapSummary;
provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.ObjectHistogram;
provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.PMap;
}

View File

@ -88,7 +88,7 @@ public class SALauncher {
}
private static boolean jsnapHelp() {
System.out.println(" <no option>\tdump performance counters");
System.out.println(" --all\tto print all performance counters");
return commonHelp();
}
@ -331,7 +331,7 @@ public class SALauncher {
private static void runJSNAP(String[] oldArgs) {
SAGetopt sg = new SAGetopt(oldArgs);
String[] longOpts = {"exe=", "core=", "pid="};
String[] longOpts = {"exe=", "core=", "pid=", "all"};
ArrayList<String> newArgs = new ArrayList();
String exe = null;
@ -352,6 +352,10 @@ public class SALauncher {
pid = sg.getOptarg();
continue;
}
if (s.equals("all")) {
newArgs.add("-a");
continue;
}
}
buildAttachArgs(newArgs, pid, exe, core);

View File

@ -31,14 +31,14 @@ import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.tools.*;
import sun.jvm.hotspot.utilities.*;
import jdk.internal.vm.agent.spi.ToolProvider;
/**
A command line tool to print class loader statistics.
*/
public class ClassLoaderStats extends Tool {
public class ClassLoaderStats extends Tool implements ToolProvider {
boolean verbose = true;
public ClassLoaderStats() {
@ -49,6 +49,16 @@ public class ClassLoaderStats extends Tool {
super(d);
}
@Override
public String getName() {
return "classLoaderStats";
}
@Override
public void run(String... arguments) {
execute(arguments);
}
public static void main(String[] args) {
ClassLoaderStats cls = new ClassLoaderStats();
cls.execute(args);

View File

@ -25,24 +25,21 @@
package sun.jvm.hotspot.tools;
import sun.jvm.hotspot.debugger.JVMDebugger;
import sun.jvm.hotspot.tools.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.VM;
import sun.jvm.hotspot.utilities.SystemDictionaryHelper;
import sun.jvm.hotspot.utilities.ObjectReader;
import sun.jvm.hotspot.utilities.MarkBits;
import jdk.internal.vm.agent.spi.ToolProvider;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
/*
* Iterates over the queue of object pending finalization and prints a
* summary of these objects in the form of a histogram.
*/
public class FinalizerInfo extends Tool {
public class FinalizerInfo extends Tool implements ToolProvider {
public FinalizerInfo() {
super();
@ -52,6 +49,16 @@ public class FinalizerInfo extends Tool {
super(d);
}
@Override
public String getName() {
return "finalizerInfo";
}
@Override
public void run(String... arguments) {
execute(arguments);
}
public static void main(String[] args) {
FinalizerInfo finfo = new FinalizerInfo();
finfo.execute(args);

View File

@ -26,6 +26,8 @@ package sun.jvm.hotspot.tools;
import sun.jvm.hotspot.utilities.HeapHprofBinWriter;
import sun.jvm.hotspot.debugger.JVMDebugger;
import jdk.internal.vm.agent.spi.ToolProvider;
import java.io.IOException;
/*
@ -33,12 +35,16 @@ import java.io.IOException;
* process/core as a HPROF binary file. It can also be used as a standalone
* tool if required.
*/
public class HeapDumper extends Tool {
public class HeapDumper extends Tool implements ToolProvider {
private static String DEFAULT_DUMP_FILE = "heap.bin";
private String dumpFile;
public HeapDumper() {
this.dumpFile = DEFAULT_DUMP_FILE;
}
public HeapDumper(String dumpFile) {
this.dumpFile = dumpFile;
}
@ -48,6 +54,11 @@ public class HeapDumper extends Tool {
this.dumpFile = dumpFile;
}
@Override
public String getName() {
return "heapDumper";
}
protected void printFlagsUsage() {
System.out.println(" <no option>\tto dump heap to " +
DEFAULT_DUMP_FILE);
@ -69,18 +80,22 @@ public class HeapDumper extends Tool {
// JDK jmap utility will always invoke this tool as:
// HeapDumper -f <file> <args...>
public static void main(String args[]) {
String file = DEFAULT_DUMP_FILE;
HeapDumper dumper = new HeapDumper();
dumper.run(args);
}
@Override
public void run(String... args) {
if (args.length > 2) {
if (args[0].equals("-f")) {
file = args[1];
this.dumpFile = args[1];
String[] newargs = new String[args.length-2];
System.arraycopy(args, 2, newargs, 0, args.length-2);
args = newargs;
}
}
HeapDumper dumper = new HeapDumper(file);
dumper.execute(args);
execute(args);
}
}

View File

@ -33,8 +33,9 @@ import sun.jvm.hotspot.debugger.JVMDebugger;
import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
import jdk.internal.vm.agent.spi.ToolProvider;
public class HeapSummary extends Tool {
public class HeapSummary extends Tool implements ToolProvider {
public HeapSummary() {
super();
@ -49,6 +50,16 @@ public class HeapSummary extends Tool {
hs.execute(args);
}
@Override
public String getName() {
return "heapSummary";
}
@Override
public void run(String... arguments) {
execute(arguments);
}
public void run() {
CollectedHeap heap = VM.getVM().getUniverse().heap();
VM.Flag[] flags = VM.getVM().getCommandLineFlags();

View File

@ -27,8 +27,9 @@ package sun.jvm.hotspot.tools;
import sun.jvm.hotspot.debugger.JVMDebugger;
import sun.jvm.hotspot.runtime.Arguments;
import sun.jvm.hotspot.runtime.VM;
import jdk.internal.vm.agent.spi.ToolProvider;
public class JInfo extends Tool {
public class JInfo extends Tool implements ToolProvider {
public JInfo() {
super();
}
@ -94,13 +95,14 @@ public class JInfo extends Tool {
tool.run();
}
public static void main(String[] args) {
@Override
public void run(String... args) {
int mode = -1;
switch (args.length) {
case 1:
if (args[0].charAt(0) == '-') {
// -h or -help or some invalid flag
new JInfo(mode).usage();
usage();
} else {
mode = MODE_BOTH;
}
@ -114,7 +116,7 @@ public class JInfo extends Tool {
mode = MODE_SYSPROPS;
} else if (modeFlag.charAt(0) == '-') {
// -h or -help or some invalid flag
new JInfo(mode).usage();
usage();
} else {
mode = MODE_BOTH;
}
@ -131,11 +133,16 @@ public class JInfo extends Tool {
}
default:
new JInfo(mode).usage();
usage();
}
JInfo jinfo = new JInfo(mode);
jinfo.execute(args);
this.mode = mode;
execute(args);
}
public static void main(String[] args) {
JInfo jinfo = new JInfo();
jinfo.run(args);
}
private void printVMFlags() {

View File

@ -25,11 +25,15 @@
package sun.jvm.hotspot.tools;
import java.io.*;
import java.util.*;
import java.util.stream.*;
import sun.jvm.hotspot.debugger.JVMDebugger;
import sun.jvm.hotspot.runtime.*;
public class JSnap extends Tool {
private boolean all;
public JSnap() {
super();
}
@ -45,7 +49,7 @@ public class JSnap extends Tool {
if (prologue.accessible()) {
PerfMemory.iterate(new PerfMemory.PerfDataEntryVisitor() {
public boolean visit(PerfDataEntry pde) {
if (pde.supported()) {
if (all || pde.supported()) {
out.print(pde.name());
out.print('=');
out.println(pde.valueAsString());
@ -62,8 +66,24 @@ public class JSnap extends Tool {
}
}
@Override
protected void printFlagsUsage() {
System.out.println(" -a\tto print all performance counters");
super.printFlagsUsage();
}
public static void main(String[] args) {
JSnap js = new JSnap();
js.all = Arrays.stream(args)
.anyMatch(s -> s.equals("-a"));
if (js.all) {
args = Arrays.stream(args)
.filter(s -> !s.equals("-a"))
.collect(Collectors.toList())
.toArray(new String[0]);
}
js.execute(args);
}
}

View File

@ -25,8 +25,9 @@
package sun.jvm.hotspot.tools;
import sun.jvm.hotspot.debugger.JVMDebugger;
import jdk.internal.vm.agent.spi.ToolProvider;
public class JStack extends Tool {
public class JStack extends Tool implements ToolProvider {
public JStack(boolean mixedMode, boolean concurrentLocks) {
this.mixedMode = mixedMode;
this.concurrentLocks = concurrentLocks;
@ -66,9 +67,8 @@ public class JStack extends Tool {
tool.run();
}
public static void main(String[] args) {
boolean mixedMode = false;
boolean concurrentLocks = false;
@Override
public void run(String... args) {
int used = 0;
for (int i = 0; i < args.length; i++) {
if (args[i].equals("-m")) {
@ -88,8 +88,12 @@ public class JStack extends Tool {
args = newArgs;
}
JStack jstack = new JStack(mixedMode, concurrentLocks);
jstack.execute(args);
execute(args);
}
public static void main(String[] args) {
JStack jstack = new JStack();
jstack.run(args);
}
private boolean mixedMode;

View File

@ -27,11 +27,13 @@ package sun.jvm.hotspot.tools;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
import jdk.internal.vm.agent.spi.ToolProvider;
import java.io.PrintStream;
/** A sample tool which uses the Serviceability Agent's APIs to obtain
an object histogram from a remote or crashed VM. */
public class ObjectHistogram extends Tool {
public class ObjectHistogram extends Tool implements ToolProvider {
public ObjectHistogram() {
super();
@ -41,6 +43,16 @@ public class ObjectHistogram extends Tool {
super(d);
}
@Override
public String getName() {
return "objectHistogram";
}
@Override
public void run(String... arguments) {
execute(arguments);
}
public void run() {
run(System.out, System.err);
}

View File

@ -28,9 +28,9 @@ import java.io.*;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.runtime.*;
import jdk.internal.vm.agent.spi.ToolProvider;
public class PMap extends Tool {
public class PMap extends Tool implements ToolProvider {
public PMap() {
super();
@ -40,6 +40,16 @@ public class PMap extends Tool {
super(d);
}
@Override
public String getName() {
return "pmap";
}
@Override
public void run(String... arguments) {
execute(arguments);
}
public void run() {
run(System.out);
}

View File

@ -1,3 +0,0 @@
jdk.vm.ci.hotspot.aarch64.AArch64HotSpotJVMCIBackendFactory
jdk.vm.ci.hotspot.amd64.AMD64HotSpotJVMCIBackendFactory
jdk.vm.ci.hotspot.sparc.SPARCHotSpotJVMCIBackendFactory

View File

@ -339,7 +339,7 @@ public class HotSpotConstantReflectionProvider implements ConstantReflectionProv
public JavaConstant readStableFieldValue(ResolvedJavaField field, JavaConstant receiver, boolean isDefaultStable) {
JavaConstant fieldValue = readNonStableFieldValue(field, receiver);
if (fieldValue.isNonNull()) {
if (fieldValue != null && fieldValue.isNonNull()) {
JavaType declaredType = field.getType();
if (declaredType.getComponentType() != null) {
int stableDimension = getArrayDimension(declaredType);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@ package jdk.vm.ci.hotspot;
import jdk.vm.ci.code.CompilationRequest;
import jdk.vm.ci.code.CompilationRequestResult;
import jdk.vm.ci.common.JVMCIError;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.Option;
import jdk.vm.ci.runtime.JVMCICompiler;
import jdk.vm.ci.runtime.JVMCICompilerFactory;
import jdk.vm.ci.runtime.JVMCIRuntime;
@ -47,29 +48,33 @@ final class HotSpotJVMCICompilerConfig {
}
}
/**
* Factory of the selected system compiler.
*/
private static JVMCICompilerFactory compilerFactory;
/**
* Selects the system compiler.
* Gets the selected system compiler factory.
*
* Called from VM. This method has an object return type to allow it to be called with a VM
* utility function used to call other static initialization methods.
* @return the selected system compiler factory
*/
static Boolean selectCompiler(String compilerName) {
assert compilerFactory == null;
for (JVMCICompilerFactory factory : Services.load(JVMCICompilerFactory.class)) {
if (factory.getCompilerName().equals(compilerName)) {
compilerFactory = factory;
return Boolean.TRUE;
}
}
throw new JVMCIError("JVMCI compiler '%s' not found", compilerName);
}
static JVMCICompilerFactory getCompilerFactory() {
if (compilerFactory == null) {
compilerFactory = new DummyCompilerFactory();
JVMCICompilerFactory factory = null;
String compilerName = Option.Compiler.getString();
if (compilerName != null) {
for (JVMCICompilerFactory f : Services.load(JVMCICompilerFactory.class)) {
if (f.getCompilerName().equals(compilerName)) {
factory = f;
}
}
if (factory == null) {
throw new JVMCIError("JVMCI compiler '%s' not found", compilerName);
}
} else {
factory = new DummyCompilerFactory();
}
compilerFactory = factory;
}
return compilerFactory;
}

View File

@ -91,6 +91,7 @@ public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider, H
* A list of all supported JVMCI options.
*/
public enum Option {
Compiler(String.class, null, "Selects the system compiler."),
ImplicitStableValues(boolean.class, true, "Mark well-known stable fields as such."),
// Note: The following one is not used (see InitTimer.ENABLED).
InitTimer(boolean.class, false, "Specifies if initialization timing is enabled."),

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
module jdk.vm.ci {
uses jdk.vm.ci.hotspot.HotSpotVMEventListener;
uses jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory;
uses jdk.vm.ci.runtime.JVMCICompilerFactory;
provides jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory with
jdk.vm.ci.hotspot.aarch64.AArch64HotSpotJVMCIBackendFactory;
provides jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory with
jdk.vm.ci.hotspot.amd64.AMD64HotSpotJVMCIBackendFactory;
provides jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory with
jdk.vm.ci.hotspot.sparc.SPARCHotSpotJVMCIBackendFactory;
}

View File

@ -300,6 +300,8 @@ provider hotspot_jni {
probe GetLongField__return(uintptr_t);
probe GetMethodID__entry(void*, void*, const char*, const char*);
probe GetMethodID__return(uintptr_t);
probe GetModule__entry(void*, void*);
probe GetModule__return(void*);
probe GetObjectArrayElement__entry(void*, void*, uintptr_t);
probe GetObjectArrayElement__return(void*);
probe GetObjectClass__entry(void*, void*);

View File

@ -26,44 +26,108 @@
#ifndef OS_CPU_LINUX_AARCH64_VM_COPY_LINUX_AARCH64_INLINE_HPP
#define OS_CPU_LINUX_AARCH64_VM_COPY_LINUX_AARCH64_INLINE_HPP
#define COPY_SMALL(from, to, count) \
{ \
long tmp0, tmp1, tmp2, tmp3; \
long tmp4, tmp5, tmp6, tmp7; \
__asm volatile( \
" adr %[t0], 0f;" \
" add %[t0], %[t0], %[cnt], lsl #5;" \
" br %[t0];" \
" .align 5;" \
"0:" \
" b 1f;" \
" .align 5;" \
" ldr %[t0], [%[s], #0];" \
" str %[t0], [%[d], #0];" \
" b 1f;" \
" .align 5;" \
" ldp %[t0], %[t1], [%[s], #0];" \
" stp %[t0], %[t1], [%[d], #0];" \
" b 1f;" \
" .align 5;" \
" ldp %[t0], %[t1], [%[s], #0];" \
" ldr %[t2], [%[s], #16];" \
" stp %[t0], %[t1], [%[d], #0];" \
" str %[t2], [%[d], #16];" \
" b 1f;" \
" .align 5;" \
" ldp %[t0], %[t1], [%[s], #0];" \
" ldp %[t2], %[t3], [%[s], #16];" \
" stp %[t0], %[t1], [%[d], #0];" \
" stp %[t2], %[t3], [%[d], #16];" \
" b 1f;" \
" .align 5;" \
" ldp %[t0], %[t1], [%[s], #0];" \
" ldp %[t2], %[t3], [%[s], #16];" \
" ldr %[t4], [%[s], #32];" \
" stp %[t0], %[t1], [%[d], #0];" \
" stp %[t2], %[t3], [%[d], #16];" \
" str %[t4], [%[d], #32];" \
" b 1f;" \
" .align 5;" \
" ldp %[t0], %[t1], [%[s], #0];" \
" ldp %[t2], %[t3], [%[s], #16];" \
" ldp %[t4], %[t5], [%[s], #32];" \
"2:" \
" stp %[t0], %[t1], [%[d], #0];" \
" stp %[t2], %[t3], [%[d], #16];" \
" stp %[t4], %[t5], [%[d], #32];" \
" b 1f;" \
" .align 5;" \
" ldr %[t6], [%[s], #0];" \
" ldp %[t0], %[t1], [%[s], #8];" \
" ldp %[t2], %[t3], [%[s], #24];" \
" ldp %[t4], %[t5], [%[s], #40];" \
" str %[t6], [%[d]], #8;" \
" b 2b;" \
" .align 5;" \
" ldp %[t0], %[t1], [%[s], #0];" \
" ldp %[t2], %[t3], [%[s], #16];" \
" ldp %[t4], %[t5], [%[s], #32];" \
" ldp %[t6], %[t7], [%[s], #48];" \
" stp %[t0], %[t1], [%[d], #0];" \
" stp %[t2], %[t3], [%[d], #16];" \
" stp %[t4], %[t5], [%[d], #32];" \
" stp %[t6], %[t7], [%[d], #48];" \
"1:" \
\
: [s]"+r"(from), [d]"+r"(to), [cnt]"+r"(count), \
[t0]"=&r"(tmp0), [t1]"=&r"(tmp1), [t2]"=&r"(tmp2), [t3]"=&r"(tmp3), \
[t4]"=&r"(tmp4), [t5]"=&r"(tmp5), [t6]"=&r"(tmp6), [t7]"=&r"(tmp7) \
: \
: "memory", "cc"); \
}
static void pd_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
(void)memmove(to, from, count * HeapWordSize);
__asm volatile( "prfm pldl1strm, [%[s], #0];" :: [s]"r"(from) : "memory");
if (__builtin_expect(count <= 8, 1)) {
COPY_SMALL(from, to, count);
return;
}
_Copy_conjoint_words(from, to, count);
}
static void pd_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
switch (count) {
case 8: to[7] = from[7];
case 7: to[6] = from[6];
case 6: to[5] = from[5];
case 5: to[4] = from[4];
case 4: to[3] = from[3];
case 3: to[2] = from[2];
case 2: to[1] = from[1];
case 1: to[0] = from[0];
case 0: break;
default:
(void)memcpy(to, from, count * HeapWordSize);
break;
if (__builtin_constant_p(count)) {
memcpy(to, from, count * sizeof(HeapWord));
return;
}
__asm volatile( "prfm pldl1strm, [%[s], #0];" :: [s]"r"(from) : "memory");
if (__builtin_expect(count <= 8, 1)) {
COPY_SMALL(from, to, count);
return;
}
_Copy_disjoint_words(from, to, count);
}
static void pd_disjoint_words_atomic(HeapWord* from, HeapWord* to, size_t count) {
switch (count) {
case 8: to[7] = from[7];
case 7: to[6] = from[6];
case 6: to[5] = from[5];
case 5: to[4] = from[4];
case 4: to[3] = from[3];
case 3: to[2] = from[2];
case 2: to[1] = from[1];
case 1: to[0] = from[0];
case 0: break;
default:
while (count-- > 0) {
*to++ = *from++;
}
break;
__asm volatile( "prfm pldl1strm, [%[s], #0];" :: [s]"r"(from) : "memory");
if (__builtin_expect(count <= 8, 1)) {
COPY_SMALL(from, to, count);
return;
}
_Copy_disjoint_words(from, to, count);
}
static void pd_aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {

View File

@ -0,0 +1,236 @@
/*
* Copyright (c) 2016, Linaro Ltd. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
.global _Copy_conjoint_words
.global _Copy_disjoint_words
s .req x0
d .req x1
count .req x2
t0 .req x3
t1 .req x4
t2 .req x5
t3 .req x6
t4 .req x7
t5 .req x8
t6 .req x9
t7 .req x10
.align 6
_Copy_disjoint_words:
// Ensure 2 word aligned
tbz s, #3, fwd_copy_aligned
ldr t0, [s], #8
str t0, [d], #8
sub count, count, #1
fwd_copy_aligned:
// Bias s & d so we only pre index on the last copy
sub s, s, #16
sub d, d, #16
ldp t0, t1, [s, #16]
ldp t2, t3, [s, #32]
ldp t4, t5, [s, #48]
ldp t6, t7, [s, #64]!
subs count, count, #16
blo fwd_copy_drain
fwd_copy_again:
prfm pldl1keep, [s, #256]
stp t0, t1, [d, #16]
ldp t0, t1, [s, #16]
stp t2, t3, [d, #32]
ldp t2, t3, [s, #32]
stp t4, t5, [d, #48]
ldp t4, t5, [s, #48]
stp t6, t7, [d, #64]!
ldp t6, t7, [s, #64]!
subs count, count, #8
bhs fwd_copy_again
fwd_copy_drain:
stp t0, t1, [d, #16]
stp t2, t3, [d, #32]
stp t4, t5, [d, #48]
stp t6, t7, [d, #64]!
// count is now -8..-1 for 0..7 words to copy
adr t0, 0f
add t0, t0, count, lsl #5
br t0
.align 5
ret // -8 == 0 words
.align 5
ldr t0, [s, #16] // -7 == 1 word
str t0, [d, #16]
ret
.align 5
ldp t0, t1, [s, #16] // -6 = 2 words
stp t0, t1, [d, #16]
ret
.align 5
ldp t0, t1, [s, #16] // -5 = 3 words
ldr t2, [s, #32]
stp t0, t1, [d, #16]
str t2, [d, #32]
ret
.align 5
ldp t0, t1, [s, #16] // -4 = 4 words
ldp t2, t3, [s, #32]
stp t0, t1, [d, #16]
stp t2, t3, [d, #32]
ret
.align 5
ldp t0, t1, [s, #16] // -3 = 5 words
ldp t2, t3, [s, #32]
ldr t4, [s, #48]
stp t0, t1, [d, #16]
stp t2, t3, [d, #32]
str t4, [d, #48]
ret
.align 5
ldp t0, t1, [s, #16] // -2 = 6 words
ldp t2, t3, [s, #32]
ldp t4, t5, [s, #48]
stp t0, t1, [d, #16]
stp t2, t3, [d, #32]
stp t4, t5, [d, #48]
ret
.align 5
ldp t0, t1, [s, #16] // -1 = 7 words
ldp t2, t3, [s, #32]
ldp t4, t5, [s, #48]
ldr t6, [s, #64]
stp t0, t1, [d, #16]
stp t2, t3, [d, #32]
stp t4, t5, [d, #48]
str t6, [d, #64]
// Is always aligned here, code for 7 words is one instruction
// too large so it just falls through.
.align 5
0:
ret
.align 6
_Copy_conjoint_words:
sub t0, d, s
cmp t0, count, lsl #3
bhs _Copy_disjoint_words
add s, s, count, lsl #3
add d, d, count, lsl #3
// Ensure 2 word aligned
tbz s, #3, bwd_copy_aligned
ldr t0, [s, #-8]!
str t0, [d, #-8]!
sub count, count, #1
bwd_copy_aligned:
ldp t0, t1, [s, #-16]
ldp t2, t3, [s, #-32]
ldp t4, t5, [s, #-48]
ldp t6, t7, [s, #-64]!
subs count, count, #16
blo bwd_copy_drain
bwd_copy_again:
prfm pldl1keep, [s, #-256]
stp t0, t1, [d, #-16]
ldp t0, t1, [s, #-16]
stp t2, t3, [d, #-32]
ldp t2, t3, [s, #-32]
stp t4, t5, [d, #-48]
ldp t4, t5, [s, #-48]
stp t6, t7, [d, #-64]!
ldp t6, t7, [s, #-64]!
subs count, count, #8
bhs bwd_copy_again
bwd_copy_drain:
stp t0, t1, [d, #-16]
stp t2, t3, [d, #-32]
stp t4, t5, [d, #-48]
stp t6, t7, [d, #-64]!
// count is now -8..-1 for 0..7 words to copy
adr t0, 0f
add t0, t0, count, lsl #5
br t0
.align 5
ret // -8 == 0 words
.align 5
ldr t0, [s, #-8] // -7 == 1 word
str t0, [d, #-8]
ret
.align 5
ldp t0, t1, [s, #-16] // -6 = 2 words
stp t0, t1, [d, #-16]
ret
.align 5
ldp t0, t1, [s, #-16] // -5 = 3 words
ldr t2, [s, #-24]
stp t0, t1, [d, #-16]
str t2, [d, #-24]
ret
.align 5
ldp t0, t1, [s, #-16] // -4 = 4 words
ldp t2, t3, [s, #-32]
stp t0, t1, [d, #-16]
stp t2, t3, [d, #-32]
ret
.align 5
ldp t0, t1, [s, #-16] // -3 = 5 words
ldp t2, t3, [s, #-32]
ldr t4, [s, #-40]
stp t0, t1, [d, #-16]
stp t2, t3, [d, #-32]
str t4, [d, #-40]
ret
.align 5
ldp t0, t1, [s, #-16] // -2 = 6 words
ldp t2, t3, [s, #-32]
ldp t4, t5, [s, #-48]
stp t0, t1, [d, #-16]
stp t2, t3, [d, #-32]
stp t4, t5, [d, #-48]
ret
.align 5
ldp t0, t1, [s, #-16] // -1 = 7 words
ldp t2, t3, [s, #-32]
ldp t4, t5, [s, #-48]
ldr t6, [s, #-56]
stp t0, t1, [d, #-16]
stp t2, t3, [d, #-32]
stp t4, t5, [d, #-48]
str t6, [d, #-56]
// Is always aligned here, code for 7 words is one instruction
// too large so it just falls through.
.align 5
0:
ret

View File

@ -257,7 +257,38 @@ void Canonicalizer::do_ArrayLength (ArrayLength* x) {
}
}
void Canonicalizer::do_LoadIndexed (LoadIndexed* x) {}
void Canonicalizer::do_LoadIndexed (LoadIndexed* x) {
StableArrayConstant* array = x->array()->type()->as_StableArrayConstant();
IntConstant* index = x->index()->type()->as_IntConstant();
assert(array == NULL || FoldStableValues, "not enabled");
// Constant fold loads from stable arrays.
if (array != NULL && index != NULL) {
jint idx = index->value();
if (idx < 0 || idx >= array->value()->length()) {
// Leave the load as is. The range check will handle it.
return;
}
ciConstant field_val = array->value()->element_value(idx);
if (!field_val.is_null_or_zero()) {
jint dimension = array->dimension();
assert(dimension <= array->value()->array_type()->dimension(), "inconsistent info");
ValueType* value = NULL;
if (dimension > 1) {
// Preserve information about the dimension for the element.
assert(field_val.as_object()->is_array(), "not an array");
value = new StableArrayConstant(field_val.as_object()->as_array(), dimension - 1);
} else {
assert(dimension == 1, "sanity");
value = as_ValueType(field_val);
}
set_canonical(new Constant(value));
}
}
}
void Canonicalizer::do_StoreIndexed (StoreIndexed* x) {
// If a value is going to be stored into a field or array some of
// the conversions emitted by javac are unneeded because the fields

View File

@ -1519,6 +1519,29 @@ void GraphBuilder::method_return(Value x) {
append(new Return(x));
}
Value GraphBuilder::make_constant(ciConstant field_value, ciField* field) {
BasicType field_type = field_value.basic_type();
ValueType* value = as_ValueType(field_value);
// Attach dimension info to stable arrays.
if (FoldStableValues &&
field->is_stable() && field_type == T_ARRAY && !field_value.is_null_or_zero()) {
ciArray* array = field_value.as_object()->as_array();
jint dimension = field->type()->as_array_klass()->dimension();
value = new StableArrayConstant(array, dimension);
}
switch (field_type) {
case T_ARRAY:
case T_OBJECT:
if (field_value.as_object()->should_be_constant()) {
return new Constant(value);
}
return NULL; // Not a constant.
default:
return new Constant(value);
}
}
void GraphBuilder::access_field(Bytecodes::Code code) {
bool will_link;
@ -1563,22 +1586,13 @@ void GraphBuilder::access_field(Bytecodes::Code code) {
switch (code) {
case Bytecodes::_getstatic: {
// check for compile-time constants, i.e., initialized static final fields
Instruction* constant = NULL;
Value constant = NULL;
if (field->is_constant() && !PatchALot) {
ciConstant field_val = field->constant_value();
BasicType field_type = field_val.basic_type();
switch (field_type) {
case T_ARRAY:
case T_OBJECT:
if (field_val.as_object()->should_be_constant()) {
constant = new Constant(as_ValueType(field_val));
}
break;
default:
constant = new Constant(as_ValueType(field_val));
}
ciConstant field_value = field->constant_value();
// Stable static fields are checked for non-default values in ciField::initialize_from().
assert(!field->is_stable() || !field_value.is_null_or_zero(),
"stable static w/ default value shouldn't be a constant");
constant = make_constant(field_value, field);
}
if (constant != NULL) {
push(type, append(constant));
@ -1591,38 +1605,29 @@ void GraphBuilder::access_field(Bytecodes::Code code) {
}
break;
}
case Bytecodes::_putstatic:
{ Value val = pop(type);
if (state_before == NULL) {
state_before = copy_state_for_exception();
}
append(new StoreField(append(obj), offset, field, val, true, state_before, needs_patching));
case Bytecodes::_putstatic: {
Value val = pop(type);
if (state_before == NULL) {
state_before = copy_state_for_exception();
}
append(new StoreField(append(obj), offset, field, val, true, state_before, needs_patching));
break;
}
case Bytecodes::_getfield: {
// Check for compile-time constants, i.e., trusted final non-static fields.
Instruction* constant = NULL;
Value constant = NULL;
obj = apop();
ObjectType* obj_type = obj->type()->as_ObjectType();
if (obj_type->is_constant() && !PatchALot) {
ciObject* const_oop = obj_type->constant_value();
if (!const_oop->is_null_object() && const_oop->is_loaded()) {
if (field->is_constant()) {
ciConstant field_val = field->constant_value_of(const_oop);
BasicType field_type = field_val.basic_type();
switch (field_type) {
case T_ARRAY:
case T_OBJECT:
if (field_val.as_object()->should_be_constant()) {
constant = new Constant(as_ValueType(field_val));
}
break;
default:
constant = new Constant(as_ValueType(field_val));
}
if (FoldStableValues && field->is_stable() && field_val.is_null_or_zero()) {
ciConstant field_value = field->constant_value_of(const_oop);
if (FoldStableValues && field->is_stable() && field_value.is_null_or_zero()) {
// Stable field with default value can't be constant.
constant = NULL;
} else {
constant = make_constant(field_value, field);
}
} else {
// For CallSite objects treat the target field as a compile time constant.
@ -3942,7 +3947,7 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, Bytecode
bool GraphBuilder::try_method_handle_inline(ciMethod* callee) {
ValueStack* state_before = state()->copy_for_parsing();
ValueStack* state_before = copy_state_before();
vmIntrinsics::ID iid = callee->intrinsic_id();
switch (iid) {
case vmIntrinsics::_invokeBasic:
@ -4032,7 +4037,7 @@ bool GraphBuilder::try_method_handle_inline(ciMethod* callee) {
fatal("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid));
break;
}
set_state(state_before);
set_state(state_before->copy_for_parsing());
return false;
}

View File

@ -276,6 +276,7 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC {
void iterate_all_blocks(bool start_in_current_block_for_inlining = false);
Dependencies* dependency_recorder() const; // = compilation()->dependencies()
bool direct_compare(ciKlass* k);
Value make_constant(ciConstant value, ciField* field);
void kill_all();

View File

@ -335,6 +335,7 @@ JRT_ENTRY(void, Runtime1::new_instance(JavaThread* thread, Klass* klass))
NOT_PRODUCT(_new_instance_slowcase_cnt++;)
assert(klass->is_klass(), "not a class");
Handle holder(THREAD, klass->klass_holder()); // keep the klass alive
instanceKlassHandle h(thread, klass);
h->check_valid_for_instantiation(true, CHECK);
// make sure klass is initialized
@ -370,6 +371,7 @@ JRT_ENTRY(void, Runtime1::new_object_array(JavaThread* thread, Klass* array_klas
// anymore after new_objArray() and no GC can happen before.
// (This may have to change if this code changes!)
assert(array_klass->is_klass(), "not a class");
Handle holder(THREAD, array_klass->klass_holder()); // keep the klass alive
Klass* elem_klass = ObjArrayKlass::cast(array_klass)->element_klass();
objArrayOop obj = oopFactory::new_objArray(elem_klass, length, CHECK);
thread->set_vm_result(obj);
@ -386,6 +388,7 @@ JRT_ENTRY(void, Runtime1::new_multi_array(JavaThread* thread, Klass* klass, int
assert(klass->is_klass(), "not a class");
assert(rank >= 1, "rank must be nonzero");
Handle holder(THREAD, klass->klass_holder()); // keep the klass alive
oop obj = ArrayKlass::cast(klass)->multi_allocate(rank, dims, CHECK);
thread->set_vm_result(obj);
JRT_END
@ -661,7 +664,7 @@ JRT_ENTRY(void, Runtime1::throw_class_cast_exception(JavaThread* thread, oopDesc
NOT_PRODUCT(_throw_class_cast_exception_count++;)
ResourceMark rm(thread);
char* message = SharedRuntime::generate_class_cast_message(
thread, object->klass()->external_name());
thread, object->klass());
SharedRuntime::throw_and_post_jvmti_exception(
thread, vmSymbols::java_lang_ClassCastException(), message);
JRT_END

View File

@ -45,6 +45,7 @@ class ObjectType;
class ObjectConstant;
class ArrayType;
class ArrayConstant;
class StableArrayConstant;
class InstanceType;
class InstanceConstant;
class MetadataType;
@ -168,6 +169,7 @@ class ValueType: public CompilationResourceObj {
virtual MethodConstant* as_MethodConstant() { return NULL; }
virtual MethodDataConstant* as_MethodDataConstant() { return NULL; }
virtual ArrayConstant* as_ArrayConstant() { return NULL; }
virtual StableArrayConstant* as_StableArrayConstant() { return NULL; }
virtual AddressConstant* as_AddressConstant() { return NULL; }
// type operations
@ -355,6 +357,20 @@ class ArrayConstant: public ArrayType {
virtual ciType* exact_type() const;
};
class StableArrayConstant: public ArrayConstant {
private:
jint _dimension;
public:
StableArrayConstant(ciArray* value, jint dimension) : ArrayConstant(value) {
assert(dimension > 0, "not a stable array");
_dimension = dimension;
}
jint dimension() const { return _dimension; }
virtual StableArrayConstant* as_StableArrayConstant() { return this; }
};
class InstanceType: public ObjectType {
public:

View File

@ -370,9 +370,9 @@ bool ciEnv::check_klass_accessibility(ciKlass* accessing_klass,
resolved_klass = ObjArrayKlass::cast(resolved_klass)->bottom_klass();
}
if (resolved_klass->is_instance_klass()) {
return Reflection::verify_class_access(accessing_klass->get_Klass(),
resolved_klass,
true);
return (Reflection::verify_class_access(accessing_klass->get_Klass(),
resolved_klass,
true) == Reflection::ACCESS_OK);
}
return true;
}

View File

@ -81,7 +81,7 @@ ciMethodData::ciMethodData() : ciMetadata(NULL) {
void ciMethodData::load_extra_data() {
MethodData* mdo = get_MethodData();
MutexLocker(mdo->extra_data_lock());
MutexLocker ml(mdo->extra_data_lock());
// speculative trap entries also hold a pointer to a Method so need to be translated
DataLayout* dp_src = mdo->extra_data_base();
@ -103,16 +103,13 @@ void ciMethodData::load_extra_data() {
switch(tag) {
case DataLayout::speculative_trap_data_tag: {
ciSpeculativeTrapData* data_dst = new ciSpeculativeTrapData(dp_dst);
SpeculativeTrapData* data_src = new SpeculativeTrapData(dp_src);
data_dst->translate_from(data_src);
#ifdef ASSERT
SpeculativeTrapData* data_src2 = new SpeculativeTrapData(dp_src);
assert(data_src2->method() == data_src->method() && data_src2->bci() == data_src->bci(), "entries changed while translating");
#endif
ciSpeculativeTrapData data_dst(dp_dst);
SpeculativeTrapData data_src(dp_src);
{ // During translation a safepoint can happen or VM lock can be taken (e.g., Compile_lock).
MutexUnlocker ml(mdo->extra_data_lock());
data_dst.translate_from(&data_src);
}
break;
}
case DataLayout::bit_data_tag:
@ -120,9 +117,11 @@ void ciMethodData::load_extra_data() {
case DataLayout::no_tag:
case DataLayout::arg_info_data_tag:
// An empty slot or ArgInfoData entry marks the end of the trap data
return;
{
return; // Need a block to avoid SS compiler bug
}
default:
fatal("bad tag = %d", dp_dst->tag());
fatal("bad tag = %d", tag);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -28,6 +28,7 @@
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/defaultMethods.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/verificationType.hpp"
@ -103,8 +104,6 @@
#define JAVA_9_VERSION 53
enum { LegalClass, LegalField, LegalMethod }; // used to verify unqualified names
void ClassFileParser::parse_constant_pool_entries(const ClassFileStream* const stream,
ConstantPool* cp,
const int length,
@ -1965,7 +1964,7 @@ AnnotationCollector::annotation_index(const ClassLoaderData* loader_data,
const vmSymbols::SID sid = vmSymbols::find_sid(name);
// Privileged code can use all annotations. Other code silently drops some.
const bool privileged = loader_data->is_the_null_class_loader_data() ||
loader_data->is_ext_class_loader_data() ||
loader_data->is_platform_class_loader_data() ||
loader_data->is_anonymous();
switch (sid) {
case vmSymbols::VM_SYMBOL_ENUM_NAME(sun_reflect_CallerSensitive_signature): {
@ -4358,17 +4357,29 @@ static Array<Klass*>* compute_transitive_interfaces(const InstanceKlass* super,
static void check_super_class_access(const InstanceKlass* this_klass, TRAPS) {
assert(this_klass != NULL, "invariant");
const Klass* const super = this_klass->super();
if ((super != NULL) &&
(!Reflection::verify_class_access(this_klass, super, false))) {
ResourceMark rm(THREAD);
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_IllegalAccessError(),
"class %s cannot access its superclass %s",
this_klass->external_name(),
super->external_name()
);
return;
if (super != NULL) {
Reflection::VerifyClassAccessResults vca_result =
Reflection::verify_class_access(this_klass, super, false);
if (vca_result != Reflection::ACCESS_OK) {
ResourceMark rm(THREAD);
char* msg = Reflection::verify_class_access_msg(this_klass, super, vca_result);
if (msg == NULL) {
ResourceMark rm(THREAD);
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_IllegalAccessError(),
"class %s cannot access its superclass %s",
this_klass->external_name(),
super->external_name());
} else {
// Add additional message content.
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_IllegalAccessError(),
"superclass access check failed: %s",
msg);
}
}
}
}
@ -4380,16 +4391,26 @@ static void check_super_interface_access(const InstanceKlass* this_klass, TRAPS)
for (int i = lng - 1; i >= 0; i--) {
Klass* const k = local_interfaces->at(i);
assert (k != NULL && k->is_interface(), "invalid interface");
if (!Reflection::verify_class_access(this_klass, k, false)) {
Reflection::VerifyClassAccessResults vca_result =
Reflection::verify_class_access(this_klass, k, false);
if (vca_result != Reflection::ACCESS_OK) {
ResourceMark rm(THREAD);
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_IllegalAccessError(),
"class %s cannot access its superinterface %s",
this_klass->external_name(),
k->external_name()
);
return;
char* msg = Reflection::verify_class_access_msg(this_klass, k, vca_result);
if (msg == NULL) {
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_IllegalAccessError(),
"class %s cannot access its superinterface %s",
this_klass->external_name(),
k->external_name());
} else {
// Add additional message content.
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_IllegalAccessError(),
"superinterface check failed: %s",
msg);
}
}
}
}
@ -4489,12 +4510,14 @@ void ClassFileParser::verify_legal_class_modifiers(jint flags, TRAPS) const {
const bool is_super = (flags & JVM_ACC_SUPER) != 0;
const bool is_enum = (flags & JVM_ACC_ENUM) != 0;
const bool is_annotation = (flags & JVM_ACC_ANNOTATION) != 0;
const bool is_module_info= (flags & JVM_ACC_MODULE) != 0;
const bool major_gte_15 = _major_version >= JAVA_1_5_VERSION;
if ((is_abstract && is_final) ||
(is_interface && !is_abstract) ||
(is_interface && major_gte_15 && (is_super || is_enum)) ||
(!is_interface && major_gte_15 && is_annotation)) {
(!is_interface && major_gte_15 && is_annotation) ||
is_module_info) {
ResourceMark rm(THREAD);
Exceptions::fthrow(
THREAD_AND_LOCATION,
@ -4650,65 +4673,9 @@ void ClassFileParser::verify_legal_utf8(const unsigned char* buffer,
int length,
TRAPS) const {
assert(_need_verify, "only called when _need_verify is true");
int i = 0;
const int count = length >> 2;
for (int k=0; k<count; k++) {
unsigned char b0 = buffer[i];
unsigned char b1 = buffer[i+1];
unsigned char b2 = buffer[i+2];
unsigned char b3 = buffer[i+3];
// For an unsigned char v,
// (v | v - 1) is < 128 (highest bit 0) for 0 < v < 128;
// (v | v - 1) is >= 128 (highest bit 1) for v == 0 or v >= 128.
const unsigned char res = b0 | b0 - 1 |
b1 | b1 - 1 |
b2 | b2 - 1 |
b3 | b3 - 1;
if (res >= 128) break;
i += 4;
if (!UTF8::is_legal_utf8(buffer, length, _major_version <= 47)) {
classfile_parse_error("Illegal UTF8 string in constant pool in class file %s", CHECK);
}
for(; i < length; i++) {
unsigned short c;
// no embedded zeros
guarantee_property((buffer[i] != 0), "Illegal UTF8 string in constant pool in class file %s", CHECK);
if(buffer[i] < 128) {
continue;
}
if ((i + 5) < length) { // see if it's legal supplementary character
if (UTF8::is_supplementary_character(&buffer[i])) {
c = UTF8::get_supplementary_character(&buffer[i]);
i += 5;
continue;
}
}
switch (buffer[i] >> 4) {
default: break;
case 0x8: case 0x9: case 0xA: case 0xB: case 0xF:
classfile_parse_error("Illegal UTF8 string in constant pool in class file %s", CHECK);
case 0xC: case 0xD: // 110xxxxx 10xxxxxx
c = (buffer[i] & 0x1F) << 6;
i++;
if ((i < length) && ((buffer[i] & 0xC0) == 0x80)) {
c += buffer[i] & 0x3F;
if (_major_version <= 47 || c == 0 || c >= 0x80) {
// for classes with major > 47, c must a null or a character in its shortest form
break;
}
}
classfile_parse_error("Illegal UTF8 string in constant pool in class file %s", CHECK);
case 0xE: // 1110xxxx 10xxxxxx 10xxxxxx
c = (buffer[i] & 0xF) << 12;
i += 2;
if ((i < length) && ((buffer[i-1] & 0xC0) == 0x80) && ((buffer[i] & 0xC0) == 0x80)) {
c += ((buffer[i-1] & 0x3F) << 6) + (buffer[i] & 0x3F);
if (_major_version <= 47 || c >= 0x800) {
// for classes with major > 47, c must be in its shortest form
break;
}
}
classfile_parse_error("Illegal UTF8 string in constant pool in class file %s", CHECK);
} // end of switch
} // end of for
}
// Unqualified names may not contain the characters '.', ';', '[', or '/'.
@ -4716,24 +4683,35 @@ void ClassFileParser::verify_legal_utf8(const unsigned char* buffer,
// or <clinit>. Note that method names may not be <init> or <clinit> in this
// method. Because these names have been checked as special cases before
// calling this method in verify_legal_method_name.
static bool verify_unqualified_name(const char* name,
unsigned int length,
int type) {
//
// This method is also called from the modular system APIs in modules.cpp
// to verify the validity of module and package names.
bool ClassFileParser::verify_unqualified_name(const char* name,
unsigned int length,
int type) {
for (const char* p = name; p != name + length;) {
jchar ch = *p;
if (ch < 128) {
p++;
if (ch == '.' || ch == ';' || ch == '[') {
if (ch == '.') {
// permit '.' in module names unless it's the first char, or
// preceding char is also a '.', or last char is a '.'.
if ((type != ClassFileParser::LegalModule) ||
(p == name) || (*(p-1) == '.') ||
(p == name + length - 1)) {
return false;
}
}
if (ch == ';' || ch == '[' ) {
return false; // do not permit '.', ';', or '['
}
if (type != LegalClass && ch == '/') {
if (type != ClassFileParser::LegalClass && ch == '/') {
return false; // do not permit '/' unless it's class name
}
if (type == LegalMethod && (ch == '<' || ch == '>')) {
if (type == ClassFileParser::LegalMethod && (ch == '<' || ch == '>')) {
return false; // do not permit '<' or '>' in method names
}
}
else {
p++;
} else {
char* tmp_p = UTF8::next(p, &ch);
p = tmp_p;
}
@ -5192,7 +5170,7 @@ static void check_methods_for_intrinsics(const InstanceKlass* ik,
}
}
InstanceKlass* ClassFileParser::create_instance_klass(TRAPS) {
InstanceKlass* ClassFileParser::create_instance_klass(bool changed_by_loadhook, TRAPS) {
if (_klass != NULL) {
return _klass;
}
@ -5200,14 +5178,14 @@ InstanceKlass* ClassFileParser::create_instance_klass(TRAPS) {
InstanceKlass* const ik =
InstanceKlass::allocate_instance_klass(*this, CHECK_NULL);
fill_instance_klass(ik, CHECK_NULL);
fill_instance_klass(ik, changed_by_loadhook, CHECK_NULL);
assert(_klass == ik, "invariant");
return ik;
}
void ClassFileParser::fill_instance_klass(InstanceKlass* ik, TRAPS) {
void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool changed_by_loadhook, TRAPS) {
assert(ik != NULL, "invariant");
set_klass_to_deallocate(ik);
@ -5272,6 +5250,12 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, TRAPS) {
ik->set_host_klass(_host_klass);
}
// Set PackageEntry for this_klass
oop cl = ik->class_loader();
Handle clh = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(cl));
ClassLoaderData* cld = ClassLoaderData::class_loader_data_or_null(clh());
ik->set_package(cld, CHECK);
const Array<Method*>* const methods = ik->methods();
assert(methods != NULL, "invariant");
const int methods_len = methods->length();
@ -5327,10 +5311,18 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, TRAPS) {
}
}
// Obtain this_klass' module entry
ModuleEntry* module_entry = ik->module();
assert(module_entry != NULL, "module_entry should always be set");
// Obtain java.lang.reflect.Module
Handle module_handle(THREAD, JNIHandles::resolve(module_entry->module()));
// Allocate mirror and initialize static fields
// The create_mirror() call will also call compute_modifiers()
java_lang_Class::create_mirror(ik,
_loader_data->class_loader(),
module_handle,
_protection_domain,
CHECK);
@ -5344,6 +5336,15 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, TRAPS) {
CHECK);
}
// Add read edges to the unnamed modules of the bootstrap and app class loaders.
if (changed_by_loadhook && !module_handle.is_null() && module_entry->is_named() &&
!module_entry->has_default_read_edges()) {
if (!module_entry->set_has_default_read_edges()) {
// We won a potential race
JvmtiExport::add_default_read_edges(module_handle, THREAD);
}
}
// Update the loader_data graph.
record_defined_class_dependencies(ik, CHECK);
@ -5351,11 +5352,24 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, TRAPS) {
if (!is_internal()) {
if (log_is_enabled(Info, classload)) {
ik->print_loading_log(LogLevel::Info, _loader_data, _stream);
}
// No 'else' here as logging levels are not mutually exclusive
if (log_is_enabled(Debug, classload)) {
ik->print_loading_log(LogLevel::Debug, _loader_data, _stream);
ResourceMark rm;
const char* module_name = NULL;
static const size_t modules_image_name_len = strlen(MODULES_IMAGE_NAME);
size_t stream_len = strlen(_stream->source());
// See if _stream->source() ends in "modules"
if (module_entry->is_named() && modules_image_name_len < stream_len &&
(strncmp(_stream->source() + stream_len - modules_image_name_len,
MODULES_IMAGE_NAME, modules_image_name_len) == 0)) {
module_name = module_entry->name()->as_C_string();
}
if (log_is_enabled(Info, classload)) {
ik->print_loading_log(LogLevel::Info, _loader_data, module_name, _stream);
}
// No 'else' here as logging levels are not mutually exclusive
if (log_is_enabled(Debug, classload)) {
ik->print_loading_log(LogLevel::Debug, _loader_data, module_name, _stream);
}
}
if (log_is_enabled(Debug, classresolve)) {

View File

@ -73,6 +73,8 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
NOF_PUBLICITY_LEVELS
};
enum { LegalClass, LegalField, LegalMethod, LegalModule }; // used to verify unqualified names
private:
const ClassFileStream* _stream; // Actual input stream
const Symbol* _requested_name;
@ -155,7 +157,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
ConstantPool* cp,
TRAPS);
void fill_instance_klass(InstanceKlass* ik, TRAPS);
void fill_instance_klass(InstanceKlass* ik, bool cf_changed_in_CFLH, TRAPS);
void set_klass(InstanceKlass* instance);
void set_class_synthetic_flag(bool x) { _synthetic_flag = x; }
@ -482,7 +484,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
~ClassFileParser();
InstanceKlass* create_instance_klass(TRAPS);
InstanceKlass* create_instance_klass(bool cf_changed_in_CFLH, TRAPS);
const ClassFileStream* clone_stream() const;
@ -512,6 +514,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
bool is_internal() const { return INTERNAL == _pub_level; }
static bool verify_unqualified_name(const char* name, unsigned int length, int type);
};
#endif // SHARE_VM_CLASSFILE_CLASSFILEPARSER_HPP

View File

@ -29,6 +29,9 @@
#include "classfile/classLoaderExt.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/jimage.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/modules.hpp"
#include "classfile/packageEntry.hpp"
#include "classfile/klassFactory.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
@ -138,11 +141,14 @@ PerfCounter* ClassLoader::_load_instance_class_failCounter = NULL;
ClassPathEntry* ClassLoader::_first_entry = NULL;
ClassPathEntry* ClassLoader::_last_entry = NULL;
int ClassLoader::_num_entries = 0;
PackageHashtable* ClassLoader::_package_hash_table = NULL;
ClassPathEntry* ClassLoader::_first_append_entry = NULL;
bool ClassLoader::_has_jimage = false;
#if INCLUDE_CDS
GrowableArray<char*>* ClassLoader::_boot_modules_array = NULL;
GrowableArray<char*>* ClassLoader::_platform_modules_array = NULL;
SharedPathsMiscInfo* ClassLoader::_shared_paths_misc_info = NULL;
#endif
// helper routines
bool string_starts_with(const char* str, const char* str_to_find) {
size_t str_len = strlen(str);
@ -162,7 +168,7 @@ static const char* get_jimage_version_string() {
return (const char*)version_string;
}
bool string_ends_with(const char* str, const char* str_to_find) {
bool ClassLoader::string_ends_with(const char* str, const char* str_to_find) {
size_t str_len = strlen(str);
size_t str_to_find_len = strlen(str_to_find);
if (str_to_find_len > str_len) {
@ -356,15 +362,49 @@ ClassFileStream* ClassPathImageEntry::open_stream(const char* name, TRAPS) {
if (location == 0) {
char package[JIMAGE_MAX_PATH];
name_to_package(name, package, JIMAGE_MAX_PATH);
#if INCLUDE_CDS
if (package[0] == '\0' && DumpSharedSpaces) {
return NULL;
}
#endif
if (package[0] != '\0') {
const char* module = (*JImagePackageToModule)(_jimage, package);
if (module == NULL) {
module = "java.base";
if (!Universe::is_module_initialized()) {
location = (*JImageFindResource)(_jimage, "java.base", get_jimage_version_string(), name, &size);
#if INCLUDE_CDS
// CDS uses the boot class loader to load classes whose packages are in
// modules defined for other class loaders. So, for now, get their module
// names from the "modules" jimage file.
if (DumpSharedSpaces && location == 0) {
const char* module_name = (*JImagePackageToModule)(_jimage, package);
if (module_name != NULL) {
location = (*JImageFindResource)(_jimage, module_name, get_jimage_version_string(), name, &size);
}
}
location = (*JImageFindResource)(_jimage, module, get_jimage_version_string(), name, &size);
#endif
} else {
// Get boot class loader's package entry table
PackageEntryTable* pkgEntryTable =
ClassLoaderData::the_null_class_loader_data()->packages();
// Get package's package entry
TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package, CHECK_NULL);
PackageEntry* package_entry = pkgEntryTable->lookup_only(pkg_symbol);
if (package_entry != NULL) {
ResourceMark rm;
// Get the module name
ModuleEntry* module = package_entry->module();
assert(module != NULL, "Boot classLoader package missing module");
assert(module->is_named(), "Boot classLoader package is in unnamed module");
const char* module_name = module->name()->as_C_string();
if (module_name != NULL) {
location = (*JImageFindResource)(_jimage, module_name, get_jimage_version_string(), name, &size);
}
}
}
}
}
if (location != 0) {
if (UsePerfData) {
ClassLoader::perf_sys_classfile_bytes_read()->inc(size);
@ -409,11 +449,11 @@ void ClassPathImageEntry::compile_the_world(Handle loader, TRAPS) {
}
}
}
#endif
bool ClassPathImageEntry::is_jrt() {
return string_ends_with(name(), BOOT_IMAGE_NAME);
return ClassLoader::is_jrt(name());
}
#endif
#if INCLUDE_CDS
void ClassLoader::exit_with_path_failure(const char* error, const char* message) {
@ -480,7 +520,7 @@ void ClassLoader::setup_bootstrap_search_path() {
_shared_paths_misc_info->add_boot_classpath(sys_class_path);
}
#endif
setup_search_path(sys_class_path);
setup_search_path(sys_class_path, true);
}
#if INCLUDE_CDS
@ -500,10 +540,11 @@ bool ClassLoader::check_shared_paths_misc_info(void *buf, int size) {
}
#endif
void ClassLoader::setup_search_path(const char *class_path) {
void ClassLoader::setup_search_path(const char *class_path, bool bootstrap_search) {
int offset = 0;
int len = (int)strlen(class_path);
int end = 0;
bool mark_append_entry = false;
// Iterate over class path entries
for (int start = 0; start < len; start = end) {
@ -512,10 +553,23 @@ void ClassLoader::setup_search_path(const char *class_path) {
}
EXCEPTION_MARK;
ResourceMark rm(THREAD);
mark_append_entry = (mark_append_entry ||
(bootstrap_search && (start == Arguments::bootclassloader_append_index())));
char* path = NEW_RESOURCE_ARRAY(char, end - start + 1);
strncpy(path, &class_path[start], end - start);
path[end - start] = '\0';
update_class_path_entry_list(path, false);
update_class_path_entry_list(path, false, mark_append_entry, false);
// Check on the state of the boot loader's append path
if (mark_append_entry && (_first_append_entry == NULL)) {
// Failure to mark the first append entry, most likely
// due to a non-existent path. Record the next entry
// as the first boot loader append entry.
mark_append_entry = true;
} else {
mark_append_entry = false;
}
#if INCLUDE_CDS
if (DumpSharedSpaces) {
check_shared_classpath(path);
@ -616,6 +670,18 @@ ClassPathZipEntry* ClassLoader::create_class_path_zip_entry(const char *path) {
return NULL;
}
// The boot class loader must adhere to specfic visibility rules.
// Prior to loading a class in a named package, the package is checked
// to see if it is in a module defined to the boot loader. If the
// package is not in a module defined to the boot loader, the class
// must be loaded only in the boot loader's append path, which
// consists of [-Xbootclasspath/a]; [jvmti appended entries]
void ClassLoader::set_first_append_entry(ClassPathEntry *new_entry) {
if (_first_append_entry == NULL) {
_first_append_entry = new_entry;
}
}
// returns true if entry already on class path
bool ClassLoader::contains_entry(ClassPathEntry *entry) {
ClassPathEntry* e = _first_entry;
@ -641,9 +707,31 @@ void ClassLoader::add_to_list(ClassPathEntry *new_entry) {
_num_entries ++;
}
void ClassLoader::prepend_to_list(ClassPathEntry *new_entry) {
if (new_entry != NULL) {
if (_last_entry == NULL) {
_first_entry = _last_entry = new_entry;
} else {
new_entry->set_next(_first_entry);
_first_entry = new_entry;
}
}
_num_entries ++;
}
void ClassLoader::add_to_list(const char *apath) {
update_class_path_entry_list((char*)apath, false, false, false);
}
void ClassLoader::prepend_to_list(const char *apath) {
update_class_path_entry_list((char*)apath, false, false, true);
}
// Returns true IFF the file/dir exists and the entry was successfully created.
bool ClassLoader::update_class_path_entry_list(const char *path,
bool check_for_duplicates,
bool mark_append_entry,
bool prepend_entry,
bool throw_exception) {
struct stat st;
if (os::stat(path, &st) == 0) {
@ -654,12 +742,20 @@ bool ClassLoader::update_class_path_entry_list(const char *path,
if (new_entry == NULL) {
return false;
}
// The kernel VM adds dynamically to the end of the classloader path and
// doesn't reorder the bootclasspath which would break java.lang.Package
// (see PackageInfo).
// Ensure that the first boot loader append entry will always be set correctly.
assert((!mark_append_entry ||
(mark_append_entry && (!check_for_duplicates || !contains_entry(new_entry)))),
"failed to mark boot loader's first append boundary");
// Do not reorder the bootclasspath which would break get_system_package().
// Add new entry to linked list
if (!check_for_duplicates || !contains_entry(new_entry)) {
ClassLoaderExt::add_class_path_entry(path, check_for_duplicates, new_entry);
ClassLoaderExt::add_class_path_entry(path, check_for_duplicates, new_entry, prepend_entry);
if (mark_append_entry) {
set_first_append_entry(new_entry);
}
}
return true;
} else {
@ -760,246 +856,205 @@ int ClassLoader::crc32(int crc, const char* buf, int len) {
return (*Crc32)(crc, (const jbyte*)buf, len);
}
// PackageInfo data exists in order to support the java.lang.Package
// class. A Package object provides information about a java package
// (version, vendor, etc.) which originates in the manifest of the jar
// file supplying the package. For application classes, the ClassLoader
// object takes care of this.
// For system (boot) classes, the Java code in the Package class needs
// to be able to identify which source jar file contained the boot
// class, so that it can extract the manifest from it. This table
// identifies java packages with jar files in the boot classpath.
// Because the boot classpath cannot change, the classpath index is
// sufficient to identify the source jar file or directory. (Since
// directories have no manifests, the directory name is not required,
// but is available.)
// When using sharing -- the pathnames of entries in the boot classpath
// may not be the same at runtime as they were when the archive was
// created (NFS, Samba, etc.). The actual files and directories named
// in the classpath must be the same files, in the same order, even
// though the exact name is not the same.
class PackageInfo: public BasicHashtableEntry<mtClass> {
public:
const char* _pkgname; // Package name
int _classpath_index; // Index of directory or JAR file loaded from
PackageInfo* next() {
return (PackageInfo*)BasicHashtableEntry<mtClass>::next();
}
const char* pkgname() { return _pkgname; }
void set_pkgname(char* pkgname) { _pkgname = pkgname; }
const char* filename() {
return ClassLoader::classpath_entry(_classpath_index)->name();
}
void set_index(int index) {
_classpath_index = index;
}
};
class PackageHashtable : public BasicHashtable<mtClass> {
private:
inline unsigned int compute_hash(const char *s, int n) {
unsigned int val = 0;
while (--n >= 0) {
val = *s++ + 31 * val;
}
return val;
}
PackageInfo* bucket(int index) {
return (PackageInfo*)BasicHashtable<mtClass>::bucket(index);
}
PackageInfo* get_entry(int index, unsigned int hash,
const char* pkgname, size_t n) {
for (PackageInfo* pp = bucket(index); pp != NULL; pp = pp->next()) {
if (pp->hash() == hash &&
strncmp(pkgname, pp->pkgname(), n) == 0 &&
pp->pkgname()[n] == '\0') {
return pp;
}
}
return NULL;
}
public:
PackageHashtable(int table_size)
: BasicHashtable<mtClass>(table_size, sizeof(PackageInfo)) {}
PackageHashtable(int table_size, HashtableBucket<mtClass>* t, int number_of_entries)
: BasicHashtable<mtClass>(table_size, sizeof(PackageInfo), t, number_of_entries) {}
PackageInfo* get_entry(const char* pkgname, int n) {
unsigned int hash = compute_hash(pkgname, n);
return get_entry(hash_to_index(hash), hash, pkgname, n);
}
PackageInfo* new_entry(char* pkgname, int n) {
unsigned int hash = compute_hash(pkgname, n);
PackageInfo* pp;
pp = (PackageInfo*)BasicHashtable<mtClass>::new_entry(hash);
pp->set_pkgname(pkgname);
return pp;
}
void add_entry(PackageInfo* pp) {
int index = hash_to_index(pp->hash());
BasicHashtable<mtClass>::add_entry(index, pp);
}
void copy_pkgnames(const char** packages) {
int n = 0;
for (int i = 0; i < table_size(); ++i) {
for (PackageInfo* pp = bucket(i); pp != NULL; pp = pp->next()) {
packages[n++] = pp->pkgname();
}
}
assert(n == number_of_entries(), "just checking");
}
CDS_ONLY(void copy_table(char** top, char* end, PackageHashtable* table);)
};
#if INCLUDE_CDS
void PackageHashtable::copy_table(char** top, char* end,
PackageHashtable* table) {
// Copy (relocate) the table to the shared space.
BasicHashtable<mtClass>::copy_table(top, end);
// Calculate the space needed for the package name strings.
int i;
intptr_t* tableSize = (intptr_t*)(*top);
*top += sizeof(intptr_t); // For table size
char* tableStart = *top;
for (i = 0; i < table_size(); ++i) {
for (PackageInfo* pp = table->bucket(i);
pp != NULL;
pp = pp->next()) {
int n1 = (int)(strlen(pp->pkgname()) + 1);
if (*top + n1 >= end) {
report_out_of_shared_space(SharedMiscData);
void ClassLoader::initialize_module_loader_map(JImageFile* jimage) {
jlong size;
JImageLocationRef location = (*JImageFindResource)(jimage, "java.base", get_jimage_version_string(), MODULE_LOADER_MAP, &size);
if (location == 0) {
vm_exit_during_initialization(
"Cannot find ModuleLoaderMap location from modules jimage.", NULL);
}
char* buffer = NEW_RESOURCE_ARRAY(char, size);
jlong read = (*JImageGetResource)(jimage, location, buffer, size);
if (read != size) {
vm_exit_during_initialization(
"Cannot find ModuleLoaderMap resource from modules jimage.", NULL);
}
char* char_buf = (char*)buffer;
int buflen = (int)strlen(char_buf);
char* begin_ptr = char_buf;
char* end_ptr = strchr(begin_ptr, '\n');
bool process_boot_modules = false;
_boot_modules_array = new (ResourceObj::C_HEAP, mtInternal)
GrowableArray<char*>(INITIAL_BOOT_MODULES_ARRAY_SIZE, true);
_platform_modules_array = new (ResourceObj::C_HEAP, mtInternal)
GrowableArray<char*>(INITIAL_PLATFORM_MODULES_ARRAY_SIZE, true);
while (end_ptr != NULL && (end_ptr - char_buf) < buflen) {
// Allocate a buffer from the C heap to be appended to the _boot_modules_array
// or the _platform_modules_array.
char* temp_name = NEW_C_HEAP_ARRAY(char, (size_t)(end_ptr - begin_ptr + 1), mtInternal);
strncpy(temp_name, begin_ptr, end_ptr - begin_ptr);
temp_name[end_ptr - begin_ptr] = '\0';
if (strncmp(temp_name, "BOOT", 4) == 0) {
process_boot_modules = true;
FREE_C_HEAP_ARRAY(char, temp_name);
} else if (strncmp(temp_name, "PLATFORM", 8) == 0) {
process_boot_modules = false;
FREE_C_HEAP_ARRAY(char, temp_name);
} else {
// module name
if (process_boot_modules) {
_boot_modules_array->append(temp_name);
} else {
_platform_modules_array->append(temp_name);
}
pp->set_pkgname((char*)memcpy(*top, pp->pkgname(), n1));
*top += n1;
}
begin_ptr = ++end_ptr;
end_ptr = strchr(begin_ptr, '\n');
}
*top = (char*)align_size_up((intptr_t)*top, sizeof(HeapWord));
if (*top >= end) {
report_out_of_shared_space(SharedMiscData);
}
// Write table size
intptr_t len = *top - (char*)tableStart;
*tableSize = len;
}
void ClassLoader::copy_package_info_buckets(char** top, char* end) {
_package_hash_table->copy_buckets(top, end);
}
void ClassLoader::copy_package_info_table(char** top, char* end) {
_package_hash_table->copy_table(top, end, _package_hash_table);
FREE_RESOURCE_ARRAY(u1, buffer, size);
}
#endif
PackageInfo* ClassLoader::lookup_package(const char *pkgname) {
const char *cp = strrchr(pkgname, '/');
// Function add_package extracts the package from the fully qualified class name
// and checks if the package is in the boot loader's package entry table. If so,
// then it sets the classpath_index in the package entry record.
//
// The classpath_index field is used to find the entry on the boot loader class
// path for packages with classes loaded by the boot loader from -Xbootclasspath/a
// in an unnamed module. It is also used to indicate (for all packages whose
// classes are loaded by the boot loader) that at least one of the package's
// classes has been loaded.
bool ClassLoader::add_package(const char *fullq_class_name, s2 classpath_index, TRAPS) {
assert(fullq_class_name != NULL, "just checking");
// Get package name from fully qualified class name.
const char *cp = strrchr(fullq_class_name, '/');
if (cp != NULL) {
// Package prefix found
int n = cp - pkgname + 1;
return _package_hash_table->get_entry(pkgname, n);
int len = cp - fullq_class_name;
PackageEntryTable* pkg_entry_tbl =
ClassLoaderData::the_null_class_loader_data()->packages();
TempNewSymbol pkg_symbol =
SymbolTable::new_symbol(fullq_class_name, len, CHECK_false);
PackageEntry* pkg_entry = pkg_entry_tbl->lookup_only(pkg_symbol);
if (pkg_entry != NULL) {
assert(classpath_index != -1, "Unexpected classpath_index");
pkg_entry->set_classpath_index(classpath_index);
} else {
return false;
}
}
return true;
}
oop ClassLoader::get_system_package(const char* name, TRAPS) {
// Look up the name in the boot loader's package entry table.
if (name != NULL) {
TempNewSymbol package_sym = SymbolTable::new_symbol(name, (int)strlen(name), CHECK_NULL);
// Look for the package entry in the boot loader's package entry table.
PackageEntry* package =
ClassLoaderData::the_null_class_loader_data()->packages()->lookup_only(package_sym);
// Return NULL if package does not exist or if no classes in that package
// have been loaded.
if (package != NULL && package->has_loaded_class()) {
ModuleEntry* module = package->module();
if (module->location() != NULL) {
ResourceMark rm(THREAD);
Handle ml = java_lang_String::create_from_str(
module->location()->as_C_string(), THREAD);
return ml();
}
// Return entry on boot loader class path.
Handle cph = java_lang_String::create_from_str(
ClassLoader::classpath_entry(package->classpath_index())->name(), THREAD);
return cph();
}
}
return NULL;
}
bool ClassLoader::add_package(const char *pkgname, int classpath_index, TRAPS) {
assert(pkgname != NULL, "just checking");
// Bootstrap loader no longer holds system loader lock obj serializing
// load_instance_class and thereby add_package
{
MutexLocker ml(PackageTable_lock, THREAD);
// First check for previously loaded entry
PackageInfo* pp = lookup_package(pkgname);
if (pp != NULL) {
// Existing entry found, check source of package
pp->set_index(classpath_index);
return true;
}
const char *cp = strrchr(pkgname, '/');
if (cp != NULL) {
// Package prefix found
int n = cp - pkgname + 1;
char* new_pkgname = NEW_C_HEAP_ARRAY(char, n + 1, mtClass);
if (new_pkgname == NULL) {
return false;
}
memcpy(new_pkgname, pkgname, n);
new_pkgname[n] = '\0';
pp = _package_hash_table->new_entry(new_pkgname, n);
pp->set_index(classpath_index);
// Insert into hash table
_package_hash_table->add_entry(pp);
}
return true;
}
}
oop ClassLoader::get_system_package(const char* name, TRAPS) {
PackageInfo* pp;
{
MutexLocker ml(PackageTable_lock, THREAD);
pp = lookup_package(name);
}
if (pp == NULL) {
return NULL;
} else {
Handle p = java_lang_String::create_from_str(pp->filename(), THREAD);
return p();
}
}
objArrayOop ClassLoader::get_system_packages(TRAPS) {
ResourceMark rm(THREAD);
int nof_entries;
const char** packages;
// List of pointers to PackageEntrys that have loaded classes.
GrowableArray<PackageEntry*>* loaded_class_pkgs = new GrowableArray<PackageEntry*>(50);
{
MutexLocker ml(PackageTable_lock, THREAD);
// Allocate resource char* array containing package names
nof_entries = _package_hash_table->number_of_entries();
if ((packages = NEW_RESOURCE_ARRAY(const char*, nof_entries)) == NULL) {
return NULL;
MutexLocker ml(Module_lock, THREAD);
PackageEntryTable* pe_table =
ClassLoaderData::the_null_class_loader_data()->packages();
// Collect the packages that have at least one loaded class.
for (int x = 0; x < pe_table->table_size(); x++) {
for (PackageEntry* package_entry = pe_table->bucket(x);
package_entry != NULL;
package_entry = package_entry->next()) {
if (package_entry->has_loaded_class()) {
loaded_class_pkgs->append(package_entry);
}
}
}
_package_hash_table->copy_pkgnames(packages);
}
// Allocate objArray and fill with java.lang.String
objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(),
nof_entries, CHECK_0);
objArrayHandle result(THREAD, r);
for (int i = 0; i < nof_entries; i++) {
Handle str = java_lang_String::create_from_str(packages[i], CHECK_0);
result->obj_at_put(i, str());
}
// Allocate objArray and fill with java.lang.String
objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(),
loaded_class_pkgs->length(), CHECK_NULL);
objArrayHandle result(THREAD, r);
for (int x = 0; x < loaded_class_pkgs->length(); x++) {
PackageEntry* package_entry = loaded_class_pkgs->at(x);
Handle str = java_lang_String::create_from_symbol(package_entry->name(), CHECK_NULL);
result->obj_at_put(x, str());
}
return result();
}
#if INCLUDE_CDS
s2 ClassLoader::module_to_classloader(const char* module_name) {
assert(_boot_modules_array != NULL, "_boot_modules_array is NULL");
assert(_platform_modules_array != NULL, "_platform_modules_array is NULL");
int array_size = _boot_modules_array->length();
for (int i = 0; i < array_size; i++) {
if (strcmp(module_name, _boot_modules_array->at(i)) == 0) {
return BOOT_LOADER;
}
}
array_size = _platform_modules_array->length();
for (int i = 0; i < array_size; i++) {
if (strcmp(module_name, _platform_modules_array->at(i)) == 0) {
return PLATFORM_LOADER;
}
}
return APP_LOADER;
}
#endif
s2 ClassLoader::classloader_type(Symbol* class_name, ClassPathEntry* e,
int classpath_index, TRAPS) {
#if INCLUDE_CDS
// obtain the classloader type based on the class name.
// First obtain the package name based on the class name. Then obtain
// the classloader type based on the package name from the jimage using
// a jimage API. If the classloader type cannot be found from the
// jimage, it is determined by the class path entry.
jshort loader_type = ClassLoader::APP_LOADER;
if (e->is_jrt()) {
int length = 0;
const jbyte* pkg_string = InstanceKlass::package_from_name(class_name, length);
if (pkg_string != NULL) {
ResourceMark rm;
TempNewSymbol pkg_name = SymbolTable::new_symbol((const char*)pkg_string, length, THREAD);
const char* pkg_name_C_string = (const char*)(pkg_name->as_C_string());
ClassPathImageEntry* cpie = (ClassPathImageEntry*)e;
JImageFile* jimage = cpie->jimage();
char* module_name = (char*)(*JImagePackageToModule)(jimage, pkg_name_C_string);
if (module_name != NULL) {
loader_type = ClassLoader::module_to_classloader(module_name);
}
}
} else if (ClassLoaderExt::is_boot_classpath(classpath_index)) {
loader_type = ClassLoader::BOOT_LOADER;
}
return loader_type;
#endif
return ClassLoader::BOOT_LOADER; // the classloader type is ignored in non-CDS cases
}
// caller needs ResourceMark
const char* ClassLoader::file_name_for_class_name(const char* class_name,
int class_name_len) {
@ -1018,7 +1073,7 @@ const char* ClassLoader::file_name_for_class_name(const char* class_name,
return file_name;
}
instanceKlassHandle ClassLoader::load_class(Symbol* name, TRAPS) {
instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_only, TRAPS) {
assert(name != NULL, "invariant");
assert(THREAD->is_Java_thread(), "must be a JavaThread");
@ -1037,24 +1092,54 @@ instanceKlassHandle ClassLoader::load_class(Symbol* name, TRAPS) {
ClassLoaderExt::Context context(class_name, file_name, THREAD);
// Lookup stream
// Lookup stream for parsing .class file
ClassFileStream* stream = NULL;
int classpath_index = 0;
ClassPathEntry* e = _first_entry;
{
PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(),
((JavaThread*)THREAD)->get_thread_stat()->perf_timers_addr(),
PerfClassTraceTime::CLASS_LOAD);
s2 classpath_index = 0;
for (; e != NULL; e = e->next(), ++classpath_index) {
stream = e->open_stream(file_name, CHECK_NULL);
if (NULL == stream) {
continue;
// If DumpSharedSpaces is true, boot loader visibility boundaries are set
// to be _first_entry to the end (all path entries).
//
// If search_append_only is true, boot loader visibility boundaries are
// set to be _fist_append_entry to the end. This includes:
// [-Xbootclasspath/a]; [jvmti appended entries]
//
// If both DumpSharedSpaces and search_append_only are false, boot loader
// visibility boundaries are set to be _first_entry to the entry before
// the _first_append_entry. This would include:
// [-Xpatch:<dirs>]; [exploded build | modules]
//
// DumpSharedSpaces and search_append_only are mutually exclusive and cannot
// be true at the same time.
ClassPathEntry* e = (search_append_only ? _first_append_entry : _first_entry);
ClassPathEntry* last_e =
(search_append_only || DumpSharedSpaces ? NULL : _first_append_entry);
{
if (search_append_only) {
// For the boot loader append path search, must calculate
// the starting classpath_index prior to attempting to
// load the classfile.
ClassPathEntry *tmp_e = _first_entry;
while ((tmp_e != NULL) && (tmp_e != _first_append_entry)) {
tmp_e = tmp_e->next();
++classpath_index;
}
}
// Attempt to load the classfile from either:
// - [-Xpatch:dir]; exploded build | modules
// or
// - [-Xbootclasspath/a]; [jvmti appended entries]
while ((e != NULL) && (e != last_e)) {
stream = e->open_stream(file_name, CHECK_NULL);
if (!context.check(stream, classpath_index)) {
return NULL;
}
break;
if (NULL != stream) {
break;
}
e = e->next();
++classpath_index;
}
}
@ -1085,32 +1170,16 @@ instanceKlassHandle ClassLoader::load_class(Symbol* name, TRAPS) {
return NULL;
}
return context.record_result(classpath_index, e, result, THREAD);
jshort loader_type = classloader_type(name, e, classpath_index, CHECK_NULL);
return context.record_result(classpath_index, loader_type, e, result, THREAD);
}
void ClassLoader::create_package_info_table(HashtableBucket<mtClass> *t, int length,
int number_of_entries) {
assert(_package_hash_table == NULL, "One package info table allowed.");
assert(length == package_hash_table_size * sizeof(HashtableBucket<mtClass>),
"bad shared package info size.");
_package_hash_table = new PackageHashtable(package_hash_table_size, t,
number_of_entries);
}
void ClassLoader::create_package_info_table() {
assert(_package_hash_table == NULL, "shouldn't have one yet");
_package_hash_table = new PackageHashtable(package_hash_table_size);
}
// Initialize the class loader's access to methods in libzip. Parse and
// process the boot classpath into a list ClassPathEntry objects. Once
// this list has been created, it must not change order (see class PackageInfo)
// it can be appended to and is by jvmti and the kernel vm.
void ClassLoader::initialize() {
assert(_package_hash_table == NULL, "should have been initialized by now.");
EXCEPTION_MARK;
if (UsePerfData) {
@ -1258,12 +1327,48 @@ bool ClassLoader::get_canonical_path(const char* orig, char* out, int len) {
return true;
}
#ifndef PRODUCT
void ClassLoader::create_javabase() {
Thread* THREAD = Thread::current();
void ClassLoader::verify() {
_package_hash_table->verify();
// Create java.base's module entry for the boot
// class loader prior to loading j.l.Ojbect.
ClassLoaderData* null_cld = ClassLoaderData::the_null_class_loader_data();
// Get module entry table
ModuleEntryTable* null_cld_modules = null_cld->modules();
if (null_cld_modules == NULL) {
vm_exit_during_initialization("No ModuleEntryTable for the boot class loader");
}
{
MutexLocker ml(Module_lock, THREAD);
ModuleEntry* jb_module = null_cld_modules->locked_create_entry_or_null(Handle(NULL), vmSymbols::java_base(), NULL, NULL, null_cld);
if (jb_module == NULL) {
vm_exit_during_initialization("Unable to create ModuleEntry for java.base");
}
ModuleEntryTable::set_javabase_module(jb_module);
}
// When looking for the jimage file, only
// search the boot loader's module path which
// can consist of [-Xpatch]; exploded build | modules
// Do not search the boot loader's append path.
ClassPathEntry* e = _first_entry;
ClassPathEntry* last_e = _first_append_entry;
while ((e != NULL) && (e != last_e)) {
JImageFile *jimage = e->jimage();
if (jimage != NULL && e->is_jrt()) {
set_has_jimage(true);
#if INCLUDE_CDS
ClassLoader::initialize_module_loader_map(jimage);
#endif
return;
}
e = e->next();
}
}
#ifndef PRODUCT
// CompileTheWorld
//
@ -1325,10 +1430,6 @@ void ClassPathDirEntry::compile_the_world(Handle loader, TRAPS) {
tty->cr();
}
bool ClassPathDirEntry::is_jrt() {
return false;
}
void ClassPathZipEntry::compile_the_world(Handle loader, TRAPS) {
real_jzfile* zip = (real_jzfile*) _zip;
tty->print_cr("CompileTheWorld : Compiling all classes in %s", zip->name);
@ -1350,10 +1451,6 @@ void ClassPathZipEntry::compile_the_world(Handle loader, TRAPS) {
}
}
bool ClassPathZipEntry::is_jrt() {
return false;
}
void ClassLoader::compile_the_world() {
EXCEPTION_MARK;
HandleMark hm(THREAD);
@ -1366,7 +1463,7 @@ void ClassLoader::compile_the_world() {
ClassPathEntry* e = _first_entry;
jlong start = os::javaTimeMillis();
while (e != NULL) {
// We stop at bootmodules.jimage, unless it is the first bootstrap path entry
// We stop at "modules" jimage, unless it is the first bootstrap path entry
if (e->is_jrt() && e != _first_entry) break;
e->compile_the_world(system_class_loader, CATCH);
e = e->next();

View File

@ -33,8 +33,17 @@
// The VM class loader.
#include <sys/stat.h>
// Name of boot module image
#define BOOT_IMAGE_NAME "bootmodules.jimage"
// Name of boot "modules" image
#define MODULES_IMAGE_NAME "modules"
// Name of the resource containing mapping from module names to defining class loader type
#define MODULE_LOADER_MAP "jdk/internal/vm/cds/resources/ModuleLoaderMap.dat"
// Initial sizes of the following arrays are based on the generated ModuleLoaderMap.dat
#define INITIAL_BOOT_MODULES_ARRAY_SIZE 30
#define INITIAL_PLATFORM_MODULES_ARRAY_SIZE 15
// Class path entry (directory or zip file)
class JImageFile;
class ClassFileStream;
@ -49,6 +58,7 @@ public:
// may have unlocked readers, so write atomically.
OrderAccess::release_store_ptr(&_next, next);
}
virtual bool is_jrt() = 0;
virtual bool is_jar_file() const = 0;
virtual const char* name() const = 0;
virtual JImageFile* jimage() const = 0;
@ -59,13 +69,13 @@ public:
virtual ClassFileStream* open_stream(const char* name, TRAPS) = 0;
// Debugging
NOT_PRODUCT(virtual void compile_the_world(Handle loader, TRAPS) = 0;)
NOT_PRODUCT(virtual bool is_jrt() = 0;)
};
class ClassPathDirEntry: public ClassPathEntry {
private:
const char* _dir; // Name of directory
public:
bool is_jrt() { return false; }
bool is_jar_file() const { return false; }
const char* name() const { return _dir; }
JImageFile* jimage() const { return NULL; }
@ -73,7 +83,6 @@ class ClassPathDirEntry: public ClassPathEntry {
ClassFileStream* open_stream(const char* name, TRAPS);
// Debugging
NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
NOT_PRODUCT(bool is_jrt();)
};
@ -96,6 +105,7 @@ class ClassPathZipEntry: public ClassPathEntry {
jzfile* _zip; // The zip archive
const char* _zip_name; // Name of zip archive
public:
bool is_jrt() { return false; }
bool is_jar_file() const { return true; }
const char* name() const { return _zip_name; }
JImageFile* jimage() const { return NULL; }
@ -106,7 +116,6 @@ class ClassPathZipEntry: public ClassPathEntry {
void contents_do(void f(const char* name, void* context), void* context);
// Debugging
NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
NOT_PRODUCT(bool is_jrt();)
};
@ -116,29 +125,28 @@ private:
JImageFile* _jimage;
const char* _name;
public:
bool is_jrt();
bool is_jar_file() const { return false; }
bool is_open() const { return _jimage != NULL; }
const char* name() const { return _name == NULL ? "" : _name; }
JImageFile* jimage() const { return _jimage; }
ClassPathImageEntry(JImageFile* jimage, const char* name);
~ClassPathImageEntry();
static void name_to_package(const char* name, char* buffer, int length);
void name_to_package(const char* name, char* package, int length);
ClassFileStream* open_stream(const char* name, TRAPS);
// Debugging
NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
NOT_PRODUCT(bool is_jrt();)
};
class PackageHashtable;
class PackageInfo;
class SharedPathsMiscInfo;
template <MEMFLAGS F> class HashtableBucket;
class ClassLoader: AllStatic {
public:
enum SomeConstants {
package_hash_table_size = 31 // Number of buckets
enum ClassLoaderType {
BOOT_LOADER = 1, /* boot loader */
PLATFORM_LOADER = 2, /* PlatformClassLoader */
APP_LOADER = 3 /* AppClassLoader */
};
protected:
@ -177,41 +185,60 @@ class ClassLoader: AllStatic {
static PerfCounter* _isUnsyncloadClass;
static PerfCounter* _load_instance_class_failCounter;
// First entry in linked list of ClassPathEntry instances
// First entry in linked list of ClassPathEntry instances.
// This consists of entries made up by:
// - boot loader modules
// [-Xpatch]; exploded build | modules;
// - boot loader append path
// [-Xbootclasspath/a]; [jvmti appended entries]
static ClassPathEntry* _first_entry;
// Last entry in linked list of ClassPathEntry instances
static ClassPathEntry* _last_entry;
static int _num_entries;
// Hash table used to keep track of loaded packages
static PackageHashtable* _package_hash_table;
// Pointer into the linked list of ClassPathEntry instances.
// Marks the start of:
// - the boot loader's append path
// [-Xbootclasspath/a]; [jvmti appended entries]
static ClassPathEntry* _first_append_entry;
static const char* _shared_archive;
// True if the boot path has a "modules" jimage
static bool _has_jimage;
// Array of module names associated with the boot class loader
CDS_ONLY(static GrowableArray<char*>* _boot_modules_array;)
// Array of module names associated with the platform class loader
CDS_ONLY(static GrowableArray<char*>* _platform_modules_array;)
// Info used by CDS
CDS_ONLY(static SharedPathsMiscInfo * _shared_paths_misc_info;)
// Hash function
static unsigned int hash(const char *s, int n);
// Returns the package file name corresponding to the specified package
// or class name, or null if not found.
static PackageInfo* lookup_package(const char *pkgname);
// Adds a new package entry for the specified class or package name and
// corresponding directory or jar file name.
static bool add_package(const char *pkgname, int classpath_index, TRAPS);
// Initialization
static void setup_bootstrap_search_path();
static void setup_search_path(const char *class_path);
static void setup_search_path(const char *class_path, bool setting_bootstrap);
static void load_zip_library();
static void load_jimage_library();
static ClassPathEntry* create_class_path_entry(const char *path, const struct stat* st,
bool throw_exception, TRAPS);
public:
// If the package for the fully qualified class name is in the boot
// loader's package entry table then add_package() sets the classpath_index
// field so that get_system_package() will know to return a non-null value
// for the package's location. And, so that the package will be added to
// the list of packages returned by get_system_packages().
// For packages whose classes are loaded from the boot loader class path, the
// classpath_index indicates which entry on the boot loader class path.
static bool add_package(const char *fullq_class_name, s2 classpath_index, TRAPS);
// Canonicalizes path names, so strcmp will work properly. This is mainly
// to avoid confusing the zip library
static bool get_canonical_path(const char* orig, char* out, int len);
static const char* file_name_for_class_name(const char* class_name,
int class_name_len);
@ -220,6 +247,8 @@ class ClassLoader: AllStatic {
static int crc32(int crc, const char* buf, int len);
static bool update_class_path_entry_list(const char *path,
bool check_for_duplicates,
bool mark_append_entry,
bool prepend_entry,
bool throw_exception=true);
static void print_bootclasspath();
@ -284,8 +313,18 @@ class ClassLoader: AllStatic {
return _load_instance_class_failCounter;
}
// Sets _has_jimage to TRUE if "modules" jimage file exists
static void set_has_jimage(bool val) {
_has_jimage = val;
}
static bool has_jimage() { return _has_jimage; }
// Create the ModuleEntry for java.base
static void create_javabase();
// Load individual .class file
static instanceKlassHandle load_class(Symbol* class_name, TRAPS);
static instanceKlassHandle load_class(Symbol* class_name, bool search_append_only, TRAPS);
// If the specified package has been loaded by the system, then returns
// the name of the directory or ZIP file that the package was loaded from.
@ -304,9 +343,7 @@ class ClassLoader: AllStatic {
// Initialization
static void initialize();
CDS_ONLY(static void initialize_shared_path();)
static void create_package_info_table();
static void create_package_info_table(HashtableBucket<mtClass> *t, int length,
int number_of_entries);
static int compute_Object_vtable();
static ClassPathEntry* classpath_entry(int n) {
@ -320,8 +357,6 @@ class ClassLoader: AllStatic {
#if INCLUDE_CDS
// Sharing dump and restore
static void copy_package_info_buckets(char** top, char* end);
static void copy_package_info_table(char** top, char* end);
static void check_shared_classpath(const char *path);
static void finalize_shared_paths_misc_info();
@ -329,7 +364,12 @@ class ClassLoader: AllStatic {
static void* get_shared_paths_misc_info();
static bool check_shared_paths_misc_info(void* info, int size);
static void exit_with_path_failure(const char* error, const char* message);
static s2 module_to_classloader(const char* module_name);
static void initialize_module_loader_map(JImageFile* jimage);
#endif
static s2 classloader_type(Symbol* class_name, ClassPathEntry* e,
int classpath_index, TRAPS);
static void trace_class_path(const char* msg, const char* name = NULL);
@ -342,15 +382,30 @@ class ClassLoader: AllStatic {
static jlong class_link_count();
static jlong class_link_time_ms();
static void set_first_append_entry(ClassPathEntry* entry);
// indicates if class path already contains a entry (exact match by name)
static bool contains_entry(ClassPathEntry* entry);
// adds a class path list
static void add_to_list(ClassPathEntry* new_entry);
// prepends a class path list
static void prepend_to_list(ClassPathEntry* new_entry);
// creates a class path zip entry (returns NULL if JAR file cannot be opened)
static ClassPathZipEntry* create_class_path_zip_entry(const char *apath);
// add a path to class path list
static void add_to_list(const char* apath);
// prepend a path to class path list
static void prepend_to_list(const char* apath);
static bool string_ends_with(const char* str, const char* str_to_find);
static bool is_jrt(const char* name) { return string_ends_with(name, MODULES_IMAGE_NAME); }
// Debugging
static void verify() PRODUCT_RETURN;

View File

@ -31,7 +31,7 @@
//
// Class loaders that implement a deterministic name resolution strategy
// (including with respect to their delegation behavior), such as the boot, the
// extension, and the system loaders of the JDK's built-in class loader
// platform, and the system loaders of the JDK's built-in class loader
// hierarchy, always produce the same linkset for a given configuration.
//
// ClassLoaderData carries information related to a linkset (e.g.,
@ -51,6 +51,8 @@
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/metadataOnStackMark.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/packageEntry.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"
#include "gc/shared/gcLocker.hpp"
@ -83,6 +85,7 @@ ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous, Depen
// The null-class-loader should always be kept alive.
_keep_alive(is_anonymous || h_class_loader.is_null()),
_metaspace(NULL), _unloading(false), _klasses(NULL),
_modules(NULL), _packages(NULL),
_claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL),
_next(NULL), _dependencies(dependencies), _shared_class_loader_id(-1),
_metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true,
@ -168,6 +171,30 @@ void ClassLoaderData::classes_do(void f(InstanceKlass*)) {
}
}
void ClassLoaderData::modules_do(void f(ModuleEntry*)) {
if (_modules != NULL) {
for (int i = 0; i < _modules->table_size(); i++) {
for (ModuleEntry* entry = _modules->bucket(i);
entry != NULL;
entry = entry->next()) {
f(entry);
}
}
}
}
void ClassLoaderData::packages_do(void f(PackageEntry*)) {
if (_packages != NULL) {
for (int i = 0; i < _packages->table_size(); i++) {
for (PackageEntry* entry = _packages->bucket(i);
entry != NULL;
entry = entry->next()) {
f(entry);
}
}
}
}
void ClassLoaderData::record_dependency(const Klass* k, TRAPS) {
assert(k != NULL, "invariant");
@ -341,6 +368,46 @@ void ClassLoaderData::unload() {
}
}
PackageEntryTable* ClassLoaderData::packages() {
// Lazily create the package entry table at first request.
if (_packages == NULL) {
MutexLockerEx m1(metaspace_lock(), Mutex::_no_safepoint_check_flag);
// Check again if _packages has been allocated while we were getting this lock.
if (_packages != NULL) {
return _packages;
}
// Ensure _packages is stable, since it is examined without a lock
OrderAccess::storestore();
_packages = new PackageEntryTable(PackageEntryTable::_packagetable_entry_size);
}
return _packages;
}
ModuleEntryTable* ClassLoaderData::modules() {
// Lazily create the module entry table at first request.
if (_modules == NULL) {
MutexLocker m1(Module_lock);
// Check again if _modules has been allocated while we were getting this lock.
if (_modules != NULL) {
return _modules;
}
ModuleEntryTable* temp_table = new ModuleEntryTable(ModuleEntryTable::_moduletable_entry_size);
// Each loader has one unnamed module entry. Create it before
// any classes, loaded by this loader, are defined in case
// they end up being defined in loader's unnamed module.
temp_table->create_unnamed_module(this);
{
MutexLockerEx m1(metaspace_lock(), Mutex::_no_safepoint_check_flag);
// Ensure _modules is stable, since it is examined without a lock
OrderAccess::storestore();
_modules = temp_table;
}
}
return _modules;
}
oop ClassLoaderData::keep_alive_object() const {
assert(!keep_alive(), "Don't use with CLDs that are artificially kept alive");
return is_anonymous() ? _klasses->java_mirror() : class_loader();
@ -358,16 +425,30 @@ ClassLoaderData::~ClassLoaderData() {
// Release C heap structures for all the classes.
classes_do(InstanceKlass::release_C_heap_structures);
// Release C heap allocated hashtable for all the packages.
if (_packages != NULL) {
// Destroy the table itself
delete _packages;
_packages = NULL;
}
// Release C heap allocated hashtable for all the modules.
if (_modules != NULL) {
// Destroy the table itself
delete _modules;
_modules = NULL;
}
// release the metaspace
Metaspace *m = _metaspace;
if (m != NULL) {
_metaspace = NULL;
// release the metaspace
delete m;
// release the handles
if (_handles != NULL) {
JNIHandleBlock::release_block(_handles);
_handles = NULL;
}
}
// release the handles
if (_handles != NULL) {
JNIHandleBlock::release_block(_handles);
_handles = NULL;
}
// Clear all the JNI handles for methods
@ -389,10 +470,10 @@ ClassLoaderData::~ClassLoaderData() {
}
/**
* Returns true if this class loader data is for the extension class loader.
* Returns true if this class loader data is for the platform class loader.
*/
bool ClassLoaderData::is_ext_class_loader_data() const {
return SystemDictionary::is_ext_class_loader(class_loader());
bool ClassLoaderData::is_platform_class_loader_data() const {
return SystemDictionary::is_platform_class_loader(class_loader());
}
Metaspace* ClassLoaderData::metaspace_non_null() {
@ -438,6 +519,10 @@ jobject ClassLoaderData::add_handle(Handle h) {
return handles()->allocate_handle(h());
}
void ClassLoaderData::remove_handle(jobject h) {
_handles->release_handle(h);
}
// Add this metadata pointer to be freed when it's safe. This is only during
// class unloading because Handles might point to this metadata field.
void ClassLoaderData::add_to_deallocate_list(Metadata* m) {
@ -712,6 +797,40 @@ void ClassLoaderDataGraph::methods_do(void f(Method*)) {
}
}
void ClassLoaderDataGraph::modules_do(void f(ModuleEntry*)) {
assert_locked_or_safepoint(Module_lock);
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
cld->modules_do(f);
}
}
void ClassLoaderDataGraph::modules_unloading_do(void f(ModuleEntry*)) {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
// Only walk the head until any clds not purged from prior unloading
// (CMS doesn't purge right away).
for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
assert(cld->is_unloading(), "invariant");
cld->modules_do(f);
}
}
void ClassLoaderDataGraph::packages_do(void f(PackageEntry*)) {
assert_locked_or_safepoint(Module_lock);
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
cld->packages_do(f);
}
}
void ClassLoaderDataGraph::packages_unloading_do(void f(PackageEntry*)) {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
// Only walk the head until any clds not purged from prior unloading
// (CMS doesn't purge right away).
for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
assert(cld->is_unloading(), "invariant");
cld->packages_do(f);
}
}
void ClassLoaderDataGraph::loaded_classes_do(KlassClosure* klass_closure) {
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
cld->loaded_classes_do(klass_closure);
@ -723,6 +842,7 @@ void ClassLoaderDataGraph::classes_unloading_do(void f(Klass* const)) {
// Only walk the head until any clds not purged from prior unloading
// (CMS doesn't purge right away).
for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
assert(cld->is_unloading(), "invariant");
cld->classes_do(f);
}
}
@ -800,6 +920,12 @@ bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure,
data = _head;
while (data != NULL) {
if (data->is_alive(is_alive_closure)) {
if (data->packages_defined()) {
data->packages()->purge_all_package_exports();
}
if (data->modules_defined()) {
data->modules()->purge_all_module_reads();
}
// clean metaspace
if (walk_all_metadata) {
data->classes_do(InstanceKlass::purge_previous_versions);
@ -992,6 +1118,7 @@ void ClassLoaderData::print_value_on(outputStream* out) const {
Ticks ClassLoaderDataGraph::_class_unload_time;
void ClassLoaderDataGraph::class_unload_event(Klass* const k) {
assert(k != NULL, "invariant");
// post class unload event
EventClassUnload event(UNTIMED);

View File

@ -53,6 +53,10 @@ class ClassLoaderData;
class JNIMethodBlock;
class JNIHandleBlock;
class Metadebug;
class ModuleEntry;
class PackageEntry;
class ModuleEntryTable;
class PackageEntryTable;
// GC root for walking class loader data created
@ -92,6 +96,10 @@ class ClassLoaderDataGraph : public AllStatic {
static void classes_do(KlassClosure* klass_closure);
static void classes_do(void f(Klass* const));
static void methods_do(void f(Method*));
static void modules_do(void f(ModuleEntry*));
static void modules_unloading_do(void f(ModuleEntry*));
static void packages_do(void f(PackageEntry*));
static void packages_unloading_do(void f(PackageEntry*));
static void loaded_classes_do(KlassClosure* klass_closure);
static void classes_unloading_do(void f(Klass* const));
static bool do_unloading(BoolObjectClosure* is_alive, bool clean_previous_versions);
@ -172,9 +180,12 @@ class ClassLoaderData : public CHeapObj<mtClass> {
volatile int _claimed; // true if claimed, for example during GC traces.
// To avoid applying oop closure more than once.
// Has to be an int because we cas it.
Klass* _klasses; // The classes defined by the class loader.
JNIHandleBlock* _handles; // Handles to constant pool arrays, Modules, etc, which
// have the same life cycle of the corresponding ClassLoader.
JNIHandleBlock* _handles; // Handles to constant pool arrays
Klass* _klasses; // The classes defined by the class loader.
PackageEntryTable* _packages; // The packages defined by the class loader.
ModuleEntryTable* _modules; // The modules defined by the class loader.
// These method IDs are created for the class loader and set to NULL when the
// class loader is unloaded. They are rarely freed, only for redefine classes
@ -218,6 +229,8 @@ class ClassLoaderData : public CHeapObj<mtClass> {
void loaded_classes_do(KlassClosure* klass_closure);
void classes_do(void f(InstanceKlass*));
void methods_do(void f(Method*));
void modules_do(void f(ModuleEntry*));
void packages_do(void f(PackageEntry*));
// Deallocate free list during class unloading.
void free_deallocate_list();
@ -256,7 +269,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
bool is_the_null_class_loader_data() const {
return this == _the_null_class_loader_data;
}
bool is_ext_class_loader_data() const;
bool is_platform_class_loader_data() const;
// The Metaspace is created lazily so may be NULL. This
// method will allocate a Metaspace if needed.
@ -293,11 +306,16 @@ class ClassLoaderData : public CHeapObj<mtClass> {
const char* loader_name();
jobject add_handle(Handle h);
void remove_handle(jobject h);
void add_class(Klass* k, bool publicize = true);
void remove_class(Klass* k);
bool contains_klass(Klass* k);
void record_dependency(const Klass* to, TRAPS);
void init_dependencies(TRAPS);
PackageEntryTable* packages();
bool packages_defined() { return (_packages != NULL); }
ModuleEntryTable* modules();
bool modules_defined() { return (_modules != NULL); }
void add_to_deallocate_list(Metadata* m);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -49,12 +49,14 @@ public:
return false;
}
instanceKlassHandle record_result(const int classpath_index,
instanceKlassHandle record_result(const s2 classpath_index,
const jshort classloader_type,
const ClassPathEntry* e,
instanceKlassHandle result, TRAPS) {
if (ClassLoader::add_package(_file_name, classpath_index, THREAD)) {
if (DumpSharedSpaces) {
result->set_shared_classpath_index(classpath_index);
result->set_class_loader_type(classloader_type);
}
return result;
} else {
@ -65,13 +67,27 @@ public:
static void add_class_path_entry(const char* path, bool check_for_duplicates,
ClassPathEntry* new_entry) {
ClassLoader::add_to_list(new_entry);
ClassPathEntry* new_entry, bool prepend_entry) {
if (prepend_entry) {
ClassLoader::prepend_to_list(new_entry);
} else {
ClassLoader::add_to_list(new_entry);
}
}
static void append_boot_classpath(ClassPathEntry* new_entry) {
ClassLoader::add_to_list(new_entry);
// During jvmti live phase an entry can be appended to the boot
// loader's ClassPathEntry instances. Need to mark the start
// of the boot loader's append path in case there was no reason
// to mark it initially in setup_bootstrap_search_path.
if (ClassLoader::_first_append_entry == NULL) {
ClassLoader::set_first_append_entry(new_entry);
}
}
static void setup_search_paths() {}
static bool is_boot_classpath(int classpath_index) {
return true;
}
static Klass* load_one_class(ClassListParser* parser, TRAPS);
};

View File

@ -24,7 +24,9 @@
#include "precompiled.hpp"
#include "classfile/altHashing.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/debugInfo.hpp"
@ -513,7 +515,6 @@ char* java_lang_String::as_quoted_ascii(oop java_string) {
return result;
}
Symbol* java_lang_String::as_symbol(Handle java_string, TRAPS) {
oop obj = java_string();
typeArrayOop value = java_lang_String::value(obj);
@ -753,7 +754,7 @@ void java_lang_Class::fixup_mirror(KlassHandle k, TRAPS) {
}
}
}
create_mirror(k, Handle(NULL), Handle(NULL), CHECK);
create_mirror(k, Handle(NULL), Handle(NULL), Handle(NULL), CHECK);
}
void java_lang_Class::initialize_mirror_fields(KlassHandle k,
@ -774,7 +775,7 @@ void java_lang_Class::initialize_mirror_fields(KlassHandle k,
}
void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader,
Handle protection_domain, TRAPS) {
Handle module, Handle protection_domain, TRAPS) {
assert(k->java_mirror() == NULL, "should only assign mirror once");
// Use this moment of initialization to cache modifier_flags also,
// to support Class.getModifiers(). Instance classes recalculate
@ -834,11 +835,25 @@ void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader,
assert(class_loader() == k->class_loader(), "should be same");
set_class_loader(mirror(), class_loader());
// set the module field in the java_lang_Class instance
// This may be null during bootstrap but will get fixed up later on.
set_module(mirror(), module());
// Setup indirection from klass->mirror last
// after any exceptions can happen during allocations.
if (!k.is_null()) {
k->set_java_mirror(mirror());
}
// Keep list of classes needing java.base module fixup.
if (!ModuleEntryTable::javabase_defined()) {
if (fixup_module_field_list() == NULL) {
GrowableArray<Klass*>* list =
new (ResourceObj::C_HEAP, mtClass) GrowableArray<Klass*>(500, true);
set_fixup_module_field_list(list);
}
fixup_module_field_list()->push(k());
}
} else {
if (fixup_mirror_list() == NULL) {
GrowableArray<Klass*>* list =
@ -849,6 +864,10 @@ void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader,
}
}
void java_lang_Class::fixup_module_field(KlassHandle k, Handle module) {
assert(_module_offset != 0, "must have been computed already");
java_lang_Class::set_module(k->java_mirror(), module());
}
int java_lang_Class::oop_size(oop java_class) {
assert(_oop_size_offset != 0, "must be set");
@ -916,6 +935,16 @@ oop java_lang_Class::class_loader(oop java_class) {
return java_class->obj_field(_class_loader_offset);
}
oop java_lang_Class::module(oop java_class) {
assert(_module_offset != 0, "must be set");
return java_class->obj_field(_module_offset);
}
void java_lang_Class::set_module(oop java_class, oop module) {
assert(_module_offset != 0, "must be set");
java_class->obj_field_put(_module_offset, module);
}
oop java_lang_Class::create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS) {
// This should be improved by adding a field at the Java level or by
// introducing a new VM klass (see comment in ClassFileParser)
@ -1101,6 +1130,10 @@ void java_lang_Class::compute_offsets() {
k, vmSymbols::componentType_name(),
vmSymbols::class_signature());
compute_offset(_module_offset,
k, vmSymbols::module_name(),
vmSymbols::module_signature());
// Init lock is a C union with component_mirror. Only instanceKlass mirrors have
// init_lock and only ArrayKlass mirrors have component_mirror. Since both are oops
// GC treats them the same.
@ -1722,28 +1755,48 @@ static void print_stack_element_to_stream(outputStream* st, Handle mirror, int m
buf_len += (int)strlen(source_file_name);
}
char *module_name = NULL, *module_version = NULL;
ModuleEntry* module = holder->module();
if (module->is_named()) {
module_name = module->name()->as_C_string();
buf_len += (int)strlen(module_name);
if (module->version() != NULL) {
module_version = module->version()->as_C_string();
buf_len += (int)strlen(module_version);
}
}
// Allocate temporary buffer with extra space for formatting and line number
char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64);
// Print stack trace line in buffer
sprintf(buf, "\tat %s.%s", klass_name, method_name);
sprintf(buf, "\tat %s.%s(", klass_name, method_name);
// Print module information
if (module_name != NULL) {
if (module_version != NULL) {
sprintf(buf + (int)strlen(buf), "%s@%s/", module_name, module_version);
} else {
sprintf(buf + (int)strlen(buf), "%s/", module_name);
}
}
if (!version_matches(method, version)) {
strcat(buf, "(Redefined)");
strcat(buf, "Redefined)");
} else {
int line_number = Backtrace::get_line_number(method, bci);
if (line_number == -2) {
strcat(buf, "(Native Method)");
strcat(buf, "Native Method)");
} else {
if (source_file_name != NULL && (line_number != -1)) {
// Sourcename and linenumber
sprintf(buf + (int)strlen(buf), "(%s:%d)", source_file_name, line_number);
sprintf(buf + (int)strlen(buf), "%s:%d)", source_file_name, line_number);
} else if (source_file_name != NULL) {
// Just sourcename
sprintf(buf + (int)strlen(buf), "(%s)", source_file_name);
sprintf(buf + (int)strlen(buf), "%s)", source_file_name);
} else {
// Neither sourcename nor linenumber
sprintf(buf + (int)strlen(buf), "(Unknown Source)");
sprintf(buf + (int)strlen(buf), "Unknown Source)");
}
nmethod* nm = method->code();
if (WizardMode && nm != NULL) {
@ -1755,7 +1808,6 @@ static void print_stack_element_to_stream(outputStream* st, Handle mirror, int m
st->print_cr("%s", buf);
}
void java_lang_Throwable::print_stack_element(outputStream *st, const methodHandle& method, int bci) {
Handle mirror = method->method_holder()->java_mirror();
int method_id = method->orig_method_idnum();
@ -2103,6 +2155,20 @@ void java_lang_StackTraceElement::fill_in(Handle element,
oop methodname = StringTable::intern(sym, CHECK);
java_lang_StackTraceElement::set_methodName(element(), methodname);
// Fill in module name and version
ModuleEntry* module = holder->module();
if (module->is_named()) {
oop module_name = StringTable::intern(module->name(), CHECK);
java_lang_StackTraceElement::set_moduleName(element(), module_name);
oop module_version;
if (module->version() != NULL) {
module_version = StringTable::intern(module->version(), CHECK);
} else {
module_version = NULL;
}
java_lang_StackTraceElement::set_moduleVersion(element(), module_version);
}
if (!version_matches(method(), version)) {
// The method was redefined, accurate line number information isn't available
java_lang_StackTraceElement::set_fileName(element(), NULL);
@ -2754,6 +2820,80 @@ void java_lang_reflect_Parameter::set_executable(oop param, oop value) {
}
int java_lang_reflect_Module::loader_offset;
int java_lang_reflect_Module::name_offset;
int java_lang_reflect_Module::_module_entry_offset = -1;
Handle java_lang_reflect_Module::create(Handle loader, Handle module_name, TRAPS) {
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
Symbol* name = vmSymbols::java_lang_reflect_Module();
Klass* k = SystemDictionary::resolve_or_fail(name, true, CHECK_NH);
instanceKlassHandle klass (THREAD, k);
Handle jlrmh = klass->allocate_instance_handle(CHECK_NH);
JavaValue result(T_VOID);
JavaCalls::call_special(&result, jlrmh, KlassHandle(THREAD, klass()),
vmSymbols::object_initializer_name(),
vmSymbols::java_lang_reflect_module_init_signature(),
loader, module_name, CHECK_NH);
return jlrmh;
}
void java_lang_reflect_Module::compute_offsets() {
Klass* k = SystemDictionary::reflect_Module_klass();
if(NULL != k) {
compute_offset(loader_offset, k, vmSymbols::loader_name(), vmSymbols::classloader_signature());
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
MODULE_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
}
}
oop java_lang_reflect_Module::loader(oop module) {
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
return module->obj_field(loader_offset);
}
void java_lang_reflect_Module::set_loader(oop module, oop value) {
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
module->obj_field_put(loader_offset, value);
}
oop java_lang_reflect_Module::name(oop module) {
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
return module->obj_field(name_offset);
}
void java_lang_reflect_Module::set_name(oop module, oop value) {
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
module->obj_field_put(name_offset, value);
}
ModuleEntry* java_lang_reflect_Module::module_entry(oop module, TRAPS) {
assert(_module_entry_offset != -1, "Uninitialized module_entry_offset");
assert(module != NULL, "module can't be null");
assert(module->is_oop(), "module must be oop");
ModuleEntry* module_entry = (ModuleEntry*)module->address_field(_module_entry_offset);
if (module_entry == NULL) {
// If the inject field containing the ModuleEntry* is null then return the
// class loader's unnamed module.
oop loader = java_lang_reflect_Module::loader(module);
Handle h_loader = Handle(THREAD, loader);
ClassLoaderData* loader_cld = SystemDictionary::register_loader(h_loader, CHECK_NULL);
return loader_cld->modules()->unnamed_module();
}
return module_entry;
}
void java_lang_reflect_Module::set_module_entry(oop module, ModuleEntry* module_entry) {
assert(_module_entry_offset != -1, "Uninitialized module_entry_offset");
assert(module != NULL, "module can't be null");
assert(module->is_oop(), "module must be oop");
module->address_field_put(_module_entry_offset, (address)module_entry);
}
Handle sun_reflect_ConstantPool::create(TRAPS) {
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
Klass* k = SystemDictionary::reflect_ConstantPool_klass();
@ -3353,6 +3493,7 @@ oop java_security_AccessControlContext::create(objArrayHandle context, bool isPr
bool java_lang_ClassLoader::offsets_computed = false;
int java_lang_ClassLoader::_loader_data_offset = -1;
int java_lang_ClassLoader::parallelCapable_offset = -1;
int java_lang_ClassLoader::unnamedModule_offset = -1;
ClassLoaderData** java_lang_ClassLoader::loader_data_addr(oop loader) {
assert(loader != NULL && loader->is_oop(), "loader must be oop");
@ -3372,6 +3513,9 @@ void java_lang_ClassLoader::compute_offsets() {
compute_optional_offset(parallelCapable_offset,
k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature());
compute_offset(unnamedModule_offset,
k1, vmSymbols::unnamedModule_name(), vmSymbols::module_signature());
CLASSLOADER_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
}
@ -3439,6 +3583,10 @@ oop java_lang_ClassLoader::non_reflection_class_loader(oop loader) {
return loader;
}
oop java_lang_ClassLoader::unnamedModule(oop loader) {
assert(is_instance(loader), "loader must be oop");
return loader->obj_field(unnamedModule_offset);
}
// Support for java_lang_System
int java_lang_System::in_offset_in_bytes() {
@ -3471,11 +3619,13 @@ int java_lang_Class::_array_klass_offset;
int java_lang_Class::_oop_size_offset;
int java_lang_Class::_static_oop_field_count_offset;
int java_lang_Class::_class_loader_offset;
int java_lang_Class::_module_offset;
int java_lang_Class::_protection_domain_offset;
int java_lang_Class::_component_mirror_offset;
int java_lang_Class::_init_lock_offset;
int java_lang_Class::_signers_offset;
GrowableArray<Klass*>* java_lang_Class::_fixup_mirror_list = NULL;
GrowableArray<Klass*>* java_lang_Class::_fixup_module_field_list = NULL;
int java_lang_Throwable::backtrace_offset;
int java_lang_Throwable::detailMessage_offset;
int java_lang_Throwable::stackTrace_offset;
@ -3535,6 +3685,8 @@ int java_lang_StackTraceElement::declaringClass_offset;
int java_lang_StackTraceElement::methodName_offset;
int java_lang_StackTraceElement::fileName_offset;
int java_lang_StackTraceElement::lineNumber_offset;
int java_lang_StackTraceElement::moduleName_offset;
int java_lang_StackTraceElement::moduleVersion_offset;
int java_lang_StackFrameInfo::_declaringClass_offset;
int java_lang_StackFrameInfo::_memberName_offset;
int java_lang_StackFrameInfo::_bci_offset;
@ -3576,6 +3728,14 @@ void java_lang_StackTraceElement::set_lineNumber(oop element, int value) {
element->int_field_put(lineNumber_offset, value);
}
void java_lang_StackTraceElement::set_moduleName(oop element, oop value) {
element->obj_field_put(moduleName_offset, value);
}
void java_lang_StackTraceElement::set_moduleVersion(oop element, oop value) {
element->obj_field_put(moduleVersion_offset, value);
}
// Support for java_lang_StackFrameInfo
void java_lang_StackFrameInfo::set_declaringClass(oop element, oop value) {
element->obj_field_put(_declaringClass_offset, value);
@ -3713,6 +3873,8 @@ void JavaClasses::compute_hard_coded_offsets() {
java_lang_System::static_security_offset = java_lang_System::hc_static_security_offset * x;
// java_lang_StackTraceElement
java_lang_StackTraceElement::moduleName_offset = java_lang_StackTraceElement::hc_moduleName_offset * x + header;
java_lang_StackTraceElement::moduleVersion_offset = java_lang_StackTraceElement::hc_moduleVersion_offset * x + header;
java_lang_StackTraceElement::declaringClass_offset = java_lang_StackTraceElement::hc_declaringClass_offset * x + header;
java_lang_StackTraceElement::methodName_offset = java_lang_StackTraceElement::hc_methodName_offset * x + header;
java_lang_StackTraceElement::fileName_offset = java_lang_StackTraceElement::hc_fileName_offset * x + header;
@ -3753,6 +3915,7 @@ void JavaClasses::compute_offsets() {
sun_reflect_ConstantPool::compute_offsets();
sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets();
java_lang_reflect_Parameter::compute_offsets();
java_lang_reflect_Module::compute_offsets();
java_lang_StackFrameInfo::compute_offsets();
java_lang_LiveStackFrameInfo::compute_offsets();
@ -3900,7 +4063,7 @@ void JavaClasses::check_offsets() {
// java.lang.ClassLoader
CHECK_OFFSET("java/lang/ClassLoader", java_lang_ClassLoader, parent, "Ljava/lang/ClassLoader;");
CHECK_OFFSET("java/lang/ClassLoader", java_lang_ClassLoader, parent, "Ljava/lang/ClassLoader;");
// java.lang.System

View File

@ -205,12 +205,14 @@ class java_lang_Class : AllStatic {
static int _init_lock_offset;
static int _signers_offset;
static int _class_loader_offset;
static int _module_offset;
static int _component_mirror_offset;
static bool offsets_computed;
static int classRedefinedCount_offset;
static GrowableArray<Klass*>* _fixup_mirror_list;
static GrowableArray<Klass*>* _fixup_module_field_list;
static void set_init_lock(oop java_class, oop init_lock);
static void set_protection_domain(oop java_class, oop protection_domain);
@ -221,10 +223,13 @@ class java_lang_Class : AllStatic {
static void compute_offsets();
// Instance creation
static void create_mirror(KlassHandle k, Handle class_loader,
static void create_mirror(KlassHandle k, Handle class_loader, Handle module,
Handle protection_domain, TRAPS);
static void fixup_mirror(KlassHandle k, TRAPS);
static oop create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS);
static void fixup_module_field(KlassHandle k, Handle module);
// Conversion
static Klass* as_Klass(oop java_class);
static void set_klass(oop java_class, Klass* klass);
@ -262,18 +267,29 @@ class java_lang_Class : AllStatic {
static void set_signers(oop java_class, objArrayOop signers);
static oop class_loader(oop java_class);
static void set_module(oop java_class, oop module);
static oop module(oop java_class);
static int oop_size(oop java_class);
static void set_oop_size(oop java_class, int size);
static int static_oop_field_count(oop java_class);
static void set_static_oop_field_count(oop java_class, int size);
static GrowableArray<Klass*>* fixup_mirror_list() {
return _fixup_mirror_list;
}
static void set_fixup_mirror_list(GrowableArray<Klass*>* v) {
_fixup_mirror_list = v;
}
static GrowableArray<Klass*>* fixup_module_field_list() {
return _fixup_module_field_list;
}
static void set_fixup_module_field_list(GrowableArray<Klass*>* v) {
_fixup_module_field_list = v;
}
// Debugging
friend class JavaClasses;
friend class InstanceKlass; // verification code accesses offsets
@ -750,6 +766,39 @@ class java_lang_reflect_Parameter {
friend class JavaClasses;
};
#define MODULE_INJECTED_FIELDS(macro) \
macro(java_lang_reflect_Module, module_entry, intptr_signature, false)
class java_lang_reflect_Module {
private:
static int loader_offset;
static int name_offset;
static int _module_entry_offset;
static void compute_offsets();
public:
// Allocation
static Handle create(Handle loader, Handle module_name, TRAPS);
// Testers
static bool is_subclass(Klass* klass) {
return klass->is_subclass_of(SystemDictionary::reflect_Module_klass());
}
static bool is_instance(oop obj);
// Accessors
static oop loader(oop module);
static void set_loader(oop module, oop value);
static oop name(oop module);
static void set_name(oop module, oop value);
static ModuleEntry* module_entry(oop module, TRAPS);
static void set_module_entry(oop module, ModuleEntry* module_entry);
friend class JavaClasses;
};
// Interface to sun.reflect.ConstantPool objects
class sun_reflect_ConstantPool {
private:
@ -1195,6 +1244,7 @@ class java_lang_ClassLoader : AllStatic {
static bool offsets_computed;
static int parent_offset;
static int parallelCapable_offset;
static int unnamedModule_offset;
public:
static void compute_offsets();
@ -1219,6 +1269,8 @@ class java_lang_ClassLoader : AllStatic {
}
static bool is_instance(oop obj);
static oop unnamedModule(oop loader);
// Debugging
friend class JavaClasses;
friend class ClassFileParser; // access to number_of_fake_fields
@ -1258,18 +1310,24 @@ class java_lang_System : AllStatic {
class java_lang_StackTraceElement: AllStatic {
private:
enum {
hc_declaringClass_offset = 0,
hc_methodName_offset = 1,
hc_fileName_offset = 2,
hc_lineNumber_offset = 3
hc_moduleName_offset = 0,
hc_moduleVersion_offset = 1,
hc_declaringClass_offset = 2,
hc_methodName_offset = 3,
hc_fileName_offset = 4,
hc_lineNumber_offset = 5
};
static int moduleName_offset;
static int moduleVersion_offset;
static int declaringClass_offset;
static int methodName_offset;
static int fileName_offset;
static int lineNumber_offset;
// Setters
static void set_moduleName(oop element, oop value);
static void set_moduleVersion(oop element, oop value);
static void set_declaringClass(oop element, oop value);
static void set_methodName(oop element, oop value);
static void set_fileName(oop element, oop value);
@ -1450,8 +1508,8 @@ class InjectedField {
CLASSLOADER_INJECTED_FIELDS(macro) \
MEMBERNAME_INJECTED_FIELDS(macro) \
CALLSITECONTEXT_INJECTED_FIELDS(macro) \
STACKFRAMEINFO_INJECTED_FIELDS(macro)
STACKFRAMEINFO_INJECTED_FIELDS(macro) \
MODULE_INJECTED_FIELDS(macro)
// Interface to hard-coded offset checking

View File

@ -171,6 +171,10 @@ inline bool java_lang_invoke_DirectMethodHandle::is_instance(oop obj) {
inline bool java_lang_reflect_Module::is_instance(oop obj) {
return obj != NULL && is_subclass(obj->klass());
}
inline int Backtrace::merge_bci_and_version(int bci, int version) {
// only store u2 for version, checking for overflow.
if (version > USHRT_MAX || version < 0) version = USHRT_MAX;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -22,7 +22,7 @@
*
*/
#include "jni.h"
#include "prims/jni.h"
// Opaque reference to a JImage file.
class JImageFile;
@ -35,6 +35,8 @@ typedef jlong JImageLocationRef;
// JImage Error Codes
// Resource was not found
#define JIMAGE_NOT_FOUND (0)
// The image file is not prefixed with 0xCAFEDADA
#define JIMAGE_BAD_MAGIC (-1)
// The image file does not have a compatible (translatable) version
@ -55,7 +57,7 @@ typedef jlong JImageLocationRef;
*
* Ex.
* jint error;
* JImageFile* jimage = (*JImageOpen)(JAVA_HOME "lib/modules/bootmodules.jimage", &error);
* JImageFile* jimage = (*JImageOpen)(JAVA_HOME "lib/modules", &error);
* if (image == NULL) {
* tty->print_cr("JImage failed to open: %d", error);
* ...

View File

@ -103,11 +103,15 @@ instanceKlassHandle KlassFactory::create_from_stream(ClassFileStream* stream,
assert(loader_data != NULL, "invariant");
assert(THREAD->is_Java_thread(), "must be a JavaThread");
bool changed_by_loadhook = false;
ResourceMark rm;
HandleMark hm;
JvmtiCachedClassFileData* cached_class_file = NULL;
ClassFileStream* old_stream = stream;
stream = prologue(stream,
name,
loader_data,
@ -125,8 +129,8 @@ instanceKlassHandle KlassFactory::create_from_stream(ClassFileStream* stream,
ClassFileParser::BROADCAST, // publicity level
CHECK_NULL);
instanceKlassHandle result = parser.create_instance_klass(CHECK_NULL);
assert(result == parser.create_instance_klass(THREAD), "invariant");
instanceKlassHandle result = parser.create_instance_klass(old_stream != stream, CHECK_NULL);
assert(result == parser.create_instance_klass(old_stream != stream, THREAD), "invariant");
if (result.is_null()) {
return NULL;

View File

@ -0,0 +1,405 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "classfile/classLoaderData.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/moduleEntry.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "oops/symbol.hpp"
#include "prims/jni.h"
#include "runtime/handles.inline.hpp"
#include "runtime/safepoint.hpp"
#include "trace/traceMacros.hpp"
#include "utilities/events.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/hashtable.inline.hpp"
ModuleEntry* ModuleEntryTable::_javabase_module = NULL;
void ModuleEntry::set_location(Symbol* location) {
if (_location != NULL) {
// _location symbol's refcounts are managed by ModuleEntry,
// must decrement the old one before updating.
_location->decrement_refcount();
}
_location = location;
if (location != NULL) {
location->increment_refcount();
}
}
void ModuleEntry::set_version(Symbol* version) {
if (_version != NULL) {
// _version symbol's refcounts are managed by ModuleEntry,
// must decrement the old one before updating.
_version->decrement_refcount();
}
_version = version;
if (version != NULL) {
version->increment_refcount();
}
}
// Returns the shared ProtectionDomain
Handle ModuleEntry::shared_protection_domain() {
return Handle(JNIHandles::resolve(_pd));
}
// Set the shared ProtectionDomain atomically
void ModuleEntry::set_shared_protection_domain(ClassLoaderData *loader_data,
Handle pd_h) {
// Create a JNI handle for the shared ProtectionDomain and save it atomically.
// If someone beats us setting the _pd cache, the created JNI handle is destroyed.
jobject obj = loader_data->add_handle(pd_h);
if (Atomic::cmpxchg_ptr(obj, &_pd, NULL) != NULL) {
loader_data->remove_handle(obj);
}
}
// Returns true if this module can read module m
bool ModuleEntry::can_read(ModuleEntry* m) const {
assert(m != NULL, "No module to lookup in this module's reads list");
// Unnamed modules read everyone and all modules
// read java.base. If either of these conditions
// hold, readability has been established.
if (!this->is_named() ||
(m == ModuleEntryTable::javabase_module())) {
return true;
}
MutexLocker m1(Module_lock);
if (!has_reads()) {
return false;
} else {
return _reads->contains(m);
}
}
// Add a new module to this module's reads list
void ModuleEntry::add_read(ModuleEntry* m) {
MutexLocker m1(Module_lock);
if (m == NULL) {
set_can_read_all_unnamed();
} else {
if (_reads == NULL) {
// Lazily create a module's reads list
_reads = new (ResourceObj::C_HEAP, mtClass)GrowableArray<ModuleEntry*>(MODULE_READS_SIZE, true);
}
_reads->append_if_missing(m);
}
}
bool ModuleEntry::has_reads() const {
assert_locked_or_safepoint(Module_lock);
return ((_reads != NULL) && !_reads->is_empty());
}
// Purge dead module entries out of reads list.
void ModuleEntry::purge_reads() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
if (has_reads()) {
// Go backwards because this removes entries that are dead.
int len = _reads->length();
for (int idx = len - 1; idx >= 0; idx--) {
ModuleEntry* module_idx = _reads->at(idx);
ClassLoaderData* cld = module_idx->loader();
if (cld->is_unloading()) {
_reads->delete_at(idx);
}
}
}
}
void ModuleEntry::module_reads_do(ModuleClosure* const f) {
assert_locked_or_safepoint(Module_lock);
assert(f != NULL, "invariant");
if (has_reads()) {
int reads_len = _reads->length();
for (int i = 0; i < reads_len; ++i) {
f->do_module(_reads->at(i));
}
}
}
void ModuleEntry::delete_reads() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
delete _reads;
_reads = NULL;
}
ModuleEntryTable::ModuleEntryTable(int table_size)
: Hashtable<Symbol*, mtClass>(table_size, sizeof(ModuleEntry)), _unnamed_module(NULL)
{
}
ModuleEntryTable::~ModuleEntryTable() {
assert_locked_or_safepoint(Module_lock);
// Walk through all buckets and all entries in each bucket,
// freeing each entry.
for (int i = 0; i < table_size(); ++i) {
for (ModuleEntry* m = bucket(i); m != NULL;) {
ModuleEntry* to_remove = m;
// read next before freeing.
m = m->next();
ResourceMark rm;
log_debug(modules)("ModuleEntryTable: deleting module: %s", to_remove->name() != NULL ?
to_remove->name()->as_C_string() : UNNAMED_MODULE);
// Clean out the C heap allocated reads list first before freeing the entry
to_remove->delete_reads();
if (to_remove->name() != NULL) {
to_remove->name()->decrement_refcount();
}
if (to_remove->version() != NULL) {
to_remove->version()->decrement_refcount();
}
if (to_remove->location() != NULL) {
to_remove->location()->decrement_refcount();
}
// Unlink from the Hashtable prior to freeing
unlink_entry(to_remove);
FREE_C_HEAP_ARRAY(char, to_remove);
}
}
assert(number_of_entries() == 0, "should have removed all entries");
assert(new_entry_free_list() == NULL, "entry present on ModuleEntryTable's free list");
free_buckets();
}
void ModuleEntryTable::create_unnamed_module(ClassLoaderData* loader_data) {
assert_locked_or_safepoint(Module_lock);
// Each ModuleEntryTable has exactly one unnamed module
if (loader_data->is_the_null_class_loader_data()) {
// For the boot loader, the java.lang.reflect.Module for the unnamed module
// is not known until a call to JVM_SetBootLoaderUnnamedModule is made. At
// this point initially create the ModuleEntry for the unnamed module.
_unnamed_module = new_entry(0, Handle(NULL), NULL, NULL, NULL, loader_data);
} else {
// For all other class loaders the java.lang.reflect.Module for their
// corresponding unnamed module can be found in the java.lang.ClassLoader object.
oop module = java_lang_ClassLoader::unnamedModule(loader_data->class_loader());
_unnamed_module = new_entry(0, Handle(module), NULL, NULL, NULL, loader_data);
// Store pointer to the ModuleEntry in the unnamed module's java.lang.reflect.Module
// object.
java_lang_reflect_Module::set_module_entry(module, _unnamed_module);
}
// Add to bucket 0, no name to hash on
add_entry(0, _unnamed_module);
}
ModuleEntry* ModuleEntryTable::new_entry(unsigned int hash, Handle module_handle, Symbol* name,
Symbol* version, Symbol* location,
ClassLoaderData* loader_data) {
assert_locked_or_safepoint(Module_lock);
ModuleEntry* entry = (ModuleEntry*) NEW_C_HEAP_ARRAY(char, entry_size(), mtClass);
// Initialize everything BasicHashtable would
entry->set_next(NULL);
entry->set_hash(hash);
entry->set_literal(name);
// Initialize fields specific to a ModuleEntry
entry->init();
if (name != NULL) {
name->increment_refcount();
} else {
// Unnamed modules can read all other unnamed modules.
entry->set_can_read_all_unnamed();
}
if (!module_handle.is_null()) {
entry->set_module(loader_data->add_handle(module_handle));
}
entry->set_loader(loader_data);
entry->set_version(version);
entry->set_location(location);
TRACE_INIT_MODULE_ID(entry);
return entry;
}
void ModuleEntryTable::add_entry(int index, ModuleEntry* new_entry) {
assert_locked_or_safepoint(Module_lock);
Hashtable<Symbol*, mtClass>::add_entry(index, (HashtableEntry<Symbol*, mtClass>*)new_entry);
}
ModuleEntry* ModuleEntryTable::locked_create_entry_or_null(Handle module_handle,
Symbol* module_name,
Symbol* module_version,
Symbol* module_location,
ClassLoaderData* loader_data) {
assert(module_name != NULL, "ModuleEntryTable locked_create_entry_or_null should never be called for unnamed module.");
assert_locked_or_safepoint(Module_lock);
// Check if module already exists.
if (lookup_only(module_name) != NULL) {
return NULL;
} else {
ModuleEntry* entry = new_entry(compute_hash(module_name), module_handle, module_name,
module_version, module_location, loader_data);
add_entry(index_for(module_name), entry);
return entry;
}
}
// lookup_only by Symbol* to find a ModuleEntry.
ModuleEntry* ModuleEntryTable::lookup_only(Symbol* name) {
if (name == NULL) {
// Return this table's unnamed module
return unnamed_module();
}
int index = index_for(name);
for (ModuleEntry* m = bucket(index); m != NULL; m = m->next()) {
if (m->name()->fast_compare(name) == 0) {
return m;
}
}
return NULL;
}
// Remove dead modules from all other alive modules' reads list.
// This should only occur at class unloading.
void ModuleEntryTable::purge_all_module_reads() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
for (int i = 0; i < table_size(); i++) {
for (ModuleEntry* entry = bucket(i);
entry != NULL;
entry = entry->next()) {
entry->purge_reads();
}
}
}
void ModuleEntryTable::finalize_javabase(Handle module_handle, Symbol* version, Symbol* location) {
assert_locked_or_safepoint(Module_lock);
ClassLoaderData* boot_loader_data = ClassLoaderData::the_null_class_loader_data();
ModuleEntryTable* module_table = boot_loader_data->modules();
assert(module_table != NULL, "boot loader's ModuleEntryTable not defined");
if (module_handle.is_null()) {
fatal("Unable to finalize module definition for java.base");
}
// Set java.lang.reflect.Module, version and location for java.base
ModuleEntry* jb_module = javabase_module();
assert(jb_module != NULL, "java.base ModuleEntry not defined");
jb_module->set_module(boot_loader_data->add_handle(module_handle));
jb_module->set_version(version);
jb_module->set_location(location);
// Store pointer to the ModuleEntry for java.base in the java.lang.reflect.Module object.
java_lang_reflect_Module::set_module_entry(module_handle(), jb_module);
}
void ModuleEntryTable::patch_javabase_entries(Handle module_handle) {
if (module_handle.is_null()) {
fatal("Unable to patch the module field of classes loaded prior to java.base's definition, invalid java.lang.reflect.Module");
}
// Do the fixups for the basic primitive types
java_lang_Class::set_module(Universe::int_mirror(), module_handle());
java_lang_Class::set_module(Universe::float_mirror(), module_handle());
java_lang_Class::set_module(Universe::double_mirror(), module_handle());
java_lang_Class::set_module(Universe::byte_mirror(), module_handle());
java_lang_Class::set_module(Universe::bool_mirror(), module_handle());
java_lang_Class::set_module(Universe::char_mirror(), module_handle());
java_lang_Class::set_module(Universe::long_mirror(), module_handle());
java_lang_Class::set_module(Universe::short_mirror(), module_handle());
java_lang_Class::set_module(Universe::void_mirror(), module_handle());
// Do the fixups for classes that have already been created.
GrowableArray <Klass*>* list = java_lang_Class::fixup_module_field_list();
int list_length = list->length();
for (int i = 0; i < list_length; i++) {
Klass* k = list->at(i);
assert(k->is_klass(), "List should only hold classes");
Thread* THREAD = Thread::current();
KlassHandle kh(THREAD, k);
java_lang_Class::fixup_module_field(kh, module_handle);
}
delete java_lang_Class::fixup_module_field_list();
java_lang_Class::set_fixup_module_field_list(NULL);
}
#ifndef PRODUCT
void ModuleEntryTable::print() {
tty->print_cr("Module Entry Table (table_size=%d, entries=%d)",
table_size(), number_of_entries());
for (int i = 0; i < table_size(); i++) {
for (ModuleEntry* probe = bucket(i);
probe != NULL;
probe = probe->next()) {
probe->print();
}
}
}
void ModuleEntry::print() {
ResourceMark rm;
tty->print_cr("entry "PTR_FORMAT" name %s module "PTR_FORMAT" loader %s version %s location %s strict %s next "PTR_FORMAT,
p2i(this),
name() == NULL ? UNNAMED_MODULE : name()->as_C_string(),
p2i(module()),
loader()->loader_name(),
version() != NULL ? version()->as_C_string() : "NULL",
location() != NULL ? location()->as_C_string() : "NULL",
BOOL_TO_STR(!can_read_all_unnamed()), p2i(next()));
}
#endif
void ModuleEntryTable::verify() {
int element_count = 0;
for (int i = 0; i < table_size(); i++) {
for (ModuleEntry* probe = bucket(i);
probe != NULL;
probe = probe->next()) {
probe->verify();
element_count++;
}
}
guarantee(number_of_entries() == element_count,
"Verify of Module Entry Table failed");
debug_only(verify_lookup_length((double)number_of_entries() / table_size()));
}
void ModuleEntry::verify() {
guarantee(loader() != NULL, "A module entry must be associated with a loader.");
}

View File

@ -0,0 +1,230 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_CLASSFILE_MODULEENTRY_HPP
#define SHARE_VM_CLASSFILE_MODULEENTRY_HPP
#include "classfile/classLoaderData.hpp"
#include "classfile/vmSymbols.hpp"
#include "oops/symbol.hpp"
#include "prims/jni.h"
#include "runtime/mutexLocker.hpp"
#include "trace/traceMacros.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/hashtable.hpp"
#define UNNAMED_MODULE "Unnamed Module"
class ModuleClosure;
// A ModuleEntry describes a module that has been defined by a call to JVM_DefineModule.
// It contains:
// - Symbol* containing the module's name.
// - pointer to the java.lang.reflect.Module for this module.
// - ClassLoaderData*, class loader of this module.
// - a growable array containg other module entries that this module can read.
// - a flag indicating if this module can read all unnamed modules.
//
// The Mutex Module_lock is shared between ModuleEntry and PackageEntry, to lock either
// data structure.
class ModuleEntry : public HashtableEntry<Symbol*, mtClass> {
private:
jobject _module; // java.lang.reflect.Module
jobject _pd; // java.security.ProtectionDomain, cached
// for shared classes from this module
ClassLoaderData* _loader;
GrowableArray<ModuleEntry*>* _reads; // list of modules that are readable by this module
Symbol* _version; // module version number
Symbol* _location; // module location
bool _can_read_all_unnamed;
bool _has_default_read_edges; // JVMTI redefine/retransform support
TRACE_DEFINE_TRACE_ID_FIELD;
enum {MODULE_READS_SIZE = 101}; // Initial size of list of modules that the module can read.
public:
void init() {
_module = NULL;
_loader = NULL;
_pd = NULL;
_reads = NULL;
_version = NULL;
_location = NULL;
_can_read_all_unnamed = false;
_has_default_read_edges = false;
}
Symbol* name() const { return literal(); }
void set_name(Symbol* n) { set_literal(n); }
jobject module() const { return _module; }
void set_module(jobject j) { _module = j; }
// The shared ProtectionDomain reference is set once the VM loads a shared class
// originated from the current Module. The referenced ProtectionDomain object is
// created by the ClassLoader when loading a class (shared or non-shared) from the
// Module for the first time. This ProtectionDomain object is used for all
// classes from the Module loaded by the same ClassLoader.
Handle shared_protection_domain();
void set_shared_protection_domain(ClassLoaderData *loader_data,
Handle pd);
ClassLoaderData* loader() const { return _loader; }
void set_loader(ClassLoaderData* l) { _loader = l; }
Symbol* version() const { return _version; }
void set_version(Symbol* version);
Symbol* location() const { return _location; }
void set_location(Symbol* location);
bool can_read(ModuleEntry* m) const;
bool has_reads() const;
void add_read(ModuleEntry* m);
bool is_named() const { return (literal() != NULL); }
bool can_read_all_unnamed() const {
assert(is_named() || _can_read_all_unnamed == true,
"unnamed modules can always read all unnamed modules");
return _can_read_all_unnamed;
}
// Modules can only go from strict to loose.
void set_can_read_all_unnamed() { _can_read_all_unnamed = true; }
bool has_default_read_edges() const {
return _has_default_read_edges;
}
// Sets true and returns the previous value.
bool set_has_default_read_edges() {
MutexLocker ml(Module_lock);
bool prev = _has_default_read_edges;
_has_default_read_edges = true;
return prev;
}
ModuleEntry* next() const {
return (ModuleEntry*)HashtableEntry<Symbol*, mtClass>::next();
}
ModuleEntry** next_addr() {
return (ModuleEntry**)HashtableEntry<Symbol*, mtClass>::next_addr();
}
// iteration support for readability
void module_reads_do(ModuleClosure* const f);
TRACE_DEFINE_TRACE_ID_METHODS;
// Purge dead weak references out of reads list when any given class loader is unloaded.
void purge_reads();
void delete_reads();
void print() PRODUCT_RETURN;
void verify();
};
// Iterator interface
class ModuleClosure: public StackObj {
public:
virtual void do_module(ModuleEntry* const module) = 0;
};
// The ModuleEntryTable is a Hashtable containing a list of all modules defined
// by a particular class loader. Each module is represented as a ModuleEntry node.
//
// Each ModuleEntryTable contains a _javabase_module field which allows for the
// creation of java.base's ModuleEntry very early in bootstrapping before the
// corresponding JVM_DefineModule call for java.base occurs during module system
// initialization. Setting up java.base's ModuleEntry early enables classes,
// loaded prior to the module system being initialized to be created with their
// PackageEntry node's correctly pointing at java.base's ModuleEntry. No class
// outside of java.base is allowed to be loaded pre-module system initialization.
//
// The ModuleEntryTable's lookup is lock free.
//
class ModuleEntryTable : public Hashtable<Symbol*, mtClass> {
friend class VMStructs;
public:
enum Constants {
_moduletable_entry_size = 109 // number of entries in module entry table
};
private:
static ModuleEntry* _javabase_module;
ModuleEntry* _unnamed_module;
ModuleEntry* new_entry(unsigned int hash, Handle module_handle, Symbol* name, Symbol* version,
Symbol* location, ClassLoaderData* class_loader);
void add_entry(int index, ModuleEntry* new_entry);
int entry_size() const { return BasicHashtable<mtClass>::entry_size(); }
ModuleEntry** bucket_addr(int i) {
return (ModuleEntry**)Hashtable<Symbol*, mtClass>::bucket_addr(i);
}
static unsigned int compute_hash(Symbol* name) { return ((name == NULL) ? 0 : (unsigned int)(name->identity_hash())); }
int index_for(Symbol* name) const { return hash_to_index(compute_hash(name)); }
public:
ModuleEntryTable(int table_size);
~ModuleEntryTable();
ModuleEntry* bucket(int i) {
return (ModuleEntry*)Hashtable<Symbol*, mtClass>::bucket(i);
}
// Create module in loader's module entry table, if already exists then
// return null. Assume Module_lock has been locked by caller.
ModuleEntry* locked_create_entry_or_null(Handle module_handle,
Symbol* module_name,
Symbol* module_version,
Symbol* module_location,
ClassLoaderData* loader_data);
// Only lookup module within loader's module entry table. The table read is lock-free.
ModuleEntry* lookup_only(Symbol* name);
// purge dead weak references out of reads list
void purge_all_module_reads();
// Special handling for unnamed module, one per class loader's ModuleEntryTable
void create_unnamed_module(ClassLoaderData* loader_data);
ModuleEntry* unnamed_module() { return _unnamed_module; }
// Special handling for java.base
static ModuleEntry* javabase_module() { return _javabase_module; }
static void set_javabase_module(ModuleEntry* java_base) { _javabase_module = java_base; }
static bool javabase_defined() { return ((_javabase_module != NULL) &&
(_javabase_module->module() != NULL)); }
static void finalize_javabase(Handle module_handle, Symbol* version, Symbol* location);
static void patch_javabase_entries(Handle module_handle);
void print() PRODUCT_RETURN;
void verify();
};
#endif // SHARE_VM_CLASSFILE_MODULEENTRY_HPP

View File

@ -0,0 +1,964 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "classfile/classFileParser.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/javaAssertions.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/modules.hpp"
#include "classfile/packageEntry.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/vmSymbols.hpp"
#include "logging/log.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "runtime/arguments.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/reflection.hpp"
#include "utilities/utf8.hpp"
static bool verify_module_name(char *module_name) {
if (module_name == NULL) return false;
int len = (int)strlen(module_name);
return (len > 0 && len <= Symbol::max_length() &&
UTF8::is_legal_utf8((unsigned char *)module_name, len, false) &&
ClassFileParser::verify_unqualified_name(module_name, len,
ClassFileParser::LegalModule));
}
bool Modules::verify_package_name(char *package_name) {
if (package_name == NULL) return false;
int len = (int)strlen(package_name);
return (len > 0 && len <= Symbol::max_length() &&
UTF8::is_legal_utf8((unsigned char *)package_name, len, false) &&
ClassFileParser::verify_unqualified_name(package_name, len,
ClassFileParser::LegalClass));
}
static char* get_module_name(oop module, TRAPS) {
oop name_oop = java_lang_reflect_Module::name(module);
if (name_oop == NULL) {
THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(), "Null module name");
}
char* module_name = java_lang_String::as_utf8_string(name_oop);
if (!verify_module_name(module_name)) {
THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Invalid module name: %s",
module_name != NULL ? module_name : "NULL"));
}
return module_name;
}
static const char* get_module_version(jstring version) {
if (version == NULL) {
return NULL;
}
return java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(version));
}
static ModuleEntryTable* get_module_entry_table(Handle h_loader, TRAPS) {
// This code can be called during start-up, before the classLoader's classLoader data got
// created. So, call register_loader() to make sure the classLoader data gets created.
ClassLoaderData *loader_cld = SystemDictionary::register_loader(h_loader, CHECK_NULL);
return loader_cld->modules();
}
static PackageEntryTable* get_package_entry_table(Handle h_loader, TRAPS) {
// This code can be called during start-up, before the classLoader's classLoader data got
// created. So, call register_loader() to make sure the classLoader data gets created.
ClassLoaderData *loader_cld = SystemDictionary::register_loader(h_loader, CHECK_NULL);
return loader_cld->packages();
}
static ModuleEntry* get_module_entry(jobject module, TRAPS) {
Handle module_h(THREAD, JNIHandles::resolve(module));
if (!java_lang_reflect_Module::is_instance(module_h())) {
THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Bad module object");
}
return java_lang_reflect_Module::module_entry(module_h(), CHECK_NULL);
}
static PackageEntry* get_package_entry(ModuleEntry* module_entry, jstring package, TRAPS) {
ResourceMark rm(THREAD);
if (package == NULL) return NULL;
const char *package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
if (package_name == NULL) return NULL;
TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package_name, CHECK_NULL);
PackageEntryTable* package_entry_table = module_entry->loader()->packages();
assert(package_entry_table != NULL, "Unexpected null package entry table");
return package_entry_table->lookup_only(pkg_symbol);
}
static PackageEntry* get_package_entry_by_name(Symbol* package,
Handle h_loader,
TRAPS) {
if (package != NULL) {
ResourceMark rm(THREAD);
if (Modules::verify_package_name(package->as_C_string())) {
PackageEntryTable* const package_entry_table =
get_package_entry_table(h_loader, CHECK_NULL);
assert(package_entry_table != NULL, "Unexpected null package entry table");
return package_entry_table->lookup_only(package);
}
}
return NULL;
}
// Check if -Xpatch:<dirs> was specified. If so, prepend each <dir>/module_name,
// if it exists, to bootpath so boot loader can find the class files. Also, if
// using exploded modules, append <java.home>/modules/module_name, if it exists,
// to bootpath so that its class files can be found by the boot loader.
static void add_to_boot_loader_list(char *module_name, TRAPS) {
// java.base should be handled by argument parsing.
assert(strcmp(module_name, "java.base") != 0, "Unexpected java.base module name");
char file_sep = os::file_separator()[0];
size_t module_len = strlen(module_name);
// If -Xpatch is set then add <patch-dir>/module_name paths.
char** patch_dirs = Arguments::patch_dirs();
if (patch_dirs != NULL) {
int dir_count = Arguments::patch_dirs_count();
for (int x = 0; x < dir_count; x++) {
// Really shouldn't be NULL, but check can't hurt
if (patch_dirs[x] != NULL) {
size_t len = strlen(patch_dirs[x]);
if (len != 0) { // Ignore empty strings.
len = len + module_len + 2;
char* prefix_path = NEW_C_HEAP_ARRAY(char, len, mtInternal);
jio_snprintf(prefix_path, len, "%s%c%s", patch_dirs[x], file_sep, module_name);
// See if Xpatch module path exists.
struct stat st;
if ((os::stat(prefix_path, &st) != 0)) {
FREE_C_HEAP_ARRAY(char, prefix_path);
} else {
{
HandleMark hm;
Handle loader_lock = Handle(THREAD, SystemDictionary::system_loader_lock());
ObjectLocker ol(loader_lock, THREAD);
ClassLoader::prepend_to_list(prefix_path);
}
log_info(classload)("opened: -Xpatch %s", prefix_path);
}
}
}
}
}
// If "modules" jimage does not exist then assume exploded form
// ${java.home}/modules/<module-name>
char* path = NULL;
if (!ClassLoader::has_jimage()) {
const char* home = Arguments::get_java_home();
size_t len = strlen(home) + module_len + 32;
path = NEW_C_HEAP_ARRAY(char, len, mtInternal);
jio_snprintf(path, len, "%s%cmodules%c%s", home, file_sep, file_sep, module_name);
struct stat st;
// See if exploded module path exists.
if ((os::stat(path, &st) != 0)) {
FREE_C_HEAP_ARRAY(char, path);
path = NULL;
}
}
if (path != NULL) {
HandleMark hm;
Handle loader_lock = Handle(THREAD, SystemDictionary::system_loader_lock());
ObjectLocker ol(loader_lock, THREAD);
log_info(classload)("opened: %s", path);
ClassLoader::add_to_list(path);
}
}
bool Modules::is_package_defined(Symbol* package, Handle h_loader, TRAPS) {
PackageEntry* res = get_package_entry_by_name(package, h_loader, CHECK_false);
return res != NULL;
}
static void define_javabase_module(jobject module, jstring version,
jstring location, jobjectArray packages, TRAPS) {
ResourceMark rm(THREAD);
Handle module_handle(THREAD, JNIHandles::resolve(module));
// Obtain java.base's module version
const char* module_version = get_module_version(version);
TempNewSymbol version_symbol;
if (module_version != NULL) {
version_symbol = SymbolTable::new_symbol(module_version, CHECK);
} else {
version_symbol = NULL;
}
// Obtain java.base's location
const char* module_location = NULL;
TempNewSymbol location_symbol = NULL;
if (location != NULL) {
module_location =
java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(location));
if (module_location != NULL) {
location_symbol = SymbolTable::new_symbol(module_location, CHECK);
}
}
objArrayOop packages_oop = objArrayOop(JNIHandles::resolve(packages));
objArrayHandle packages_h(THREAD, packages_oop);
int num_packages = (packages_h == NULL ? 0 : packages_h->length());
// Check that the list of packages has no duplicates and that the
// packages are syntactically ok.
GrowableArray<Symbol*>* pkg_list = new GrowableArray<Symbol*>(num_packages);
for (int x = 0; x < num_packages; x++) {
oop string_obj = packages_h->obj_at(x);
if (string_obj == NULL || !string_obj->is_a(SystemDictionary::String_klass())) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Bad package name for module: java.base");
}
char *package_name = java_lang_String::as_utf8_string(string_obj);
if (!Modules::verify_package_name(package_name)) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Invalid package name: %s for module: java.base", package_name));
}
Symbol* pkg_symbol = SymbolTable::new_symbol(package_name, CHECK);
// append_if_missing() returns FALSE if entry already exists.
if (!pkg_list->append_if_missing(pkg_symbol)) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Duplicate package name: %s for module java.base",
package_name));
}
}
// Validate java_base's loader is the boot loader.
oop loader = java_lang_reflect_Module::loader(module_handle());
if (loader != NULL) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Class loader must be the boot class loader");
}
Handle h_loader = Handle(THREAD, loader);
// Ensure the boot loader's PackageEntryTable has been created
PackageEntryTable* package_table = get_package_entry_table(h_loader, CHECK);
assert(pkg_list->length() == 0 || package_table != NULL, "Bad package_table");
// Ensure java.base's ModuleEntry has been created
assert(ModuleEntryTable::javabase_module() != NULL, "No ModuleEntry for java.base");
{
MutexLocker m1(Module_lock, THREAD);
// Verify that all java.base packages created during bootstrapping are in
// pkg_list. If any are not in pkg_list, than a non-java.base class was
// loaded erroneously pre java.base module definition.
package_table->verify_javabase_packages(pkg_list);
// loop through and add any new packages for java.base
PackageEntry* pkg;
for (int x = 0; x < pkg_list->length(); x++) {
// Some of java.base's packages were added early in bootstrapping, ignore duplicates.
if (package_table->lookup_only(pkg_list->at(x)) == NULL) {
pkg = package_table->locked_create_entry_or_null(pkg_list->at(x), ModuleEntryTable::javabase_module());
assert(pkg != NULL, "Unable to create a java.base package entry");
}
// Unable to have a GrowableArray of TempNewSymbol. Must decrement the refcount of
// the Symbol* that was created above for each package. The refcount was incremented
// by SymbolTable::new_symbol and as well by the PackageEntry creation.
pkg_list->at(x)->decrement_refcount();
}
// Finish defining java.base's ModuleEntry
ModuleEntryTable::finalize_javabase(module_handle, version_symbol, location_symbol);
}
log_debug(modules)("define_javabase_module(): Definition of module: java.base,"
" version: %s, location: %s, package #: %d",
module_version != NULL ? module_version : "NULL",
module_location != NULL ? module_location : "NULL",
pkg_list->length());
// packages defined to java.base
for (int x = 0; x < pkg_list->length(); x++) {
log_trace(modules)("define_javabase_module(): creation of package %s for module java.base",
(pkg_list->at(x))->as_C_string());
}
// Patch any previously loaded classes' module field with java.base's jlr.Module.
ModuleEntryTable::patch_javabase_entries(module_handle);
}
void Modules::define_module(jobject module, jstring version,
jstring location, jobjectArray packages, TRAPS) {
ResourceMark rm(THREAD);
if (module == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Null module object");
}
Handle module_handle(THREAD, JNIHandles::resolve(module));
if (!java_lang_reflect_Module::is_subclass(module_handle->klass())) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"module is not a subclass of java.lang.reflect.Module");
}
char* module_name = get_module_name(module_handle(), CHECK);
if (module_name == NULL) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Module name cannot be null");
}
// Special handling of java.base definition
if (strcmp(module_name, "java.base") == 0) {
define_javabase_module(module, version, location, packages, CHECK);
return;
}
const char* module_version = get_module_version(version);
objArrayOop packages_oop = objArrayOop(JNIHandles::resolve(packages));
objArrayHandle packages_h(THREAD, packages_oop);
int num_packages = (packages_h == NULL ? 0 : packages_h->length());
// Check that the list of packages has no duplicates and that the
// packages are syntactically ok.
GrowableArray<Symbol*>* pkg_list = new GrowableArray<Symbol*>(num_packages);
for (int x = 0; x < num_packages; x++) {
oop string_obj = packages_h->obj_at(x);
if (string_obj == NULL || !string_obj->is_a(SystemDictionary::String_klass())) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Bad package name for module: %s", module_name));
}
char *package_name = java_lang_String::as_utf8_string(string_obj);
if (!verify_package_name(package_name)) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Invalid package name: %s for module: %s",
package_name, module_name));
}
Symbol* pkg_symbol = SymbolTable::new_symbol(package_name, CHECK);
// append_if_missing() returns FALSE if entry already exists.
if (!pkg_list->append_if_missing(pkg_symbol)) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Duplicate package name: %s for module %s",
package_name, module_name));
}
}
oop loader = java_lang_reflect_Module::loader(module_handle());
// Make sure loader is not the sun.reflect.DelegatingClassLoader.
if (loader != java_lang_ClassLoader::non_reflection_class_loader(loader)) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Class loader is an invalid delegating class loader");
}
Handle h_loader = Handle(THREAD, loader);
// Check that loader is a subclass of java.lang.ClassLoader.
if (loader != NULL && !java_lang_ClassLoader::is_subclass(h_loader->klass())) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Class loader is not a subclass of java.lang.ClassLoader");
}
ModuleEntryTable* module_table = get_module_entry_table(h_loader, CHECK);
assert(module_table != NULL, "module entry table shouldn't be null");
// Create symbol* entry for module name.
TempNewSymbol module_symbol = SymbolTable::new_symbol(module_name, CHECK);
int dupl_pkg_index = -1;
bool dupl_modules = false;
// Create symbol* entry for module version.
TempNewSymbol version_symbol;
if (module_version != NULL) {
version_symbol = SymbolTable::new_symbol(module_version, CHECK);
} else {
version_symbol = NULL;
}
// Create symbol* entry for module location.
const char* module_location = NULL;
TempNewSymbol location_symbol = NULL;
if (location != NULL) {
module_location =
java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(location));
if (module_location != NULL) {
location_symbol = SymbolTable::new_symbol(module_location, CHECK);
}
}
ClassLoaderData* loader_data = ClassLoaderData::class_loader_data_or_null(h_loader());
assert(loader_data != NULL, "class loader data shouldn't be null");
PackageEntryTable* package_table = NULL;
{
MutexLocker ml(Module_lock, THREAD);
if (num_packages > 0) {
package_table = get_package_entry_table(h_loader, CHECK);
assert(package_table != NULL, "Missing package_table");
// Check that none of the packages exist in the class loader's package table.
for (int x = 0; x < pkg_list->length(); x++) {
if (package_table->lookup_only(pkg_list->at(x)) != NULL) {
// This could be because the module was already defined. If so,
// report that error instead of the package error.
if (module_table->lookup_only(module_symbol) != NULL) {
dupl_modules = true;
} else {
dupl_pkg_index = x;
}
break;
}
}
} // if (num_packages > 0)...
// Add the module and its packages.
if (!dupl_modules && dupl_pkg_index == -1) {
// Create the entry for this module in the class loader's module entry table.
ModuleEntry* module_entry = module_table->locked_create_entry_or_null(module_handle, module_symbol,
version_symbol, location_symbol, loader_data);
if (module_entry == NULL) {
dupl_modules = true;
} else {
// Add the packages.
assert(pkg_list->length() == 0 || package_table != NULL, "Bad package table");
PackageEntry* pkg;
for (int y = 0; y < pkg_list->length(); y++) {
pkg = package_table->locked_create_entry_or_null(pkg_list->at(y), module_entry);
assert(pkg != NULL, "Unable to create a module's package entry");
// Unable to have a GrowableArray of TempNewSymbol. Must decrement the refcount of
// the Symbol* that was created above for each package. The refcount was incremented
// by SymbolTable::new_symbol and as well by the PackageEntry creation.
pkg_list->at(y)->decrement_refcount();
}
// Store pointer to ModuleEntry record in java.lang.reflect.Module object.
java_lang_reflect_Module::set_module_entry(module_handle(), module_entry);
}
}
} // Release the lock
// any errors ?
if (dupl_modules) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Module %s is already defined", module_name));
}
if (dupl_pkg_index != -1) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Package %s for module %s already exists for class loader",
pkg_list->at(dupl_pkg_index)->as_C_string(), module_name));
}
if (log_is_enabled(Debug, modules)) {
outputStream* logst = LogHandle(modules)::debug_stream();
logst->print("define_module(): creation of module: %s, version: %s, location: %s, ",
module_name, module_version != NULL ? module_version : "NULL",
module_location != NULL ? module_location : "NULL");
loader_data->print_value_on(logst);
logst->print_cr(", package #: %d", pkg_list->length());
for (int y = 0; y < pkg_list->length(); y++) {
log_trace(modules)("define_module(): creation of package %s for module %s",
(pkg_list->at(y))->as_C_string(), module_name);
}
}
if (loader == NULL && !Universe::is_module_initialized()) {
// Now that the module is defined, if it is in the bootloader, make sure that
// its classes can be found. Check if -Xpatch:<path> was specified. If
// so prepend <path>/module_name, if it exists, to bootpath. Also, if using
// exploded modules, prepend <java.home>/modules/module_name, if it exists,
// to bootpath.
add_to_boot_loader_list(module_name, CHECK);
}
}
void Modules::set_bootloader_unnamed_module(jobject module, TRAPS) {
ResourceMark rm(THREAD);
if (module == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Null module object");
}
Handle module_handle(THREAD, JNIHandles::resolve(module));
if (!java_lang_reflect_Module::is_subclass(module_handle->klass())) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"module is not a subclass of java.lang.reflect.Module");
}
// Ensure that this is an unnamed module
oop name = java_lang_reflect_Module::name(module_handle());
if (name != NULL) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"boot loader's unnamed module's java.lang.reflect.Module has a name");
}
// Validate java_base's loader is the boot loader.
oop loader = java_lang_reflect_Module::loader(module_handle());
if (loader != NULL) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Class loader must be the boot class loader");
}
Handle h_loader = Handle(THREAD, loader);
log_debug(modules)("set_bootloader_unnamed_module(): recording unnamed module for boot loader");
// Ensure the boot loader's PackageEntryTable has been created
ModuleEntryTable* module_table = get_module_entry_table(h_loader, CHECK);
// Set java.lang.reflect.Module for the boot loader's unnamed module
ModuleEntry* unnamed_module = module_table->unnamed_module();
assert(unnamed_module != NULL, "boot loader's unnamed ModuleEntry not defined");
unnamed_module->set_module(ClassLoaderData::the_null_class_loader_data()->add_handle(module_handle));
// Store pointer to the ModuleEntry in the unnamed module's java.lang.reflect.Module object.
java_lang_reflect_Module::set_module_entry(module_handle(), unnamed_module);
}
void Modules::add_module_exports(jobject from_module, jstring package, jobject to_module, TRAPS) {
if (package == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"package is null");
}
if (from_module == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"from_module is null");
}
ModuleEntry* from_module_entry = get_module_entry(from_module, CHECK);
if (from_module_entry == NULL) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"from_module cannot be found");
}
// All packages in unnamed are exported by default.
if (!from_module_entry->is_named()) return;
ModuleEntry* to_module_entry;
if (to_module == NULL) {
to_module_entry = NULL; // It's an unqualified export.
} else {
to_module_entry = get_module_entry(to_module, CHECK);
if (to_module_entry == NULL) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"to_module is invalid");
}
}
PackageEntry *package_entry = get_package_entry(from_module_entry, package, CHECK);
ResourceMark rm(THREAD);
if (package_entry == NULL) {
const char *package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Package %s not found in from_module %s",
package_name != NULL ? package_name : "",
from_module_entry->name()->as_C_string()));
}
if (package_entry->module() != from_module_entry) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Package: %s found in module %s, not in from_module: %s",
package_entry->name()->as_C_string(),
package_entry->module()->name()->as_C_string(),
from_module_entry->name()->as_C_string()));
}
log_debug(modules)("add_module_exports(): package %s in module %s is exported to module %s",
package_entry->name()->as_C_string(),
from_module_entry->name()->as_C_string(),
to_module_entry == NULL ? "NULL" :
to_module_entry->is_named() ?
to_module_entry->name()->as_C_string() : UNNAMED_MODULE);
// Do nothing if modules are the same or if package is already exported unqualifiedly.
if (from_module_entry != to_module_entry && !package_entry->is_unqual_exported()) {
package_entry->set_exported(to_module_entry);
}
}
void Modules::add_module_exports_qualified(jobject from_module, jstring package,
jobject to_module, TRAPS) {
if (to_module == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"to_module is null");
}
add_module_exports(from_module, package, to_module, CHECK);
}
void Modules::add_reads_module(jobject from_module, jobject to_module, TRAPS) {
if (from_module == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"from_module is null");
}
ModuleEntry* from_module_entry = get_module_entry(from_module, CHECK);
if (from_module_entry == NULL) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"from_module is not valid");
}
ModuleEntry* to_module_entry;
if (to_module != NULL) {
to_module_entry = get_module_entry(to_module, CHECK);
if (to_module_entry == NULL) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"to_module is invalid");
}
} else {
to_module_entry = NULL;
}
ResourceMark rm(THREAD);
log_debug(modules)("add_reads_module(): Adding read from module %s to module %s",
from_module_entry->is_named() ?
from_module_entry->name()->as_C_string() : UNNAMED_MODULE,
to_module_entry == NULL ? "all unnamed" :
(to_module_entry->is_named() ?
to_module_entry->name()->as_C_string() : UNNAMED_MODULE));
// if modules are the same or if from_module is unnamed then no need to add the read.
if (from_module_entry != to_module_entry && from_module_entry->is_named()) {
from_module_entry->add_read(to_module_entry);
}
}
jboolean Modules::can_read_module(jobject asking_module, jobject target_module, TRAPS) {
if (asking_module == NULL) {
THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
"asking_module is null", JNI_FALSE);
}
ModuleEntry* asking_module_entry = get_module_entry(asking_module, CHECK_false);
if (asking_module_entry == NULL) {
THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
"asking_module is invalid", JNI_FALSE);
}
// Calling can_read_all_unnamed() with NULL tests if a module is loose.
if (target_module == NULL) {
return asking_module_entry->can_read_all_unnamed();
}
ModuleEntry* target_module_entry = get_module_entry(target_module, CHECK_false);
if (target_module_entry == NULL) {
THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
"target_module is invalid", JNI_FALSE);
}
ResourceMark rm(THREAD);
log_debug(modules)("can_read_module(): module %s trying to read module %s, allowed = %s",
asking_module_entry->is_named() ?
asking_module_entry->name()->as_C_string() : UNNAMED_MODULE,
target_module_entry->is_named() ?
target_module_entry->name()->as_C_string() : UNNAMED_MODULE,
BOOL_TO_STR(asking_module_entry == target_module_entry ||
(asking_module_entry->can_read_all_unnamed() &&
!target_module_entry->is_named()) ||
asking_module_entry->can_read(target_module_entry)));
// Return true if:
// 1. the modules are the same, or
// 2. the asking_module is unnamed (because unnamed modules read everybody), or
// 3. the asking_module is loose and the target module is unnamed, or
// 4. if can_read() returns true.
if (asking_module_entry == target_module_entry ||
(asking_module_entry->can_read_all_unnamed() && !target_module_entry->is_named())) {
return true;
}
return asking_module_entry->can_read(target_module_entry);
}
jboolean Modules::is_exported_to_module(jobject from_module, jstring package,
jobject to_module, TRAPS) {
if (package == NULL) {
THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
"package is null", JNI_FALSE);
}
if (from_module == NULL) {
THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
"from_module is null", JNI_FALSE);
}
ModuleEntry* from_module_entry = get_module_entry(from_module, CHECK_false);
if (from_module_entry == NULL) {
THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
"from_module is invalid", JNI_FALSE);
}
ModuleEntry* to_module_entry;
if (to_module == NULL) {
THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
"to_module is null", JNI_FALSE);
}
to_module_entry = get_module_entry(to_module, CHECK_false);
if (to_module_entry == NULL) {
THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
"to_module is invalid", JNI_FALSE);
}
PackageEntry *package_entry = get_package_entry(from_module_entry, package,
CHECK_false);
ResourceMark rm(THREAD);
if (package_entry == NULL) {
THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Package not found in from_module: %s",
from_module_entry->is_named() ?
from_module_entry->name()->as_C_string() : UNNAMED_MODULE),
JNI_FALSE);
}
if (package_entry->module() != from_module_entry) {
THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Package: %s found in module %s, not in from_module: %s",
package_entry->name()->as_C_string(),
package_entry->module()->is_named() ?
package_entry->module()->name()->as_C_string() : UNNAMED_MODULE,
from_module_entry->is_named() ?
from_module_entry->name()->as_C_string() : UNNAMED_MODULE),
JNI_FALSE);
}
log_debug(modules)("is_exported_to_module: package %s from module %s checking"
" if exported to module %s, exported? = %s",
package_entry->name()->as_C_string(),
from_module_entry->is_named() ?
from_module_entry->name()->as_C_string() : UNNAMED_MODULE,
to_module_entry->is_named() ?
to_module_entry->name()->as_C_string() : UNNAMED_MODULE,
BOOL_TO_STR(!from_module_entry->is_named() ||
package_entry->is_unqual_exported() ||
from_module_entry == to_module_entry ||
package_entry->is_qexported_to(to_module_entry)));
// Return true if:
// 1. from_module is unnamed because unnamed modules export all their packages (by default), or
// 2. if the package is unqualifiedly exported, or
// 3. if the modules are the same, or
// 4. if the package is exported to to_module
return (!from_module_entry->is_named() ||
package_entry->is_unqual_exported() ||
from_module_entry == to_module_entry ||
package_entry->is_qexported_to(to_module_entry));
}
// This method is called by JFR and JNI.
jobject Modules::get_module(jclass clazz, TRAPS) {
assert(ModuleEntryTable::javabase_defined(), "Attempt to call get_module before java.base is defined");
if (clazz == NULL) {
THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
"class is null", JNI_FALSE);
}
oop mirror = JNIHandles::resolve_non_null(clazz);
if (mirror == NULL) {
log_debug(modules)("get_module(): no mirror, returning NULL");
return NULL;
}
if (!java_lang_Class::is_instance(mirror)) {
THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
"Invalid class", JNI_FALSE);
}
oop module = java_lang_Class::module(mirror);
assert(module != NULL, "java.lang.Class module field not set");
assert(java_lang_reflect_Module::is_subclass(module->klass()), "Module is not a java.lang.reflect.Module");
if (log_is_enabled(Debug, modules)) {
ResourceMark rm(THREAD);
outputStream* logst = LogHandle(modules)::debug_stream();
Klass* klass = java_lang_Class::as_Klass(mirror);
oop module_name = java_lang_reflect_Module::name(module);
if (module_name != NULL) {
logst->print("get_module(): module ");
java_lang_String::print(module_name, tty);
} else {
logst->print("get_module(): Unamed Module");
}
if (klass != NULL) {
logst->print_cr(" for class %s", klass->external_name());
} else {
logst->print_cr(" for primitive class");
}
}
return JNIHandles::make_local(THREAD, module);
}
jobject Modules::get_module_by_package_name(jobject loader, jstring package, TRAPS) {
ResourceMark rm(THREAD);
assert(ModuleEntryTable::javabase_defined(),
"Attempt to call get_module_from_pkg before java.base is defined");
if (NULL == package) {
THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
"package is null", JNI_FALSE);
}
const char* package_str =
java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
if (NULL == package_str) {
THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
"Invalid package", JNI_FALSE);
}
Handle h_loader (THREAD, JNIHandles::resolve(loader));
// Check that loader is a subclass of java.lang.ClassLoader.
if (loader != NULL && !java_lang_ClassLoader::is_subclass(h_loader->klass())) {
THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
"Class loader is not a subclass of java.lang.ClassLoader", JNI_FALSE);
}
if (strlen(package_str) == 0) {
// Return the unnamed module
ModuleEntryTable* module_table = get_module_entry_table(h_loader, CHECK_NULL);
if (NULL == module_table) return NULL;
const ModuleEntry* const unnamed_module = module_table->unnamed_module();
return JNIHandles::make_local(THREAD, JNIHandles::resolve(unnamed_module->module()));
} else {
TempNewSymbol package_sym = SymbolTable::new_symbol(package_str, CHECK_NULL);
return get_module(package_sym, h_loader, CHECK_NULL);
}
return NULL;
}
// This method is called by JFR and by the above method.
jobject Modules::get_module(Symbol* package_name, Handle h_loader, TRAPS) {
const PackageEntry* const pkg_entry =
get_package_entry_by_name(package_name, h_loader, THREAD);
const ModuleEntry* const module_entry = (pkg_entry != NULL ? pkg_entry->module() : NULL);
if (module_entry != NULL &&
module_entry->module() != NULL) {
return JNIHandles::make_local(THREAD, JNIHandles::resolve(module_entry->module()));
}
return NULL;
}
void Modules::add_module_package(jobject module, jstring package, TRAPS) {
ResourceMark rm(THREAD);
if (module == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"module is null");
}
if (package == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"package is null");
}
ModuleEntry* module_entry = get_module_entry(module, CHECK);
if (module_entry == NULL) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"module is invalid");
}
if (!module_entry->is_named()) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"module cannot be an unnamed module");
}
char *package_name = java_lang_String::as_utf8_string(
JNIHandles::resolve_non_null(package));
if (package_name == NULL) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Bad package");
}
if (!verify_package_name(package_name)) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Invalid package name: %s", package_name));
}
log_debug(modules)("add_module_package(): Adding package %s to module %s",
package_name, module_entry->name()->as_C_string());
TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package_name, CHECK);
PackageEntryTable* package_table = module_entry->loader()->packages();
assert(package_table != NULL, "Missing package_table");
bool pkg_exists = false;
{
MutexLocker ml(Module_lock, THREAD);
// Check that the package does not exist in the class loader's package table.
if (!package_table->lookup_only(pkg_symbol)) {
PackageEntry* pkg = package_table->locked_create_entry_or_null(pkg_symbol, module_entry);
assert(pkg != NULL, "Unable to create a module's package entry");
} else {
pkg_exists = true;
}
}
if (pkg_exists) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Package %s already exists for class loader", package_name));
}
}
// Export package in module to all unnamed modules.
void Modules::add_module_exports_to_all_unnamed(jobject module, jstring package, TRAPS) {
if (module == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"module is null");
}
if (package == NULL) {
THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"package is null");
}
ModuleEntry* module_entry = get_module_entry(module, CHECK);
if (module_entry == NULL) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"module is invalid");
}
if (module_entry->is_named()) { // No-op for unnamed module.
PackageEntry *package_entry = get_package_entry(module_entry, package, CHECK);
ResourceMark rm(THREAD);
if (package_entry == NULL) {
const char *package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Package %s not found in module %s",
package_name != NULL ? package_name : "",
module_entry->name()->as_C_string()));
}
if (package_entry->module() != module_entry) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
err_msg("Package: %s found in module %s, not in module: %s",
package_entry->name()->as_C_string(),
package_entry->module()->name()->as_C_string(),
module_entry->name()->as_C_string()));
}
log_debug(modules)("add_module_exports_to_all_unnamed(): package %s in module"
" %s is exported to all unnamed modules",
package_entry->name()->as_C_string(),
module_entry->name()->as_C_string());
// Mark package as exported to all unnamed modules, unless already
// unqualifiedly exported.
if (!package_entry->is_unqual_exported()) {
package_entry->set_is_exported_allUnnamed();
}
}
}

View File

@ -0,0 +1,151 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_CLASSFILE_MODULES_HPP
#define SHARE_VM_CLASSFILE_MODULES_HPP
#include "memory/allocation.hpp"
#include "runtime/handles.hpp"
class Symbol;
class Modules : AllStatic {
public:
// define_module defines a module containing the specified packages. It binds the
// module to its class loader by creating the ModuleEntry record in the
// ClassLoader's ModuleEntry table, and creates PackageEntry records in the class
// loader's PackageEntry table. As in JVM_DefineClass the jstring format for all
// package names must use "/" and not "."
//
// IllegalArgumentExceptions are thrown for the following :
// * Module's Class loader is not a subclass of java.lang.ClassLoader
// * Module's Class loader already has a module with that name
// * Module's Class loader has already defined types for any of the module's packages
// * Module_name is syntactically bad
// * Packages contains an illegal package name
// * Packages contains a duplicate package name
// * A package already exists in another module for this class loader
// * Module is an unnamed module
// NullPointerExceptions are thrown if module is null.
static void define_module(jobject module, jstring version,
jstring location, jobjectArray packages, TRAPS);
// Provides the java.lang.reflect.Module for the unnamed module defined
// to the boot loader.
//
// IllegalArgumentExceptions are thrown for the following :
// * Module has a name
// * Module is not a subclass of java.lang.reflect.Module
// * Module's class loader is not the boot loader
// NullPointerExceptions are thrown if module is null.
static void set_bootloader_unnamed_module(jobject module, TRAPS);
// This either does a qualified export of package in module from_module to module
// to_module or, if to_module is null, does an unqualified export of package.
// The format for the package name must use "/' not ".".
//
// Error conditions causing IlegalArgumentException to be throw :
// * Module from_module does not exist
// * Module to_module is not null and does not exist
// * Package is not syntactically correct
// * Package is not defined for from_module's class loader
// * Package is not in module from_module.
static void add_module_exports(jobject from_module, jstring package, jobject to_module, TRAPS);
// This does a qualified export of package in module from_module to module
// to_module. The format for the package name must use "/' not ".".
//
// Error conditions causing IlegalArgumentException to be throw :
// * Module from_module does not exist
// * Module to_module does not exist
// * Package is not syntactically correct
// * Package is not defined for from_module's class loader
// * Package is not in module from_module.
static void add_module_exports_qualified(jobject from_module, jstring package, jobject to_module, TRAPS);
// add_reads_module adds module to_module to the list of modules that from_module
// can read. If from_module is the same as to_module then this is a no-op.
// If to_module is null then from_module is marked as a loose module (meaning that
// from_module can read all current and future unnamed modules).
// An IllegalArgumentException is thrown if from_module is null or either (non-null)
// module does not exist.
static void add_reads_module(jobject from_module, jobject to_module, TRAPS);
// can_read_module returns TRUE if module asking_module can read module target_module,
// or if they are the same module, or if the asking_module is loose and target_module
// is null.
//
// Throws IllegalArgumentException if:
// * either asking_module or target_module is not a java.lang.reflect.Module
static jboolean can_read_module(jobject asking_module, jobject target_module, TRAPS);
// If package is valid then this returns TRUE if module from_module exports
// package to module to_module, if from_module and to_module are the same
// module, or if package is exported without qualification.
//
// IllegalArgumentException is throw if:
// * Either to_module or from_module does not exist
// * package is syntactically incorrect
// * package is not in from_module
static jboolean is_exported_to_module(jobject from_module, jstring package, jobject to_module, TRAPS);
// Return the java.lang.reflect.Module object for this class object.
static jobject get_module(jclass clazz, TRAPS);
// Return the java.lang.reflect.Module object for this class loader and package.
// Returns NULL if the class loader has not loaded any classes in the package.
// The package should contain /'s, not .'s, as in java/lang, not java.lang.
// NullPointerException is thrown if package is null.
// IllegalArgumentException is thrown if loader is neither null nor a subtype of
// java/lang/ClassLoader.
static jobject get_module_by_package_name(jobject loader, jstring package, TRAPS);
// If package is defined by loader, return the
// java.lang.reflect.Module object for the module in which the package is defined.
// Returns NULL if package is invalid or not defined by loader.
static jobject get_module(Symbol* package_name, Handle h_loader, TRAPS);
// This adds package to module.
// It throws IllegalArgumentException if:
// * Module is bad
// * Module is unnamed
// * Package is not syntactically correct
// * Package is already defined for module's class loader.
static void add_module_package(jobject module, jstring package, TRAPS);
// Marks the specified package as exported to all unnamed modules.
// If either module or package is null then NullPointerException is thrown.
// If module or package is bad, or module is unnamed, or package is not in
// module then IllegalArgumentException is thrown.
static void add_module_exports_to_all_unnamed(jobject module, jstring package, TRAPS);
// Return TRUE if package_name is syntactically valid, false otherwise.
static bool verify_package_name(char *package_name);
// Return TRUE iff package is defined by loader
static bool is_package_defined(Symbol* package_name, Handle h_loader, TRAPS);
};
#endif // SHARE_VM_CLASSFILE_MODULES_HPP

View File

@ -0,0 +1,322 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/packageEntry.hpp"
#include "memory/resourceArea.hpp"
#include "oops/symbol.hpp"
#include "runtime/handles.inline.hpp"
#include "trace/traceMacros.hpp"
#include "utilities/events.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/hashtable.inline.hpp"
// Return true if this package is exported to m.
bool PackageEntry::is_qexported_to(ModuleEntry* m) const {
assert(m != NULL, "No module to lookup in this package's qualified exports list");
MutexLocker m1(Module_lock);
if (!_is_exported) {
return false;
} else if (_is_exported_allUnnamed && !m->is_named()) {
return true;
} else if (_qualified_exports == NULL) {
return false;
} else {
return _qualified_exports->contains(m);
}
}
// Add a module to the package's qualified export list.
void PackageEntry::add_qexport(ModuleEntry* m) {
assert_locked_or_safepoint(Module_lock);
assert(_is_exported == true, "Adding a qualified export to a package that is not exported");
if (_qualified_exports == NULL) {
// Lazily create a package's qualified exports list.
// Initial size is small, do not anticipate export lists to be large.
_qualified_exports =
new (ResourceObj::C_HEAP, mtClass) GrowableArray<ModuleEntry*>(QUAL_EXP_SIZE, true);
}
_qualified_exports->append_if_missing(m);
}
// Set the package's exported state based on the value of the ModuleEntry.
void PackageEntry::set_exported(ModuleEntry* m) {
MutexLocker m1(Module_lock);
if (is_unqual_exported()) {
// An exception could be thrown, but choose to simply ignore.
// Illegal to convert an unqualified exported package to be qualifiedly exported
return;
}
if (m == NULL) {
// NULL indicates the package is being unqualifiedly exported
if (_is_exported && _qualified_exports != NULL) {
// Legit to transition a package from being qualifiedly exported
// to unqualified. Clean up the qualified lists at the next
// safepoint.
_exported_pending_delete = _qualified_exports;
}
// Mark package as unqualifiedly exported
set_unqual_exported();
} else {
// Add the exported module
_is_exported = true;
add_qexport(m);
}
}
// Remove dead module entries within the package's exported list.
void PackageEntry::purge_qualified_exports() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
if (_qualified_exports != NULL) {
// Go backwards because this removes entries that are dead.
int len = _qualified_exports->length();
for (int idx = len - 1; idx >= 0; idx--) {
ModuleEntry* module_idx = _qualified_exports->at(idx);
ClassLoaderData* cld = module_idx->loader();
if (cld->is_unloading()) {
_qualified_exports->delete_at(idx);
}
}
}
}
void PackageEntry::delete_qualified_exports() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
if (_exported_pending_delete != NULL) {
// If a transition occurred from qualified to unqualified, the _qualified_exports
// field should have been NULL'ed out.
assert(_qualified_exports == NULL, "Package's exported pending delete, exported list should not be active");
delete _exported_pending_delete;
}
if (_qualified_exports != NULL) {
delete _qualified_exports;
}
_exported_pending_delete = NULL;
_qualified_exports = NULL;
}
PackageEntryTable::PackageEntryTable(int table_size)
: Hashtable<Symbol*, mtClass>(table_size, sizeof(PackageEntry))
{
}
PackageEntryTable::~PackageEntryTable() {
assert_locked_or_safepoint(Module_lock);
// Walk through all buckets and all entries in each bucket,
// freeing each entry.
for (int i = 0; i < table_size(); ++i) {
for (PackageEntry* p = bucket(i); p != NULL;) {
PackageEntry* to_remove = p;
// read next before freeing.
p = p->next();
// Clean out the C heap allocated qualified exports list first before freeing the entry
to_remove->delete_qualified_exports();
to_remove->name()->decrement_refcount();
// Unlink from the Hashtable prior to freeing
unlink_entry(to_remove);
FREE_C_HEAP_ARRAY(char, to_remove);
}
}
assert(number_of_entries() == 0, "should have removed all entries");
assert(new_entry_free_list() == NULL, "entry present on PackageEntryTable's free list");
free_buckets();
}
PackageEntry* PackageEntryTable::new_entry(unsigned int hash, Symbol* name, ModuleEntry* module) {
assert_locked_or_safepoint(Module_lock);
PackageEntry* entry = (PackageEntry*) NEW_C_HEAP_ARRAY(char, entry_size(), mtClass);
// Initialize everything BasicHashtable would
entry->set_next(NULL);
entry->set_hash(hash);
entry->set_literal(name);
TRACE_INIT_PACKAGE_ID(entry);
// Initialize fields specific to a PackageEntry
entry->init();
entry->name()->increment_refcount();
if (!module->is_named()) {
// Set the exported state to true because all packages
// within the unnamed module are unqualifiedly exported
entry->set_exported(true);
}
entry->set_module(module);
return entry;
}
void PackageEntryTable::add_entry(int index, PackageEntry* new_entry) {
assert_locked_or_safepoint(Module_lock);
Hashtable<Symbol*, mtClass>::add_entry(index, (HashtableEntry<Symbol*, mtClass>*)new_entry);
}
// Create package in loader's package entry table and return the entry.
// If entry already exists, return null. Assume Module lock was taken by caller.
PackageEntry* PackageEntryTable::locked_create_entry_or_null(Symbol* name, ModuleEntry* module) {
assert_locked_or_safepoint(Module_lock);
// Check if package already exists. Return NULL if it does.
if (lookup_only(name) != NULL) {
return NULL;
} else {
PackageEntry* entry = new_entry(compute_hash(name), name, module);
add_entry(index_for(name), entry);
return entry;
}
}
PackageEntry* PackageEntryTable::lookup(Symbol* name, ModuleEntry* module) {
PackageEntry* p = lookup_only(name);
if (p != NULL) {
return p;
} else {
// If not found, add to table. Grab the PackageEntryTable lock first.
MutexLocker ml(Module_lock);
// Since look-up was done lock-free, we need to check if another thread beat
// us in the race to insert the package.
PackageEntry* test = lookup_only(name);
if (test != NULL) {
// A race occurred and another thread introduced the package.
return test;
} else {
assert(module != NULL, "module should never be null");
PackageEntry* entry = new_entry(compute_hash(name), name, module);
add_entry(index_for(name), entry);
return entry;
}
}
}
PackageEntry* PackageEntryTable::lookup_only(Symbol* name) {
int index = index_for(name);
for (PackageEntry* p = bucket(index); p != NULL; p = p->next()) {
if (p->name()->fast_compare(name) == 0) {
return p;
}
}
return NULL;
}
// Called when a define module for java.base is being processed.
// Verify the packages loaded thus far are in java.base's package list.
void PackageEntryTable::verify_javabase_packages(GrowableArray<Symbol*> *pkg_list) {
for (int i = 0; i < table_size(); i++) {
for (PackageEntry* entry = bucket(i);
entry != NULL;
entry = entry->next()) {
ModuleEntry* m = entry->module();
Symbol* module_name = (m == NULL ? NULL : m->name());
if (module_name != NULL &&
(module_name->fast_compare(vmSymbols::java_base()) == 0) &&
!pkg_list->contains(entry->name())) {
ResourceMark rm;
vm_exit_during_initialization("A non-java.base package was loaded prior to module system initialization", entry->name()->as_C_string());
}
}
}
}
// Remove dead entries from all packages' exported list
void PackageEntryTable::purge_all_package_exports() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
for (int i = 0; i < table_size(); i++) {
for (PackageEntry* entry = bucket(i);
entry != NULL;
entry = entry->next()) {
if (entry->exported_pending_delete()) {
// exported list is pending deletion due to a transition
// from qualified to unqualified
entry->delete_qualified_exports();
} else if (entry->is_qual_exported()) {
entry->purge_qualified_exports();
}
}
}
}
#ifndef PRODUCT
void PackageEntryTable::print() {
tty->print_cr("Package Entry Table (table_size=%d, entries=%d)",
table_size(), number_of_entries());
for (int i = 0; i < table_size(); i++) {
for (PackageEntry* probe = bucket(i);
probe != NULL;
probe = probe->next()) {
probe->print();
}
}
}
void PackageEntry::print() {
ResourceMark rm;
tty->print_cr("package entry "PTR_FORMAT" name %s module %s classpath_index "
INT32_FORMAT " is_exported %d is_exported_allUnnamed %d " "next "PTR_FORMAT,
p2i(this), name()->as_C_string(),
(module()->is_named() ? module()->name()->as_C_string() : UNNAMED_MODULE),
_classpath_index, _is_exported, _is_exported_allUnnamed, p2i(next()));
}
#endif
void PackageEntryTable::verify() {
int element_count = 0;
for (int index = 0; index < table_size(); index++) {
for (PackageEntry* probe = bucket(index);
probe != NULL;
probe = probe->next()) {
probe->verify();
element_count++;
}
}
guarantee(number_of_entries() == element_count,
"Verify of Package Entry Table failed");
debug_only(verify_lookup_length((double)number_of_entries() / table_size()));
}
void PackageEntry::verify() {
guarantee(name() != NULL, "A package entry must have a corresponding symbol name.");
}
// iteration of qualified exports
void PackageEntry::package_exports_do(ModuleClosure* const f) {
assert_locked_or_safepoint(Module_lock);
assert(f != NULL, "invariant");
if (is_qual_exported()) {
int qe_len = _qualified_exports->length();
for (int i = 0; i < qe_len; ++i) {
f->do_module(_qualified_exports->at(i));
}
}
}

View File

@ -0,0 +1,202 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_CLASSFILE_PACKAGEENTRY_HPP
#define SHARE_VM_CLASSFILE_PACKAGEENTRY_HPP
#include "classfile/moduleEntry.hpp"
#include "oops/symbol.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/hashtable.hpp"
// A PackageEntry basically represents a Java package. It contains:
// - Symbol* containing the package's name.
// - ModuleEntry* for this package's containing module.
// - a flag indicating if package is exported, either qualifiedly or
// unqualifiedly.
// - a flag indicating if this package is exported to all unnamed modules.
// - a growable array containing other module entries that this
// package is exported to.
//
// Packages that are:
// - not exported: _qualified_exports = NULL && _is_exported is false
// - qualified exports: (_qualified_exports != NULL || _is_exported_allUnnamed is true) && _is_exported is true
// - unqualified exports: (_qualified_exports = NULL && _is_exported_allUnnamed is false) && _is_exported is true
//
// The Mutex Module_lock is shared between ModuleEntry and PackageEntry, to lock either
// data structure.
class PackageEntry : public HashtableEntry<Symbol*, mtClass> {
private:
ModuleEntry* _module;
// Used to indicate for packages with classes loaded by the boot loader that
// a class in that package has been loaded. And, for packages with classes
// loaded by the boot loader from -Xbootclasspath/a in an unnamed module, it
// indicates from which class path entry.
s2 _classpath_index;
bool _is_exported;
bool _is_exported_allUnnamed;
GrowableArray<ModuleEntry*>* _exported_pending_delete; // transitioned from qualified to unqualified, delete at safepoint
GrowableArray<ModuleEntry*>* _qualified_exports;
TRACE_DEFINE_TRACE_ID_FIELD;
// Initial size of a package entry's list of qualified exports.
enum {QUAL_EXP_SIZE = 43};
public:
void init() {
_module = NULL;
_classpath_index = -1;
_is_exported = false;
_is_exported_allUnnamed = false;
_exported_pending_delete = NULL;
_qualified_exports = NULL;
}
// package name
Symbol* name() const { return literal(); }
void set_name(Symbol* n) { set_literal(n); }
// the module containing the package definition
ModuleEntry* module() const { return _module; }
void set_module(ModuleEntry* m) { _module = m; }
// package's export state
bool is_exported() const { return _is_exported; } // qualifiedly or unqualifiedly exported
bool is_qual_exported() const {
return (_is_exported && (_qualified_exports != NULL || _is_exported_allUnnamed));
}
bool is_unqual_exported() const {
return (_is_exported && (_qualified_exports == NULL && !_is_exported_allUnnamed));
}
void set_unqual_exported() {
_is_exported = true;
_is_exported_allUnnamed = false;
_qualified_exports = NULL;
}
bool exported_pending_delete() const { return (_exported_pending_delete != NULL); }
void set_exported(bool e) { _is_exported = e; }
void set_exported(ModuleEntry* m);
void set_is_exported_allUnnamed() {
if (!is_unqual_exported()) {
_is_exported_allUnnamed = true;
_is_exported = true;
}
}
bool is_exported_allUnnamed() const {
assert(_is_exported || !_is_exported_allUnnamed,
"is_allUnnamed set without is_exported being set");
return _is_exported_allUnnamed;
}
void set_classpath_index(s2 classpath_index) {
_classpath_index = classpath_index;
}
s2 classpath_index() const { return _classpath_index; }
bool has_loaded_class() const { return _classpath_index != -1; }
// returns true if the package is defined in the unnamed module
bool in_unnamed_module() const { return !_module->is_named(); }
// returns true if the package specifies m as a qualified export
bool is_qexported_to(ModuleEntry* m) const;
// add the module to the package's qualified exports
void add_qexport(ModuleEntry* m);
PackageEntry* next() const {
return (PackageEntry*)HashtableEntry<Symbol*, mtClass>::next();
}
PackageEntry** next_addr() {
return (PackageEntry**)HashtableEntry<Symbol*, mtClass>::next_addr();
}
// iteration of qualified exports
void package_exports_do(ModuleClosure* const f);
TRACE_DEFINE_TRACE_ID_METHODS;
// Purge dead weak references out of exported list when any given class loader is unloaded.
void purge_qualified_exports();
void delete_qualified_exports();
void print() PRODUCT_RETURN;
void verify();
};
// The PackageEntryTable is a Hashtable containing a list of all packages defined
// by a particular class loader. Each package is represented as a PackageEntry node.
// The PackageEntryTable's lookup is lock free.
//
class PackageEntryTable : public Hashtable<Symbol*, mtClass> {
friend class VMStructs;
public:
enum Constants {
_packagetable_entry_size = 1009 // number of entries in package entry table
};
private:
PackageEntry* new_entry(unsigned int hash, Symbol* name, ModuleEntry* module);
void add_entry(int index, PackageEntry* new_entry);
int entry_size() const { return BasicHashtable<mtClass>::entry_size(); }
PackageEntry** bucket_addr(int i) {
return (PackageEntry**)Hashtable<Symbol*, mtClass>::bucket_addr(i);
}
static unsigned int compute_hash(Symbol* name) { return (unsigned int)(name->identity_hash()); }
int index_for(Symbol* name) const { return hash_to_index(compute_hash(name)); }
public:
PackageEntryTable(int table_size);
~PackageEntryTable();
PackageEntry* bucket(int i) {
return (PackageEntry*)Hashtable<Symbol*, mtClass>::bucket(i);
}
// Create package in loader's package entry table and return the entry.
// If entry already exists, return null. Assume Module lock was taken by caller.
PackageEntry* locked_create_entry_or_null(Symbol* name, ModuleEntry* module);
// lookup Package with loader's package entry table, if not found add
PackageEntry* lookup(Symbol* name, ModuleEntry* module);
// Only lookup Package within loader's package entry table. The table read is lock-free.
PackageEntry* lookup_only(Symbol* Package);
void verify_javabase_packages(GrowableArray<Symbol*> *pkg_list);
// purge dead weak references out of exported list
void purge_all_package_exports();
void print() PRODUCT_RETURN;
void verify();
};
#endif // SHARE_VM_CLASSFILE_PACKAGEENTRY_HPP

View File

@ -77,7 +77,7 @@ void SharedPathsMiscInfo::print_path(int type, const char* path) {
outputStream* out = LogHandle(classpath)::info_stream();
switch (type) {
case BOOT:
out->print("Expecting -Dsun.boot.class.path=%s", path);
out->print("Expecting BOOT path=%s", path);
break;
case NON_EXIST:
out->print("Expecting that %s does not exist", path);
@ -126,7 +126,7 @@ bool SharedPathsMiscInfo::check(jint type, const char* path) {
switch (type) {
case BOOT:
if (os::file_name_strcmp(path, Arguments::get_sysclasspath()) != 0) {
return fail("[BOOT classpath mismatch, actual: -Dsun.boot.class.path=", Arguments::get_sysclasspath());
return fail("[BOOT classpath mismatch, actual =", Arguments::get_sysclasspath());
}
break;
case NON_EXIST: // fall-through

View File

@ -32,6 +32,7 @@
#include "classfile/javaClasses.inline.hpp"
#include "classfile/klassFactory.hpp"
#include "classfile/loaderConstraints.hpp"
#include "classfile/packageEntry.hpp"
#include "classfile/placeholders.hpp"
#include "classfile/resolutionErrors.hpp"
#include "classfile/stringTable.hpp"
@ -51,6 +52,7 @@
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "oops/typeArrayKlass.hpp"
#include "prims/jvmtiEnvBase.hpp"
#include "prims/methodHandles.hpp"
@ -172,13 +174,13 @@ bool SystemDictionary::is_parallelDefine(Handle class_loader) {
}
/**
* Returns true if the passed class loader is the extension class loader.
* Returns true if the passed class loader is the platform class loader.
*/
bool SystemDictionary::is_ext_class_loader(Handle class_loader) {
bool SystemDictionary::is_platform_class_loader(Handle class_loader) {
if (class_loader.is_null()) {
return false;
}
return (class_loader->klass()->name() == vmSymbols::sun_misc_Launcher_ExtClassLoader());
return (class_loader->klass() == SystemDictionary::jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass());
}
// ----------------------------------------------------------------------------
@ -1145,6 +1147,7 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name,
const char* pkg = "java/";
if (!HAS_PENDING_EXCEPTION &&
!class_loader.is_null() &&
!SystemDictionary::is_platform_class_loader(class_loader) &&
parsed_name != NULL &&
!strncmp((const char*)parsed_name->bytes(), pkg, strlen(pkg))) {
// It is illegal to define classes in the "java." package from
@ -1237,13 +1240,88 @@ instanceKlassHandle SystemDictionary::load_shared_class(
instanceKlassHandle ik (THREAD, find_shared_class(class_name));
// Make sure we only return the boot class for the NULL classloader.
if (ik.not_null() &&
SharedClassUtil::is_shared_boot_class(ik()) && class_loader.is_null()) {
ik->is_shared_boot_class() && class_loader.is_null()) {
Handle protection_domain;
return load_shared_class(ik, class_loader, protection_domain, THREAD);
}
return instanceKlassHandle();
}
// Check if a shared class can be loaded by the specific classloader:
//
// NULL classloader:
// - Module class from "modules" jimage. ModuleEntry must be defined in the classloader.
// - Class from -Xbootclasspath/a. The class has no defined PackageEntry, or must
// be defined in an unnamed module.
bool SystemDictionary::is_shared_class_visible(Symbol* class_name,
instanceKlassHandle ik,
Handle class_loader, TRAPS) {
int path_index = ik->shared_classpath_index();
SharedClassPathEntry* ent =
(SharedClassPathEntry*)FileMapInfo::shared_classpath(path_index);
if (!Universe::is_module_initialized()) {
assert(ent->is_jrt(),
"Loading non-bootstrap classes before the module system is initialized");
assert(class_loader.is_null(), "sanity");
return true;
}
// Get the pkg_entry from the classloader
TempNewSymbol pkg_name = NULL;
PackageEntry* pkg_entry = NULL;
ModuleEntry* mod_entry = NULL;
int length = 0;
ClassLoaderData* loader_data = class_loader_data(class_loader);
const jbyte* pkg_string = InstanceKlass::package_from_name(class_name, length);
if (pkg_string != NULL) {
pkg_name = SymbolTable::new_symbol((const char*)pkg_string,
length, CHECK_(false));
if (loader_data != NULL) {
pkg_entry = loader_data->packages()->lookup_only(pkg_name);
}
if (pkg_entry != NULL) {
mod_entry = pkg_entry->module();
}
}
if (class_loader.is_null()) {
// The NULL classloader can load archived class originated from the
// "modules" jimage and the -Xbootclasspath/a. For class from the
// "modules" jimage, the PackageEntry/ModuleEntry must be defined
// by the NULL classloader.
if (mod_entry != NULL) {
// PackageEntry/ModuleEntry is found in the classloader. Check if the
// ModuleEntry's location agrees with the archived class' origination.
if (ent->is_jrt() && mod_entry->location()->starts_with("jrt:")) {
return true; // Module class from the "module" jimage
}
}
// If the archived class is not from the "module" jimage, the class can be
// loaded by the NULL classloader if
//
// 1. the class is from the unamed package
// 2. or, the class is not from a module defined in the NULL classloader
// 3. or, the class is from an unamed module
if (!ent->is_jrt() && ik->is_shared_boot_class()) {
// the class is from the -Xbootclasspath/a
if (pkg_string == NULL ||
pkg_entry == NULL ||
pkg_entry->in_unnamed_module()) {
assert(mod_entry == NULL ||
mod_entry == loader_data->modules()->unnamed_module(),
"the unnamed module is not defined in the classloader");
return true;
}
}
return false;
} else {
bool res = SystemDictionaryShared::is_shared_class_visible_for_classloader(
ik, class_loader, pkg_string, pkg_name,
pkg_entry, mod_entry, CHECK_(false));
return res;
}
}
instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik,
Handle class_loader,
Handle protection_domain, TRAPS) {
@ -1251,6 +1329,12 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik,
instanceKlassHandle nh = instanceKlassHandle(); // null Handle
Symbol* class_name = ik->name();
bool visible = is_shared_class_visible(
class_name, ik, class_loader, CHECK_(nh));
if (!visible) {
return nh;
}
// Found the class, now load the superclass and interfaces. If they
// are shared, add them to the main system dictionary and reset
// their hierarchy references (supers, subs, and interfaces).
@ -1304,12 +1388,20 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik,
}
if (log_is_enabled(Info, classload)) {
ik()->print_loading_log(LogLevel::Info, loader_data, NULL);
ik()->print_loading_log(LogLevel::Info, loader_data, NULL, NULL);
}
// No 'else' here as logging levels are not mutually exclusive
if (log_is_enabled(Debug, classload)) {
ik()->print_loading_log(LogLevel::Debug, loader_data, NULL);
ik()->print_loading_log(LogLevel::Debug, loader_data, NULL, NULL);
}
// For boot loader, ensure that GetSystemPackage knows that a class in this
// package was loaded.
if (class_loader.is_null()) {
int path_index = ik->shared_classpath_index();
ResourceMark rm;
ClassLoader::add_package(ik->name()->as_C_string(), path_index, THREAD);
}
if (DumpLoadedClassList != NULL && classlist_file->is_open()) {
@ -1330,7 +1422,68 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik,
instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) {
instanceKlassHandle nh = instanceKlassHandle(); // null Handle
if (class_loader.is_null()) {
int length = 0;
PackageEntry* pkg_entry = NULL;
bool search_only_bootloader_append = false;
ClassLoaderData *loader_data = class_loader_data(class_loader);
// Find the package in the boot loader's package entry table.
const jbyte* pkg_string = InstanceKlass::package_from_name(class_name, length);
if (pkg_string != NULL) {
TempNewSymbol pkg_name = SymbolTable::new_symbol((const char*)pkg_string, length, CHECK_(nh));
pkg_entry = loader_data->packages()->lookup_only(pkg_name);
}
// Prior to attempting to load the class, enforce the boot loader's
// visibility boundaries.
if (!Universe::is_module_initialized()) {
// During bootstrapping, prior to module initialization, any
// class attempting to be loaded must be checked against the
// java.base packages in the boot loader's PackageEntryTable.
// No class outside of java.base is allowed to be loaded during
// this bootstrapping window.
if (!DumpSharedSpaces) {
if (pkg_entry == NULL || pkg_entry->in_unnamed_module()) {
// Class is either in the unnamed package or in
// a named package within the unnamed module. Either
// case is outside of java.base, do not attempt to
// load the class post java.base definition. If
// java.base has not been defined, let the class load
// and its package will be checked later by
// ModuleEntryTable::verify_javabase_packages.
if (ModuleEntryTable::javabase_defined()) {
return nh;
}
} else {
// Check that the class' package is defined within java.base.
ModuleEntry* mod_entry = pkg_entry->module();
Symbol* mod_entry_name = mod_entry->name();
if (mod_entry_name->fast_compare(vmSymbols::java_base()) != 0) {
return nh;
}
}
}
} else {
assert(!DumpSharedSpaces, "Archive dumped after module system initialization");
// After the module system has been initialized, check if the class'
// package is in a module defined to the boot loader.
if (pkg_string == NULL || pkg_entry == NULL || pkg_entry->in_unnamed_module()) {
// Class is either in the unnamed package, in a named package
// within a module not defined to the boot loader or in a
// a named package within the unnamed module. In all cases,
// limit visibility to search for the class only in the boot
// loader's append path.
search_only_bootloader_append = true;
}
}
// Prior to bootstrapping's module initialization, never load a class outside
// of the boot loader's module path
assert(Universe::is_module_initialized() || DumpSharedSpaces ||
!search_only_bootloader_append,
"Attempt to load a class outside of boot loader's module path");
// Search the shared system dictionary for classes preloaded into the
// shared spaces.
@ -1345,7 +1498,7 @@ instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Ha
if (k.is_null()) {
// Use VM class loader
PerfTraceTime vmtimer(ClassLoader::perf_sys_classload_time());
k = ClassLoader::load_class(class_name, CHECK_(nh));
k = ClassLoader::load_class(class_name, search_only_bootloader_append, CHECK_(nh));
}
// find_or_define_instance_class may return a different InstanceKlass
@ -1672,7 +1825,7 @@ Klass* SystemDictionary::find_class(Symbol* class_name, ClassLoaderData* loader_
}
// Get the next class in the diictionary.
// Get the next class in the dictionary.
Klass* SystemDictionary::try_get_next_class() {
return dictionary()->try_get_next_class();
}
@ -1943,6 +2096,11 @@ void SystemDictionary::initialize_wk_klasses_until(WKID limit_id, WKID &start_id
void SystemDictionary::initialize_preloaded_classes(TRAPS) {
assert(WK_KLASS(Object_klass) == NULL, "preloaded classes should only be initialized once");
// Create the ModuleEntry for java.base. This call needs to be done here,
// after vmSymbols::initialize() is called but before any classes are pre-loaded.
ClassLoader::create_javabase();
// Preload commonly used klasses
WKID scan = FIRST_WKID;
// first do Object, then String, Class

View File

@ -135,6 +135,7 @@ class SymbolPropertyTable;
do_klass(Properties_klass, java_util_Properties, Pre ) \
do_klass(reflect_AccessibleObject_klass, java_lang_reflect_AccessibleObject, Pre ) \
do_klass(reflect_Field_klass, java_lang_reflect_Field, Pre ) \
do_klass(reflect_Module_klass, java_lang_reflect_Module, Pre ) \
do_klass(reflect_Parameter_klass, java_lang_reflect_Parameter, Opt ) \
do_klass(reflect_Method_klass, java_lang_reflect_Method, Pre ) \
do_klass(reflect_Constructor_klass, java_lang_reflect_Constructor, Pre ) \
@ -167,15 +168,17 @@ class SymbolPropertyTable;
do_klass(StringBuffer_klass, java_lang_StringBuffer, Pre ) \
do_klass(StringBuilder_klass, java_lang_StringBuilder, Pre ) \
do_klass(internal_Unsafe_klass, jdk_internal_misc_Unsafe, Pre ) \
do_klass(module_Modules_klass, jdk_internal_module_Modules, Pre ) \
\
/* support for CDS */ \
do_klass(ByteArrayInputStream_klass, java_io_ByteArrayInputStream, Pre ) \
do_klass(File_klass, java_io_File, Pre ) \
do_klass(URLClassLoader_klass, java_net_URLClassLoader, Pre ) \
do_klass(URL_klass, java_net_URL, Pre ) \
do_klass(Jar_Manifest_klass, java_util_jar_Manifest, Pre ) \
do_klass(sun_misc_Launcher_klass, sun_misc_Launcher, Pre ) \
do_klass(jdk_internal_loader_ClassLoaders_AppClassLoader_klass, jdk_internal_loader_ClassLoaders_AppClassLoader, Pre ) \
do_klass(jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass, jdk_internal_loader_ClassLoaders_PlatformClassLoader, Pre ) \
do_klass(CodeSource_klass, java_security_CodeSource, Pre ) \
do_klass(ParseUtil_klass, sun_net_www_ParseUtil, Pre ) \
\
do_klass(StackTraceElement_klass, java_lang_StackTraceElement, Opt ) \
\
@ -639,6 +642,8 @@ protected:
static instanceKlassHandle find_or_define_instance_class(Symbol* class_name,
Handle class_loader,
instanceKlassHandle k, TRAPS);
static bool is_shared_class_visible(Symbol* class_name, instanceKlassHandle ik,
Handle class_loader, TRAPS);
static instanceKlassHandle load_shared_class(instanceKlassHandle ik,
Handle class_loader,
Handle protection_domain,
@ -653,7 +658,7 @@ public:
static instanceKlassHandle load_shared_class(Symbol* class_name,
Handle class_loader,
TRAPS);
static bool is_ext_class_loader(Handle class_loader);
static bool is_platform_class_loader(Handle class_loader);
protected:
static Klass* find_shared_class(Symbol* class_name);

View File

@ -44,6 +44,16 @@ public:
oop class_loader = loader_data->class_loader();
return (class_loader == NULL);
}
static bool is_shared_class_visible_for_classloader(
instanceKlassHandle ik,
Handle class_loader,
const jbyte* pkg_string,
Symbol* pkg_name,
PackageEntry* pkg_entry,
ModuleEntry* mod_entry,
TRAPS) {
return false;
}
static Klass* dump_time_resolve_super_or_fail(Symbol* child_name,
Symbol* class_name,

View File

@ -49,10 +49,12 @@
// Mapping function names to values. New entries should be added below.
#define VM_SYMBOLS_DO(template, do_alias) \
/* commonly used class names */ \
/* commonly used class, package, module names */ \
template(java_base, "java.base") \
template(java_lang_System, "java/lang/System") \
template(java_lang_Object, "java/lang/Object") \
template(java_lang_Class, "java/lang/Class") \
template(java_lang_Package, "java/lang/Package") \
template(java_lang_String, "java/lang/String") \
template(java_lang_StringLatin1, "java/lang/StringLatin1") \
template(java_lang_StringUTF16, "java/lang/StringUTF16") \
@ -87,6 +89,7 @@
template(java_lang_reflect_Method, "java/lang/reflect/Method") \
template(java_lang_reflect_Constructor, "java/lang/reflect/Constructor") \
template(java_lang_reflect_Field, "java/lang/reflect/Field") \
template(java_lang_reflect_Module, "java/lang/reflect/Module") \
template(java_lang_reflect_Parameter, "java/lang/reflect/Parameter") \
template(java_lang_reflect_Array, "java/lang/reflect/Array") \
template(java_lang_StringBuffer, "java/lang/StringBuffer") \
@ -97,7 +100,6 @@
template(java_security_CodeSource, "java/security/CodeSource") \
template(java_security_ProtectionDomain, "java/security/ProtectionDomain") \
template(java_security_SecureClassLoader, "java/security/SecureClassLoader") \
template(java_net_URLClassLoader, "java/net/URLClassLoader") \
template(java_net_URL, "java/net/URL") \
template(java_util_jar_Manifest, "java/util/jar/Manifest") \
template(impliesCreateAccessControlContext_name, "impliesCreateAccessControlContext") \
@ -116,17 +118,25 @@
template(java_util_Hashtable, "java/util/Hashtable") \
template(java_lang_Compiler, "java/lang/Compiler") \
template(jdk_internal_misc_Signal, "jdk/internal/misc/Signal") \
template(sun_misc_Launcher, "sun/misc/Launcher") \
template(java_lang_AssertionStatusDirectives, "java/lang/AssertionStatusDirectives") \
template(getBootClassPathEntryForClass_name, "getBootClassPathEntryForClass") \
template(sun_misc_PostVMInitHook, "sun/misc/PostVMInitHook") \
template(sun_misc_Launcher_ExtClassLoader, "sun/misc/Launcher$ExtClassLoader") \
template(sun_net_www_ParseUtil, "sun/net/www/ParseUtil") \
\
template(jdk_internal_loader_ClassLoaders_AppClassLoader, "jdk/internal/loader/ClassLoaders$AppClassLoader") \
template(jdk_internal_loader_ClassLoaders_PlatformClassLoader, "jdk/internal/loader/ClassLoaders$PlatformClassLoader") \
\
/* Java runtime version access */ \
template(java_lang_VersionProps, "java/lang/VersionProps") \
template(java_runtime_name_name, "java_runtime_name") \
template(java_runtime_version_name, "java_runtime_version") \
\
/* system initialization */ \
template(initPhase1_name, "initPhase1") \
template(initPhase2_name, "initPhase2") \
template(initPhase3_name, "initPhase3") \
template(java_lang_reflect_module_init_signature, "(Ljava/lang/ClassLoader;Ljava/lang/String;)V") \
\
/* class file format tags */ \
template(tag_source_file, "SourceFile") \
template(tag_inner_classes, "InnerClasses") \
@ -360,7 +370,6 @@
template(run_finalization_name, "runFinalization") \
template(run_finalizers_on_exit_name, "runFinalizersOnExit") \
template(dispatchUncaughtException_name, "dispatchUncaughtException") \
template(initializeSystemClass_name, "initializeSystemClass") \
template(loadClass_name, "loadClass") \
template(loadClassInternal_name, "loadClassInternal") \
template(get_name, "get") \
@ -447,14 +456,22 @@
template(signers_name, "signers_name") \
template(loader_data_name, "loader_data") \
template(vmdependencies_name, "vmdependencies") \
template(loader_name, "loader") \
template(module_name, "module") \
template(getModule_name, "getModule") \
template(addReads_name, "addReads") \
template(addReads_signature, "(Ljava/lang/reflect/Module;Ljava/lang/reflect/Module;)V") \
template(input_stream_void_signature, "(Ljava/io/InputStream;)V") \
template(getFileURL_name, "getFileURL") \
template(getFileURL_signature, "(Ljava/io/File;)Ljava/net/URL;") \
template(definePackageInternal_name, "definePackageInternal") \
template(definePackageInternal_signature, "(Ljava/lang/String;Ljava/util/jar/Manifest;Ljava/net/URL;)V") \
template(definePackage_name, "definePackage") \
template(definePackage_signature, "(Ljava/lang/String;Ljava/lang/reflect/Module;)Ljava/lang/Package;") \
template(defineOrCheckPackage_name, "defineOrCheckPackage") \
template(defineOrCheckPackage_signature, "(Ljava/lang/String;Ljava/util/jar/Manifest;Ljava/net/URL;)Ljava/lang/Package;") \
template(fileToEncodedURL_name, "fileToEncodedURL") \
template(fileToEncodedURL_signature, "(Ljava/io/File;)Ljava/net/URL;") \
template(getProtectionDomain_name, "getProtectionDomain") \
template(getProtectionDomain_signature, "(Ljava/security/CodeSource;)Ljava/security/ProtectionDomain;") \
template(url_code_signer_array_void_signature, "(Ljava/net/URL;[Ljava/security/CodeSigner;)V") \
template(module_entry_name, "module_entry") \
\
/* non-intrinsic name/signature pairs: */ \
template(register_method_name, "register") \
@ -532,6 +549,7 @@
template(void_class_signature, "()Ljava/lang/Class;") \
template(void_class_array_signature, "()[Ljava/lang/Class;") \
template(void_string_signature, "()Ljava/lang/String;") \
template(void_module_signature, "()Ljava/lang/reflect/Module;") \
template(object_array_object_signature, "([Ljava/lang/Object;)Ljava/lang/Object;") \
template(object_object_array_object_signature, "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")\
template(exception_void_signature, "(Ljava/lang/Exception;)V") \
@ -551,6 +569,7 @@
template(reference_signature, "Ljava/lang/ref/Reference;") \
template(sun_misc_Cleaner_signature, "Lsun/misc/Cleaner;") \
template(executable_signature, "Ljava/lang/reflect/Executable;") \
template(module_signature, "Ljava/lang/reflect/Module;") \
template(concurrenthashmap_signature, "Ljava/util/concurrent/ConcurrentHashMap;") \
template(String_StringBuilder_signature, "(Ljava/lang/String;)Ljava/lang/StringBuilder;") \
template(int_StringBuilder_signature, "(I)Ljava/lang/StringBuilder;") \
@ -575,6 +594,9 @@
/* used to identify class loaders handling parallel class loading */ \
template(parallelCapable_name, "parallelLockMap") \
\
/* used to return a class loader's unnamed module */ \
template(unnamedModule_name, "unnamedModule") \
\
/* JVM monitoring and management support */ \
template(java_lang_StackTraceElement_array, "[Ljava/lang/StackTraceElement;") \
template(java_lang_management_ThreadState, "java/lang/management/ThreadState") \
@ -633,7 +655,10 @@
template(addThreadDumpForSynchronizers_signature, "(Ljava/lang/management/ThreadInfo;[Ljava/lang/Object;)V") \
\
/* JVMTI/java.lang.instrument support and VM Attach mechanism */ \
template(jdk_internal_module_Modules, "jdk/internal/module/Modules") \
template(sun_misc_VMSupport, "sun/misc/VMSupport") \
template(transformedByAgent_name, "transformedByAgent") \
template(transformedByAgent_signature, "(Ljava/lang/reflect/Module;)V") \
template(appendToClassPathForInstrumentation_name, "appendToClassPathForInstrumentation") \
do_alias(appendToClassPathForInstrumentation_signature, string_void_signature) \
template(serializePropertiesToByteArray_name, "serializePropertiesToByteArray") \
@ -1065,11 +1090,6 @@
do_name( isCompileConstant_name, "isCompileConstant") \
do_alias( isCompileConstant_signature, object_boolean_signature) \
\
do_class(sun_hotspot_WhiteBox, "sun/hotspot/WhiteBox") \
do_intrinsic(_deoptimize, sun_hotspot_WhiteBox, deoptimize_name, deoptimize_signature, F_R) \
do_name( deoptimize_name, "deoptimize") \
do_alias( deoptimize_signature, void_method_signature) \
\
/* unsafe memory references (there are a lot of them...) */ \
do_signature(getObject_signature, "(Ljava/lang/Object;J)Ljava/lang/Object;") \
do_signature(putObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;)V") \

View File

@ -369,7 +369,6 @@ void DebugInformationRecorder::describe_scope(int pc_offset,
assert(method == NULL ||
(method->is_native() && bci == 0) ||
(!method->is_native() && 0 <= bci && bci < method->code_size()) ||
(method->is_compiled_lambda_form() && bci == -99) || // this might happen in C1
bci == -1, "illegal bci");
// serialize the locals/expressions/monitors

View File

@ -840,12 +840,8 @@ void CompileBroker::compile_method_base(const methodHandle& method,
const methodHandle& hot_method,
int hot_count,
const char* comment,
bool blocking,
Thread* thread) {
// do nothing if compiler thread(s) is not available
if (!_initialized) {
return;
}
guarantee(!method->is_abstract(), "cannot compile abstract methods");
assert(method->method_holder()->is_instance_klass(),
"sanity check");
@ -918,7 +914,6 @@ void CompileBroker::compile_method_base(const methodHandle& method,
// Outputs from the following MutexLocker block:
CompileTask* task = NULL;
bool blocking = false;
CompileQueue* queue = compile_queue(comp_level);
// Acquire our lock.
@ -948,9 +943,6 @@ void CompileBroker::compile_method_base(const methodHandle& method,
return;
}
// Should this thread wait for completion of the compile?
blocking = is_compile_blocking();
#if INCLUDE_JVMCI
if (UseJVMCICompiler) {
if (blocking) {
@ -1036,11 +1028,28 @@ void CompileBroker::compile_method_base(const methodHandle& method,
}
}
nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci,
int comp_level,
const methodHandle& hot_method, int hot_count,
const char* comment, Thread* THREAD) {
// do nothing if compilebroker is not available
if (!_initialized) {
return NULL;
}
AbstractCompiler *comp = CompileBroker::compiler(comp_level);
assert(comp != NULL, "Ensure we don't compile before compilebroker init");
DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, comp);
nmethod* nm = CompileBroker::compile_method(method, osr_bci, comp_level, hot_method, hot_count, comment, directive, THREAD);
DirectivesStack::release(directive);
return nm;
}
nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci,
int comp_level,
const methodHandle& hot_method, int hot_count,
const char* comment, DirectiveSet* directive,
Thread* THREAD) {
// make sure arguments make sense
assert(method->method_holder()->is_instance_klass(), "not an instance method");
assert(osr_bci == InvocationEntryBci || (0 <= osr_bci && osr_bci < method->code_size()), "bci out of range");
@ -1053,8 +1062,8 @@ nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci,
// lock, make sure that the compilation
// isn't prohibited in a straightforward way.
AbstractCompiler *comp = CompileBroker::compiler(comp_level);
if (comp == NULL || !comp->can_compile_method(method) ||
compilation_is_prohibited(method, osr_bci, comp_level)) {
if (!comp->can_compile_method(method) ||
compilation_is_prohibited(method, osr_bci, comp_level, directive->ExcludeOption)) {
return NULL;
}
@ -1162,7 +1171,7 @@ nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci,
CompilationPolicy::policy()->delay_compilation(method());
return NULL;
}
compile_method_base(method, osr_bci, comp_level, hot_method, hot_count, comment, THREAD);
compile_method_base(method, osr_bci, comp_level, hot_method, hot_count, comment, !directive->BackgroundCompilationOption, THREAD);
}
// return requested nmethod
@ -1219,7 +1228,7 @@ bool CompileBroker::compilation_is_in_queue(const methodHandle& method) {
// CompileBroker::compilation_is_prohibited
//
// See if this compilation is not allowed.
bool CompileBroker::compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level) {
bool CompileBroker::compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level, bool excluded) {
bool is_native = method->is_native();
// Some compilers may not support the compilation of natives.
AbstractCompiler *comp = compiler(comp_level);
@ -1237,11 +1246,6 @@ bool CompileBroker::compilation_is_prohibited(const methodHandle& method, int os
return true;
}
// Breaking the abstraction - directives are only used inside a compilation otherwise.
DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, comp);
bool excluded = directive->ExcludeOption;
DirectivesStack::release(directive);
// The method may be explicitly excluded by the user.
double scale;
if (excluded || (CompilerOracle::has_option_value(method, "CompileThresholdScaling", scale) && scale == 0)) {
@ -1306,16 +1310,6 @@ uint CompileBroker::assign_compile_id_unlocked(Thread* thread, const methodHandl
return assign_compile_id(method, osr_bci);
}
/**
* Should the current thread block until this compilation request
* has been fulfilled?
*/
bool CompileBroker::is_compile_blocking() {
assert(!ReferencePendingListLocker::is_locked_by_self(), "possible deadlock");
return !BackgroundCompilation;
}
// ------------------------------------------------------------------
// CompileBroker::preload_classes
void CompileBroker::preload_classes(const methodHandle& method, TRAPS) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -222,8 +222,7 @@ class CompileBroker: AllStatic {
static JavaThread* make_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, AbstractCompiler* comp, bool compiler_thread, TRAPS);
static void init_compiler_sweeper_threads(int c1_compiler_count, int c2_compiler_count);
static bool compilation_is_complete (const methodHandle& method, int osr_bci, int comp_level);
static bool compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level);
static bool is_compile_blocking();
static bool compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level, bool excluded);
static void preload_classes (const methodHandle& method, TRAPS);
static CompileTask* create_compile_task(CompileQueue* queue,
@ -253,6 +252,7 @@ class CompileBroker: AllStatic {
const methodHandle& hot_method,
int hot_count,
const char* comment,
bool blocking,
Thread* thread);
static CompileQueue* compile_queue(int comp_level);
@ -291,6 +291,15 @@ public:
int hot_count,
const char* comment, Thread* thread);
static nmethod* compile_method(const methodHandle& method,
int osr_bci,
int comp_level,
const methodHandle& hot_method,
int hot_count,
const char* comment,
DirectiveSet* directive,
Thread* thread);
// Acquire any needed locks and assign a compile id
static uint assign_compile_id_unlocked(Thread* thread, const methodHandle& method, int osr_bci);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -472,9 +472,12 @@ void DirectivesStack::push(CompilerDirectives* directive) {
_depth++;
}
void DirectivesStack::pop() {
void DirectivesStack::pop(int count) {
MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
pop_inner();
assert(count > -1, "No negative values");
for (int i = 0; i < count; i++) {
pop_inner();
}
}
void DirectivesStack::pop_inner() {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -42,6 +42,7 @@
cflags(PrintAssembly, bool, PrintAssembly, PrintAssembly) \
cflags(PrintInlining, bool, PrintInlining, PrintInlining) \
cflags(PrintNMethods, bool, PrintNMethods, PrintNMethods) \
cflags(BackgroundCompilation, bool, BackgroundCompilation, BackgroundCompilation) \
cflags(ReplayInline, bool, false, ReplayInline) \
cflags(DumpReplay, bool, false, DumpReplay) \
cflags(DumpInline, bool, false, DumpInline) \
@ -87,7 +88,7 @@ public:
static DirectiveSet* getMatchingDirective(methodHandle mh, AbstractCompiler* comp);
static DirectiveSet* getDefaultDirective(AbstractCompiler* comp);
static void push(CompilerDirectives* directive);
static void pop();
static void pop(int count);
static bool check_capacity(int request_size, outputStream* st);
static void clear();
static void print(outputStream* st);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -55,7 +55,7 @@ void DirectivesParser::clean_tmp() {
assert(_tmp_depth == 0, "Consistency");
}
bool DirectivesParser::parse_string(const char* text, outputStream* st) {
int DirectivesParser::parse_string(const char* text, outputStream* st) {
DirectivesParser cd(text, st);
if (cd.valid()) {
return cd.install_directives();
@ -63,7 +63,7 @@ bool DirectivesParser::parse_string(const char* text, outputStream* st) {
cd.clean_tmp();
st->flush();
st->print_cr("Parsing of compiler directives failed");
return false;
return -1;
}
}
@ -97,17 +97,17 @@ bool DirectivesParser::parse_from_file_inner(const char* filename, outputStream*
buffer[num_read] = '\0';
// close file
os::close(file_handle);
return parse_string(buffer, stream);
return parse_string(buffer, stream) > 0;
}
}
return false;
}
bool DirectivesParser::install_directives() {
int DirectivesParser::install_directives() {
// Check limit
if (!DirectivesStack::check_capacity(_tmp_depth, _st)) {
clean_tmp();
return false;
return 0;
}
// Pop from internal temporary stack and push to compileBroker.
@ -120,14 +120,14 @@ bool DirectivesParser::install_directives() {
}
if (i == 0) {
_st->print_cr("No directives in file");
return false;
return 0;
} else {
_st->print_cr("%i compiler directives added", i);
if (CompilerDirectivesPrint) {
// Print entire directives stack after new has been pushed.
DirectivesStack::print(_st);
}
return true;
return i;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -51,8 +51,8 @@ public:
static bool has_file();
static bool parse_from_flag();
static bool parse_from_file(const char* filename, outputStream* st);
static bool parse_string(const char* string, outputStream* st);
bool install_directives();
static int parse_string(const char* string, outputStream* st);
int install_directives();
private:
DirectivesParser(const char* text, outputStream* st);

View File

@ -2258,10 +2258,8 @@ run:
// Decrement counter at checkcast.
BI_PROFILE_SUBTYPECHECK_FAILED(objKlass);
ResourceMark rm(THREAD);
const char* objName = objKlass->external_name();
const char* klassName = klassOf->external_name();
char* message = SharedRuntime::generate_class_cast_message(
objName, klassName);
objKlass, klassOf);
VM_JAVA_ERROR(vmSymbols::java_lang_ClassCastException(), message, note_classCheck_trap);
}
// Profile checkcast with null_seen and receiver.

View File

@ -381,7 +381,7 @@ IRT_ENTRY(void, InterpreterRuntime::throw_ClassCastException(
ResourceMark rm(thread);
char* message = SharedRuntime::generate_class_cast_message(
thread, obj->klass()->external_name());
thread, obj->klass());
if (ProfileTraps) {
note_trap(thread, Deoptimization::Reason_class_check, CHECK);

View File

@ -273,18 +273,25 @@ void LinkInfo::print() {
// Klass resolution
void LinkResolver::check_klass_accessability(KlassHandle ref_klass, KlassHandle sel_klass, TRAPS) {
if (!Reflection::verify_class_access(ref_klass(),
sel_klass(),
true)) {
Reflection::VerifyClassAccessResults vca_result =
Reflection::verify_class_access(ref_klass(), sel_klass(), true);
if (vca_result != Reflection::ACCESS_OK) {
ResourceMark rm(THREAD);
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_IllegalAccessError(),
"tried to access class %s from class %s",
sel_klass->external_name(),
ref_klass->external_name()
);
return;
char* msg = Reflection::verify_class_access_msg(ref_klass(), sel_klass(), vca_result);
if (msg == NULL) {
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_IllegalAccessError(),
"failed to access class %s from class %s",
sel_klass->external_name(),
ref_klass->external_name());
} else {
// Use module specific message returned by verify_class_access_msg().
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_IllegalAccessError(),
"%s", msg);
}
}
}

View File

@ -162,6 +162,9 @@ void JVMCICompiler::compile_method(const methodHandle& method, int entry_bci, JV
CLEAR_PENDING_EXCEPTION;
java_lang_Throwable::java_printStackTrace(exception, THREAD);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
}
env->set_failure("exception throw", false);
} else {

View File

@ -77,7 +77,9 @@ bool JVMCIEnv::check_klass_accessibility(KlassHandle accessing_klass, KlassHandl
resolved_klass = ObjArrayKlass::cast(resolved_klass())->bottom_klass();
}
if (resolved_klass->is_instance_klass()) {
return Reflection::verify_class_access(accessing_klass(), resolved_klass(), true);
Reflection::VerifyClassAccessResults result =
Reflection::verify_class_access(accessing_klass(), resolved_klass(), true);
return result == Reflection::ACCESS_OK;
}
return true;
}

View File

@ -51,7 +51,6 @@
jobject JVMCIRuntime::_HotSpotJVMCIRuntime_instance = NULL;
bool JVMCIRuntime::_HotSpotJVMCIRuntime_initialized = false;
bool JVMCIRuntime::_well_known_classes_initialized = false;
const char* JVMCIRuntime::_compiler = NULL;
int JVMCIRuntime::_trivial_prefixes_count = 0;
char** JVMCIRuntime::_trivial_prefixes = NULL;
bool JVMCIRuntime::_shutdown_called = false;
@ -104,6 +103,7 @@ static void deopt_caller() {
JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_instance(JavaThread* thread, Klass* klass))
JRT_BLOCK;
assert(klass->is_klass(), "not a class");
Handle holder(THREAD, klass->klass_holder()); // keep the klass alive
instanceKlassHandle h(thread, klass);
h->check_valid_for_instantiation(true, CHECK);
// make sure klass is initialized
@ -129,6 +129,7 @@ JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_array(JavaThread* thread, Klass* array_k
BasicType elt_type = TypeArrayKlass::cast(array_klass)->element_type();
obj = oopFactory::new_typeArray(elt_type, length, CHECK);
} else {
Handle holder(THREAD, array_klass->klass_holder()); // keep the klass alive
Klass* elem_klass = ObjArrayKlass::cast(array_klass)->element_klass();
obj = oopFactory::new_objArray(elem_klass, length, CHECK);
}
@ -172,6 +173,7 @@ void JVMCIRuntime::new_store_pre_barrier(JavaThread* thread) {
JRT_ENTRY(void, JVMCIRuntime::new_multi_array(JavaThread* thread, Klass* klass, int rank, jint* dims))
assert(klass->is_klass(), "not a class");
assert(rank >= 1, "rank must be nonzero");
Handle holder(THREAD, klass->klass_holder()); // keep the klass alive
oop obj = ArrayKlass::cast(klass)->multi_allocate(rank, dims, CHECK);
thread->set_vm_result(obj);
JRT_END
@ -642,15 +644,6 @@ void JVMCIRuntime::initialize_HotSpotJVMCIRuntime(TRAPS) {
"HotSpotJVMCIRuntime initialization should only be triggered through JVMCI initialization");
#endif
if (_compiler != NULL) {
JavaCallArguments args;
oop compiler = java_lang_String::create_oop_from_str(_compiler, CHECK);
args.push_oop(compiler);
callStatic("jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig",
"selectCompiler",
"(Ljava/lang/String;)Ljava/lang/Boolean;", &args, CHECK);
}
Handle result = callStatic("jdk/vm/ci/hotspot/HotSpotJVMCIRuntime",
"runtime",
"()Ljdk/vm/ci/hotspot/HotSpotJVMCIRuntime;", NULL, CHECK);
@ -783,66 +776,6 @@ JVM_ENTRY(void, JVM_RegisterJVMCINatives(JNIEnv *env, jclass c2vmClass))
}
JVM_END
/**
* Closure for parsing a line from a *.properties file in jre/lib/jvmci/properties.
* The line must match the regular expression "[^=]+=.*". That is one or more
* characters other than '=' followed by '=' followed by zero or more characters.
* Everything before the '=' is the property name and everything after '=' is the value.
* Lines that start with '#' are treated as comments and ignored.
* No special processing of whitespace or any escape characters is performed.
* The last definition of a property "wins" (i.e., it overrides all earlier
* definitions of the property).
*/
class JVMCIPropertiesFileClosure : public ParseClosure {
SystemProperty** _plist;
public:
JVMCIPropertiesFileClosure(SystemProperty** plist) : _plist(plist) {}
void do_line(char* line) {
if (line[0] == '#') {
// skip comment
return;
}
size_t len = strlen(line);
char* sep = strchr(line, '=');
if (sep == NULL) {
warn_and_abort("invalid format: could not find '=' character");
return;
}
if (sep == line) {
warn_and_abort("invalid format: name cannot be empty");
return;
}
*sep = '\0';
const char* name = line;
char* value = sep + 1;
Arguments::PropertyList_unique_add(_plist, name, value);
}
};
void JVMCIRuntime::init_system_properties(SystemProperty** plist) {
char jvmciDir[JVM_MAXPATHLEN];
const char* fileSep = os::file_separator();
jio_snprintf(jvmciDir, sizeof(jvmciDir), "%s%slib%sjvmci",
Arguments::get_java_home(), fileSep, fileSep, fileSep);
DIR* dir = os::opendir(jvmciDir);
if (dir != NULL) {
struct dirent *entry;
char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(jvmciDir), mtInternal);
JVMCIPropertiesFileClosure closure(plist);
const unsigned suffix_len = (unsigned)strlen(".properties");
while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL && !closure.is_aborted()) {
const char* name = entry->d_name;
if (strlen(name) > suffix_len && strcmp(name + strlen(name) - suffix_len, ".properties") == 0) {
char propertiesFilePath[JVM_MAXPATHLEN];
jio_snprintf(propertiesFilePath, sizeof(propertiesFilePath), "%s%s%s",jvmciDir, fileSep, name);
JVMCIRuntime::parse_lines(propertiesFilePath, &closure, false);
}
}
FREE_C_HEAP_ARRAY(char, dbuf);
os::closedir(dir);
}
}
#define CHECK_WARN_ABORT_(message) THREAD); \
if (HAS_PENDING_EXCEPTION) { \
warning(message); \
@ -853,12 +786,6 @@ void JVMCIRuntime::init_system_properties(SystemProperty** plist) {
} \
(void)(0
void JVMCIRuntime::save_compiler(const char* compiler) {
assert(compiler != NULL, "npe");
assert(_compiler == NULL, "cannot reassign JVMCI compiler");
_compiler = compiler;
}
void JVMCIRuntime::shutdown(TRAPS) {
if (_HotSpotJVMCIRuntime_instance != NULL) {
_shutdown_called = true;
@ -884,69 +811,3 @@ bool JVMCIRuntime::treat_as_trivial(Method* method) {
}
return false;
}
void JVMCIRuntime::parse_lines(char* path, ParseClosure* closure, bool warnStatFailure) {
struct stat st;
if (::stat(path, &st) == 0 && (st.st_mode & S_IFREG) == S_IFREG) { // exists & is regular file
int file_handle = ::open(path, os::default_file_open_flags(), 0);
if (file_handle != -1) {
char* buffer = NEW_C_HEAP_ARRAY(char, st.st_size + 1, mtInternal);
int num_read;
num_read = (int) ::read(file_handle, (char*) buffer, st.st_size);
if (num_read == -1) {
warning("Error reading file %s due to %s", path, strerror(errno));
} else if (num_read != st.st_size) {
warning("Only read %d of " SIZE_FORMAT " bytes from %s", num_read, (size_t) st.st_size, path);
}
::close(file_handle);
closure->set_filename(path);
if (num_read == st.st_size) {
buffer[num_read] = '\0';
char* line = buffer;
while (line - buffer < num_read && !closure->is_aborted()) {
// find line end (\r, \n or \r\n)
char* nextline = NULL;
char* cr = strchr(line, '\r');
char* lf = strchr(line, '\n');
if (cr != NULL && lf != NULL) {
char* min = MIN2(cr, lf);
*min = '\0';
if (lf == cr + 1) {
nextline = lf + 1;
} else {
nextline = min + 1;
}
} else if (cr != NULL) {
*cr = '\0';
nextline = cr + 1;
} else if (lf != NULL) {
*lf = '\0';
nextline = lf + 1;
}
// trim left
while (*line == ' ' || *line == '\t') line++;
char* end = line + strlen(line);
// trim right
while (end > line && (*(end -1) == ' ' || *(end -1) == '\t')) end--;
*end = '\0';
// skip comments and empty lines
if (*line != '#' && strlen(line) > 0) {
closure->parse_line(line);
}
if (nextline != NULL) {
line = nextline;
} else {
// File without newline at the end
break;
}
}
}
FREE_C_HEAP_ARRAY(char, buffer);
} else {
warning("Error opening file %s due to %s", path, strerror(errno));
}
} else if (warnStatFailure) {
warning("Could not stat file %s due to %s", path, strerror(errno));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -70,7 +70,6 @@ class JVMCIRuntime: public AllStatic {
static jobject _HotSpotJVMCIRuntime_instance;
static bool _HotSpotJVMCIRuntime_initialized;
static bool _well_known_classes_initialized;
static const char* _compiler;
static int _trivial_prefixes_count;
static char** _trivial_prefixes;
@ -85,19 +84,9 @@ class JVMCIRuntime: public AllStatic {
static Handle create_Service(const char* name, TRAPS);
public:
/**
* Parses *.properties files in jre/lib/jvmci/ and adds the properties to plist.
*/
static void init_system_properties(SystemProperty** plist);
/**
* Saves the value of the "jvmci.compiler" system property for processing
* when JVMCI is initialized.
*/
static void save_compiler(const char* compiler);
static bool is_HotSpotJVMCIRuntime_initialized() { return _HotSpotJVMCIRuntime_initialized; }
static bool is_HotSpotJVMCIRuntime_initialized() {
return _HotSpotJVMCIRuntime_initialized;
}
/**
* Gets the singleton HotSpotJVMCIRuntime instance, initializing it if necessary
@ -136,7 +125,6 @@ class JVMCIRuntime: public AllStatic {
}
static bool treat_as_trivial(Method* method);
static void parse_lines(char* path, ParseClosure* closure, bool warnStatFailure);
static BasicType kindToBasicType(Handle kind, TRAPS);

View File

@ -63,6 +63,7 @@
LOG_TAG(logging) \
LOG_TAG(marking) \
LOG_TAG(metaspace) \
LOG_TAG(modules) \
LOG_TAG(monitorinflation) \
LOG_TAG(os) \
LOG_TAG(phases) \

View File

@ -226,12 +226,21 @@ void FileMapInfo::allocate_classpath_entry_table() {
SharedClassUtil::update_shared_classpath(cpe, ent, st.st_mtime, st.st_size, THREAD);
} else {
struct stat st;
if ((os::stat(name, &st) == 0) && ((st.st_mode & S_IFDIR) == S_IFDIR)) {
if (!os::dir_is_empty(name)) {
ClassLoader::exit_with_path_failure("Cannot have non-empty directory in archived classpaths", name);
if (os::stat(name, &st) == 0) {
if (cpe->is_jrt()) {
// it's the "modules" jimage
ent->_timestamp = st.st_mtime;
ent->_filesize = st.st_size;
} else if ((st.st_mode & S_IFDIR) == S_IFDIR) {
if (!os::dir_is_empty(name)) {
ClassLoader::exit_with_path_failure(
"Cannot have non-empty directory in archived classpaths", name);
}
ent->_filesize = -1;
}
ent->_filesize = -1;
} else {
}
if (ent->_filesize == 0) {
// unknown
ent->_filesize = -2;
}
}
@ -282,7 +291,7 @@ bool FileMapInfo::validate_classpath_entry_table() {
fail_continue("directory is not empty: %s", name);
ok = false;
}
} else if (ent->is_jar()) {
} else if (ent->is_jar_or_bootimage()) {
if (ent->_timestamp != st.st_mtime ||
ent->_filesize != st.st_size) {
ok = false;
@ -291,7 +300,7 @@ bool FileMapInfo::validate_classpath_entry_table() {
"Timestamp mismatch" :
"File size mismatch");
} else {
fail_continue("A jar file is not the one used while building"
fail_continue("A jar/jimage file is not the one used while building"
" the shared archive file: %s", name);
}
}
@ -871,6 +880,11 @@ bool FileMapInfo::FileMapHeader::validate() {
return false;
}
if (Arguments::patch_dirs() != NULL) {
FileMapInfo::fail_continue("The shared archive file cannot be used with -Xpatch.");
return false;
}
if (_version != current_version()) {
FileMapInfo::fail_continue("The shared archive file is the wrong version.");
return false;

View File

@ -44,14 +44,20 @@ class Metaspace;
class SharedClassPathEntry VALUE_OBJ_CLASS_SPEC {
public:
const char *_name;
time_t _timestamp; // jar timestamp, 0 if is directory or other
long _filesize; // jar file size, -1 if is directory, -2 if other
bool is_jar() {
time_t _timestamp; // jar/jimage timestamp, 0 if is directory or other
long _filesize; // jar/jimage file size, -1 if is directory, -2 if other
// The _timestamp only gets set for jar files and "modules" jimage.
bool is_jar_or_bootimage() {
return _timestamp != 0;
}
bool is_dir() {
return _filesize == -1;
}
bool is_jrt() {
return ClassLoader::is_jrt(_name);
}
};
class FileMapInfo : public CHeapObj<mtInternal> {

View File

@ -603,14 +603,7 @@ void VM_PopulateDumpSharedSpace::doit() {
SystemDictionary::reverse();
SystemDictionary::copy_buckets(&md_top, md_end);
ClassLoader::verify();
ClassLoader::copy_package_info_buckets(&md_top, md_end);
ClassLoader::verify();
SystemDictionary::copy_table(&md_top, md_end);
ClassLoader::verify();
ClassLoader::copy_package_info_table(&md_top, md_end);
ClassLoader::verify();
// Write the other data to the output array.
WriteClosure wc(md_top, md_end);
@ -716,8 +709,7 @@ void VM_PopulateDumpSharedSpace::doit() {
}
void MetaspaceShared::link_one_shared_class(Klass* obj, TRAPS) {
Klass* k = obj;
void MetaspaceShared::link_one_shared_class(Klass* k, TRAPS) {
if (k->is_instance_klass()) {
InstanceKlass* ik = InstanceKlass::cast(k);
// Link the class to cause the bytecodes to be rewritten and the
@ -734,6 +726,16 @@ void MetaspaceShared::check_one_shared_class(Klass* k) {
}
}
void MetaspaceShared::check_shared_class_loader_type(Klass* k) {
if (k->is_instance_klass()) {
InstanceKlass* ik = InstanceKlass::cast(k);
u2 loader_type = ik->loader_type();
ResourceMark rm;
guarantee(loader_type != 0,
"Class loader type is not set for this class %s", ik->name()->as_C_string());
}
}
void MetaspaceShared::link_and_cleanup_shared_classes(TRAPS) {
// We need to iterate because verification may cause additional classes
// to be loaded.
@ -765,6 +767,7 @@ void MetaspaceShared::link_and_cleanup_shared_classes(TRAPS) {
}
void MetaspaceShared::prepare_for_dumping() {
Arguments::check_unsupported_dumping_properties();
ClassLoader::initialize_shared_path();
FileMapInfo::allocate_classpath_entry_table();
}
@ -901,7 +904,7 @@ bool MetaspaceShared::try_link_class(InstanceKlass* ik, TRAPS) {
assert(DumpSharedSpaces, "should only be called during dumping");
if (ik->init_state() < InstanceKlass::linked) {
bool saved = BytecodeVerificationLocal;
if (!SharedClassUtil::is_shared_boot_class(ik)) {
if (!(ik->is_shared_boot_class())) {
// The verification decision is based on BytecodeVerificationRemote
// for non-system classes. Since we are using the NULL classloader
// to load non-system classes during dumping, we need to temporarily
@ -1089,36 +1092,14 @@ void MetaspaceShared::initialize_shared_spaces() {
number_of_entries);
buffer += sharedDictionaryLen;
// Create the package info table using the bucket array at this spot in
// the misc data space. Since the package info table is never
// modified, this region (of mapped pages) will be (effectively, if
// not explicitly) read-only.
int pkgInfoLen = *(intptr_t*)buffer;
buffer += sizeof(intptr_t);
number_of_entries = *(intptr_t*)buffer;
buffer += sizeof(intptr_t);
ClassLoader::create_package_info_table((HashtableBucket<mtClass>*)buffer, pkgInfoLen,
number_of_entries);
buffer += pkgInfoLen;
ClassLoader::verify();
// The following data in the shared misc data region are the linked
// list elements (HashtableEntry objects) for the shared dictionary
// and package info table.
// table.
int len = *(intptr_t*)buffer; // skip over shared dictionary entries
buffer += sizeof(intptr_t);
buffer += len;
len = *(intptr_t*)buffer; // skip over package info table entries
buffer += sizeof(intptr_t);
buffer += len;
len = *(intptr_t*)buffer; // skip over package info table char[] arrays.
buffer += sizeof(intptr_t);
buffer += len;
intptr_t* array = (intptr_t*)buffer;
ReadClosure rc(&array);
serialize(&rc);

View File

@ -208,6 +208,7 @@ class MetaspaceShared : AllStatic {
static bool try_link_class(InstanceKlass* ik, TRAPS);
static void link_one_shared_class(Klass* obj, TRAPS);
static void check_one_shared_class(Klass* obj);
static void check_shared_class_loader_type(Klass* obj);
static void link_and_cleanup_shared_classes(TRAPS);
static int count_class(const char* classlist_file);

View File

@ -154,6 +154,7 @@ uintptr_t Universe::_verify_oop_bits = (uintptr_t) -1;
int Universe::_base_vtable_size = 0;
bool Universe::_bootstrapping = false;
bool Universe::_module_initialized = false;
bool Universe::_fully_initialized = false;
size_t Universe::_heap_capacity_at_last_gc;
@ -665,7 +666,6 @@ jint universe_init() {
} else {
SymbolTable::create_table();
StringTable::create_table();
ClassLoader::create_package_info_table();
if (DumpSharedSpaces) {
MetaspaceShared::prepare_for_dumping();
@ -884,6 +884,10 @@ void universe2_init() {
Universe::genesis(CATCH);
}
// Set after initialization of the module runtime, call_initModuleRuntime
void universe_post_module_init() {
Universe::_module_initialized = true;
}
bool universe_post_init() {
assert(!is_init_completed(), "Error: initialization not yet completed!");

View File

@ -111,6 +111,7 @@ class Universe: AllStatic {
friend jint universe_init();
friend void universe2_init();
friend bool universe_post_init();
friend void universe_post_module_init();
private:
// Known classes in the VM
@ -205,6 +206,7 @@ class Universe: AllStatic {
// Initialization
static bool _bootstrapping; // true during genesis
static bool _module_initialized; // true after call_initPhase2 called
static bool _fully_initialized; // true after universe_init and initialize_vtables called
// the array of preallocated errors with backtraces
@ -436,6 +438,7 @@ class Universe: AllStatic {
// Testers
static bool is_bootstrapping() { return _bootstrapping; }
static bool is_module_initialized() { return _module_initialized; }
static bool is_fully_initialized() { return _fully_initialized; }
static inline bool element_type_should_be_aligned(BasicType type);

View File

@ -95,11 +95,18 @@ ArrayKlass::ArrayKlass(Symbol* name) :
// Initialization of vtables and mirror object is done separatly from base_create_array_klass,
// since a GC can happen. At this point all instance variables of the ArrayKlass must be setup.
void ArrayKlass::complete_create_array_klass(ArrayKlass* k, KlassHandle super_klass, TRAPS) {
void ArrayKlass::complete_create_array_klass(ArrayKlass* k, KlassHandle super_klass, ModuleEntry* module_entry, TRAPS) {
ResourceMark rm(THREAD);
k->initialize_supers(super_klass(), CHECK);
k->vtable()->initialize_vtable(false, CHECK);
java_lang_Class::create_mirror(k, Handle(THREAD, k->class_loader()), Handle(NULL), CHECK);
// During bootstrapping, before java.base is defined, the module_entry may not be present yet.
// These classes will be put on a fixup list and their module fields will be patched once
// java.base is defined.
assert((module_entry != NULL) || ((module_entry == NULL) && !ModuleEntryTable::javabase_defined()),
"module entry not available post java.base definition");
oop module = (module_entry != NULL) ? JNIHandles::resolve(module_entry->module()) : (oop)NULL;
java_lang_Class::create_mirror(k, Handle(THREAD, k->class_loader()), Handle(THREAD, module), Handle(NULL), CHECK);
}
GrowableArray<Klass*>* ArrayKlass::compute_secondary_supers(int num_extra_slots) {

View File

@ -113,7 +113,7 @@ class ArrayKlass: public Klass {
void array_klasses_do(void f(Klass* k, TRAPS), TRAPS);
// Return a handle.
static void complete_create_array_klass(ArrayKlass* k, KlassHandle super_klass, TRAPS);
static void complete_create_array_klass(ArrayKlass* k, KlassHandle super_klass, ModuleEntry* module, TRAPS);
// jvm support

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -1972,8 +1972,9 @@ static void restore_unshareable_in_class(Klass* k, TRAPS) {
}
void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
Klass::restore_unshareable_info(loader_data, protection_domain, CHECK);
instanceKlassHandle ik(THREAD, this);
ik->set_package(loader_data, CHECK);
Klass::restore_unshareable_info(loader_data, protection_domain, CHECK);
Array<Method*>* methods = ik->methods();
int num_methods = methods->length();
@ -2178,26 +2179,135 @@ const char* InstanceKlass::signature_name() const {
return dest;
}
// different verisons of is_same_class_package
bool InstanceKlass::is_same_class_package(const Klass* class2) const {
const Klass* const class1 = (const Klass* const)this;
oop classloader1 = InstanceKlass::cast(class1)->class_loader();
const Symbol* const classname1 = class1->name();
const jbyte* InstanceKlass::package_from_name(const Symbol* name, int& length) {
ResourceMark rm;
length = 0;
if (name == NULL) {
return NULL;
} else {
const jbyte* base_name = name->base();
const jbyte* last_slash = UTF8::strrchr(base_name, name->utf8_length(), '/');
if (last_slash == NULL) {
// No package name
return NULL;
} else {
// Skip over '['s
if (*base_name == '[') {
do {
base_name++;
} while (*base_name == '[');
if (*base_name != 'L') {
// Fully qualified class names should not contain a 'L'.
// Set length to -1 to indicate that the package name
// could not be obtained due to an error condition.
// In this situtation, is_same_class_package returns false.
length = -1;
return NULL;
}
}
// Found the package name, look it up in the symbol table.
length = last_slash - base_name;
assert(length > 0, "Bad length for package name");
return base_name;
}
}
}
ModuleEntry* InstanceKlass::module() const {
if (!in_unnamed_package()) {
return _package_entry->module();
}
const Klass* host = host_klass();
if (host == NULL) {
return class_loader_data()->modules()->unnamed_module();
}
return host->class_loader_data()->modules()->unnamed_module();
}
void InstanceKlass::set_package(ClassLoaderData* loader_data, TRAPS) {
int length = 0;
const jbyte* base_name = package_from_name(name(), length);
if (base_name != NULL && loader_data != NULL) {
TempNewSymbol pkg_name = SymbolTable::new_symbol((const char*)base_name, length, CHECK);
// Find in class loader's package entry table.
_package_entry = loader_data->packages()->lookup_only(pkg_name);
// If the package name is not found in the loader's package
// entry table, it is an indication that the package has not
// been defined. Consider it defined within the unnamed module.
if (_package_entry == NULL) {
ResourceMark rm;
if (!ModuleEntryTable::javabase_defined()) {
// Before java.base is defined during bootstrapping, define all packages in
// the java.base module. If a non-java.base package is erroneously placed
// in the java.base module it will be caught later when java.base
// is defined by ModuleEntryTable::verify_javabase_packages check.
assert(ModuleEntryTable::javabase_module() != NULL, "java.base module is NULL");
_package_entry = loader_data->packages()->lookup(pkg_name, ModuleEntryTable::javabase_module());
} else {
assert(loader_data->modules()->unnamed_module() != NULL, "unnamed module is NULL");
_package_entry = loader_data->packages()->lookup(pkg_name,
loader_data->modules()->unnamed_module());
}
// A package should have been successfully created
assert(_package_entry != NULL, "Package entry for class %s not found, loader %s",
name()->as_C_string(), loader_data->loader_name());
}
if (log_is_enabled(Debug, modules)) {
ResourceMark rm;
ModuleEntry* m = _package_entry->module();
log_trace(modules)("Setting package: class: %s, package: %s, loader: %s, module: %s",
external_name(),
pkg_name->as_C_string(),
loader_data->loader_name(),
(m->is_named() ? m->name()->as_C_string() : UNNAMED_MODULE));
}
} else {
ResourceMark rm;
log_trace(modules)("Setting package: class: %s, package: unnamed, loader: %s, module: %s",
external_name(),
(loader_data != NULL) ? loader_data->loader_name() : "NULL",
UNNAMED_MODULE);
}
}
// different versions of is_same_class_package
bool InstanceKlass::is_same_class_package(const Klass* class2) const {
oop classloader1 = this->class_loader();
PackageEntry* classpkg1 = this->package();
if (class2->is_objArray_klass()) {
class2 = ObjArrayKlass::cast(class2)->bottom_klass();
}
oop classloader2;
PackageEntry* classpkg2;
if (class2->is_instance_klass()) {
classloader2 = InstanceKlass::cast(class2)->class_loader();
classloader2 = class2->class_loader();
classpkg2 = InstanceKlass::cast(class2)->package();
} else {
assert(class2->is_typeArray_klass(), "should be type array");
classloader2 = NULL;
classpkg2 = NULL;
}
const Symbol* classname2 = class2->name();
return InstanceKlass::is_same_class_package(classloader1, classname1,
classloader2, classname2);
// Same package is determined by comparing class loader
// and package entries. Both must be the same. This rule
// applies even to classes that are defined in the unnamed
// package, they still must have the same class loader.
if ((classloader1 == classloader2) && (classpkg1 == classpkg2)) {
return true;
}
return false;
}
bool InstanceKlass::is_same_class_package(oop other_class_loader,
@ -2225,43 +2335,24 @@ bool InstanceKlass::is_same_class_package(oop class_loader1, const Symbol* class
// The Symbol*'s are in UTF8 encoding. Since we only need to check explicitly
// for ASCII characters ('/', 'L', '['), we can keep them in UTF8 encoding.
// Otherwise, we just compare jbyte values between the strings.
const jbyte *name1 = class_name1->base();
const jbyte *name2 = class_name2->base();
int length1 = 0;
int length2 = 0;
const jbyte *name1 = package_from_name(class_name1, length1);
const jbyte *name2 = package_from_name(class_name2, length2);
const jbyte *last_slash1 = UTF8::strrchr(name1, class_name1->utf8_length(), '/');
const jbyte *last_slash2 = UTF8::strrchr(name2, class_name2->utf8_length(), '/');
if ((length1 < 0) || (length2 < 0)) {
// error occurred parsing package name.
return false;
}
if ((last_slash1 == NULL) || (last_slash2 == NULL)) {
if ((name1 == NULL) || (name2 == NULL)) {
// One of the two doesn't have a package. Only return true
// if the other one also doesn't have a package.
return last_slash1 == last_slash2;
} else {
// Skip over '['s
if (*name1 == '[') {
do {
name1++;
} while (*name1 == '[');
if (*name1 != 'L') {
// Something is terribly wrong. Shouldn't be here.
return false;
}
}
if (*name2 == '[') {
do {
name2++;
} while (*name2 == '[');
if (*name2 != 'L') {
// Something is terribly wrong. Shouldn't be here.
return false;
}
}
// Check that package part is identical
int length1 = last_slash1 - name1;
int length2 = last_slash2 - name2;
return UTF8::equal(name1, length1, name2, length2);
return name1 == name2;
}
// Check that package part is identical
return UTF8::equal(name1, length1, name2, length2);
}
}
@ -2300,7 +2391,7 @@ bool InstanceKlass::is_same_package_member_impl(const InstanceKlass* class1,
if (!class2->is_instance_klass()) return false;
// must be in same package before we try anything else
if (!class1->is_same_class_package(class2->class_loader(), class2->name()))
if (!class1->is_same_class_package(class2))
return false;
// As long as there is an outer1.getEnclosingClass,
@ -2908,6 +2999,7 @@ const char* InstanceKlass::internal_name() const {
void InstanceKlass::print_loading_log(LogLevel::type type,
ClassLoaderData* loader_data,
const char* module_name,
const ClassFileStream* cfs) const {
ResourceMark rm;
outputStream* log;
@ -2928,7 +3020,11 @@ void InstanceKlass::print_loading_log(LogLevel::type type,
// Source
if (cfs != NULL) {
if (cfs->source() != NULL) {
log->print(" source: %s", cfs->source());
if (module_name != NULL) {
log->print(" source: jrt:/%s", module_name);
} else {
log->print(" source: %s", cfs->source());
}
} else if (loader_data == ClassLoaderData::the_null_class_loader_data()) {
Thread* THREAD = Thread::current();
Klass* caller =

View File

@ -25,8 +25,11 @@
#ifndef SHARE_VM_OOPS_INSTANCEKLASS_HPP
#define SHARE_VM_OOPS_INSTANCEKLASS_HPP
#include "classfile/classLoader.hpp"
#include "classfile/classLoaderData.hpp"
#include "classfile/packageEntry.hpp"
#include "gc/shared/specialized_oop_closures.hpp"
#include "classfile/moduleEntry.hpp"
#include "logging/logLevel.hpp"
#include "memory/referenceType.hpp"
#include "oops/annotations.hpp"
@ -140,6 +143,8 @@ class InstanceKlass: public Klass {
protected:
// Annotations for this class
Annotations* _annotations;
// Package this class is defined in
PackageEntry* _package_entry;
// Array classes holding elements of this class.
Klass* _array_klasses;
// Constant pool for this class.
@ -199,16 +204,22 @@ class InstanceKlass: public Klass {
// Start after _misc_kind field.
enum {
_misc_rewritten = 1 << 2, // methods rewritten.
_misc_has_nonstatic_fields = 1 << 3, // for sizing with UseCompressedOops
_misc_should_verify_class = 1 << 4, // allow caching of preverification
_misc_is_anonymous = 1 << 5, // has embedded _host_klass field
_misc_is_contended = 1 << 6, // marked with contended annotation
_misc_has_default_methods = 1 << 7, // class/superclass/implemented interfaces has default methods
_misc_declares_default_methods = 1 << 8, // directly declares default methods (any access)
_misc_has_been_redefined = 1 << 9, // class has been redefined
_misc_is_scratch_class = 1 << 10 // class is the redefined scratch class
_misc_rewritten = 1 << 2, // methods rewritten.
_misc_has_nonstatic_fields = 1 << 3, // for sizing with UseCompressedOops
_misc_should_verify_class = 1 << 4, // allow caching of preverification
_misc_is_anonymous = 1 << 5, // has embedded _host_klass field
_misc_is_contended = 1 << 6, // marked with contended annotation
_misc_has_default_methods = 1 << 7, // class/superclass/implemented interfaces has default methods
_misc_declares_default_methods = 1 << 8, // directly declares default methods (any access)
_misc_has_been_redefined = 1 << 9, // class has been redefined
_misc_is_scratch_class = 1 << 10, // class is the redefined scratch class
_misc_is_shared_boot_class = 1 << 11, // defining class loader is boot class loader
_misc_is_shared_platform_class = 1 << 12, // defining class loader is platform class loader
_misc_is_shared_app_class = 1 << 13 // defining class loader is app class loader
};
u2 loader_type_bits() {
return _misc_is_shared_boot_class|_misc_is_shared_platform_class|_misc_is_shared_app_class;
}
u2 _misc_flags;
u2 _minor_version; // minor version number of class file
u2 _major_version; // major version number of class file
@ -290,6 +301,39 @@ class InstanceKlass: public Klass {
friend class SystemDictionary;
public:
u2 loader_type() {
return _misc_flags & loader_type_bits();
}
bool is_shared_boot_class() const {
return (_misc_flags & _misc_is_shared_boot_class) != 0;
}
bool is_shared_platform_class() const {
return (_misc_flags & _misc_is_shared_platform_class) != 0;
}
bool is_shared_app_class() const {
return (_misc_flags & _misc_is_shared_app_class) != 0;
}
void set_class_loader_type(jshort loader_type) {
assert(( _misc_flags & loader_type_bits()) == 0,
"Should only be called once for each class.");
switch (loader_type) {
case ClassLoader::BOOT_LOADER:
_misc_flags |= _misc_is_shared_boot_class;
break;
case ClassLoader::PLATFORM_LOADER:
_misc_flags |= _misc_is_shared_platform_class;
break;
case ClassLoader::APP_LOADER:
_misc_flags |= _misc_is_shared_app_class;
break;
default:
ShouldNotReachHere();
break;
}
}
bool has_nonstatic_fields() const {
return (_misc_flags & _misc_has_nonstatic_fields) != 0;
}
@ -395,6 +439,11 @@ class InstanceKlass: public Klass {
bool is_override(const methodHandle& super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS);
// package
PackageEntry* package() const { return _package_entry; }
ModuleEntry* module() const;
bool in_unnamed_package() const { return (_package_entry == NULL); }
void set_package(PackageEntry* p) { _package_entry = p; }
void set_package(ClassLoaderData* loader_data, TRAPS);
bool is_same_class_package(const Klass* class2) const;
bool is_same_class_package(oop classloader2, const Symbol* classname2) const;
static bool is_same_class_package(oop class_loader1,
@ -1030,6 +1079,7 @@ public:
// Naming
const char* signature_name() const;
static const jbyte* package_from_name(const Symbol* name, int& length);
// GC specific object visitors
//
@ -1247,7 +1297,8 @@ public:
void oop_verify_on(oop obj, outputStream* st);
// Logging
void print_loading_log(LogLevel::type type, ClassLoaderData* loader_data, const ClassFileStream* cfs) const;
void print_loading_log(LogLevel::type type, ClassLoaderData* loader_data,
const char* module_name, const ClassFileStream* cfs) const;
};
// for adding methods

View File

@ -512,7 +512,21 @@ void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protec
// gotten an OOM later but keep the mirror if it was created.
if (java_mirror() == NULL) {
Handle loader = loader_data->class_loader();
java_lang_Class::create_mirror(this, loader, protection_domain, CHECK);
ModuleEntry* module_entry = NULL;
Klass* k = this;
if (k->is_objArray_klass()) {
k = ObjArrayKlass::cast(k)->bottom_klass();
}
// Obtain klass' module.
if (k->is_instance_klass()) {
InstanceKlass* ik = (InstanceKlass*) k;
module_entry = ik->module();
} else {
module_entry = ModuleEntryTable::javabase_module();
}
// Obtain java.lang.reflect.Module, if available
Handle module_handle(THREAD, ((module_entry != NULL) ? JNIHandles::resolve(module_entry->module()) : (oop)NULL));
java_lang_Class::create_mirror(this, loader, module_handle, protection_domain, CHECK);
}
}

View File

@ -1330,7 +1330,7 @@ vmSymbols::SID Method::klass_id_for_intrinsics(const Klass* holder) {
// exception: the AES intrinsics come from lib/ext/sunjce_provider.jar
// which does not use the class default class loader so we check for its loader here
const InstanceKlass* ik = InstanceKlass::cast(holder);
if ((ik->class_loader() != NULL) && !SystemDictionary::is_ext_class_loader(ik->class_loader())) {
if ((ik->class_loader() != NULL) && !SystemDictionary::is_platform_class_loader(ik->class_loader())) {
return vmSymbols::NO_SID; // regardless of name, no intrinsics here
}

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