Merge
This commit is contained in:
commit
708adb84ed
@ -352,3 +352,4 @@ be58b02c11f90b88c67e4d0e2cb5e4cf2d9b3c57 jdk-9+105
|
|||||||
4d65eba233a8730f913734a6804910b842d2cb54 jdk-9+107
|
4d65eba233a8730f913734a6804910b842d2cb54 jdk-9+107
|
||||||
c7be2a78c31b3b6132f2f5e9e4b3d3bb1c20245c jdk-9+108
|
c7be2a78c31b3b6132f2f5e9e4b3d3bb1c20245c jdk-9+108
|
||||||
1787bdaabb2b6f4193406e25a50cb0419ea8e8f3 jdk-9+109
|
1787bdaabb2b6f4193406e25a50cb0419ea8e8f3 jdk-9+109
|
||||||
|
925be13b3740d07a5958ccb5ab3c0ae1baba7055 jdk-9+110
|
||||||
|
@ -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])
|
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.
|
# 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])
|
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.
|
# 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])
|
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.
|
# The generated Makefile knows where the spec.gmk is and where the source is.
|
||||||
|
@ -304,6 +304,18 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK],
|
|||||||
# When compiling code to be executed by the Boot JDK, force jdk8 compatibility.
|
# When compiling code to be executed by the Boot JDK, force jdk8 compatibility.
|
||||||
BOOT_JDK_SOURCETARGET="-source 8 -target 8"
|
BOOT_JDK_SOURCETARGET="-source 8 -target 8"
|
||||||
AC_SUBST(BOOT_JDK_SOURCETARGET)
|
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)
|
AC_SUBST(JAVAC_FLAGS)
|
||||||
|
|
||||||
# Check if the boot jdk is 32 or 64 bit
|
# Check if the boot jdk is 32 or 64 bit
|
||||||
@ -397,3 +409,100 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS],
|
|||||||
done
|
done
|
||||||
AC_SUBST(JAVA_TOOL_FLAGS_SMALL)
|
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)
|
||||||
|
])
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
# Support for building boot cycle builds
|
# Support for building boot cycle builds
|
||||||
|
|
||||||
|
BOOT_JDK_MODULAR := true
|
||||||
|
|
||||||
# First include the real base spec.gmk file
|
# First include the real base spec.gmk file
|
||||||
include @SPEC@
|
include @SPEC@
|
||||||
|
|
||||||
|
148
common/autoconf/buildjdk-spec.gmk.in
Normal file
148
common/autoconf/buildjdk-spec.gmk.in
Normal 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
|
@ -134,6 +134,7 @@ BASIC_SETUP_DEFAULT_MAKE_TARGET
|
|||||||
|
|
||||||
# We need build & target for this.
|
# We need build & target for this.
|
||||||
JDKOPT_SETUP_JDK_OPTIONS
|
JDKOPT_SETUP_JDK_OPTIONS
|
||||||
|
JDKOPT_SETUP_JLINK_OPTIONS
|
||||||
HOTSPOT_SETUP_HOTSPOT_OPTIONS
|
HOTSPOT_SETUP_HOTSPOT_OPTIONS
|
||||||
JDKVER_SETUP_JDK_VERSION_NUMBERS
|
JDKVER_SETUP_JDK_VERSION_NUMBERS
|
||||||
|
|
||||||
@ -144,6 +145,7 @@ JDKVER_SETUP_JDK_VERSION_NUMBERS
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
BOOTJDK_SETUP_BOOT_JDK
|
BOOTJDK_SETUP_BOOT_JDK
|
||||||
|
BOOTJDK_SETUP_BUILD_JDK
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#
|
#
|
||||||
@ -155,6 +157,8 @@ SRCDIRS_SETUP_TOPDIRS
|
|||||||
SRCDIRS_SETUP_ALTERNATIVE_TOPDIRS
|
SRCDIRS_SETUP_ALTERNATIVE_TOPDIRS
|
||||||
SRCDIRS_SETUP_OUTPUT_DIRS
|
SRCDIRS_SETUP_OUTPUT_DIRS
|
||||||
|
|
||||||
|
SRCDIRS_SETUP_IMPORT_MODULES
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#
|
#
|
||||||
# Setup the toolchain (compilers etc), i.e. tools used to compile and process
|
# Setup the toolchain (compilers etc), i.e. tools used to compile and process
|
||||||
|
@ -689,9 +689,6 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK],
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# Setup LP64
|
|
||||||
COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK $ADD_LP64"
|
|
||||||
|
|
||||||
# Set some common defines. These works for all compilers, but assume
|
# Set some common defines. These works for all compilers, but assume
|
||||||
# -D is universally accepted.
|
# -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"
|
COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D$OPENJDK_TARGET_OS_UPPERCASE"
|
||||||
|
|
||||||
# Setup target CPU
|
# 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
|
# Setup debug/release defines
|
||||||
if test "x$DEBUG_LEVEL" = xrelease; then
|
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"
|
-I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/libjava"
|
||||||
|
|
||||||
# The shared libraries are compiled using the picflag.
|
# The shared libraries are compiled using the picflag.
|
||||||
CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA"
|
CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \
|
||||||
CXXFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_JDK $PICFLAG $CXXFLAGS_JDKLIB_EXTRA"
|
$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
|
# Executable flags
|
||||||
CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK"
|
CFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $OPENJDK_TARGET_CCXXFLAGS_JDK \
|
||||||
CXXFLAGS_JDKEXE="$COMMON_CCXXFLAGS_JDK $CXXFLAGS_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_JDKLIB)
|
||||||
AC_SUBST(CFLAGS_JDKEXE)
|
AC_SUBST(CFLAGS_JDKEXE)
|
||||||
AC_SUBST(CXXFLAGS_JDKLIB)
|
AC_SUBST(CXXFLAGS_JDKLIB)
|
||||||
AC_SUBST(CXXFLAGS_JDKEXE)
|
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
|
# Flags for compiling test libraries
|
||||||
CFLAGS_TESTLIB="$COMMON_CCXXFLAGS_JDK $CFLAGS_JDK $PICFLAG $CFLAGS_JDKLIB_EXTRA"
|
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"
|
LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE -Wl,--allow-shlib-undefined"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
OPENJDK_BUILD_LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE}"
|
||||||
|
LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE} ${EXTRA_LDFLAGS_JDK}"
|
||||||
|
|
||||||
# Customize LDFLAGS for libs
|
# Customize LDFLAGS for libs
|
||||||
LDFLAGS_JDKLIB="${LDFLAGS_JDK}"
|
LDFLAGS_JDKLIB="${LDFLAGS_JDK}"
|
||||||
|
|
||||||
@ -882,30 +905,39 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK],
|
|||||||
JDKLIB_LIBS=""
|
JDKLIB_LIBS=""
|
||||||
else
|
else
|
||||||
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} \
|
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.
|
# 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.
|
# 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.
|
# Only add client dir if client is being built. Add minimal (note not minimal1) if only building minimal1.
|
||||||
# Default to server for other variants.
|
# Default to server for other variants.
|
||||||
if test "x$JVM_VARIANT_SERVER" = xtrue; then
|
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
|
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
|
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
|
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
|
fi
|
||||||
|
|
||||||
JDKLIB_LIBS="-ljava -ljvm"
|
JDKLIB_LIBS="-ljava -ljvm"
|
||||||
if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
|
if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
|
||||||
JDKLIB_LIBS="$JDKLIB_LIBS -lc"
|
JDKLIB_LIBS="$JDKLIB_LIBS -lc"
|
||||||
fi
|
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
|
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_JDKLIB)
|
||||||
AC_SUBST(LDFLAGS_JDKEXE)
|
AC_SUBST(LDFLAGS_JDKEXE)
|
||||||
|
AC_SUBST(OPENJDK_BUILD_LDFLAGS_JDKLIB)
|
||||||
|
AC_SUBST(OPENJDK_BUILD_LDFLAGS_JDKEXE)
|
||||||
AC_SUBST(JDKLIB_LIBS)
|
AC_SUBST(JDKLIB_LIBS)
|
||||||
AC_SUBST(JDKEXE_LIBS)
|
AC_SUBST(JDKEXE_LIBS)
|
||||||
AC_SUBST(LDFLAGS_CXX_JDK)
|
AC_SUBST(LDFLAGS_CXX_JDK)
|
||||||
@ -1075,5 +1107,6 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_MISC],
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
AC_SUBST(DISABLE_WARNING_PREFIX)
|
AC_SUBST(DISABLE_WARNING_PREFIX)
|
||||||
|
AC_SUBST(BUILD_CC_DISABLE_WARNING_PREFIX)
|
||||||
AC_SUBST(CFLAGS_WARNINGS_ARE_ERRORS)
|
AC_SUBST(CFLAGS_WARNINGS_ARE_ERRORS)
|
||||||
])
|
])
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -405,3 +405,31 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_STATIC_BUILD],
|
|||||||
|
|
||||||
AC_SUBST(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)
|
||||||
|
])
|
||||||
|
@ -304,6 +304,37 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS],
|
|||||||
fi
|
fi
|
||||||
AC_SUBST(OPENJDK_TARGET_CPU_LIBDIR)
|
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
|
# 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:
|
# /amd64 or /sparcv9. This string is appended to some library paths, like this:
|
||||||
# /usr/lib${OPENJDK_TARGET_CPU_ISADIR}/libexample.so
|
# /usr/lib${OPENJDK_TARGET_CPU_ISADIR}/libexample.so
|
||||||
@ -346,6 +377,24 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS],
|
|||||||
fi
|
fi
|
||||||
AC_SUBST(OPENJDK_TARGET_CPU_JLI_CFLAGS)
|
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
|
if test "x$OPENJDK_TARGET_OS" = xmacosx; then
|
||||||
OPENJDK_TARGET_OS_EXPORT_DIR=macosx
|
OPENJDK_TARGET_OS_EXPORT_DIR=macosx
|
||||||
else
|
else
|
||||||
@ -362,6 +411,11 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS],
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
AC_SUBST(LP64,$A_LP64)
|
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
|
if test "x$COMPILE_TYPE" = "xcross"; then
|
||||||
# FIXME: ... or should this include reduced builds..?
|
# FIXME: ... or should this include reduced builds..?
|
||||||
|
@ -84,3 +84,56 @@ AC_DEFUN_ONCE([SRCDIRS_SETUP_OUTPUT_DIRS],
|
|||||||
|
|
||||||
JDK_OUTPUTDIR="$OUTPUT_ROOT/jdk"
|
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)
|
||||||
|
])
|
||||||
|
@ -130,6 +130,14 @@ JAXP_TOPDIR:=@JAXP_TOPDIR@
|
|||||||
JAXWS_TOPDIR:=@JAXWS_TOPDIR@
|
JAXWS_TOPDIR:=@JAXWS_TOPDIR@
|
||||||
HOTSPOT_TOPDIR:=@HOTSPOT_TOPDIR@
|
HOTSPOT_TOPDIR:=@HOTSPOT_TOPDIR@
|
||||||
NASHORN_TOPDIR:=@NASHORN_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@
|
COPYRIGHT_YEAR:=@COPYRIGHT_YEAR@
|
||||||
|
|
||||||
# New (JEP-223) version information
|
# New (JEP-223) version information
|
||||||
@ -246,6 +254,7 @@ TESTMAKE_OUTPUTDIR=$(BUILD_OUTPUT)/test-make
|
|||||||
MAKESUPPORT_OUTPUTDIR=$(BUILD_OUTPUT)/make-support
|
MAKESUPPORT_OUTPUTDIR=$(BUILD_OUTPUT)/make-support
|
||||||
# This does not get overridden in a bootcycle build
|
# This does not get overridden in a bootcycle build
|
||||||
CONFIGURESUPPORT_OUTPUTDIR:=@CONFIGURESUPPORT_OUTPUTDIR@
|
CONFIGURESUPPORT_OUTPUTDIR:=@CONFIGURESUPPORT_OUTPUTDIR@
|
||||||
|
BUILDJDK_OUTPUTDIR=$(BUILD_OUTPUT)/buildjdk
|
||||||
|
|
||||||
HOTSPOT_DIST=@HOTSPOT_DIST@
|
HOTSPOT_DIST=@HOTSPOT_DIST@
|
||||||
|
|
||||||
@ -255,6 +264,9 @@ BUILD_HOTSPOT=@BUILD_HOTSPOT@
|
|||||||
# it in sync.
|
# it in sync.
|
||||||
BOOT_JDK:=@BOOT_JDK@
|
BOOT_JDK:=@BOOT_JDK@
|
||||||
|
|
||||||
|
BUILD_JDK:=@BUILD_JDK@
|
||||||
|
CREATE_BUILDJDK:=@CREATE_BUILDJDK@
|
||||||
|
|
||||||
# When compiling Java source to be run by the boot jdk
|
# When compiling Java source to be run by the boot jdk
|
||||||
# use these extra flags, eg -source 6 -target 6
|
# use these extra flags, eg -source 6 -target 6
|
||||||
BOOT_JDK_SOURCETARGET:=@BOOT_JDK_SOURCETARGET@
|
BOOT_JDK_SOURCETARGET:=@BOOT_JDK_SOURCETARGET@
|
||||||
@ -405,6 +417,8 @@ BUILD_LDCXX:=@FIXPATH@ @BUILD_LDCXX@
|
|||||||
BUILD_AS:=@FIXPATH@ @BUILD_AS@
|
BUILD_AS:=@FIXPATH@ @BUILD_AS@
|
||||||
BUILD_AR:=@FIXPATH@ @BUILD_AR@
|
BUILD_AR:=@FIXPATH@ @BUILD_AR@
|
||||||
BUILD_NM:=@FIXPATH@ @BUILD_NM@
|
BUILD_NM:=@FIXPATH@ @BUILD_NM@
|
||||||
|
BUILD_OBJCOPY:=@BUILD_OBJCOPY@
|
||||||
|
BUILD_STRIP:=@BUILD_STRIP@
|
||||||
BUILD_SYSROOT_CFLAGS:=@BUILD_SYSROOT_CFLAGS@
|
BUILD_SYSROOT_CFLAGS:=@BUILD_SYSROOT_CFLAGS@
|
||||||
BUILD_SYSROOT_LDFLAGS:=@BUILD_SYSROOT_LDFLAGS@
|
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 ?=.
|
# overriding that value by using ?=.
|
||||||
JAVAC_FLAGS?=@JAVAC_FLAGS@
|
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) ...
|
# 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
|
# Use = assignment to be able to override in bootcycle-spec.gmk
|
||||||
INTERIM_LANGTOOLS_JAR = $(BUILDTOOLS_OUTPUTDIR)/interim_langtools.jar
|
NEW_JAVAC = $(INTERIM_LANGTOOLS_ARGS) $(JAVAC_MAIN_CLASS)
|
||||||
INTERIM_LANGTOOLS_ARGS = "-Xbootclasspath/p:$(INTERIM_LANGTOOLS_JAR)" -cp $(INTERIM_LANGTOOLS_JAR)
|
NEW_JAVADOC = $(INTERIM_LANGTOOLS_ARGS) $(JAVADOC_MAIN_CLASS)
|
||||||
NEW_JAVAC = $(INTERIM_LANGTOOLS_ARGS) com.sun.tools.javac.Main
|
|
||||||
NEW_JAVADOC = $(INTERIM_LANGTOOLS_ARGS) jdk.javadoc.internal.tool.Main
|
# 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
|
# Base flags for RC
|
||||||
# Guarding this against resetting value. Legacy make files include spec multiple
|
# Guarding this against resetting value. Legacy make files include spec multiple
|
||||||
|
@ -797,6 +797,10 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_BUILD_COMPILERS],
|
|||||||
BASIC_FIXUP_EXECUTABLE(BUILD_NM)
|
BASIC_FIXUP_EXECUTABLE(BUILD_NM)
|
||||||
BASIC_PATH_PROGS(BUILD_AR, ar gcc-ar)
|
BASIC_PATH_PROGS(BUILD_AR, ar gcc-ar)
|
||||||
BASIC_FIXUP_EXECUTABLE(BUILD_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
|
# Assume the C compiler is the assembler
|
||||||
BUILD_AS="$BUILD_CC -c"
|
BUILD_AS="$BUILD_CC -c"
|
||||||
# Just like for the target compiler, use the compiler as linker
|
# 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_LDCXX="$LDCXX"
|
||||||
BUILD_NM="$NM"
|
BUILD_NM="$NM"
|
||||||
BUILD_AS="$AS"
|
BUILD_AS="$AS"
|
||||||
|
BUILD_OBJCOPY="$OBJCOPY"
|
||||||
|
BUILD_STRIP="$STRIP"
|
||||||
BUILD_SYSROOT_CFLAGS="$SYSROOT_CFLAGS"
|
BUILD_SYSROOT_CFLAGS="$SYSROOT_CFLAGS"
|
||||||
BUILD_SYSROOT_LDFLAGS="$SYSROOT_LDFLAGS"
|
BUILD_SYSROOT_LDFLAGS="$SYSROOT_LDFLAGS"
|
||||||
BUILD_AR="$AR"
|
BUILD_AR="$AR"
|
||||||
|
@ -290,9 +290,9 @@ compare_general_files() {
|
|||||||
|
|
||||||
GENERAL_FILES=$(cd $THIS_DIR && $FIND . -type f ! -name "*.so" ! -name "*.jar" \
|
GENERAL_FILES=$(cd $THIS_DIR && $FIND . -type f ! -name "*.so" ! -name "*.jar" \
|
||||||
! -name "*.zip" ! -name "*.debuginfo" ! -name "*.dylib" ! -name "jexec" \
|
! -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 "*.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 "*.obj" ! -name "*.o" ! -name "JavaControlPanelHelper" \
|
||||||
! -name "JavaUpdater" ! -name "JavaWSApplicationStub" \
|
! -name "JavaUpdater" ! -name "JavaWSApplicationStub" \
|
||||||
! -name "jspawnhelper" ! -name "JavawsLauncher" ! -name "*.a" \
|
! -name "jspawnhelper" ! -name "JavawsLauncher" ! -name "*.a" \
|
||||||
@ -389,13 +389,13 @@ compare_zip_file() {
|
|||||||
$RM -rf $THIS_UNZIPDIR $OTHER_UNZIPDIR
|
$RM -rf $THIS_UNZIPDIR $OTHER_UNZIPDIR
|
||||||
$MKDIR -p $THIS_UNZIPDIR
|
$MKDIR -p $THIS_UNZIPDIR
|
||||||
$MKDIR -p $OTHER_UNZIPDIR
|
$MKDIR -p $OTHER_UNZIPDIR
|
||||||
if [ "$TYPE" = "jimage" ]
|
if [ "$TYPE" = "jar" || "$TYPE" = "war" || "$TYPE" = "zip" || "$TYPE" = "jmod"]
|
||||||
then
|
then
|
||||||
(cd $THIS_UNZIPDIR && $JIMAGE extract $THIS_ZIP)
|
|
||||||
(cd $OTHER_UNZIPDIR && $JIMAGE extract $OTHER_ZIP)
|
|
||||||
else
|
|
||||||
(cd $THIS_UNZIPDIR && $UNARCHIVE $THIS_ZIP)
|
(cd $THIS_UNZIPDIR && $UNARCHIVE $THIS_ZIP)
|
||||||
(cd $OTHER_UNZIPDIR && $UNARCHIVE $OTHER_ZIP)
|
(cd $OTHER_UNZIPDIR && $UNARCHIVE $OTHER_ZIP)
|
||||||
|
else
|
||||||
|
(cd $THIS_UNZIPDIR && $JIMAGE extract $THIS_ZIP)
|
||||||
|
(cd $OTHER_UNZIPDIR && $JIMAGE extract $OTHER_ZIP)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Find all archives inside and unzip them as well to compare the contents rather than
|
# 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?
|
# TODO filter?
|
||||||
ZIPS=$(cd $THIS_DIR && $FIND . -type f -name "*.jar" -o -name "*.war" \
|
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
|
if [ -n "$ZIPS" ]; then
|
||||||
echo Jar files...
|
echo Jar files...
|
||||||
|
@ -421,10 +421,10 @@ var getJibProfilesDependencies = function (input, common) {
|
|||||||
|
|
||||||
jtreg: {
|
jtreg: {
|
||||||
server: "javare",
|
server: "javare",
|
||||||
revision: "4.1",
|
revision: "4.2",
|
||||||
build_number: "b12",
|
build_number: "b01",
|
||||||
checksum_file: "MD5_VALUES",
|
checksum_file: "MD5_VALUES",
|
||||||
file: "jtreg_bin-4.1.zip",
|
file: "jtreg_bin-4.2.zip",
|
||||||
environment_name: "JT_HOME"
|
environment_name: "JT_HOME"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -352,3 +352,4 @@ e385e95e6101711d5c63e7b1a827e99b6ec7a1cc jdk-9+104
|
|||||||
49202432b69445164a42be7cbdf74ed5fce98157 jdk-9+107
|
49202432b69445164a42be7cbdf74ed5fce98157 jdk-9+107
|
||||||
84f2862a25eb3232ff36c376b4e2bf2a83dfced3 jdk-9+108
|
84f2862a25eb3232ff36c376b4e2bf2a83dfced3 jdk-9+108
|
||||||
b75afa17aefe480c23c616a6a2497063312f7189 jdk-9+109
|
b75afa17aefe480c23c616a6a2497063312f7189 jdk-9+109
|
||||||
|
9666775734fb6028ee86df9972626b3667b6a318 jdk-9+110
|
||||||
|
@ -47,7 +47,7 @@ $(eval $(call SetupJavaCompilation,BUILD_IDLJ, \
|
|||||||
BIN := $(BUILDTOOLS_OUTPUTDIR)/idlj_classes, \
|
BIN := $(BUILDTOOLS_OUTPUTDIR)/idlj_classes, \
|
||||||
COPY := .prp, \
|
COPY := .prp, \
|
||||||
INCLUDES := com/sun/tools/corba/se/idl, \
|
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.
|
# Force the language to english for predictable source code generation.
|
||||||
TOOL_IDLJ_CMD := $(JAVA) -cp $(BUILDTOOLS_OUTPUTDIR)/idlj_classes \
|
TOOL_IDLJ_CMD := $(JAVA) -cp $(BUILDTOOLS_OUTPUTDIR)/idlj_classes \
|
||||||
|
77
corba/src/java.corba/share/classes/module-info.java
Normal file
77
corba/src/java.corba/share/classes/module-info.java
Normal 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;
|
||||||
|
}
|
@ -512,3 +512,4 @@ c5f55130b1b69510d9a6f4a3105b58e21cd7ffe1 jdk-9+103
|
|||||||
c5146d4da417f76edfc43097d2e2ced042a65b4e jdk-9+107
|
c5146d4da417f76edfc43097d2e2ced042a65b4e jdk-9+107
|
||||||
934f6793f5f7dca44f69b4559d525fa64b31840d jdk-9+108
|
934f6793f5f7dca44f69b4559d525fa64b31840d jdk-9+108
|
||||||
7e7e50ac4faf19899fc811569e32cfa478759ebb jdk-9+109
|
7e7e50ac4faf19899fc811569e32cfa478759ebb jdk-9+109
|
||||||
|
2f5d1578b24060ea06bd1f340a124db95d1475b2 jdk-9+110
|
||||||
|
@ -168,3 +168,15 @@
|
|||||||
JVM_TotalMemory;
|
JVM_TotalMemory;
|
||||||
JVM_UnloadLibrary;
|
JVM_UnloadLibrary;
|
||||||
JVM_Yield;
|
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;
|
||||||
|
@ -45,6 +45,7 @@ BUILD_HOTSPOT_JTREG_NATIVE_SRC := \
|
|||||||
$(HOTSPOT_TOPDIR)/test/runtime/jni/8025979 \
|
$(HOTSPOT_TOPDIR)/test/runtime/jni/8025979 \
|
||||||
$(HOTSPOT_TOPDIR)/test/runtime/jni/8033445 \
|
$(HOTSPOT_TOPDIR)/test/runtime/jni/8033445 \
|
||||||
$(HOTSPOT_TOPDIR)/test/runtime/jni/ToStringInInterfaceTest \
|
$(HOTSPOT_TOPDIR)/test/runtime/jni/ToStringInInterfaceTest \
|
||||||
|
$(HOTSPOT_TOPDIR)/test/runtime/modules/getModuleJNI \
|
||||||
$(HOTSPOT_TOPDIR)/test/runtime/SameObject \
|
$(HOTSPOT_TOPDIR)/test/runtime/SameObject \
|
||||||
$(HOTSPOT_TOPDIR)/test/compiler/floatingpoint/ \
|
$(HOTSPOT_TOPDIR)/test/compiler/floatingpoint/ \
|
||||||
$(HOTSPOT_TOPDIR)/test/compiler/calls \
|
$(HOTSPOT_TOPDIR)/test/compiler/calls \
|
||||||
|
49
hotspot/src/jdk.hotspot.agent/share/classes/module-info.java
Normal file
49
hotspot/src/jdk.hotspot.agent/share/classes/module-info.java
Normal 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;
|
||||||
|
}
|
||||||
|
|
@ -31,14 +31,14 @@ import sun.jvm.hotspot.debugger.*;
|
|||||||
import sun.jvm.hotspot.memory.*;
|
import sun.jvm.hotspot.memory.*;
|
||||||
import sun.jvm.hotspot.oops.*;
|
import sun.jvm.hotspot.oops.*;
|
||||||
import sun.jvm.hotspot.runtime.*;
|
import sun.jvm.hotspot.runtime.*;
|
||||||
import sun.jvm.hotspot.tools.*;
|
|
||||||
import sun.jvm.hotspot.utilities.*;
|
import sun.jvm.hotspot.utilities.*;
|
||||||
|
import jdk.internal.vm.agent.spi.ToolProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
A command line tool to print class loader statistics.
|
A command line tool to print class loader statistics.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class ClassLoaderStats extends Tool {
|
public class ClassLoaderStats extends Tool implements ToolProvider {
|
||||||
boolean verbose = true;
|
boolean verbose = true;
|
||||||
|
|
||||||
public ClassLoaderStats() {
|
public ClassLoaderStats() {
|
||||||
@ -49,6 +49,16 @@ public class ClassLoaderStats extends Tool {
|
|||||||
super(d);
|
super(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "classLoaderStats";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(String... arguments) {
|
||||||
|
execute(arguments);
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
ClassLoaderStats cls = new ClassLoaderStats();
|
ClassLoaderStats cls = new ClassLoaderStats();
|
||||||
cls.execute(args);
|
cls.execute(args);
|
||||||
|
@ -25,24 +25,21 @@
|
|||||||
package sun.jvm.hotspot.tools;
|
package sun.jvm.hotspot.tools;
|
||||||
|
|
||||||
import sun.jvm.hotspot.debugger.JVMDebugger;
|
import sun.jvm.hotspot.debugger.JVMDebugger;
|
||||||
import sun.jvm.hotspot.tools.*;
|
|
||||||
|
|
||||||
import sun.jvm.hotspot.oops.*;
|
import sun.jvm.hotspot.oops.*;
|
||||||
import sun.jvm.hotspot.runtime.VM;
|
|
||||||
import sun.jvm.hotspot.utilities.SystemDictionaryHelper;
|
import sun.jvm.hotspot.utilities.SystemDictionaryHelper;
|
||||||
import sun.jvm.hotspot.utilities.ObjectReader;
|
import jdk.internal.vm.agent.spi.ToolProvider;
|
||||||
import sun.jvm.hotspot.utilities.MarkBits;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Iterates over the queue of object pending finalization and prints a
|
* Iterates over the queue of object pending finalization and prints a
|
||||||
* summary of these objects in the form of a histogram.
|
* summary of these objects in the form of a histogram.
|
||||||
*/
|
*/
|
||||||
public class FinalizerInfo extends Tool {
|
public class FinalizerInfo extends Tool implements ToolProvider {
|
||||||
|
|
||||||
public FinalizerInfo() {
|
public FinalizerInfo() {
|
||||||
super();
|
super();
|
||||||
@ -52,6 +49,16 @@ public class FinalizerInfo extends Tool {
|
|||||||
super(d);
|
super(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "finalizerInfo";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(String... arguments) {
|
||||||
|
execute(arguments);
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
FinalizerInfo finfo = new FinalizerInfo();
|
FinalizerInfo finfo = new FinalizerInfo();
|
||||||
finfo.execute(args);
|
finfo.execute(args);
|
||||||
|
@ -26,6 +26,8 @@ package sun.jvm.hotspot.tools;
|
|||||||
|
|
||||||
import sun.jvm.hotspot.utilities.HeapHprofBinWriter;
|
import sun.jvm.hotspot.utilities.HeapHprofBinWriter;
|
||||||
import sun.jvm.hotspot.debugger.JVMDebugger;
|
import sun.jvm.hotspot.debugger.JVMDebugger;
|
||||||
|
import jdk.internal.vm.agent.spi.ToolProvider;
|
||||||
|
|
||||||
import java.io.IOException;
|
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
|
* process/core as a HPROF binary file. It can also be used as a standalone
|
||||||
* tool if required.
|
* tool if required.
|
||||||
*/
|
*/
|
||||||
public class HeapDumper extends Tool {
|
public class HeapDumper extends Tool implements ToolProvider {
|
||||||
|
|
||||||
private static String DEFAULT_DUMP_FILE = "heap.bin";
|
private static String DEFAULT_DUMP_FILE = "heap.bin";
|
||||||
|
|
||||||
private String dumpFile;
|
private String dumpFile;
|
||||||
|
|
||||||
|
public HeapDumper() {
|
||||||
|
this.dumpFile = DEFAULT_DUMP_FILE;
|
||||||
|
}
|
||||||
|
|
||||||
public HeapDumper(String dumpFile) {
|
public HeapDumper(String dumpFile) {
|
||||||
this.dumpFile = dumpFile;
|
this.dumpFile = dumpFile;
|
||||||
}
|
}
|
||||||
@ -48,6 +54,11 @@ public class HeapDumper extends Tool {
|
|||||||
this.dumpFile = dumpFile;
|
this.dumpFile = dumpFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "heapDumper";
|
||||||
|
}
|
||||||
|
|
||||||
protected void printFlagsUsage() {
|
protected void printFlagsUsage() {
|
||||||
System.out.println(" <no option>\tto dump heap to " +
|
System.out.println(" <no option>\tto dump heap to " +
|
||||||
DEFAULT_DUMP_FILE);
|
DEFAULT_DUMP_FILE);
|
||||||
@ -69,18 +80,22 @@ public class HeapDumper extends Tool {
|
|||||||
// JDK jmap utility will always invoke this tool as:
|
// JDK jmap utility will always invoke this tool as:
|
||||||
// HeapDumper -f <file> <args...>
|
// HeapDumper -f <file> <args...>
|
||||||
public static void main(String 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.length > 2) {
|
||||||
if (args[0].equals("-f")) {
|
if (args[0].equals("-f")) {
|
||||||
file = args[1];
|
this.dumpFile = args[1];
|
||||||
String[] newargs = new String[args.length-2];
|
String[] newargs = new String[args.length-2];
|
||||||
System.arraycopy(args, 2, newargs, 0, args.length-2);
|
System.arraycopy(args, 2, newargs, 0, args.length-2);
|
||||||
args = newargs;
|
args = newargs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HeapDumper dumper = new HeapDumper(file);
|
execute(args);
|
||||||
dumper.execute(args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -33,8 +33,9 @@ import sun.jvm.hotspot.debugger.JVMDebugger;
|
|||||||
import sun.jvm.hotspot.memory.*;
|
import sun.jvm.hotspot.memory.*;
|
||||||
import sun.jvm.hotspot.oops.*;
|
import sun.jvm.hotspot.oops.*;
|
||||||
import sun.jvm.hotspot.runtime.*;
|
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() {
|
public HeapSummary() {
|
||||||
super();
|
super();
|
||||||
@ -49,6 +50,16 @@ public class HeapSummary extends Tool {
|
|||||||
hs.execute(args);
|
hs.execute(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "heapSummary";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(String... arguments) {
|
||||||
|
execute(arguments);
|
||||||
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
CollectedHeap heap = VM.getVM().getUniverse().heap();
|
CollectedHeap heap = VM.getVM().getUniverse().heap();
|
||||||
VM.Flag[] flags = VM.getVM().getCommandLineFlags();
|
VM.Flag[] flags = VM.getVM().getCommandLineFlags();
|
||||||
|
@ -27,8 +27,9 @@ package sun.jvm.hotspot.tools;
|
|||||||
import sun.jvm.hotspot.debugger.JVMDebugger;
|
import sun.jvm.hotspot.debugger.JVMDebugger;
|
||||||
import sun.jvm.hotspot.runtime.Arguments;
|
import sun.jvm.hotspot.runtime.Arguments;
|
||||||
import sun.jvm.hotspot.runtime.VM;
|
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() {
|
public JInfo() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
@ -94,13 +95,14 @@ public class JInfo extends Tool {
|
|||||||
tool.run();
|
tool.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
@Override
|
||||||
|
public void run(String... args) {
|
||||||
int mode = -1;
|
int mode = -1;
|
||||||
switch (args.length) {
|
switch (args.length) {
|
||||||
case 1:
|
case 1:
|
||||||
if (args[0].charAt(0) == '-') {
|
if (args[0].charAt(0) == '-') {
|
||||||
// -h or -help or some invalid flag
|
// -h or -help or some invalid flag
|
||||||
new JInfo(mode).usage();
|
usage();
|
||||||
} else {
|
} else {
|
||||||
mode = MODE_BOTH;
|
mode = MODE_BOTH;
|
||||||
}
|
}
|
||||||
@ -114,7 +116,7 @@ public class JInfo extends Tool {
|
|||||||
mode = MODE_SYSPROPS;
|
mode = MODE_SYSPROPS;
|
||||||
} else if (modeFlag.charAt(0) == '-') {
|
} else if (modeFlag.charAt(0) == '-') {
|
||||||
// -h or -help or some invalid flag
|
// -h or -help or some invalid flag
|
||||||
new JInfo(mode).usage();
|
usage();
|
||||||
} else {
|
} else {
|
||||||
mode = MODE_BOTH;
|
mode = MODE_BOTH;
|
||||||
}
|
}
|
||||||
@ -131,11 +133,16 @@ public class JInfo extends Tool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
new JInfo(mode).usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
JInfo jinfo = new JInfo(mode);
|
this.mode = mode;
|
||||||
jinfo.execute(args);
|
execute(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
JInfo jinfo = new JInfo();
|
||||||
|
jinfo.run(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void printVMFlags() {
|
private void printVMFlags() {
|
||||||
|
@ -25,8 +25,9 @@
|
|||||||
package sun.jvm.hotspot.tools;
|
package sun.jvm.hotspot.tools;
|
||||||
|
|
||||||
import sun.jvm.hotspot.debugger.JVMDebugger;
|
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) {
|
public JStack(boolean mixedMode, boolean concurrentLocks) {
|
||||||
this.mixedMode = mixedMode;
|
this.mixedMode = mixedMode;
|
||||||
this.concurrentLocks = concurrentLocks;
|
this.concurrentLocks = concurrentLocks;
|
||||||
@ -66,9 +67,8 @@ public class JStack extends Tool {
|
|||||||
tool.run();
|
tool.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
@Override
|
||||||
boolean mixedMode = false;
|
public void run(String... args) {
|
||||||
boolean concurrentLocks = false;
|
|
||||||
int used = 0;
|
int used = 0;
|
||||||
for (int i = 0; i < args.length; i++) {
|
for (int i = 0; i < args.length; i++) {
|
||||||
if (args[i].equals("-m")) {
|
if (args[i].equals("-m")) {
|
||||||
@ -88,8 +88,12 @@ public class JStack extends Tool {
|
|||||||
args = newArgs;
|
args = newArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
JStack jstack = new JStack(mixedMode, concurrentLocks);
|
execute(args);
|
||||||
jstack.execute(args);
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
JStack jstack = new JStack();
|
||||||
|
jstack.run(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean mixedMode;
|
private boolean mixedMode;
|
||||||
|
@ -27,11 +27,13 @@ package sun.jvm.hotspot.tools;
|
|||||||
import sun.jvm.hotspot.debugger.*;
|
import sun.jvm.hotspot.debugger.*;
|
||||||
import sun.jvm.hotspot.oops.*;
|
import sun.jvm.hotspot.oops.*;
|
||||||
import sun.jvm.hotspot.runtime.*;
|
import sun.jvm.hotspot.runtime.*;
|
||||||
|
import jdk.internal.vm.agent.spi.ToolProvider;
|
||||||
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
|
||||||
/** A sample tool which uses the Serviceability Agent's APIs to obtain
|
/** A sample tool which uses the Serviceability Agent's APIs to obtain
|
||||||
an object histogram from a remote or crashed VM. */
|
an object histogram from a remote or crashed VM. */
|
||||||
public class ObjectHistogram extends Tool {
|
public class ObjectHistogram extends Tool implements ToolProvider {
|
||||||
|
|
||||||
public ObjectHistogram() {
|
public ObjectHistogram() {
|
||||||
super();
|
super();
|
||||||
@ -41,6 +43,16 @@ public class ObjectHistogram extends Tool {
|
|||||||
super(d);
|
super(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "objectHistogram";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(String... arguments) {
|
||||||
|
execute(arguments);
|
||||||
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
run(System.out, System.err);
|
run(System.out, System.err);
|
||||||
}
|
}
|
||||||
|
@ -28,9 +28,9 @@ import java.io.*;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import sun.jvm.hotspot.debugger.*;
|
import sun.jvm.hotspot.debugger.*;
|
||||||
import sun.jvm.hotspot.debugger.cdbg.*;
|
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() {
|
public PMap() {
|
||||||
super();
|
super();
|
||||||
@ -40,6 +40,16 @@ public class PMap extends Tool {
|
|||||||
super(d);
|
super(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "pmap";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(String... arguments) {
|
||||||
|
execute(arguments);
|
||||||
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
run(System.out);
|
run(System.out);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
jdk.vm.ci.hotspot.aarch64.AArch64HotSpotJVMCIBackendFactory
|
|
||||||
jdk.vm.ci.hotspot.amd64.AMD64HotSpotJVMCIBackendFactory
|
|
||||||
jdk.vm.ci.hotspot.sparc.SPARCHotSpotJVMCIBackendFactory
|
|
37
hotspot/src/jdk.vm.ci/share/classes/module-info.java
Normal file
37
hotspot/src/jdk.vm.ci/share/classes/module-info.java
Normal 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;
|
||||||
|
}
|
@ -300,6 +300,8 @@ provider hotspot_jni {
|
|||||||
probe GetLongField__return(uintptr_t);
|
probe GetLongField__return(uintptr_t);
|
||||||
probe GetMethodID__entry(void*, void*, const char*, const char*);
|
probe GetMethodID__entry(void*, void*, const char*, const char*);
|
||||||
probe GetMethodID__return(uintptr_t);
|
probe GetMethodID__return(uintptr_t);
|
||||||
|
probe GetModule__entry(void*, void*);
|
||||||
|
probe GetModule__return(void*);
|
||||||
probe GetObjectArrayElement__entry(void*, void*, uintptr_t);
|
probe GetObjectArrayElement__entry(void*, void*, uintptr_t);
|
||||||
probe GetObjectArrayElement__return(void*);
|
probe GetObjectArrayElement__return(void*);
|
||||||
probe GetObjectClass__entry(void*, void*);
|
probe GetObjectClass__entry(void*, void*);
|
||||||
|
@ -661,7 +661,7 @@ JRT_ENTRY(void, Runtime1::throw_class_cast_exception(JavaThread* thread, oopDesc
|
|||||||
NOT_PRODUCT(_throw_class_cast_exception_count++;)
|
NOT_PRODUCT(_throw_class_cast_exception_count++;)
|
||||||
ResourceMark rm(thread);
|
ResourceMark rm(thread);
|
||||||
char* message = SharedRuntime::generate_class_cast_message(
|
char* message = SharedRuntime::generate_class_cast_message(
|
||||||
thread, object->klass()->external_name());
|
thread, object->klass());
|
||||||
SharedRuntime::throw_and_post_jvmti_exception(
|
SharedRuntime::throw_and_post_jvmti_exception(
|
||||||
thread, vmSymbols::java_lang_ClassCastException(), message);
|
thread, vmSymbols::java_lang_ClassCastException(), message);
|
||||||
JRT_END
|
JRT_END
|
||||||
|
@ -370,9 +370,9 @@ bool ciEnv::check_klass_accessibility(ciKlass* accessing_klass,
|
|||||||
resolved_klass = ObjArrayKlass::cast(resolved_klass)->bottom_klass();
|
resolved_klass = ObjArrayKlass::cast(resolved_klass)->bottom_klass();
|
||||||
}
|
}
|
||||||
if (resolved_klass->is_instance_klass()) {
|
if (resolved_klass->is_instance_klass()) {
|
||||||
return Reflection::verify_class_access(accessing_klass->get_Klass(),
|
return (Reflection::verify_class_access(accessing_klass->get_Klass(),
|
||||||
resolved_klass,
|
resolved_klass,
|
||||||
true);
|
true) == Reflection::ACCESS_OK);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -28,6 +28,7 @@
|
|||||||
#include "classfile/classLoaderData.inline.hpp"
|
#include "classfile/classLoaderData.inline.hpp"
|
||||||
#include "classfile/defaultMethods.hpp"
|
#include "classfile/defaultMethods.hpp"
|
||||||
#include "classfile/javaClasses.inline.hpp"
|
#include "classfile/javaClasses.inline.hpp"
|
||||||
|
#include "classfile/moduleEntry.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/symbolTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "classfile/verificationType.hpp"
|
#include "classfile/verificationType.hpp"
|
||||||
@ -103,8 +104,6 @@
|
|||||||
|
|
||||||
#define JAVA_9_VERSION 53
|
#define JAVA_9_VERSION 53
|
||||||
|
|
||||||
enum { LegalClass, LegalField, LegalMethod }; // used to verify unqualified names
|
|
||||||
|
|
||||||
void ClassFileParser::parse_constant_pool_entries(const ClassFileStream* const stream,
|
void ClassFileParser::parse_constant_pool_entries(const ClassFileStream* const stream,
|
||||||
ConstantPool* cp,
|
ConstantPool* cp,
|
||||||
const int length,
|
const int length,
|
||||||
@ -1965,7 +1964,7 @@ AnnotationCollector::annotation_index(const ClassLoaderData* loader_data,
|
|||||||
const vmSymbols::SID sid = vmSymbols::find_sid(name);
|
const vmSymbols::SID sid = vmSymbols::find_sid(name);
|
||||||
// Privileged code can use all annotations. Other code silently drops some.
|
// Privileged code can use all annotations. Other code silently drops some.
|
||||||
const bool privileged = loader_data->is_the_null_class_loader_data() ||
|
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();
|
loader_data->is_anonymous();
|
||||||
switch (sid) {
|
switch (sid) {
|
||||||
case vmSymbols::VM_SYMBOL_ENUM_NAME(sun_reflect_CallerSensitive_signature): {
|
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) {
|
static void check_super_class_access(const InstanceKlass* this_klass, TRAPS) {
|
||||||
assert(this_klass != NULL, "invariant");
|
assert(this_klass != NULL, "invariant");
|
||||||
const Klass* const super = this_klass->super();
|
const Klass* const super = this_klass->super();
|
||||||
if ((super != NULL) &&
|
if (super != NULL) {
|
||||||
(!Reflection::verify_class_access(this_klass, super, false))) {
|
Reflection::VerifyClassAccessResults vca_result =
|
||||||
ResourceMark rm(THREAD);
|
Reflection::verify_class_access(this_klass, super, false);
|
||||||
Exceptions::fthrow(
|
if (vca_result != Reflection::ACCESS_OK) {
|
||||||
THREAD_AND_LOCATION,
|
ResourceMark rm(THREAD);
|
||||||
vmSymbols::java_lang_IllegalAccessError(),
|
char* msg = Reflection::verify_class_access_msg(this_klass, super, vca_result);
|
||||||
"class %s cannot access its superclass %s",
|
if (msg == NULL) {
|
||||||
this_klass->external_name(),
|
ResourceMark rm(THREAD);
|
||||||
super->external_name()
|
Exceptions::fthrow(
|
||||||
);
|
THREAD_AND_LOCATION,
|
||||||
return;
|
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--) {
|
for (int i = lng - 1; i >= 0; i--) {
|
||||||
Klass* const k = local_interfaces->at(i);
|
Klass* const k = local_interfaces->at(i);
|
||||||
assert (k != NULL && k->is_interface(), "invalid interface");
|
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);
|
ResourceMark rm(THREAD);
|
||||||
Exceptions::fthrow(
|
char* msg = Reflection::verify_class_access_msg(this_klass, k, vca_result);
|
||||||
THREAD_AND_LOCATION,
|
if (msg == NULL) {
|
||||||
vmSymbols::java_lang_IllegalAccessError(),
|
Exceptions::fthrow(
|
||||||
"class %s cannot access its superinterface %s",
|
THREAD_AND_LOCATION,
|
||||||
this_klass->external_name(),
|
vmSymbols::java_lang_IllegalAccessError(),
|
||||||
k->external_name()
|
"class %s cannot access its superinterface %s",
|
||||||
);
|
this_klass->external_name(),
|
||||||
return;
|
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_super = (flags & JVM_ACC_SUPER) != 0;
|
||||||
const bool is_enum = (flags & JVM_ACC_ENUM) != 0;
|
const bool is_enum = (flags & JVM_ACC_ENUM) != 0;
|
||||||
const bool is_annotation = (flags & JVM_ACC_ANNOTATION) != 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;
|
const bool major_gte_15 = _major_version >= JAVA_1_5_VERSION;
|
||||||
|
|
||||||
if ((is_abstract && is_final) ||
|
if ((is_abstract && is_final) ||
|
||||||
(is_interface && !is_abstract) ||
|
(is_interface && !is_abstract) ||
|
||||||
(is_interface && major_gte_15 && (is_super || is_enum)) ||
|
(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);
|
ResourceMark rm(THREAD);
|
||||||
Exceptions::fthrow(
|
Exceptions::fthrow(
|
||||||
THREAD_AND_LOCATION,
|
THREAD_AND_LOCATION,
|
||||||
@ -4650,65 +4673,9 @@ void ClassFileParser::verify_legal_utf8(const unsigned char* buffer,
|
|||||||
int length,
|
int length,
|
||||||
TRAPS) const {
|
TRAPS) const {
|
||||||
assert(_need_verify, "only called when _need_verify is true");
|
assert(_need_verify, "only called when _need_verify is true");
|
||||||
int i = 0;
|
if (!UTF8::is_legal_utf8(buffer, length, _major_version <= 47)) {
|
||||||
const int count = length >> 2;
|
classfile_parse_error("Illegal UTF8 string in constant pool in class file %s", CHECK);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
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 '/'.
|
// 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
|
// 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
|
// method. Because these names have been checked as special cases before
|
||||||
// calling this method in verify_legal_method_name.
|
// calling this method in verify_legal_method_name.
|
||||||
static bool verify_unqualified_name(const char* name,
|
//
|
||||||
unsigned int length,
|
// This method is also called from the modular system APIs in modules.cpp
|
||||||
int type) {
|
// 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;) {
|
for (const char* p = name; p != name + length;) {
|
||||||
jchar ch = *p;
|
jchar ch = *p;
|
||||||
if (ch < 128) {
|
if (ch < 128) {
|
||||||
p++;
|
if (ch == '.') {
|
||||||
if (ch == '.' || ch == ';' || 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 '['
|
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
|
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
|
return false; // do not permit '<' or '>' in method names
|
||||||
}
|
}
|
||||||
}
|
p++;
|
||||||
else {
|
} else {
|
||||||
char* tmp_p = UTF8::next(p, &ch);
|
char* tmp_p = UTF8::next(p, &ch);
|
||||||
p = tmp_p;
|
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) {
|
if (_klass != NULL) {
|
||||||
return _klass;
|
return _klass;
|
||||||
}
|
}
|
||||||
@ -5200,14 +5178,14 @@ InstanceKlass* ClassFileParser::create_instance_klass(TRAPS) {
|
|||||||
InstanceKlass* const ik =
|
InstanceKlass* const ik =
|
||||||
InstanceKlass::allocate_instance_klass(*this, CHECK_NULL);
|
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");
|
assert(_klass == ik, "invariant");
|
||||||
|
|
||||||
return ik;
|
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");
|
assert(ik != NULL, "invariant");
|
||||||
|
|
||||||
set_klass_to_deallocate(ik);
|
set_klass_to_deallocate(ik);
|
||||||
@ -5272,6 +5250,12 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, TRAPS) {
|
|||||||
ik->set_host_klass(_host_klass);
|
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();
|
const Array<Method*>* const methods = ik->methods();
|
||||||
assert(methods != NULL, "invariant");
|
assert(methods != NULL, "invariant");
|
||||||
const int methods_len = methods->length();
|
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
|
// Allocate mirror and initialize static fields
|
||||||
// The create_mirror() call will also call compute_modifiers()
|
// The create_mirror() call will also call compute_modifiers()
|
||||||
java_lang_Class::create_mirror(ik,
|
java_lang_Class::create_mirror(ik,
|
||||||
_loader_data->class_loader(),
|
_loader_data->class_loader(),
|
||||||
|
module_handle,
|
||||||
_protection_domain,
|
_protection_domain,
|
||||||
CHECK);
|
CHECK);
|
||||||
|
|
||||||
@ -5344,6 +5336,15 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, TRAPS) {
|
|||||||
CHECK);
|
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.
|
// Update the loader_data graph.
|
||||||
record_defined_class_dependencies(ik, CHECK);
|
record_defined_class_dependencies(ik, CHECK);
|
||||||
|
|
||||||
@ -5351,11 +5352,24 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, TRAPS) {
|
|||||||
|
|
||||||
if (!is_internal()) {
|
if (!is_internal()) {
|
||||||
if (log_is_enabled(Info, classload)) {
|
if (log_is_enabled(Info, classload)) {
|
||||||
ik->print_loading_log(LogLevel::Info, _loader_data, _stream);
|
ResourceMark rm;
|
||||||
}
|
const char* module_name = NULL;
|
||||||
// No 'else' here as logging levels are not mutually exclusive
|
static const size_t modules_image_name_len = strlen(MODULES_IMAGE_NAME);
|
||||||
if (log_is_enabled(Debug, classload)) {
|
size_t stream_len = strlen(_stream->source());
|
||||||
ik->print_loading_log(LogLevel::Debug, _loader_data, _stream);
|
// 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(Info, classresolve)) {
|
if (log_is_enabled(Info, classresolve)) {
|
||||||
|
@ -73,6 +73,8 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
|||||||
NOF_PUBLICITY_LEVELS
|
NOF_PUBLICITY_LEVELS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum { LegalClass, LegalField, LegalMethod, LegalModule }; // used to verify unqualified names
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const ClassFileStream* _stream; // Actual input stream
|
const ClassFileStream* _stream; // Actual input stream
|
||||||
const Symbol* _requested_name;
|
const Symbol* _requested_name;
|
||||||
@ -155,7 +157,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
|||||||
ConstantPool* cp,
|
ConstantPool* cp,
|
||||||
TRAPS);
|
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_klass(InstanceKlass* instance);
|
||||||
|
|
||||||
void set_class_synthetic_flag(bool x) { _synthetic_flag = x; }
|
void set_class_synthetic_flag(bool x) { _synthetic_flag = x; }
|
||||||
@ -482,7 +484,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
|||||||
|
|
||||||
~ClassFileParser();
|
~ClassFileParser();
|
||||||
|
|
||||||
InstanceKlass* create_instance_klass(TRAPS);
|
InstanceKlass* create_instance_klass(bool cf_changed_in_CFLH, TRAPS);
|
||||||
|
|
||||||
const ClassFileStream* clone_stream() const;
|
const ClassFileStream* clone_stream() const;
|
||||||
|
|
||||||
@ -512,6 +514,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
|||||||
|
|
||||||
bool is_internal() const { return INTERNAL == _pub_level; }
|
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
|
#endif // SHARE_VM_CLASSFILE_CLASSFILEPARSER_HPP
|
||||||
|
@ -29,6 +29,9 @@
|
|||||||
#include "classfile/classLoaderExt.hpp"
|
#include "classfile/classLoaderExt.hpp"
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
#include "classfile/jimage.hpp"
|
#include "classfile/jimage.hpp"
|
||||||
|
#include "classfile/moduleEntry.hpp"
|
||||||
|
#include "classfile/modules.hpp"
|
||||||
|
#include "classfile/packageEntry.hpp"
|
||||||
#include "classfile/klassFactory.hpp"
|
#include "classfile/klassFactory.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "classfile/vmSymbols.hpp"
|
#include "classfile/vmSymbols.hpp"
|
||||||
@ -138,11 +141,14 @@ PerfCounter* ClassLoader::_load_instance_class_failCounter = NULL;
|
|||||||
ClassPathEntry* ClassLoader::_first_entry = NULL;
|
ClassPathEntry* ClassLoader::_first_entry = NULL;
|
||||||
ClassPathEntry* ClassLoader::_last_entry = NULL;
|
ClassPathEntry* ClassLoader::_last_entry = NULL;
|
||||||
int ClassLoader::_num_entries = 0;
|
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
|
#if INCLUDE_CDS
|
||||||
|
GrowableArray<char*>* ClassLoader::_boot_modules_array = NULL;
|
||||||
|
GrowableArray<char*>* ClassLoader::_platform_modules_array = NULL;
|
||||||
SharedPathsMiscInfo* ClassLoader::_shared_paths_misc_info = NULL;
|
SharedPathsMiscInfo* ClassLoader::_shared_paths_misc_info = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// helper routines
|
// helper routines
|
||||||
bool string_starts_with(const char* str, const char* str_to_find) {
|
bool string_starts_with(const char* str, const char* str_to_find) {
|
||||||
size_t str_len = strlen(str);
|
size_t str_len = strlen(str);
|
||||||
@ -162,7 +168,7 @@ static const char* get_jimage_version_string() {
|
|||||||
return (const char*)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_len = strlen(str);
|
||||||
size_t str_to_find_len = strlen(str_to_find);
|
size_t str_to_find_len = strlen(str_to_find);
|
||||||
if (str_to_find_len > str_len) {
|
if (str_to_find_len > str_len) {
|
||||||
@ -356,15 +362,49 @@ ClassFileStream* ClassPathImageEntry::open_stream(const char* name, TRAPS) {
|
|||||||
if (location == 0) {
|
if (location == 0) {
|
||||||
char package[JIMAGE_MAX_PATH];
|
char package[JIMAGE_MAX_PATH];
|
||||||
name_to_package(name, 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') {
|
if (package[0] != '\0') {
|
||||||
const char* module = (*JImagePackageToModule)(_jimage, package);
|
if (!Universe::is_module_initialized()) {
|
||||||
if (module == NULL) {
|
location = (*JImageFindResource)(_jimage, "java.base", get_jimage_version_string(), name, &size);
|
||||||
module = "java.base";
|
#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 (location != 0) {
|
||||||
if (UsePerfData) {
|
if (UsePerfData) {
|
||||||
ClassLoader::perf_sys_classfile_bytes_read()->inc(size);
|
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() {
|
bool ClassPathImageEntry::is_jrt() {
|
||||||
return string_ends_with(name(), BOOT_IMAGE_NAME);
|
return ClassLoader::is_jrt(name());
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if INCLUDE_CDS
|
#if INCLUDE_CDS
|
||||||
void ClassLoader::exit_with_path_failure(const char* error, const char* message) {
|
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);
|
_shared_paths_misc_info->add_boot_classpath(sys_class_path);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
setup_search_path(sys_class_path);
|
setup_search_path(sys_class_path, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if INCLUDE_CDS
|
#if INCLUDE_CDS
|
||||||
@ -500,10 +540,11 @@ bool ClassLoader::check_shared_paths_misc_info(void *buf, int size) {
|
|||||||
}
|
}
|
||||||
#endif
|
#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 offset = 0;
|
||||||
int len = (int)strlen(class_path);
|
int len = (int)strlen(class_path);
|
||||||
int end = 0;
|
int end = 0;
|
||||||
|
bool mark_append_entry = false;
|
||||||
|
|
||||||
// Iterate over class path entries
|
// Iterate over class path entries
|
||||||
for (int start = 0; start < len; start = end) {
|
for (int start = 0; start < len; start = end) {
|
||||||
@ -512,10 +553,23 @@ void ClassLoader::setup_search_path(const char *class_path) {
|
|||||||
}
|
}
|
||||||
EXCEPTION_MARK;
|
EXCEPTION_MARK;
|
||||||
ResourceMark rm(THREAD);
|
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);
|
char* path = NEW_RESOURCE_ARRAY(char, end - start + 1);
|
||||||
strncpy(path, &class_path[start], end - start);
|
strncpy(path, &class_path[start], end - start);
|
||||||
path[end - start] = '\0';
|
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 INCLUDE_CDS
|
||||||
if (DumpSharedSpaces) {
|
if (DumpSharedSpaces) {
|
||||||
check_shared_classpath(path);
|
check_shared_classpath(path);
|
||||||
@ -616,6 +670,18 @@ ClassPathZipEntry* ClassLoader::create_class_path_zip_entry(const char *path) {
|
|||||||
return NULL;
|
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
|
// returns true if entry already on class path
|
||||||
bool ClassLoader::contains_entry(ClassPathEntry *entry) {
|
bool ClassLoader::contains_entry(ClassPathEntry *entry) {
|
||||||
ClassPathEntry* e = _first_entry;
|
ClassPathEntry* e = _first_entry;
|
||||||
@ -641,9 +707,31 @@ void ClassLoader::add_to_list(ClassPathEntry *new_entry) {
|
|||||||
_num_entries ++;
|
_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.
|
// Returns true IFF the file/dir exists and the entry was successfully created.
|
||||||
bool ClassLoader::update_class_path_entry_list(const char *path,
|
bool ClassLoader::update_class_path_entry_list(const char *path,
|
||||||
bool check_for_duplicates,
|
bool check_for_duplicates,
|
||||||
|
bool mark_append_entry,
|
||||||
|
bool prepend_entry,
|
||||||
bool throw_exception) {
|
bool throw_exception) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (os::stat(path, &st) == 0) {
|
if (os::stat(path, &st) == 0) {
|
||||||
@ -654,12 +742,20 @@ bool ClassLoader::update_class_path_entry_list(const char *path,
|
|||||||
if (new_entry == NULL) {
|
if (new_entry == NULL) {
|
||||||
return false;
|
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
|
// Ensure that the first boot loader append entry will always be set correctly.
|
||||||
// (see PackageInfo).
|
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
|
// Add new entry to linked list
|
||||||
|
|
||||||
if (!check_for_duplicates || !contains_entry(new_entry)) {
|
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;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -760,246 +856,205 @@ int ClassLoader::crc32(int crc, const char* buf, int len) {
|
|||||||
return (*Crc32)(crc, (const jbyte*)buf, 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
|
#if INCLUDE_CDS
|
||||||
void PackageHashtable::copy_table(char** top, char* end,
|
void ClassLoader::initialize_module_loader_map(JImageFile* jimage) {
|
||||||
PackageHashtable* table) {
|
jlong size;
|
||||||
// Copy (relocate) the table to the shared space.
|
JImageLocationRef location = (*JImageFindResource)(jimage, "java.base", get_jimage_version_string(), MODULE_LOADER_MAP, &size);
|
||||||
BasicHashtable<mtClass>::copy_table(top, end);
|
if (location == 0) {
|
||||||
|
vm_exit_during_initialization(
|
||||||
// Calculate the space needed for the package name strings.
|
"Cannot find ModuleLoaderMap location from modules jimage.", NULL);
|
||||||
int i;
|
}
|
||||||
intptr_t* tableSize = (intptr_t*)(*top);
|
char* buffer = NEW_RESOURCE_ARRAY(char, size);
|
||||||
*top += sizeof(intptr_t); // For table size
|
jlong read = (*JImageGetResource)(jimage, location, buffer, size);
|
||||||
char* tableStart = *top;
|
if (read != size) {
|
||||||
|
vm_exit_during_initialization(
|
||||||
for (i = 0; i < table_size(); ++i) {
|
"Cannot find ModuleLoaderMap resource from modules jimage.", NULL);
|
||||||
for (PackageInfo* pp = table->bucket(i);
|
}
|
||||||
pp != NULL;
|
char* char_buf = (char*)buffer;
|
||||||
pp = pp->next()) {
|
int buflen = (int)strlen(char_buf);
|
||||||
int n1 = (int)(strlen(pp->pkgname()) + 1);
|
char* begin_ptr = char_buf;
|
||||||
if (*top + n1 >= end) {
|
char* end_ptr = strchr(begin_ptr, '\n');
|
||||||
report_out_of_shared_space(SharedMiscData);
|
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));
|
FREE_RESOURCE_ARRAY(u1, buffer, size);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PackageInfo* ClassLoader::lookup_package(const char *pkgname) {
|
// Function add_package extracts the package from the fully qualified class name
|
||||||
const char *cp = strrchr(pkgname, '/');
|
// 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) {
|
if (cp != NULL) {
|
||||||
// Package prefix found
|
int len = cp - fullq_class_name;
|
||||||
int n = cp - pkgname + 1;
|
PackageEntryTable* pkg_entry_tbl =
|
||||||
return _package_hash_table->get_entry(pkgname, n);
|
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;
|
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) {
|
objArrayOop ClassLoader::get_system_packages(TRAPS) {
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
int nof_entries;
|
// List of pointers to PackageEntrys that have loaded classes.
|
||||||
const char** packages;
|
GrowableArray<PackageEntry*>* loaded_class_pkgs = new GrowableArray<PackageEntry*>(50);
|
||||||
{
|
{
|
||||||
MutexLocker ml(PackageTable_lock, THREAD);
|
MutexLocker ml(Module_lock, THREAD);
|
||||||
// Allocate resource char* array containing package names
|
|
||||||
nof_entries = _package_hash_table->number_of_entries();
|
PackageEntryTable* pe_table =
|
||||||
if ((packages = NEW_RESOURCE_ARRAY(const char*, nof_entries)) == NULL) {
|
ClassLoaderData::the_null_class_loader_data()->packages();
|
||||||
return NULL;
|
|
||||||
|
// 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();
|
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
|
// caller needs ResourceMark
|
||||||
const char* ClassLoader::file_name_for_class_name(const char* class_name,
|
const char* ClassLoader::file_name_for_class_name(const char* class_name,
|
||||||
int class_name_len) {
|
int class_name_len) {
|
||||||
@ -1018,7 +1073,7 @@ const char* ClassLoader::file_name_for_class_name(const char* class_name,
|
|||||||
return file_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(name != NULL, "invariant");
|
||||||
assert(THREAD->is_Java_thread(), "must be a JavaThread");
|
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);
|
ClassLoaderExt::Context context(class_name, file_name, THREAD);
|
||||||
|
|
||||||
// Lookup stream
|
// Lookup stream for parsing .class file
|
||||||
ClassFileStream* stream = NULL;
|
ClassFileStream* stream = NULL;
|
||||||
int classpath_index = 0;
|
s2 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);
|
|
||||||
|
|
||||||
for (; e != NULL; e = e->next(), ++classpath_index) {
|
// If DumpSharedSpaces is true, boot loader visibility boundaries are set
|
||||||
stream = e->open_stream(file_name, CHECK_NULL);
|
// to be _first_entry to the end (all path entries).
|
||||||
if (NULL == stream) {
|
//
|
||||||
continue;
|
// 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)) {
|
if (!context.check(stream, classpath_index)) {
|
||||||
return NULL;
|
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 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
|
// Initialize the class loader's access to methods in libzip. Parse and
|
||||||
// process the boot classpath into a list ClassPathEntry objects. Once
|
// process the boot classpath into a list ClassPathEntry objects. Once
|
||||||
// this list has been created, it must not change order (see class PackageInfo)
|
// 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.
|
// it can be appended to and is by jvmti and the kernel vm.
|
||||||
|
|
||||||
void ClassLoader::initialize() {
|
void ClassLoader::initialize() {
|
||||||
assert(_package_hash_table == NULL, "should have been initialized by now.");
|
|
||||||
EXCEPTION_MARK;
|
EXCEPTION_MARK;
|
||||||
|
|
||||||
if (UsePerfData) {
|
if (UsePerfData) {
|
||||||
@ -1258,12 +1327,48 @@ bool ClassLoader::get_canonical_path(const char* orig, char* out, int len) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
void ClassLoader::create_javabase() {
|
||||||
|
Thread* THREAD = Thread::current();
|
||||||
|
|
||||||
void ClassLoader::verify() {
|
// Create java.base's module entry for the boot
|
||||||
_package_hash_table->verify();
|
// 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
|
// CompileTheWorld
|
||||||
//
|
//
|
||||||
@ -1325,10 +1430,6 @@ void ClassPathDirEntry::compile_the_world(Handle loader, TRAPS) {
|
|||||||
tty->cr();
|
tty->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClassPathDirEntry::is_jrt() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClassPathZipEntry::compile_the_world(Handle loader, TRAPS) {
|
void ClassPathZipEntry::compile_the_world(Handle loader, TRAPS) {
|
||||||
real_jzfile* zip = (real_jzfile*) _zip;
|
real_jzfile* zip = (real_jzfile*) _zip;
|
||||||
tty->print_cr("CompileTheWorld : Compiling all classes in %s", zip->name);
|
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() {
|
void ClassLoader::compile_the_world() {
|
||||||
EXCEPTION_MARK;
|
EXCEPTION_MARK;
|
||||||
HandleMark hm(THREAD);
|
HandleMark hm(THREAD);
|
||||||
@ -1366,7 +1463,7 @@ void ClassLoader::compile_the_world() {
|
|||||||
ClassPathEntry* e = _first_entry;
|
ClassPathEntry* e = _first_entry;
|
||||||
jlong start = os::javaTimeMillis();
|
jlong start = os::javaTimeMillis();
|
||||||
while (e != NULL) {
|
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;
|
if (e->is_jrt() && e != _first_entry) break;
|
||||||
e->compile_the_world(system_class_loader, CATCH);
|
e->compile_the_world(system_class_loader, CATCH);
|
||||||
e = e->next();
|
e = e->next();
|
||||||
|
@ -33,8 +33,17 @@
|
|||||||
// The VM class loader.
|
// The VM class loader.
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
// Name of boot module image
|
// Name of boot "modules" image
|
||||||
#define BOOT_IMAGE_NAME "bootmodules.jimage"
|
#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 JImageFile;
|
||||||
class ClassFileStream;
|
class ClassFileStream;
|
||||||
@ -49,6 +58,7 @@ public:
|
|||||||
// may have unlocked readers, so write atomically.
|
// may have unlocked readers, so write atomically.
|
||||||
OrderAccess::release_store_ptr(&_next, next);
|
OrderAccess::release_store_ptr(&_next, next);
|
||||||
}
|
}
|
||||||
|
virtual bool is_jrt() = 0;
|
||||||
virtual bool is_jar_file() const = 0;
|
virtual bool is_jar_file() const = 0;
|
||||||
virtual const char* name() const = 0;
|
virtual const char* name() const = 0;
|
||||||
virtual JImageFile* jimage() const = 0;
|
virtual JImageFile* jimage() const = 0;
|
||||||
@ -59,13 +69,13 @@ public:
|
|||||||
virtual ClassFileStream* open_stream(const char* name, TRAPS) = 0;
|
virtual ClassFileStream* open_stream(const char* name, TRAPS) = 0;
|
||||||
// Debugging
|
// Debugging
|
||||||
NOT_PRODUCT(virtual void compile_the_world(Handle loader, TRAPS) = 0;)
|
NOT_PRODUCT(virtual void compile_the_world(Handle loader, TRAPS) = 0;)
|
||||||
NOT_PRODUCT(virtual bool is_jrt() = 0;)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ClassPathDirEntry: public ClassPathEntry {
|
class ClassPathDirEntry: public ClassPathEntry {
|
||||||
private:
|
private:
|
||||||
const char* _dir; // Name of directory
|
const char* _dir; // Name of directory
|
||||||
public:
|
public:
|
||||||
|
bool is_jrt() { return false; }
|
||||||
bool is_jar_file() const { return false; }
|
bool is_jar_file() const { return false; }
|
||||||
const char* name() const { return _dir; }
|
const char* name() const { return _dir; }
|
||||||
JImageFile* jimage() const { return NULL; }
|
JImageFile* jimage() const { return NULL; }
|
||||||
@ -73,7 +83,6 @@ class ClassPathDirEntry: public ClassPathEntry {
|
|||||||
ClassFileStream* open_stream(const char* name, TRAPS);
|
ClassFileStream* open_stream(const char* name, TRAPS);
|
||||||
// Debugging
|
// Debugging
|
||||||
NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
|
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
|
jzfile* _zip; // The zip archive
|
||||||
const char* _zip_name; // Name of zip archive
|
const char* _zip_name; // Name of zip archive
|
||||||
public:
|
public:
|
||||||
|
bool is_jrt() { return false; }
|
||||||
bool is_jar_file() const { return true; }
|
bool is_jar_file() const { return true; }
|
||||||
const char* name() const { return _zip_name; }
|
const char* name() const { return _zip_name; }
|
||||||
JImageFile* jimage() const { return NULL; }
|
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);
|
void contents_do(void f(const char* name, void* context), void* context);
|
||||||
// Debugging
|
// Debugging
|
||||||
NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
|
NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
|
||||||
NOT_PRODUCT(bool is_jrt();)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -116,29 +125,28 @@ private:
|
|||||||
JImageFile* _jimage;
|
JImageFile* _jimage;
|
||||||
const char* _name;
|
const char* _name;
|
||||||
public:
|
public:
|
||||||
|
bool is_jrt();
|
||||||
bool is_jar_file() const { return false; }
|
bool is_jar_file() const { return false; }
|
||||||
bool is_open() const { return _jimage != NULL; }
|
bool is_open() const { return _jimage != NULL; }
|
||||||
const char* name() const { return _name == NULL ? "" : _name; }
|
const char* name() const { return _name == NULL ? "" : _name; }
|
||||||
JImageFile* jimage() const { return _jimage; }
|
JImageFile* jimage() const { return _jimage; }
|
||||||
ClassPathImageEntry(JImageFile* jimage, const char* name);
|
ClassPathImageEntry(JImageFile* jimage, const char* name);
|
||||||
~ClassPathImageEntry();
|
~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);
|
ClassFileStream* open_stream(const char* name, TRAPS);
|
||||||
|
|
||||||
// Debugging
|
// Debugging
|
||||||
NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
|
NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
|
||||||
NOT_PRODUCT(bool is_jrt();)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class PackageHashtable;
|
|
||||||
class PackageInfo;
|
|
||||||
class SharedPathsMiscInfo;
|
class SharedPathsMiscInfo;
|
||||||
template <MEMFLAGS F> class HashtableBucket;
|
|
||||||
|
|
||||||
class ClassLoader: AllStatic {
|
class ClassLoader: AllStatic {
|
||||||
public:
|
public:
|
||||||
enum SomeConstants {
|
enum ClassLoaderType {
|
||||||
package_hash_table_size = 31 // Number of buckets
|
BOOT_LOADER = 1, /* boot loader */
|
||||||
|
PLATFORM_LOADER = 2, /* PlatformClassLoader */
|
||||||
|
APP_LOADER = 3 /* AppClassLoader */
|
||||||
};
|
};
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
@ -177,41 +185,60 @@ class ClassLoader: AllStatic {
|
|||||||
static PerfCounter* _isUnsyncloadClass;
|
static PerfCounter* _isUnsyncloadClass;
|
||||||
static PerfCounter* _load_instance_class_failCounter;
|
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;
|
static ClassPathEntry* _first_entry;
|
||||||
// Last entry in linked list of ClassPathEntry instances
|
// Last entry in linked list of ClassPathEntry instances
|
||||||
static ClassPathEntry* _last_entry;
|
static ClassPathEntry* _last_entry;
|
||||||
static int _num_entries;
|
static int _num_entries;
|
||||||
|
|
||||||
// Hash table used to keep track of loaded packages
|
// Pointer into the linked list of ClassPathEntry instances.
|
||||||
static PackageHashtable* _package_hash_table;
|
// 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;
|
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
|
// Info used by CDS
|
||||||
CDS_ONLY(static SharedPathsMiscInfo * _shared_paths_misc_info;)
|
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
|
// Initialization
|
||||||
static void setup_bootstrap_search_path();
|
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_zip_library();
|
||||||
static void load_jimage_library();
|
static void load_jimage_library();
|
||||||
static ClassPathEntry* create_class_path_entry(const char *path, const struct stat* st,
|
static ClassPathEntry* create_class_path_entry(const char *path, const struct stat* st,
|
||||||
bool throw_exception, TRAPS);
|
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
|
// Canonicalizes path names, so strcmp will work properly. This is mainly
|
||||||
// to avoid confusing the zip library
|
// to avoid confusing the zip library
|
||||||
static bool get_canonical_path(const char* orig, char* out, int len);
|
static bool get_canonical_path(const char* orig, char* out, int len);
|
||||||
|
|
||||||
static const char* file_name_for_class_name(const char* class_name,
|
static const char* file_name_for_class_name(const char* class_name,
|
||||||
int class_name_len);
|
int class_name_len);
|
||||||
|
|
||||||
@ -220,6 +247,8 @@ class ClassLoader: AllStatic {
|
|||||||
static int crc32(int crc, const char* buf, int len);
|
static int crc32(int crc, const char* buf, int len);
|
||||||
static bool update_class_path_entry_list(const char *path,
|
static bool update_class_path_entry_list(const char *path,
|
||||||
bool check_for_duplicates,
|
bool check_for_duplicates,
|
||||||
|
bool mark_append_entry,
|
||||||
|
bool prepend_entry,
|
||||||
bool throw_exception=true);
|
bool throw_exception=true);
|
||||||
static void print_bootclasspath();
|
static void print_bootclasspath();
|
||||||
|
|
||||||
@ -284,8 +313,18 @@ class ClassLoader: AllStatic {
|
|||||||
return _load_instance_class_failCounter;
|
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
|
// 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
|
// 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.
|
// the name of the directory or ZIP file that the package was loaded from.
|
||||||
@ -304,9 +343,7 @@ class ClassLoader: AllStatic {
|
|||||||
// Initialization
|
// Initialization
|
||||||
static void initialize();
|
static void initialize();
|
||||||
CDS_ONLY(static void initialize_shared_path();)
|
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 int compute_Object_vtable();
|
||||||
|
|
||||||
static ClassPathEntry* classpath_entry(int n) {
|
static ClassPathEntry* classpath_entry(int n) {
|
||||||
@ -320,8 +357,6 @@ class ClassLoader: AllStatic {
|
|||||||
|
|
||||||
#if INCLUDE_CDS
|
#if INCLUDE_CDS
|
||||||
// Sharing dump and restore
|
// 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 check_shared_classpath(const char *path);
|
||||||
static void finalize_shared_paths_misc_info();
|
static void finalize_shared_paths_misc_info();
|
||||||
@ -329,7 +364,12 @@ class ClassLoader: AllStatic {
|
|||||||
static void* get_shared_paths_misc_info();
|
static void* get_shared_paths_misc_info();
|
||||||
static bool check_shared_paths_misc_info(void* info, int size);
|
static bool check_shared_paths_misc_info(void* info, int size);
|
||||||
static void exit_with_path_failure(const char* error, const char* message);
|
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
|
#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);
|
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_count();
|
||||||
static jlong class_link_time_ms();
|
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)
|
// indicates if class path already contains a entry (exact match by name)
|
||||||
static bool contains_entry(ClassPathEntry* entry);
|
static bool contains_entry(ClassPathEntry* entry);
|
||||||
|
|
||||||
// adds a class path list
|
// adds a class path list
|
||||||
static void add_to_list(ClassPathEntry* new_entry);
|
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)
|
// creates a class path zip entry (returns NULL if JAR file cannot be opened)
|
||||||
static ClassPathZipEntry* create_class_path_zip_entry(const char *apath);
|
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
|
// Debugging
|
||||||
static void verify() PRODUCT_RETURN;
|
static void verify() PRODUCT_RETURN;
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
//
|
//
|
||||||
// Class loaders that implement a deterministic name resolution strategy
|
// Class loaders that implement a deterministic name resolution strategy
|
||||||
// (including with respect to their delegation behavior), such as the boot, the
|
// (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.
|
// hierarchy, always produce the same linkset for a given configuration.
|
||||||
//
|
//
|
||||||
// ClassLoaderData carries information related to a linkset (e.g.,
|
// ClassLoaderData carries information related to a linkset (e.g.,
|
||||||
@ -51,6 +51,8 @@
|
|||||||
#include "classfile/classLoaderData.inline.hpp"
|
#include "classfile/classLoaderData.inline.hpp"
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
#include "classfile/metadataOnStackMark.hpp"
|
#include "classfile/metadataOnStackMark.hpp"
|
||||||
|
#include "classfile/moduleEntry.hpp"
|
||||||
|
#include "classfile/packageEntry.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
#include "gc/shared/gcLocker.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.
|
// The null-class-loader should always be kept alive.
|
||||||
_keep_alive(is_anonymous || h_class_loader.is_null()),
|
_keep_alive(is_anonymous || h_class_loader.is_null()),
|
||||||
_metaspace(NULL), _unloading(false), _klasses(NULL),
|
_metaspace(NULL), _unloading(false), _klasses(NULL),
|
||||||
|
_modules(NULL), _packages(NULL),
|
||||||
_claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL),
|
_claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL),
|
||||||
_next(NULL), _dependencies(dependencies), _shared_class_loader_id(-1),
|
_next(NULL), _dependencies(dependencies), _shared_class_loader_id(-1),
|
||||||
_metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true,
|
_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) {
|
void ClassLoaderData::record_dependency(const Klass* k, TRAPS) {
|
||||||
assert(k != NULL, "invariant");
|
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 {
|
oop ClassLoaderData::keep_alive_object() const {
|
||||||
assert(!keep_alive(), "Don't use with CLDs that are artificially kept alive");
|
assert(!keep_alive(), "Don't use with CLDs that are artificially kept alive");
|
||||||
return is_anonymous() ? _klasses->java_mirror() : class_loader();
|
return is_anonymous() ? _klasses->java_mirror() : class_loader();
|
||||||
@ -358,16 +425,30 @@ ClassLoaderData::~ClassLoaderData() {
|
|||||||
// Release C heap structures for all the classes.
|
// Release C heap structures for all the classes.
|
||||||
classes_do(InstanceKlass::release_C_heap_structures);
|
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;
|
Metaspace *m = _metaspace;
|
||||||
if (m != NULL) {
|
if (m != NULL) {
|
||||||
_metaspace = NULL;
|
_metaspace = NULL;
|
||||||
// release the metaspace
|
|
||||||
delete m;
|
delete m;
|
||||||
// release the handles
|
}
|
||||||
if (_handles != NULL) {
|
// release the handles
|
||||||
JNIHandleBlock::release_block(_handles);
|
if (_handles != NULL) {
|
||||||
_handles = NULL;
|
JNIHandleBlock::release_block(_handles);
|
||||||
}
|
_handles = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear all the JNI handles for methods
|
// 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 {
|
bool ClassLoaderData::is_platform_class_loader_data() const {
|
||||||
return SystemDictionary::is_ext_class_loader(class_loader());
|
return SystemDictionary::is_platform_class_loader(class_loader());
|
||||||
}
|
}
|
||||||
|
|
||||||
Metaspace* ClassLoaderData::metaspace_non_null() {
|
Metaspace* ClassLoaderData::metaspace_non_null() {
|
||||||
@ -438,6 +519,10 @@ jobject ClassLoaderData::add_handle(Handle h) {
|
|||||||
return handles()->allocate_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
|
// 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.
|
// class unloading because Handles might point to this metadata field.
|
||||||
void ClassLoaderData::add_to_deallocate_list(Metadata* m) {
|
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) {
|
void ClassLoaderDataGraph::loaded_classes_do(KlassClosure* klass_closure) {
|
||||||
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
|
for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
|
||||||
cld->loaded_classes_do(klass_closure);
|
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
|
// Only walk the head until any clds not purged from prior unloading
|
||||||
// (CMS doesn't purge right away).
|
// (CMS doesn't purge right away).
|
||||||
for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
|
for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
|
||||||
|
assert(cld->is_unloading(), "invariant");
|
||||||
cld->classes_do(f);
|
cld->classes_do(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -800,6 +920,12 @@ bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure,
|
|||||||
data = _head;
|
data = _head;
|
||||||
while (data != NULL) {
|
while (data != NULL) {
|
||||||
if (data->is_alive(is_alive_closure)) {
|
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
|
// clean metaspace
|
||||||
if (walk_all_metadata) {
|
if (walk_all_metadata) {
|
||||||
data->classes_do(InstanceKlass::purge_previous_versions);
|
data->classes_do(InstanceKlass::purge_previous_versions);
|
||||||
@ -992,6 +1118,7 @@ void ClassLoaderData::print_value_on(outputStream* out) const {
|
|||||||
Ticks ClassLoaderDataGraph::_class_unload_time;
|
Ticks ClassLoaderDataGraph::_class_unload_time;
|
||||||
|
|
||||||
void ClassLoaderDataGraph::class_unload_event(Klass* const k) {
|
void ClassLoaderDataGraph::class_unload_event(Klass* const k) {
|
||||||
|
assert(k != NULL, "invariant");
|
||||||
|
|
||||||
// post class unload event
|
// post class unload event
|
||||||
EventClassUnload event(UNTIMED);
|
EventClassUnload event(UNTIMED);
|
||||||
|
@ -53,6 +53,10 @@ class ClassLoaderData;
|
|||||||
class JNIMethodBlock;
|
class JNIMethodBlock;
|
||||||
class JNIHandleBlock;
|
class JNIHandleBlock;
|
||||||
class Metadebug;
|
class Metadebug;
|
||||||
|
class ModuleEntry;
|
||||||
|
class PackageEntry;
|
||||||
|
class ModuleEntryTable;
|
||||||
|
class PackageEntryTable;
|
||||||
|
|
||||||
// GC root for walking class loader data created
|
// 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(KlassClosure* klass_closure);
|
||||||
static void classes_do(void f(Klass* const));
|
static void classes_do(void f(Klass* const));
|
||||||
static void methods_do(void f(Method*));
|
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 loaded_classes_do(KlassClosure* klass_closure);
|
||||||
static void classes_unloading_do(void f(Klass* const));
|
static void classes_unloading_do(void f(Klass* const));
|
||||||
static bool do_unloading(BoolObjectClosure* is_alive, bool clean_previous_versions);
|
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.
|
volatile int _claimed; // true if claimed, for example during GC traces.
|
||||||
// To avoid applying oop closure more than once.
|
// To avoid applying oop closure more than once.
|
||||||
// Has to be an int because we cas it.
|
// 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
|
// 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
|
// 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 loaded_classes_do(KlassClosure* klass_closure);
|
||||||
void classes_do(void f(InstanceKlass*));
|
void classes_do(void f(InstanceKlass*));
|
||||||
void methods_do(void f(Method*));
|
void methods_do(void f(Method*));
|
||||||
|
void modules_do(void f(ModuleEntry*));
|
||||||
|
void packages_do(void f(PackageEntry*));
|
||||||
|
|
||||||
// Deallocate free list during class unloading.
|
// Deallocate free list during class unloading.
|
||||||
void free_deallocate_list();
|
void free_deallocate_list();
|
||||||
@ -256,7 +269,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
|||||||
bool is_the_null_class_loader_data() const {
|
bool is_the_null_class_loader_data() const {
|
||||||
return this == _the_null_class_loader_data;
|
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
|
// The Metaspace is created lazily so may be NULL. This
|
||||||
// method will allocate a Metaspace if needed.
|
// method will allocate a Metaspace if needed.
|
||||||
@ -293,11 +306,16 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
|||||||
const char* loader_name();
|
const char* loader_name();
|
||||||
|
|
||||||
jobject add_handle(Handle h);
|
jobject add_handle(Handle h);
|
||||||
|
void remove_handle(jobject h);
|
||||||
void add_class(Klass* k, bool publicize = true);
|
void add_class(Klass* k, bool publicize = true);
|
||||||
void remove_class(Klass* k);
|
void remove_class(Klass* k);
|
||||||
bool contains_klass(Klass* k);
|
bool contains_klass(Klass* k);
|
||||||
void record_dependency(const Klass* to, TRAPS);
|
void record_dependency(const Klass* to, TRAPS);
|
||||||
void init_dependencies(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);
|
void add_to_deallocate_list(Metadata* m);
|
||||||
|
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -49,12 +49,14 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceKlassHandle record_result(const int classpath_index,
|
instanceKlassHandle record_result(const s2 classpath_index,
|
||||||
|
const jshort classloader_type,
|
||||||
const ClassPathEntry* e,
|
const ClassPathEntry* e,
|
||||||
instanceKlassHandle result, TRAPS) {
|
instanceKlassHandle result, TRAPS) {
|
||||||
if (ClassLoader::add_package(_file_name, classpath_index, THREAD)) {
|
if (ClassLoader::add_package(_file_name, classpath_index, THREAD)) {
|
||||||
if (DumpSharedSpaces) {
|
if (DumpSharedSpaces) {
|
||||||
result->set_shared_classpath_index(classpath_index);
|
result->set_shared_classpath_index(classpath_index);
|
||||||
|
result->set_class_loader_type(classloader_type);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
@ -65,13 +67,27 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
static void add_class_path_entry(const char* path, bool check_for_duplicates,
|
static void add_class_path_entry(const char* path, bool check_for_duplicates,
|
||||||
ClassPathEntry* new_entry) {
|
ClassPathEntry* new_entry, bool prepend_entry) {
|
||||||
ClassLoader::add_to_list(new_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) {
|
static void append_boot_classpath(ClassPathEntry* new_entry) {
|
||||||
ClassLoader::add_to_list(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 void setup_search_paths() {}
|
||||||
|
static bool is_boot_classpath(int classpath_index) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
static Klass* load_one_class(ClassListParser* parser, TRAPS);
|
static Klass* load_one_class(ClassListParser* parser, TRAPS);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -24,7 +24,9 @@
|
|||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/altHashing.hpp"
|
#include "classfile/altHashing.hpp"
|
||||||
|
#include "classfile/classLoaderData.inline.hpp"
|
||||||
#include "classfile/javaClasses.inline.hpp"
|
#include "classfile/javaClasses.inline.hpp"
|
||||||
|
#include "classfile/moduleEntry.hpp"
|
||||||
#include "classfile/stringTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/vmSymbols.hpp"
|
#include "classfile/vmSymbols.hpp"
|
||||||
#include "code/debugInfo.hpp"
|
#include "code/debugInfo.hpp"
|
||||||
@ -768,7 +770,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,
|
void java_lang_Class::initialize_mirror_fields(KlassHandle k,
|
||||||
@ -789,7 +791,7 @@ void java_lang_Class::initialize_mirror_fields(KlassHandle k,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader,
|
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");
|
assert(k->java_mirror() == NULL, "should only assign mirror once");
|
||||||
// Use this moment of initialization to cache modifier_flags also,
|
// Use this moment of initialization to cache modifier_flags also,
|
||||||
// to support Class.getModifiers(). Instance classes recalculate
|
// to support Class.getModifiers(). Instance classes recalculate
|
||||||
@ -849,11 +851,25 @@ void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader,
|
|||||||
assert(class_loader() == k->class_loader(), "should be same");
|
assert(class_loader() == k->class_loader(), "should be same");
|
||||||
set_class_loader(mirror(), class_loader());
|
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
|
// Setup indirection from klass->mirror last
|
||||||
// after any exceptions can happen during allocations.
|
// after any exceptions can happen during allocations.
|
||||||
if (!k.is_null()) {
|
if (!k.is_null()) {
|
||||||
k->set_java_mirror(mirror());
|
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 {
|
} else {
|
||||||
if (fixup_mirror_list() == NULL) {
|
if (fixup_mirror_list() == NULL) {
|
||||||
GrowableArray<Klass*>* list =
|
GrowableArray<Klass*>* list =
|
||||||
@ -864,6 +880,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) {
|
int java_lang_Class::oop_size(oop java_class) {
|
||||||
assert(_oop_size_offset != 0, "must be set");
|
assert(_oop_size_offset != 0, "must be set");
|
||||||
@ -931,6 +951,16 @@ oop java_lang_Class::class_loader(oop java_class) {
|
|||||||
return java_class->obj_field(_class_loader_offset);
|
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) {
|
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
|
// This should be improved by adding a field at the Java level or by
|
||||||
// introducing a new VM klass (see comment in ClassFileParser)
|
// introducing a new VM klass (see comment in ClassFileParser)
|
||||||
@ -1116,6 +1146,10 @@ void java_lang_Class::compute_offsets() {
|
|||||||
k, vmSymbols::componentType_name(),
|
k, vmSymbols::componentType_name(),
|
||||||
vmSymbols::class_signature());
|
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 is a C union with component_mirror. Only instanceKlass mirrors have
|
||||||
// init_lock and only ArrayKlass mirrors have component_mirror. Since both are oops
|
// init_lock and only ArrayKlass mirrors have component_mirror. Since both are oops
|
||||||
// GC treats them the same.
|
// GC treats them the same.
|
||||||
@ -1668,28 +1702,48 @@ char* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror,
|
|||||||
buf_len += (int)strlen(source_file_name);
|
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
|
// Allocate temporary buffer with extra space for formatting and line number
|
||||||
char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64);
|
char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64);
|
||||||
|
|
||||||
// Print stack trace line in buffer
|
// 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)) {
|
if (!version_matches(method, version)) {
|
||||||
strcat(buf, "(Redefined)");
|
strcat(buf, "Redefined)");
|
||||||
} else {
|
} else {
|
||||||
int line_number = Backtrace::get_line_number(method, bci);
|
int line_number = Backtrace::get_line_number(method, bci);
|
||||||
if (line_number == -2) {
|
if (line_number == -2) {
|
||||||
strcat(buf, "(Native Method)");
|
strcat(buf, "Native Method)");
|
||||||
} else {
|
} else {
|
||||||
if (source_file_name != NULL && (line_number != -1)) {
|
if (source_file_name != NULL && (line_number != -1)) {
|
||||||
// Sourcename and linenumber
|
// 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) {
|
} else if (source_file_name != NULL) {
|
||||||
// Just sourcename
|
// Just sourcename
|
||||||
sprintf(buf + (int)strlen(buf), "(%s)", source_file_name);
|
sprintf(buf + (int)strlen(buf), "%s)", source_file_name);
|
||||||
} else {
|
} else {
|
||||||
// Neither sourcename nor linenumber
|
// Neither sourcename nor linenumber
|
||||||
sprintf(buf + (int)strlen(buf), "(Unknown Source)");
|
sprintf(buf + (int)strlen(buf), "Unknown Source)");
|
||||||
}
|
}
|
||||||
nmethod* nm = method->code();
|
nmethod* nm = method->code();
|
||||||
if (WizardMode && nm != NULL) {
|
if (WizardMode && nm != NULL) {
|
||||||
@ -2094,6 +2148,20 @@ oop java_lang_StackTraceElement::create(Handle mirror, int method_id,
|
|||||||
oop methodname = StringTable::intern(sym, CHECK_0);
|
oop methodname = StringTable::intern(sym, CHECK_0);
|
||||||
java_lang_StackTraceElement::set_methodName(element(), methodname);
|
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_0);
|
||||||
|
java_lang_StackTraceElement::set_moduleName(element(), module_name);
|
||||||
|
oop module_version;
|
||||||
|
if (module->version() != NULL) {
|
||||||
|
module_version = StringTable::intern(module->version(), CHECK_0);
|
||||||
|
} else {
|
||||||
|
module_version = NULL;
|
||||||
|
}
|
||||||
|
java_lang_StackTraceElement::set_moduleVersion(element(), module_version);
|
||||||
|
}
|
||||||
|
|
||||||
if (!version_matches(method, version)) {
|
if (!version_matches(method, version)) {
|
||||||
// The method was redefined, accurate line number information isn't available
|
// The method was redefined, accurate line number information isn't available
|
||||||
java_lang_StackTraceElement::set_fileName(element(), NULL);
|
java_lang_StackTraceElement::set_fileName(element(), NULL);
|
||||||
@ -2753,6 +2821,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) {
|
Handle sun_reflect_ConstantPool::create(TRAPS) {
|
||||||
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
|
||||||
Klass* k = SystemDictionary::reflect_ConstantPool_klass();
|
Klass* k = SystemDictionary::reflect_ConstantPool_klass();
|
||||||
@ -3352,6 +3494,7 @@ oop java_security_AccessControlContext::create(objArrayHandle context, bool isPr
|
|||||||
bool java_lang_ClassLoader::offsets_computed = false;
|
bool java_lang_ClassLoader::offsets_computed = false;
|
||||||
int java_lang_ClassLoader::_loader_data_offset = -1;
|
int java_lang_ClassLoader::_loader_data_offset = -1;
|
||||||
int java_lang_ClassLoader::parallelCapable_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) {
|
ClassLoaderData** java_lang_ClassLoader::loader_data_addr(oop loader) {
|
||||||
assert(loader != NULL && loader->is_oop(), "loader must be oop");
|
assert(loader != NULL && loader->is_oop(), "loader must be oop");
|
||||||
@ -3371,6 +3514,9 @@ void java_lang_ClassLoader::compute_offsets() {
|
|||||||
compute_optional_offset(parallelCapable_offset,
|
compute_optional_offset(parallelCapable_offset,
|
||||||
k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature());
|
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);
|
CLASSLOADER_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3438,6 +3584,10 @@ oop java_lang_ClassLoader::non_reflection_class_loader(oop loader) {
|
|||||||
return 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
|
// Support for java_lang_System
|
||||||
int java_lang_System::in_offset_in_bytes() {
|
int java_lang_System::in_offset_in_bytes() {
|
||||||
@ -3470,11 +3620,13 @@ int java_lang_Class::_array_klass_offset;
|
|||||||
int java_lang_Class::_oop_size_offset;
|
int java_lang_Class::_oop_size_offset;
|
||||||
int java_lang_Class::_static_oop_field_count_offset;
|
int java_lang_Class::_static_oop_field_count_offset;
|
||||||
int java_lang_Class::_class_loader_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::_protection_domain_offset;
|
||||||
int java_lang_Class::_component_mirror_offset;
|
int java_lang_Class::_component_mirror_offset;
|
||||||
int java_lang_Class::_init_lock_offset;
|
int java_lang_Class::_init_lock_offset;
|
||||||
int java_lang_Class::_signers_offset;
|
int java_lang_Class::_signers_offset;
|
||||||
GrowableArray<Klass*>* java_lang_Class::_fixup_mirror_list = NULL;
|
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::backtrace_offset;
|
||||||
int java_lang_Throwable::detailMessage_offset;
|
int java_lang_Throwable::detailMessage_offset;
|
||||||
int java_lang_Throwable::cause_offset;
|
int java_lang_Throwable::cause_offset;
|
||||||
@ -3534,6 +3686,8 @@ int java_lang_StackTraceElement::declaringClass_offset;
|
|||||||
int java_lang_StackTraceElement::methodName_offset;
|
int java_lang_StackTraceElement::methodName_offset;
|
||||||
int java_lang_StackTraceElement::fileName_offset;
|
int java_lang_StackTraceElement::fileName_offset;
|
||||||
int java_lang_StackTraceElement::lineNumber_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::_declaringClass_offset;
|
||||||
int java_lang_StackFrameInfo::_memberName_offset;
|
int java_lang_StackFrameInfo::_memberName_offset;
|
||||||
int java_lang_StackFrameInfo::_bci_offset;
|
int java_lang_StackFrameInfo::_bci_offset;
|
||||||
@ -3575,6 +3729,14 @@ void java_lang_StackTraceElement::set_lineNumber(oop element, int value) {
|
|||||||
element->int_field_put(lineNumber_offset, 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
|
// Support for java_lang_StackFrameInfo
|
||||||
void java_lang_StackFrameInfo::set_declaringClass(oop element, oop value) {
|
void java_lang_StackFrameInfo::set_declaringClass(oop element, oop value) {
|
||||||
element->obj_field_put(_declaringClass_offset, value);
|
element->obj_field_put(_declaringClass_offset, value);
|
||||||
@ -3713,6 +3875,8 @@ void JavaClasses::compute_hard_coded_offsets() {
|
|||||||
java_lang_System::static_security_offset = java_lang_System::hc_static_security_offset * x;
|
java_lang_System::static_security_offset = java_lang_System::hc_static_security_offset * x;
|
||||||
|
|
||||||
// java_lang_StackTraceElement
|
// 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::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::methodName_offset = java_lang_StackTraceElement::hc_methodName_offset * x + header;
|
||||||
java_lang_StackTraceElement::fileName_offset = java_lang_StackTraceElement::hc_fileName_offset * x + header;
|
java_lang_StackTraceElement::fileName_offset = java_lang_StackTraceElement::hc_fileName_offset * x + header;
|
||||||
@ -3752,6 +3916,7 @@ void JavaClasses::compute_offsets() {
|
|||||||
sun_reflect_ConstantPool::compute_offsets();
|
sun_reflect_ConstantPool::compute_offsets();
|
||||||
sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets();
|
sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets();
|
||||||
java_lang_reflect_Parameter::compute_offsets();
|
java_lang_reflect_Parameter::compute_offsets();
|
||||||
|
java_lang_reflect_Module::compute_offsets();
|
||||||
java_lang_StackFrameInfo::compute_offsets();
|
java_lang_StackFrameInfo::compute_offsets();
|
||||||
java_lang_LiveStackFrameInfo::compute_offsets();
|
java_lang_LiveStackFrameInfo::compute_offsets();
|
||||||
|
|
||||||
@ -3899,7 +4064,7 @@ void JavaClasses::check_offsets() {
|
|||||||
|
|
||||||
// java.lang.ClassLoader
|
// 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
|
// java.lang.System
|
||||||
|
|
||||||
|
@ -210,12 +210,14 @@ class java_lang_Class : AllStatic {
|
|||||||
static int _init_lock_offset;
|
static int _init_lock_offset;
|
||||||
static int _signers_offset;
|
static int _signers_offset;
|
||||||
static int _class_loader_offset;
|
static int _class_loader_offset;
|
||||||
|
static int _module_offset;
|
||||||
static int _component_mirror_offset;
|
static int _component_mirror_offset;
|
||||||
|
|
||||||
static bool offsets_computed;
|
static bool offsets_computed;
|
||||||
static int classRedefinedCount_offset;
|
static int classRedefinedCount_offset;
|
||||||
|
|
||||||
static GrowableArray<Klass*>* _fixup_mirror_list;
|
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_init_lock(oop java_class, oop init_lock);
|
||||||
static void set_protection_domain(oop java_class, oop protection_domain);
|
static void set_protection_domain(oop java_class, oop protection_domain);
|
||||||
@ -226,10 +228,13 @@ class java_lang_Class : AllStatic {
|
|||||||
static void compute_offsets();
|
static void compute_offsets();
|
||||||
|
|
||||||
// Instance creation
|
// 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);
|
Handle protection_domain, TRAPS);
|
||||||
static void fixup_mirror(KlassHandle k, TRAPS);
|
static void fixup_mirror(KlassHandle k, TRAPS);
|
||||||
static oop create_basic_type_mirror(const char* basic_type_name, BasicType type, 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
|
// Conversion
|
||||||
static Klass* as_Klass(oop java_class);
|
static Klass* as_Klass(oop java_class);
|
||||||
static void set_klass(oop java_class, Klass* klass);
|
static void set_klass(oop java_class, Klass* klass);
|
||||||
@ -267,18 +272,29 @@ class java_lang_Class : AllStatic {
|
|||||||
static void set_signers(oop java_class, objArrayOop signers);
|
static void set_signers(oop java_class, objArrayOop signers);
|
||||||
|
|
||||||
static oop class_loader(oop java_class);
|
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 int oop_size(oop java_class);
|
||||||
static void set_oop_size(oop java_class, int size);
|
static void set_oop_size(oop java_class, int size);
|
||||||
static int static_oop_field_count(oop java_class);
|
static int static_oop_field_count(oop java_class);
|
||||||
static void set_static_oop_field_count(oop java_class, int size);
|
static void set_static_oop_field_count(oop java_class, int size);
|
||||||
|
|
||||||
|
|
||||||
static GrowableArray<Klass*>* fixup_mirror_list() {
|
static GrowableArray<Klass*>* fixup_mirror_list() {
|
||||||
return _fixup_mirror_list;
|
return _fixup_mirror_list;
|
||||||
}
|
}
|
||||||
static void set_fixup_mirror_list(GrowableArray<Klass*>* v) {
|
static void set_fixup_mirror_list(GrowableArray<Klass*>* v) {
|
||||||
_fixup_mirror_list = 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
|
// Debugging
|
||||||
friend class JavaClasses;
|
friend class JavaClasses;
|
||||||
friend class InstanceKlass; // verification code accesses offsets
|
friend class InstanceKlass; // verification code accesses offsets
|
||||||
@ -758,6 +774,39 @@ class java_lang_reflect_Parameter {
|
|||||||
friend class JavaClasses;
|
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
|
// Interface to sun.reflect.ConstantPool objects
|
||||||
class sun_reflect_ConstantPool {
|
class sun_reflect_ConstantPool {
|
||||||
private:
|
private:
|
||||||
@ -1203,6 +1252,7 @@ class java_lang_ClassLoader : AllStatic {
|
|||||||
static bool offsets_computed;
|
static bool offsets_computed;
|
||||||
static int parent_offset;
|
static int parent_offset;
|
||||||
static int parallelCapable_offset;
|
static int parallelCapable_offset;
|
||||||
|
static int unnamedModule_offset;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void compute_offsets();
|
static void compute_offsets();
|
||||||
@ -1227,6 +1277,8 @@ class java_lang_ClassLoader : AllStatic {
|
|||||||
}
|
}
|
||||||
static bool is_instance(oop obj);
|
static bool is_instance(oop obj);
|
||||||
|
|
||||||
|
static oop unnamedModule(oop loader);
|
||||||
|
|
||||||
// Debugging
|
// Debugging
|
||||||
friend class JavaClasses;
|
friend class JavaClasses;
|
||||||
friend class ClassFileParser; // access to number_of_fake_fields
|
friend class ClassFileParser; // access to number_of_fake_fields
|
||||||
@ -1266,12 +1318,16 @@ class java_lang_System : AllStatic {
|
|||||||
class java_lang_StackTraceElement: AllStatic {
|
class java_lang_StackTraceElement: AllStatic {
|
||||||
private:
|
private:
|
||||||
enum {
|
enum {
|
||||||
hc_declaringClass_offset = 0,
|
hc_moduleName_offset = 0,
|
||||||
hc_methodName_offset = 1,
|
hc_moduleVersion_offset = 1,
|
||||||
hc_fileName_offset = 2,
|
hc_declaringClass_offset = 2,
|
||||||
hc_lineNumber_offset = 3
|
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 declaringClass_offset;
|
||||||
static int methodName_offset;
|
static int methodName_offset;
|
||||||
static int fileName_offset;
|
static int fileName_offset;
|
||||||
@ -1279,6 +1335,8 @@ class java_lang_StackTraceElement: AllStatic {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// Setters
|
// 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_declaringClass(oop element, oop value);
|
||||||
static void set_methodName(oop element, oop value);
|
static void set_methodName(oop element, oop value);
|
||||||
static void set_fileName(oop element, oop value);
|
static void set_fileName(oop element, oop value);
|
||||||
@ -1456,8 +1514,8 @@ class InjectedField {
|
|||||||
CLASSLOADER_INJECTED_FIELDS(macro) \
|
CLASSLOADER_INJECTED_FIELDS(macro) \
|
||||||
MEMBERNAME_INJECTED_FIELDS(macro) \
|
MEMBERNAME_INJECTED_FIELDS(macro) \
|
||||||
CALLSITECONTEXT_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
|
// Interface to hard-coded offset checking
|
||||||
|
|
||||||
|
@ -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) {
|
inline int Backtrace::merge_bci_and_version(int bci, int version) {
|
||||||
// only store u2 for version, checking for overflow.
|
// only store u2 for version, checking for overflow.
|
||||||
if (version > USHRT_MAX || version < 0) version = USHRT_MAX;
|
if (version > USHRT_MAX || version < 0) version = USHRT_MAX;
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -22,7 +22,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "jni.h"
|
#include "prims/jni.h"
|
||||||
|
|
||||||
// Opaque reference to a JImage file.
|
// Opaque reference to a JImage file.
|
||||||
class JImageFile;
|
class JImageFile;
|
||||||
@ -35,6 +35,8 @@ typedef jlong JImageLocationRef;
|
|||||||
|
|
||||||
// JImage Error Codes
|
// JImage Error Codes
|
||||||
|
|
||||||
|
// Resource was not found
|
||||||
|
#define JIMAGE_NOT_FOUND (0)
|
||||||
// The image file is not prefixed with 0xCAFEDADA
|
// The image file is not prefixed with 0xCAFEDADA
|
||||||
#define JIMAGE_BAD_MAGIC (-1)
|
#define JIMAGE_BAD_MAGIC (-1)
|
||||||
// The image file does not have a compatible (translatable) version
|
// The image file does not have a compatible (translatable) version
|
||||||
@ -55,7 +57,7 @@ typedef jlong JImageLocationRef;
|
|||||||
*
|
*
|
||||||
* Ex.
|
* Ex.
|
||||||
* jint error;
|
* jint error;
|
||||||
* JImageFile* jimage = (*JImageOpen)(JAVA_HOME "lib/modules/bootmodules.jimage", &error);
|
* JImageFile* jimage = (*JImageOpen)(JAVA_HOME "lib/modules", &error);
|
||||||
* if (image == NULL) {
|
* if (image == NULL) {
|
||||||
* tty->print_cr("JImage failed to open: %d", error);
|
* tty->print_cr("JImage failed to open: %d", error);
|
||||||
* ...
|
* ...
|
||||||
|
@ -103,11 +103,15 @@ instanceKlassHandle KlassFactory::create_from_stream(ClassFileStream* stream,
|
|||||||
assert(loader_data != NULL, "invariant");
|
assert(loader_data != NULL, "invariant");
|
||||||
assert(THREAD->is_Java_thread(), "must be a JavaThread");
|
assert(THREAD->is_Java_thread(), "must be a JavaThread");
|
||||||
|
|
||||||
|
bool changed_by_loadhook = false;
|
||||||
|
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
HandleMark hm;
|
HandleMark hm;
|
||||||
|
|
||||||
JvmtiCachedClassFileData* cached_class_file = NULL;
|
JvmtiCachedClassFileData* cached_class_file = NULL;
|
||||||
|
|
||||||
|
ClassFileStream* old_stream = stream;
|
||||||
|
|
||||||
stream = prologue(stream,
|
stream = prologue(stream,
|
||||||
name,
|
name,
|
||||||
loader_data,
|
loader_data,
|
||||||
@ -125,8 +129,8 @@ instanceKlassHandle KlassFactory::create_from_stream(ClassFileStream* stream,
|
|||||||
ClassFileParser::BROADCAST, // publicity level
|
ClassFileParser::BROADCAST, // publicity level
|
||||||
CHECK_NULL);
|
CHECK_NULL);
|
||||||
|
|
||||||
instanceKlassHandle result = parser.create_instance_klass(CHECK_NULL);
|
instanceKlassHandle result = parser.create_instance_klass(old_stream != stream, CHECK_NULL);
|
||||||
assert(result == parser.create_instance_klass(THREAD), "invariant");
|
assert(result == parser.create_instance_klass(old_stream != stream, THREAD), "invariant");
|
||||||
|
|
||||||
if (result.is_null()) {
|
if (result.is_null()) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
405
hotspot/src/share/vm/classfile/moduleEntry.cpp
Normal file
405
hotspot/src/share/vm/classfile/moduleEntry.cpp
Normal 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.");
|
||||||
|
}
|
230
hotspot/src/share/vm/classfile/moduleEntry.hpp
Normal file
230
hotspot/src/share/vm/classfile/moduleEntry.hpp
Normal 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
|
964
hotspot/src/share/vm/classfile/modules.cpp
Normal file
964
hotspot/src/share/vm/classfile/modules.cpp
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
151
hotspot/src/share/vm/classfile/modules.hpp
Normal file
151
hotspot/src/share/vm/classfile/modules.hpp
Normal 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
|
322
hotspot/src/share/vm/classfile/packageEntry.cpp
Normal file
322
hotspot/src/share/vm/classfile/packageEntry.cpp
Normal 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
202
hotspot/src/share/vm/classfile/packageEntry.hpp
Normal file
202
hotspot/src/share/vm/classfile/packageEntry.hpp
Normal 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
|
@ -77,7 +77,7 @@ void SharedPathsMiscInfo::print_path(int type, const char* path) {
|
|||||||
outputStream* out = LogHandle(classpath)::info_stream();
|
outputStream* out = LogHandle(classpath)::info_stream();
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case BOOT:
|
case BOOT:
|
||||||
out->print("Expecting -Dsun.boot.class.path=%s", path);
|
out->print("Expecting BOOT path=%s", path);
|
||||||
break;
|
break;
|
||||||
case NON_EXIST:
|
case NON_EXIST:
|
||||||
out->print("Expecting that %s does not exist", path);
|
out->print("Expecting that %s does not exist", path);
|
||||||
@ -126,7 +126,7 @@ bool SharedPathsMiscInfo::check(jint type, const char* path) {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case BOOT:
|
case BOOT:
|
||||||
if (os::file_name_strcmp(path, Arguments::get_sysclasspath()) != 0) {
|
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;
|
break;
|
||||||
case NON_EXIST: // fall-through
|
case NON_EXIST: // fall-through
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "classfile/javaClasses.inline.hpp"
|
#include "classfile/javaClasses.inline.hpp"
|
||||||
#include "classfile/klassFactory.hpp"
|
#include "classfile/klassFactory.hpp"
|
||||||
#include "classfile/loaderConstraints.hpp"
|
#include "classfile/loaderConstraints.hpp"
|
||||||
|
#include "classfile/packageEntry.hpp"
|
||||||
#include "classfile/placeholders.hpp"
|
#include "classfile/placeholders.hpp"
|
||||||
#include "classfile/resolutionErrors.hpp"
|
#include "classfile/resolutionErrors.hpp"
|
||||||
#include "classfile/stringTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
@ -51,6 +52,7 @@
|
|||||||
#include "oops/objArrayKlass.hpp"
|
#include "oops/objArrayKlass.hpp"
|
||||||
#include "oops/objArrayOop.inline.hpp"
|
#include "oops/objArrayOop.inline.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
|
#include "oops/symbol.hpp"
|
||||||
#include "oops/typeArrayKlass.hpp"
|
#include "oops/typeArrayKlass.hpp"
|
||||||
#include "prims/jvmtiEnvBase.hpp"
|
#include "prims/jvmtiEnvBase.hpp"
|
||||||
#include "prims/methodHandles.hpp"
|
#include "prims/methodHandles.hpp"
|
||||||
@ -171,13 +173,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()) {
|
if (class_loader.is_null()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (class_loader->klass()->name() == vmSymbols::sun_misc_Launcher_ExtClassLoader());
|
return (class_loader->klass() == SystemDictionary::jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -1144,6 +1146,7 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name,
|
|||||||
const char* pkg = "java/";
|
const char* pkg = "java/";
|
||||||
if (!HAS_PENDING_EXCEPTION &&
|
if (!HAS_PENDING_EXCEPTION &&
|
||||||
!class_loader.is_null() &&
|
!class_loader.is_null() &&
|
||||||
|
!SystemDictionary::is_platform_class_loader(class_loader) &&
|
||||||
parsed_name != NULL &&
|
parsed_name != NULL &&
|
||||||
!strncmp((const char*)parsed_name->bytes(), pkg, strlen(pkg))) {
|
!strncmp((const char*)parsed_name->bytes(), pkg, strlen(pkg))) {
|
||||||
// It is illegal to define classes in the "java." package from
|
// It is illegal to define classes in the "java." package from
|
||||||
@ -1236,13 +1239,88 @@ instanceKlassHandle SystemDictionary::load_shared_class(
|
|||||||
instanceKlassHandle ik (THREAD, find_shared_class(class_name));
|
instanceKlassHandle ik (THREAD, find_shared_class(class_name));
|
||||||
// Make sure we only return the boot class for the NULL classloader.
|
// Make sure we only return the boot class for the NULL classloader.
|
||||||
if (ik.not_null() &&
|
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;
|
Handle protection_domain;
|
||||||
return load_shared_class(ik, class_loader, protection_domain, THREAD);
|
return load_shared_class(ik, class_loader, protection_domain, THREAD);
|
||||||
}
|
}
|
||||||
return instanceKlassHandle();
|
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,
|
instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik,
|
||||||
Handle class_loader,
|
Handle class_loader,
|
||||||
Handle protection_domain, TRAPS) {
|
Handle protection_domain, TRAPS) {
|
||||||
@ -1250,6 +1328,12 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik,
|
|||||||
instanceKlassHandle nh = instanceKlassHandle(); // null Handle
|
instanceKlassHandle nh = instanceKlassHandle(); // null Handle
|
||||||
Symbol* class_name = ik->name();
|
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
|
// Found the class, now load the superclass and interfaces. If they
|
||||||
// are shared, add them to the main system dictionary and reset
|
// are shared, add them to the main system dictionary and reset
|
||||||
// their hierarchy references (supers, subs, and interfaces).
|
// their hierarchy references (supers, subs, and interfaces).
|
||||||
@ -1303,12 +1387,20 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (log_is_enabled(Info, classload)) {
|
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
|
// No 'else' here as logging levels are not mutually exclusive
|
||||||
|
|
||||||
if (log_is_enabled(Debug, classload)) {
|
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()) {
|
if (DumpLoadedClassList != NULL && classlist_file->is_open()) {
|
||||||
@ -1329,7 +1421,68 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik,
|
|||||||
|
|
||||||
instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) {
|
instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) {
|
||||||
instanceKlassHandle nh = instanceKlassHandle(); // null Handle
|
instanceKlassHandle nh = instanceKlassHandle(); // null Handle
|
||||||
|
|
||||||
if (class_loader.is_null()) {
|
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
|
// Search the shared system dictionary for classes preloaded into the
|
||||||
// shared spaces.
|
// shared spaces.
|
||||||
@ -1344,7 +1497,7 @@ instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Ha
|
|||||||
if (k.is_null()) {
|
if (k.is_null()) {
|
||||||
// Use VM class loader
|
// Use VM class loader
|
||||||
PerfTraceTime vmtimer(ClassLoader::perf_sys_classload_time());
|
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
|
// find_or_define_instance_class may return a different InstanceKlass
|
||||||
@ -1669,7 +1822,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() {
|
Klass* SystemDictionary::try_get_next_class() {
|
||||||
return dictionary()->try_get_next_class();
|
return dictionary()->try_get_next_class();
|
||||||
}
|
}
|
||||||
@ -1940,6 +2093,11 @@ void SystemDictionary::initialize_wk_klasses_until(WKID limit_id, WKID &start_id
|
|||||||
|
|
||||||
void SystemDictionary::initialize_preloaded_classes(TRAPS) {
|
void SystemDictionary::initialize_preloaded_classes(TRAPS) {
|
||||||
assert(WK_KLASS(Object_klass) == NULL, "preloaded classes should only be initialized once");
|
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
|
// Preload commonly used klasses
|
||||||
WKID scan = FIRST_WKID;
|
WKID scan = FIRST_WKID;
|
||||||
// first do Object, then String, Class
|
// first do Object, then String, Class
|
||||||
|
@ -135,6 +135,7 @@ class SymbolPropertyTable;
|
|||||||
do_klass(Properties_klass, java_util_Properties, Pre ) \
|
do_klass(Properties_klass, java_util_Properties, Pre ) \
|
||||||
do_klass(reflect_AccessibleObject_klass, java_lang_reflect_AccessibleObject, Pre ) \
|
do_klass(reflect_AccessibleObject_klass, java_lang_reflect_AccessibleObject, Pre ) \
|
||||||
do_klass(reflect_Field_klass, java_lang_reflect_Field, 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_Parameter_klass, java_lang_reflect_Parameter, Opt ) \
|
||||||
do_klass(reflect_Method_klass, java_lang_reflect_Method, Pre ) \
|
do_klass(reflect_Method_klass, java_lang_reflect_Method, Pre ) \
|
||||||
do_klass(reflect_Constructor_klass, java_lang_reflect_Constructor, 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(StringBuffer_klass, java_lang_StringBuffer, Pre ) \
|
||||||
do_klass(StringBuilder_klass, java_lang_StringBuilder, Pre ) \
|
do_klass(StringBuilder_klass, java_lang_StringBuilder, Pre ) \
|
||||||
do_klass(internal_Unsafe_klass, jdk_internal_misc_Unsafe, Pre ) \
|
do_klass(internal_Unsafe_klass, jdk_internal_misc_Unsafe, Pre ) \
|
||||||
|
do_klass(module_Modules_klass, jdk_internal_module_Modules, Pre ) \
|
||||||
\
|
\
|
||||||
/* support for CDS */ \
|
/* support for CDS */ \
|
||||||
do_klass(ByteArrayInputStream_klass, java_io_ByteArrayInputStream, Pre ) \
|
do_klass(ByteArrayInputStream_klass, java_io_ByteArrayInputStream, Pre ) \
|
||||||
do_klass(File_klass, java_io_File, 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(URL_klass, java_net_URL, Pre ) \
|
||||||
do_klass(Jar_Manifest_klass, java_util_jar_Manifest, 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(CodeSource_klass, java_security_CodeSource, Pre ) \
|
||||||
|
do_klass(ParseUtil_klass, sun_net_www_ParseUtil, Pre ) \
|
||||||
\
|
\
|
||||||
do_klass(StackTraceElement_klass, java_lang_StackTraceElement, Opt ) \
|
do_klass(StackTraceElement_klass, java_lang_StackTraceElement, Opt ) \
|
||||||
\
|
\
|
||||||
@ -639,6 +642,8 @@ protected:
|
|||||||
static instanceKlassHandle find_or_define_instance_class(Symbol* class_name,
|
static instanceKlassHandle find_or_define_instance_class(Symbol* class_name,
|
||||||
Handle class_loader,
|
Handle class_loader,
|
||||||
instanceKlassHandle k, TRAPS);
|
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,
|
static instanceKlassHandle load_shared_class(instanceKlassHandle ik,
|
||||||
Handle class_loader,
|
Handle class_loader,
|
||||||
Handle protection_domain,
|
Handle protection_domain,
|
||||||
@ -653,7 +658,7 @@ public:
|
|||||||
static instanceKlassHandle load_shared_class(Symbol* class_name,
|
static instanceKlassHandle load_shared_class(Symbol* class_name,
|
||||||
Handle class_loader,
|
Handle class_loader,
|
||||||
TRAPS);
|
TRAPS);
|
||||||
static bool is_ext_class_loader(Handle class_loader);
|
static bool is_platform_class_loader(Handle class_loader);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static Klass* find_shared_class(Symbol* class_name);
|
static Klass* find_shared_class(Symbol* class_name);
|
||||||
|
@ -44,6 +44,16 @@ public:
|
|||||||
oop class_loader = loader_data->class_loader();
|
oop class_loader = loader_data->class_loader();
|
||||||
return (class_loader == NULL);
|
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,
|
static Klass* dump_time_resolve_super_or_fail(Symbol* child_name,
|
||||||
Symbol* class_name,
|
Symbol* class_name,
|
||||||
|
@ -49,10 +49,12 @@
|
|||||||
// Mapping function names to values. New entries should be added below.
|
// Mapping function names to values. New entries should be added below.
|
||||||
|
|
||||||
#define VM_SYMBOLS_DO(template, do_alias) \
|
#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_System, "java/lang/System") \
|
||||||
template(java_lang_Object, "java/lang/Object") \
|
template(java_lang_Object, "java/lang/Object") \
|
||||||
template(java_lang_Class, "java/lang/Class") \
|
template(java_lang_Class, "java/lang/Class") \
|
||||||
|
template(java_lang_Package, "java/lang/Package") \
|
||||||
template(java_lang_String, "java/lang/String") \
|
template(java_lang_String, "java/lang/String") \
|
||||||
template(java_lang_StringLatin1, "java/lang/StringLatin1") \
|
template(java_lang_StringLatin1, "java/lang/StringLatin1") \
|
||||||
template(java_lang_StringUTF16, "java/lang/StringUTF16") \
|
template(java_lang_StringUTF16, "java/lang/StringUTF16") \
|
||||||
@ -87,6 +89,7 @@
|
|||||||
template(java_lang_reflect_Method, "java/lang/reflect/Method") \
|
template(java_lang_reflect_Method, "java/lang/reflect/Method") \
|
||||||
template(java_lang_reflect_Constructor, "java/lang/reflect/Constructor") \
|
template(java_lang_reflect_Constructor, "java/lang/reflect/Constructor") \
|
||||||
template(java_lang_reflect_Field, "java/lang/reflect/Field") \
|
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_Parameter, "java/lang/reflect/Parameter") \
|
||||||
template(java_lang_reflect_Array, "java/lang/reflect/Array") \
|
template(java_lang_reflect_Array, "java/lang/reflect/Array") \
|
||||||
template(java_lang_StringBuffer, "java/lang/StringBuffer") \
|
template(java_lang_StringBuffer, "java/lang/StringBuffer") \
|
||||||
@ -97,7 +100,6 @@
|
|||||||
template(java_security_CodeSource, "java/security/CodeSource") \
|
template(java_security_CodeSource, "java/security/CodeSource") \
|
||||||
template(java_security_ProtectionDomain, "java/security/ProtectionDomain") \
|
template(java_security_ProtectionDomain, "java/security/ProtectionDomain") \
|
||||||
template(java_security_SecureClassLoader, "java/security/SecureClassLoader") \
|
template(java_security_SecureClassLoader, "java/security/SecureClassLoader") \
|
||||||
template(java_net_URLClassLoader, "java/net/URLClassLoader") \
|
|
||||||
template(java_net_URL, "java/net/URL") \
|
template(java_net_URL, "java/net/URL") \
|
||||||
template(java_util_jar_Manifest, "java/util/jar/Manifest") \
|
template(java_util_jar_Manifest, "java/util/jar/Manifest") \
|
||||||
template(impliesCreateAccessControlContext_name, "impliesCreateAccessControlContext") \
|
template(impliesCreateAccessControlContext_name, "impliesCreateAccessControlContext") \
|
||||||
@ -116,17 +118,25 @@
|
|||||||
template(java_util_Hashtable, "java/util/Hashtable") \
|
template(java_util_Hashtable, "java/util/Hashtable") \
|
||||||
template(java_lang_Compiler, "java/lang/Compiler") \
|
template(java_lang_Compiler, "java/lang/Compiler") \
|
||||||
template(jdk_internal_misc_Signal, "jdk/internal/misc/Signal") \
|
template(jdk_internal_misc_Signal, "jdk/internal/misc/Signal") \
|
||||||
template(sun_misc_Launcher, "sun/misc/Launcher") \
|
|
||||||
template(java_lang_AssertionStatusDirectives, "java/lang/AssertionStatusDirectives") \
|
template(java_lang_AssertionStatusDirectives, "java/lang/AssertionStatusDirectives") \
|
||||||
template(getBootClassPathEntryForClass_name, "getBootClassPathEntryForClass") \
|
template(getBootClassPathEntryForClass_name, "getBootClassPathEntryForClass") \
|
||||||
template(sun_misc_PostVMInitHook, "sun/misc/PostVMInitHook") \
|
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 */ \
|
/* Java runtime version access */ \
|
||||||
template(java_lang_VersionProps, "java/lang/VersionProps") \
|
template(java_lang_VersionProps, "java/lang/VersionProps") \
|
||||||
template(java_runtime_name_name, "java_runtime_name") \
|
template(java_runtime_name_name, "java_runtime_name") \
|
||||||
template(java_runtime_version_name, "java_runtime_version") \
|
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 */ \
|
/* class file format tags */ \
|
||||||
template(tag_source_file, "SourceFile") \
|
template(tag_source_file, "SourceFile") \
|
||||||
template(tag_inner_classes, "InnerClasses") \
|
template(tag_inner_classes, "InnerClasses") \
|
||||||
@ -360,7 +370,6 @@
|
|||||||
template(run_finalization_name, "runFinalization") \
|
template(run_finalization_name, "runFinalization") \
|
||||||
template(run_finalizers_on_exit_name, "runFinalizersOnExit") \
|
template(run_finalizers_on_exit_name, "runFinalizersOnExit") \
|
||||||
template(dispatchUncaughtException_name, "dispatchUncaughtException") \
|
template(dispatchUncaughtException_name, "dispatchUncaughtException") \
|
||||||
template(initializeSystemClass_name, "initializeSystemClass") \
|
|
||||||
template(loadClass_name, "loadClass") \
|
template(loadClass_name, "loadClass") \
|
||||||
template(loadClassInternal_name, "loadClassInternal") \
|
template(loadClassInternal_name, "loadClassInternal") \
|
||||||
template(get_name, "get") \
|
template(get_name, "get") \
|
||||||
@ -446,14 +455,22 @@
|
|||||||
template(signers_name, "signers_name") \
|
template(signers_name, "signers_name") \
|
||||||
template(loader_data_name, "loader_data") \
|
template(loader_data_name, "loader_data") \
|
||||||
template(vmdependencies_name, "vmdependencies") \
|
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(input_stream_void_signature, "(Ljava/io/InputStream;)V") \
|
||||||
template(getFileURL_name, "getFileURL") \
|
template(definePackage_name, "definePackage") \
|
||||||
template(getFileURL_signature, "(Ljava/io/File;)Ljava/net/URL;") \
|
template(definePackage_signature, "(Ljava/lang/String;Ljava/lang/reflect/Module;)Ljava/lang/Package;") \
|
||||||
template(definePackageInternal_name, "definePackageInternal") \
|
template(defineOrCheckPackage_name, "defineOrCheckPackage") \
|
||||||
template(definePackageInternal_signature, "(Ljava/lang/String;Ljava/util/jar/Manifest;Ljava/net/URL;)V") \
|
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_name, "getProtectionDomain") \
|
||||||
template(getProtectionDomain_signature, "(Ljava/security/CodeSource;)Ljava/security/ProtectionDomain;") \
|
template(getProtectionDomain_signature, "(Ljava/security/CodeSource;)Ljava/security/ProtectionDomain;") \
|
||||||
template(url_code_signer_array_void_signature, "(Ljava/net/URL;[Ljava/security/CodeSigner;)V") \
|
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: */ \
|
/* non-intrinsic name/signature pairs: */ \
|
||||||
template(register_method_name, "register") \
|
template(register_method_name, "register") \
|
||||||
@ -531,6 +548,7 @@
|
|||||||
template(void_class_signature, "()Ljava/lang/Class;") \
|
template(void_class_signature, "()Ljava/lang/Class;") \
|
||||||
template(void_class_array_signature, "()[Ljava/lang/Class;") \
|
template(void_class_array_signature, "()[Ljava/lang/Class;") \
|
||||||
template(void_string_signature, "()Ljava/lang/String;") \
|
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_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(object_object_array_object_signature, "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")\
|
||||||
template(exception_void_signature, "(Ljava/lang/Exception;)V") \
|
template(exception_void_signature, "(Ljava/lang/Exception;)V") \
|
||||||
@ -550,6 +568,7 @@
|
|||||||
template(reference_signature, "Ljava/lang/ref/Reference;") \
|
template(reference_signature, "Ljava/lang/ref/Reference;") \
|
||||||
template(sun_misc_Cleaner_signature, "Lsun/misc/Cleaner;") \
|
template(sun_misc_Cleaner_signature, "Lsun/misc/Cleaner;") \
|
||||||
template(executable_signature, "Ljava/lang/reflect/Executable;") \
|
template(executable_signature, "Ljava/lang/reflect/Executable;") \
|
||||||
|
template(module_signature, "Ljava/lang/reflect/Module;") \
|
||||||
template(concurrenthashmap_signature, "Ljava/util/concurrent/ConcurrentHashMap;") \
|
template(concurrenthashmap_signature, "Ljava/util/concurrent/ConcurrentHashMap;") \
|
||||||
template(String_StringBuilder_signature, "(Ljava/lang/String;)Ljava/lang/StringBuilder;") \
|
template(String_StringBuilder_signature, "(Ljava/lang/String;)Ljava/lang/StringBuilder;") \
|
||||||
template(int_StringBuilder_signature, "(I)Ljava/lang/StringBuilder;") \
|
template(int_StringBuilder_signature, "(I)Ljava/lang/StringBuilder;") \
|
||||||
@ -574,6 +593,9 @@
|
|||||||
/* used to identify class loaders handling parallel class loading */ \
|
/* used to identify class loaders handling parallel class loading */ \
|
||||||
template(parallelCapable_name, "parallelLockMap") \
|
template(parallelCapable_name, "parallelLockMap") \
|
||||||
\
|
\
|
||||||
|
/* used to return a class loader's unnamed module */ \
|
||||||
|
template(unnamedModule_name, "unnamedModule") \
|
||||||
|
\
|
||||||
/* JVM monitoring and management support */ \
|
/* JVM monitoring and management support */ \
|
||||||
template(java_lang_StackTraceElement_array, "[Ljava/lang/StackTraceElement;") \
|
template(java_lang_StackTraceElement_array, "[Ljava/lang/StackTraceElement;") \
|
||||||
template(java_lang_management_ThreadState, "java/lang/management/ThreadState") \
|
template(java_lang_management_ThreadState, "java/lang/management/ThreadState") \
|
||||||
@ -632,7 +654,10 @@
|
|||||||
template(addThreadDumpForSynchronizers_signature, "(Ljava/lang/management/ThreadInfo;[Ljava/lang/Object;)V") \
|
template(addThreadDumpForSynchronizers_signature, "(Ljava/lang/management/ThreadInfo;[Ljava/lang/Object;)V") \
|
||||||
\
|
\
|
||||||
/* JVMTI/java.lang.instrument support and VM Attach mechanism */ \
|
/* 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(sun_misc_VMSupport, "sun/misc/VMSupport") \
|
||||||
|
template(transformedByAgent_name, "transformedByAgent") \
|
||||||
|
template(transformedByAgent_signature, "(Ljava/lang/reflect/Module;)V") \
|
||||||
template(appendToClassPathForInstrumentation_name, "appendToClassPathForInstrumentation") \
|
template(appendToClassPathForInstrumentation_name, "appendToClassPathForInstrumentation") \
|
||||||
do_alias(appendToClassPathForInstrumentation_signature, string_void_signature) \
|
do_alias(appendToClassPathForInstrumentation_signature, string_void_signature) \
|
||||||
template(serializePropertiesToByteArray_name, "serializePropertiesToByteArray") \
|
template(serializePropertiesToByteArray_name, "serializePropertiesToByteArray") \
|
||||||
@ -1063,11 +1088,6 @@
|
|||||||
do_name( isCompileConstant_name, "isCompileConstant") \
|
do_name( isCompileConstant_name, "isCompileConstant") \
|
||||||
do_alias( isCompileConstant_signature, object_boolean_signature) \
|
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...) */ \
|
/* unsafe memory references (there are a lot of them...) */ \
|
||||||
do_signature(getObject_signature, "(Ljava/lang/Object;J)Ljava/lang/Object;") \
|
do_signature(getObject_signature, "(Ljava/lang/Object;J)Ljava/lang/Object;") \
|
||||||
do_signature(putObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;)V") \
|
do_signature(putObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;)V") \
|
||||||
|
@ -2258,10 +2258,8 @@ run:
|
|||||||
// Decrement counter at checkcast.
|
// Decrement counter at checkcast.
|
||||||
BI_PROFILE_SUBTYPECHECK_FAILED(objKlass);
|
BI_PROFILE_SUBTYPECHECK_FAILED(objKlass);
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
const char* objName = objKlass->external_name();
|
|
||||||
const char* klassName = klassOf->external_name();
|
|
||||||
char* message = SharedRuntime::generate_class_cast_message(
|
char* message = SharedRuntime::generate_class_cast_message(
|
||||||
objName, klassName);
|
objKlass, klassOf);
|
||||||
VM_JAVA_ERROR(vmSymbols::java_lang_ClassCastException(), message, note_classCheck_trap);
|
VM_JAVA_ERROR(vmSymbols::java_lang_ClassCastException(), message, note_classCheck_trap);
|
||||||
}
|
}
|
||||||
// Profile checkcast with null_seen and receiver.
|
// Profile checkcast with null_seen and receiver.
|
||||||
|
@ -384,7 +384,7 @@ IRT_ENTRY(void, InterpreterRuntime::throw_ClassCastException(
|
|||||||
|
|
||||||
ResourceMark rm(thread);
|
ResourceMark rm(thread);
|
||||||
char* message = SharedRuntime::generate_class_cast_message(
|
char* message = SharedRuntime::generate_class_cast_message(
|
||||||
thread, obj->klass()->external_name());
|
thread, obj->klass());
|
||||||
|
|
||||||
if (ProfileTraps) {
|
if (ProfileTraps) {
|
||||||
note_trap(thread, Deoptimization::Reason_class_check, CHECK);
|
note_trap(thread, Deoptimization::Reason_class_check, CHECK);
|
||||||
|
@ -273,18 +273,25 @@ void LinkInfo::print() {
|
|||||||
// Klass resolution
|
// Klass resolution
|
||||||
|
|
||||||
void LinkResolver::check_klass_accessability(KlassHandle ref_klass, KlassHandle sel_klass, TRAPS) {
|
void LinkResolver::check_klass_accessability(KlassHandle ref_klass, KlassHandle sel_klass, TRAPS) {
|
||||||
if (!Reflection::verify_class_access(ref_klass(),
|
Reflection::VerifyClassAccessResults vca_result =
|
||||||
sel_klass(),
|
Reflection::verify_class_access(ref_klass(), sel_klass(), true);
|
||||||
true)) {
|
if (vca_result != Reflection::ACCESS_OK) {
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
Exceptions::fthrow(
|
char* msg = Reflection::verify_class_access_msg(ref_klass(), sel_klass(), vca_result);
|
||||||
THREAD_AND_LOCATION,
|
if (msg == NULL) {
|
||||||
vmSymbols::java_lang_IllegalAccessError(),
|
Exceptions::fthrow(
|
||||||
"tried to access class %s from class %s",
|
THREAD_AND_LOCATION,
|
||||||
sel_klass->external_name(),
|
vmSymbols::java_lang_IllegalAccessError(),
|
||||||
ref_klass->external_name()
|
"failed to access class %s from class %s",
|
||||||
);
|
sel_klass->external_name(),
|
||||||
return;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +77,9 @@ bool JVMCIEnv::check_klass_accessibility(KlassHandle accessing_klass, KlassHandl
|
|||||||
resolved_klass = ObjArrayKlass::cast(resolved_klass())->bottom_klass();
|
resolved_klass = ObjArrayKlass::cast(resolved_klass())->bottom_klass();
|
||||||
}
|
}
|
||||||
if (resolved_klass->is_instance_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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,7 @@
|
|||||||
LOG_TAG(logging) \
|
LOG_TAG(logging) \
|
||||||
LOG_TAG(marking) \
|
LOG_TAG(marking) \
|
||||||
LOG_TAG(metaspace) \
|
LOG_TAG(metaspace) \
|
||||||
|
LOG_TAG(modules) \
|
||||||
LOG_TAG(monitorinflation) \
|
LOG_TAG(monitorinflation) \
|
||||||
LOG_TAG(os) \
|
LOG_TAG(os) \
|
||||||
LOG_TAG(phases) \
|
LOG_TAG(phases) \
|
||||||
|
@ -226,12 +226,21 @@ void FileMapInfo::allocate_classpath_entry_table() {
|
|||||||
SharedClassUtil::update_shared_classpath(cpe, ent, st.st_mtime, st.st_size, THREAD);
|
SharedClassUtil::update_shared_classpath(cpe, ent, st.st_mtime, st.st_size, THREAD);
|
||||||
} else {
|
} else {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if ((os::stat(name, &st) == 0) && ((st.st_mode & S_IFDIR) == S_IFDIR)) {
|
if (os::stat(name, &st) == 0) {
|
||||||
if (!os::dir_is_empty(name)) {
|
if (cpe->is_jrt()) {
|
||||||
ClassLoader::exit_with_path_failure("Cannot have non-empty directory in archived classpaths", name);
|
// 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;
|
ent->_filesize = -2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -282,7 +291,7 @@ bool FileMapInfo::validate_classpath_entry_table() {
|
|||||||
fail_continue("directory is not empty: %s", name);
|
fail_continue("directory is not empty: %s", name);
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
} else if (ent->is_jar()) {
|
} else if (ent->is_jar_or_bootimage()) {
|
||||||
if (ent->_timestamp != st.st_mtime ||
|
if (ent->_timestamp != st.st_mtime ||
|
||||||
ent->_filesize != st.st_size) {
|
ent->_filesize != st.st_size) {
|
||||||
ok = false;
|
ok = false;
|
||||||
@ -291,7 +300,7 @@ bool FileMapInfo::validate_classpath_entry_table() {
|
|||||||
"Timestamp mismatch" :
|
"Timestamp mismatch" :
|
||||||
"File size mismatch");
|
"File size mismatch");
|
||||||
} else {
|
} 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);
|
" the shared archive file: %s", name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -871,6 +880,11 @@ bool FileMapInfo::FileMapHeader::validate() {
|
|||||||
return false;
|
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()) {
|
if (_version != current_version()) {
|
||||||
FileMapInfo::fail_continue("The shared archive file is the wrong version.");
|
FileMapInfo::fail_continue("The shared archive file is the wrong version.");
|
||||||
return false;
|
return false;
|
||||||
|
@ -44,14 +44,20 @@ class Metaspace;
|
|||||||
class SharedClassPathEntry VALUE_OBJ_CLASS_SPEC {
|
class SharedClassPathEntry VALUE_OBJ_CLASS_SPEC {
|
||||||
public:
|
public:
|
||||||
const char *_name;
|
const char *_name;
|
||||||
time_t _timestamp; // jar timestamp, 0 if is directory or other
|
time_t _timestamp; // jar/jimage timestamp, 0 if is directory or other
|
||||||
long _filesize; // jar file size, -1 if is directory, -2 if other
|
long _filesize; // jar/jimage file size, -1 if is directory, -2 if other
|
||||||
bool is_jar() {
|
|
||||||
|
// The _timestamp only gets set for jar files and "modules" jimage.
|
||||||
|
bool is_jar_or_bootimage() {
|
||||||
return _timestamp != 0;
|
return _timestamp != 0;
|
||||||
}
|
}
|
||||||
bool is_dir() {
|
bool is_dir() {
|
||||||
return _filesize == -1;
|
return _filesize == -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_jrt() {
|
||||||
|
return ClassLoader::is_jrt(_name);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class FileMapInfo : public CHeapObj<mtInternal> {
|
class FileMapInfo : public CHeapObj<mtInternal> {
|
||||||
|
@ -603,14 +603,7 @@ void VM_PopulateDumpSharedSpace::doit() {
|
|||||||
SystemDictionary::reverse();
|
SystemDictionary::reverse();
|
||||||
SystemDictionary::copy_buckets(&md_top, md_end);
|
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);
|
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.
|
// Write the other data to the output array.
|
||||||
WriteClosure wc(md_top, md_end);
|
WriteClosure wc(md_top, md_end);
|
||||||
@ -716,8 +709,7 @@ void VM_PopulateDumpSharedSpace::doit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MetaspaceShared::link_one_shared_class(Klass* obj, TRAPS) {
|
void MetaspaceShared::link_one_shared_class(Klass* k, TRAPS) {
|
||||||
Klass* k = obj;
|
|
||||||
if (k->is_instance_klass()) {
|
if (k->is_instance_klass()) {
|
||||||
InstanceKlass* ik = InstanceKlass::cast(k);
|
InstanceKlass* ik = InstanceKlass::cast(k);
|
||||||
// Link the class to cause the bytecodes to be rewritten and the
|
// 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) {
|
void MetaspaceShared::link_and_cleanup_shared_classes(TRAPS) {
|
||||||
// We need to iterate because verification may cause additional classes
|
// We need to iterate because verification may cause additional classes
|
||||||
// to be loaded.
|
// to be loaded.
|
||||||
@ -765,6 +767,7 @@ void MetaspaceShared::link_and_cleanup_shared_classes(TRAPS) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MetaspaceShared::prepare_for_dumping() {
|
void MetaspaceShared::prepare_for_dumping() {
|
||||||
|
Arguments::check_unsupported_dumping_properties();
|
||||||
ClassLoader::initialize_shared_path();
|
ClassLoader::initialize_shared_path();
|
||||||
FileMapInfo::allocate_classpath_entry_table();
|
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");
|
assert(DumpSharedSpaces, "should only be called during dumping");
|
||||||
if (ik->init_state() < InstanceKlass::linked) {
|
if (ik->init_state() < InstanceKlass::linked) {
|
||||||
bool saved = BytecodeVerificationLocal;
|
bool saved = BytecodeVerificationLocal;
|
||||||
if (!SharedClassUtil::is_shared_boot_class(ik)) {
|
if (!(ik->is_shared_boot_class())) {
|
||||||
// The verification decision is based on BytecodeVerificationRemote
|
// The verification decision is based on BytecodeVerificationRemote
|
||||||
// for non-system classes. Since we are using the NULL classloader
|
// for non-system classes. Since we are using the NULL classloader
|
||||||
// to load non-system classes during dumping, we need to temporarily
|
// to load non-system classes during dumping, we need to temporarily
|
||||||
@ -1089,36 +1092,14 @@ void MetaspaceShared::initialize_shared_spaces() {
|
|||||||
number_of_entries);
|
number_of_entries);
|
||||||
buffer += sharedDictionaryLen;
|
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
|
// The following data in the shared misc data region are the linked
|
||||||
// list elements (HashtableEntry objects) for the shared dictionary
|
// list elements (HashtableEntry objects) for the shared dictionary
|
||||||
// and package info table.
|
// table.
|
||||||
|
|
||||||
int len = *(intptr_t*)buffer; // skip over shared dictionary entries
|
int len = *(intptr_t*)buffer; // skip over shared dictionary entries
|
||||||
buffer += sizeof(intptr_t);
|
buffer += sizeof(intptr_t);
|
||||||
buffer += len;
|
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;
|
intptr_t* array = (intptr_t*)buffer;
|
||||||
ReadClosure rc(&array);
|
ReadClosure rc(&array);
|
||||||
serialize(&rc);
|
serialize(&rc);
|
||||||
|
@ -208,6 +208,7 @@ class MetaspaceShared : AllStatic {
|
|||||||
static bool try_link_class(InstanceKlass* ik, TRAPS);
|
static bool try_link_class(InstanceKlass* ik, TRAPS);
|
||||||
static void link_one_shared_class(Klass* obj, TRAPS);
|
static void link_one_shared_class(Klass* obj, TRAPS);
|
||||||
static void check_one_shared_class(Klass* obj);
|
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 void link_and_cleanup_shared_classes(TRAPS);
|
||||||
|
|
||||||
static int count_class(const char* classlist_file);
|
static int count_class(const char* classlist_file);
|
||||||
|
@ -155,6 +155,7 @@ uintptr_t Universe::_verify_oop_bits = (uintptr_t) -1;
|
|||||||
|
|
||||||
int Universe::_base_vtable_size = 0;
|
int Universe::_base_vtable_size = 0;
|
||||||
bool Universe::_bootstrapping = false;
|
bool Universe::_bootstrapping = false;
|
||||||
|
bool Universe::_module_initialized = false;
|
||||||
bool Universe::_fully_initialized = false;
|
bool Universe::_fully_initialized = false;
|
||||||
|
|
||||||
size_t Universe::_heap_capacity_at_last_gc;
|
size_t Universe::_heap_capacity_at_last_gc;
|
||||||
@ -667,7 +668,6 @@ jint universe_init() {
|
|||||||
} else {
|
} else {
|
||||||
SymbolTable::create_table();
|
SymbolTable::create_table();
|
||||||
StringTable::create_table();
|
StringTable::create_table();
|
||||||
ClassLoader::create_package_info_table();
|
|
||||||
|
|
||||||
if (DumpSharedSpaces) {
|
if (DumpSharedSpaces) {
|
||||||
MetaspaceShared::prepare_for_dumping();
|
MetaspaceShared::prepare_for_dumping();
|
||||||
@ -886,6 +886,10 @@ void universe2_init() {
|
|||||||
Universe::genesis(CATCH);
|
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() {
|
bool universe_post_init() {
|
||||||
assert(!is_init_completed(), "Error: initialization not yet completed!");
|
assert(!is_init_completed(), "Error: initialization not yet completed!");
|
||||||
|
@ -111,6 +111,7 @@ class Universe: AllStatic {
|
|||||||
friend jint universe_init();
|
friend jint universe_init();
|
||||||
friend void universe2_init();
|
friend void universe2_init();
|
||||||
friend bool universe_post_init();
|
friend bool universe_post_init();
|
||||||
|
friend void universe_post_module_init();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Known classes in the VM
|
// Known classes in the VM
|
||||||
@ -205,6 +206,7 @@ class Universe: AllStatic {
|
|||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
static bool _bootstrapping; // true during genesis
|
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
|
static bool _fully_initialized; // true after universe_init and initialize_vtables called
|
||||||
|
|
||||||
// the array of preallocated errors with backtraces
|
// the array of preallocated errors with backtraces
|
||||||
@ -436,6 +438,7 @@ class Universe: AllStatic {
|
|||||||
|
|
||||||
// Testers
|
// Testers
|
||||||
static bool is_bootstrapping() { return _bootstrapping; }
|
static bool is_bootstrapping() { return _bootstrapping; }
|
||||||
|
static bool is_module_initialized() { return _module_initialized; }
|
||||||
static bool is_fully_initialized() { return _fully_initialized; }
|
static bool is_fully_initialized() { return _fully_initialized; }
|
||||||
|
|
||||||
static inline bool element_type_should_be_aligned(BasicType type);
|
static inline bool element_type_should_be_aligned(BasicType type);
|
||||||
|
@ -95,11 +95,18 @@ ArrayKlass::ArrayKlass(Symbol* name) :
|
|||||||
|
|
||||||
// Initialization of vtables and mirror object is done separatly from base_create_array_klass,
|
// 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.
|
// 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);
|
ResourceMark rm(THREAD);
|
||||||
k->initialize_supers(super_klass(), CHECK);
|
k->initialize_supers(super_klass(), CHECK);
|
||||||
k->vtable()->initialize_vtable(false, 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) {
|
GrowableArray<Klass*>* ArrayKlass::compute_secondary_supers(int num_extra_slots) {
|
||||||
|
@ -113,7 +113,7 @@ class ArrayKlass: public Klass {
|
|||||||
void array_klasses_do(void f(Klass* k, TRAPS), TRAPS);
|
void array_klasses_do(void f(Klass* k, TRAPS), TRAPS);
|
||||||
|
|
||||||
// Return a handle.
|
// 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
|
// jvm support
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -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) {
|
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);
|
instanceKlassHandle ik(THREAD, this);
|
||||||
|
ik->set_package(loader_data, CHECK);
|
||||||
|
Klass::restore_unshareable_info(loader_data, protection_domain, CHECK);
|
||||||
|
|
||||||
Array<Method*>* methods = ik->methods();
|
Array<Method*>* methods = ik->methods();
|
||||||
int num_methods = methods->length();
|
int num_methods = methods->length();
|
||||||
@ -2178,26 +2179,135 @@ const char* InstanceKlass::signature_name() const {
|
|||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
// different verisons of is_same_class_package
|
const jbyte* InstanceKlass::package_from_name(const Symbol* name, int& length) {
|
||||||
bool InstanceKlass::is_same_class_package(const Klass* class2) const {
|
ResourceMark rm;
|
||||||
const Klass* const class1 = (const Klass* const)this;
|
length = 0;
|
||||||
oop classloader1 = InstanceKlass::cast(class1)->class_loader();
|
if (name == NULL) {
|
||||||
const Symbol* const classname1 = class1->name();
|
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()) {
|
if (class2->is_objArray_klass()) {
|
||||||
class2 = ObjArrayKlass::cast(class2)->bottom_klass();
|
class2 = ObjArrayKlass::cast(class2)->bottom_klass();
|
||||||
}
|
}
|
||||||
|
|
||||||
oop classloader2;
|
oop classloader2;
|
||||||
|
PackageEntry* classpkg2;
|
||||||
if (class2->is_instance_klass()) {
|
if (class2->is_instance_klass()) {
|
||||||
classloader2 = InstanceKlass::cast(class2)->class_loader();
|
classloader2 = class2->class_loader();
|
||||||
|
classpkg2 = InstanceKlass::cast(class2)->package();
|
||||||
} else {
|
} else {
|
||||||
assert(class2->is_typeArray_klass(), "should be type array");
|
assert(class2->is_typeArray_klass(), "should be type array");
|
||||||
classloader2 = NULL;
|
classloader2 = NULL;
|
||||||
|
classpkg2 = NULL;
|
||||||
}
|
}
|
||||||
const Symbol* classname2 = class2->name();
|
|
||||||
|
|
||||||
return InstanceKlass::is_same_class_package(classloader1, classname1,
|
// Same package is determined by comparing class loader
|
||||||
classloader2, classname2);
|
// 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,
|
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
|
// 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.
|
// for ASCII characters ('/', 'L', '['), we can keep them in UTF8 encoding.
|
||||||
// Otherwise, we just compare jbyte values between the strings.
|
// Otherwise, we just compare jbyte values between the strings.
|
||||||
const jbyte *name1 = class_name1->base();
|
int length1 = 0;
|
||||||
const jbyte *name2 = class_name2->base();
|
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(), '/');
|
if ((length1 < 0) || (length2 < 0)) {
|
||||||
const jbyte *last_slash2 = UTF8::strrchr(name2, class_name2->utf8_length(), '/');
|
// 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
|
// One of the two doesn't have a package. Only return true
|
||||||
// if the other one also doesn't have a package.
|
// if the other one also doesn't have a package.
|
||||||
return last_slash1 == last_slash2;
|
return name1 == name2;
|
||||||
} 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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;
|
if (!class2->is_instance_klass()) return false;
|
||||||
|
|
||||||
// must be in same package before we try anything else
|
// 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;
|
return false;
|
||||||
|
|
||||||
// As long as there is an outer1.getEnclosingClass,
|
// 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,
|
void InstanceKlass::print_loading_log(LogLevel::type type,
|
||||||
ClassLoaderData* loader_data,
|
ClassLoaderData* loader_data,
|
||||||
|
const char* module_name,
|
||||||
const ClassFileStream* cfs) const {
|
const ClassFileStream* cfs) const {
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
outputStream* log;
|
outputStream* log;
|
||||||
@ -2928,7 +3020,11 @@ void InstanceKlass::print_loading_log(LogLevel::type type,
|
|||||||
// Source
|
// Source
|
||||||
if (cfs != NULL) {
|
if (cfs != NULL) {
|
||||||
if (cfs->source() != 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()) {
|
} else if (loader_data == ClassLoaderData::the_null_class_loader_data()) {
|
||||||
Thread* THREAD = Thread::current();
|
Thread* THREAD = Thread::current();
|
||||||
Klass* caller =
|
Klass* caller =
|
||||||
|
@ -25,8 +25,11 @@
|
|||||||
#ifndef SHARE_VM_OOPS_INSTANCEKLASS_HPP
|
#ifndef SHARE_VM_OOPS_INSTANCEKLASS_HPP
|
||||||
#define SHARE_VM_OOPS_INSTANCEKLASS_HPP
|
#define SHARE_VM_OOPS_INSTANCEKLASS_HPP
|
||||||
|
|
||||||
|
#include "classfile/classLoader.hpp"
|
||||||
#include "classfile/classLoaderData.hpp"
|
#include "classfile/classLoaderData.hpp"
|
||||||
|
#include "classfile/packageEntry.hpp"
|
||||||
#include "gc/shared/specialized_oop_closures.hpp"
|
#include "gc/shared/specialized_oop_closures.hpp"
|
||||||
|
#include "classfile/moduleEntry.hpp"
|
||||||
#include "logging/logLevel.hpp"
|
#include "logging/logLevel.hpp"
|
||||||
#include "memory/referenceType.hpp"
|
#include "memory/referenceType.hpp"
|
||||||
#include "oops/annotations.hpp"
|
#include "oops/annotations.hpp"
|
||||||
@ -140,6 +143,8 @@ class InstanceKlass: public Klass {
|
|||||||
protected:
|
protected:
|
||||||
// Annotations for this class
|
// Annotations for this class
|
||||||
Annotations* _annotations;
|
Annotations* _annotations;
|
||||||
|
// Package this class is defined in
|
||||||
|
PackageEntry* _package_entry;
|
||||||
// Array classes holding elements of this class.
|
// Array classes holding elements of this class.
|
||||||
Klass* _array_klasses;
|
Klass* _array_klasses;
|
||||||
// Constant pool for this class.
|
// Constant pool for this class.
|
||||||
@ -199,16 +204,22 @@ class InstanceKlass: public Klass {
|
|||||||
|
|
||||||
// Start after _misc_kind field.
|
// Start after _misc_kind field.
|
||||||
enum {
|
enum {
|
||||||
_misc_rewritten = 1 << 2, // methods rewritten.
|
_misc_rewritten = 1 << 2, // methods rewritten.
|
||||||
_misc_has_nonstatic_fields = 1 << 3, // for sizing with UseCompressedOops
|
_misc_has_nonstatic_fields = 1 << 3, // for sizing with UseCompressedOops
|
||||||
_misc_should_verify_class = 1 << 4, // allow caching of preverification
|
_misc_should_verify_class = 1 << 4, // allow caching of preverification
|
||||||
_misc_is_anonymous = 1 << 5, // has embedded _host_klass field
|
_misc_is_anonymous = 1 << 5, // has embedded _host_klass field
|
||||||
_misc_is_contended = 1 << 6, // marked with contended annotation
|
_misc_is_contended = 1 << 6, // marked with contended annotation
|
||||||
_misc_has_default_methods = 1 << 7, // class/superclass/implemented interfaces has default methods
|
_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_declares_default_methods = 1 << 8, // directly declares default methods (any access)
|
||||||
_misc_has_been_redefined = 1 << 9, // class has been redefined
|
_misc_has_been_redefined = 1 << 9, // class has been redefined
|
||||||
_misc_is_scratch_class = 1 << 10 // class is the redefined scratch class
|
_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 _misc_flags;
|
||||||
u2 _minor_version; // minor version number of class file
|
u2 _minor_version; // minor version number of class file
|
||||||
u2 _major_version; // major 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;
|
friend class SystemDictionary;
|
||||||
|
|
||||||
public:
|
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 {
|
bool has_nonstatic_fields() const {
|
||||||
return (_misc_flags & _misc_has_nonstatic_fields) != 0;
|
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);
|
bool is_override(const methodHandle& super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS);
|
||||||
|
|
||||||
// package
|
// 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(const Klass* class2) const;
|
||||||
bool is_same_class_package(oop classloader2, const Symbol* classname2) const;
|
bool is_same_class_package(oop classloader2, const Symbol* classname2) const;
|
||||||
static bool is_same_class_package(oop class_loader1,
|
static bool is_same_class_package(oop class_loader1,
|
||||||
@ -1030,6 +1079,7 @@ public:
|
|||||||
|
|
||||||
// Naming
|
// Naming
|
||||||
const char* signature_name() const;
|
const char* signature_name() const;
|
||||||
|
static const jbyte* package_from_name(const Symbol* name, int& length);
|
||||||
|
|
||||||
// GC specific object visitors
|
// GC specific object visitors
|
||||||
//
|
//
|
||||||
@ -1247,7 +1297,8 @@ public:
|
|||||||
void oop_verify_on(oop obj, outputStream* st);
|
void oop_verify_on(oop obj, outputStream* st);
|
||||||
|
|
||||||
// Logging
|
// 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
|
// for adding methods
|
||||||
|
@ -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.
|
// gotten an OOM later but keep the mirror if it was created.
|
||||||
if (java_mirror() == NULL) {
|
if (java_mirror() == NULL) {
|
||||||
Handle loader = loader_data->class_loader();
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1329,7 +1329,7 @@ vmSymbols::SID Method::klass_id_for_intrinsics(const Klass* holder) {
|
|||||||
// exception: the AES intrinsics come from lib/ext/sunjce_provider.jar
|
// 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
|
// which does not use the class default class loader so we check for its loader here
|
||||||
const InstanceKlass* ik = InstanceKlass::cast(holder);
|
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
|
return vmSymbols::NO_SID; // regardless of name, no intrinsics here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,8 +135,18 @@ Klass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_data,
|
|||||||
// GC walks these as strong roots.
|
// GC walks these as strong roots.
|
||||||
loader_data->add_class(oak);
|
loader_data->add_class(oak);
|
||||||
|
|
||||||
|
// The array is defined in the module of its bottom class
|
||||||
|
Klass* bottom_klass = oak->bottom_klass();
|
||||||
|
ModuleEntry* module;
|
||||||
|
if (bottom_klass->is_instance_klass()) {
|
||||||
|
module = InstanceKlass::cast(bottom_klass)->module();
|
||||||
|
} else {
|
||||||
|
module = ModuleEntryTable::javabase_module();
|
||||||
|
}
|
||||||
|
assert(module != NULL, "No module entry for array");
|
||||||
|
|
||||||
// Call complete_create_array_klass after all instance variables has been initialized.
|
// Call complete_create_array_klass after all instance variables has been initialized.
|
||||||
ArrayKlass::complete_create_array_klass(oak, super_klass, CHECK_0);
|
ArrayKlass::complete_create_array_klass(oak, super_klass, module, CHECK_0);
|
||||||
|
|
||||||
return oak;
|
return oak;
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ TypeArrayKlass* TypeArrayKlass::create_klass(BasicType type,
|
|||||||
null_loader_data->add_class(ak);
|
null_loader_data->add_class(ak);
|
||||||
|
|
||||||
// Call complete_create_array_klass after all instance variables have been initialized.
|
// Call complete_create_array_klass after all instance variables have been initialized.
|
||||||
complete_create_array_klass(ak, ak->super(), CHECK_NULL);
|
complete_create_array_klass(ak, ak->super(), ModuleEntryTable::javabase_module(), CHECK_NULL);
|
||||||
|
|
||||||
return ak;
|
return ak;
|
||||||
}
|
}
|
||||||
|
@ -319,8 +319,6 @@ class LibraryCallKit : public GraphKit {
|
|||||||
|
|
||||||
bool inline_profileBoolean();
|
bool inline_profileBoolean();
|
||||||
bool inline_isCompileConstant();
|
bool inline_isCompileConstant();
|
||||||
|
|
||||||
bool inline_deoptimize();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------make_vm_intrinsic----------------------------
|
//---------------------------make_vm_intrinsic----------------------------
|
||||||
@ -821,9 +819,6 @@ bool LibraryCallKit::try_to_inline(int predicate) {
|
|||||||
case vmIntrinsics::_hasNegatives:
|
case vmIntrinsics::_hasNegatives:
|
||||||
return inline_hasNegatives();
|
return inline_hasNegatives();
|
||||||
|
|
||||||
case vmIntrinsics::_deoptimize:
|
|
||||||
return inline_deoptimize();
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// If you get here, it may be that someone has added a new intrinsic
|
// If you get here, it may be that someone has added a new intrinsic
|
||||||
// to the list in vmSymbols.hpp without implementing it here.
|
// to the list in vmSymbols.hpp without implementing it here.
|
||||||
@ -6754,12 +6749,3 @@ bool LibraryCallKit::inline_isCompileConstant() {
|
|||||||
set_result(n->is_Con() ? intcon(1) : intcon(0));
|
set_result(n->is_Con() ? intcon(1) : intcon(0));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LibraryCallKit::inline_deoptimize() {
|
|
||||||
assert(WhiteBoxAPI, "");
|
|
||||||
PreserveReexecuteState preexecs(this);
|
|
||||||
jvms()->set_should_reexecute(false);
|
|
||||||
uncommon_trap(Deoptimization::Reason_intrinsic,
|
|
||||||
Deoptimization::Action_none);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
@ -58,6 +58,9 @@
|
|||||||
# include "classfile/classFileStream.hpp"
|
# include "classfile/classFileStream.hpp"
|
||||||
# include "classfile/classLoader.hpp"
|
# include "classfile/classLoader.hpp"
|
||||||
# include "classfile/javaClasses.hpp"
|
# include "classfile/javaClasses.hpp"
|
||||||
|
# include "classfile/moduleEntry.hpp"
|
||||||
|
# include "classfile/modules.hpp"
|
||||||
|
# include "classfile/packageEntry.hpp"
|
||||||
# include "classfile/symbolTable.hpp"
|
# include "classfile/symbolTable.hpp"
|
||||||
# include "classfile/systemDictionary.hpp"
|
# include "classfile/systemDictionary.hpp"
|
||||||
# include "classfile/vmSymbols.hpp"
|
# include "classfile/vmSymbols.hpp"
|
||||||
|
@ -28,7 +28,9 @@
|
|||||||
#include "classfile/altHashing.hpp"
|
#include "classfile/altHashing.hpp"
|
||||||
#include "classfile/classFileStream.hpp"
|
#include "classfile/classFileStream.hpp"
|
||||||
#include "classfile/classLoader.hpp"
|
#include "classfile/classLoader.hpp"
|
||||||
|
#include "classfile/javaClasses.hpp"
|
||||||
#include "classfile/javaClasses.inline.hpp"
|
#include "classfile/javaClasses.inline.hpp"
|
||||||
|
#include "classfile/modules.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/symbolTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "classfile/vmSymbols.hpp"
|
#include "classfile/vmSymbols.hpp"
|
||||||
@ -3443,6 +3445,47 @@ JNI_LEAF(jint, jni_GetJavaVM(JNIEnv *env, JavaVM **vm))
|
|||||||
return JNI_OK;
|
return JNI_OK;
|
||||||
JNI_END
|
JNI_END
|
||||||
|
|
||||||
|
|
||||||
|
JNI_ENTRY(jobject, jni_GetModule(JNIEnv* env, jclass clazz))
|
||||||
|
JNIWrapper("GetModule");
|
||||||
|
return Modules::get_module(clazz, THREAD);
|
||||||
|
JNI_END
|
||||||
|
|
||||||
|
|
||||||
|
JNI_ENTRY(void, jni_AddModuleReads(JNIEnv* env, jobject m1, jobject m2))
|
||||||
|
JNIWrapper("AddModuleReads");
|
||||||
|
if (m1 == NULL || m2 == NULL) {
|
||||||
|
THROW(vmSymbols::java_lang_NullPointerException());
|
||||||
|
}
|
||||||
|
JavaValue result(T_VOID);
|
||||||
|
Handle m1_h(THREAD, JNIHandles::resolve(m1));
|
||||||
|
if (!java_lang_reflect_Module::is_instance(m1_h())) {
|
||||||
|
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Bad m1 object");
|
||||||
|
}
|
||||||
|
Handle m2_h(THREAD, JNIHandles::resolve(m2));
|
||||||
|
if (!java_lang_reflect_Module::is_instance(m2_h())) {
|
||||||
|
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Bad m2 object");
|
||||||
|
}
|
||||||
|
JavaCalls::call_static(&result,
|
||||||
|
KlassHandle(THREAD, SystemDictionary::module_Modules_klass()),
|
||||||
|
vmSymbols::addReads_name(),
|
||||||
|
vmSymbols::addReads_signature(),
|
||||||
|
m1_h,
|
||||||
|
m2_h,
|
||||||
|
THREAD);
|
||||||
|
JNI_END
|
||||||
|
|
||||||
|
|
||||||
|
JNI_ENTRY(jboolean, jni_CanReadModule(JNIEnv* env, jobject m1, jobject m2))
|
||||||
|
JNIWrapper("CanReadModule");
|
||||||
|
if (m1 == NULL || m2 == NULL) {
|
||||||
|
THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);
|
||||||
|
}
|
||||||
|
jboolean res = Modules::can_read_module(m1, m2, CHECK_false);
|
||||||
|
return res;
|
||||||
|
JNI_END
|
||||||
|
|
||||||
|
|
||||||
// Structure containing all jni functions
|
// Structure containing all jni functions
|
||||||
struct JNINativeInterface_ jni_NativeInterface = {
|
struct JNINativeInterface_ jni_NativeInterface = {
|
||||||
NULL,
|
NULL,
|
||||||
@ -3722,7 +3765,13 @@ struct JNINativeInterface_ jni_NativeInterface = {
|
|||||||
|
|
||||||
// New 1_6 features
|
// New 1_6 features
|
||||||
|
|
||||||
jni_GetObjectRefType
|
jni_GetObjectRefType,
|
||||||
|
|
||||||
|
// Module features
|
||||||
|
|
||||||
|
jni_GetModule,
|
||||||
|
jni_AddModuleReads,
|
||||||
|
jni_CanReadModule
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -765,6 +765,17 @@ struct JNINativeInterface_ {
|
|||||||
|
|
||||||
jobjectRefType (JNICALL *GetObjectRefType)
|
jobjectRefType (JNICALL *GetObjectRefType)
|
||||||
(JNIEnv* env, jobject obj);
|
(JNIEnv* env, jobject obj);
|
||||||
|
|
||||||
|
/* Module Features */
|
||||||
|
|
||||||
|
jobject (JNICALL *GetModule)
|
||||||
|
(JNIEnv* env, jclass clazz);
|
||||||
|
|
||||||
|
void (JNICALL *AddModuleReads)
|
||||||
|
(JNIEnv* env, jobject m1, jobject m2);
|
||||||
|
|
||||||
|
jboolean (JNICALL *CanReadModule)
|
||||||
|
(JNIEnv* env, jobject m1, jobject m2);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1857,6 +1868,20 @@ struct JNIEnv_ {
|
|||||||
return functions->GetObjectRefType(this, obj);
|
return functions->GetObjectRefType(this, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Module Features */
|
||||||
|
|
||||||
|
jobject GetModule(jclass clazz) {
|
||||||
|
return functions->GetModule(this, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddModuleReads(jobject fromModule, jobject sourceModule) {
|
||||||
|
functions->AddModuleReads(this, fromModule, sourceModule);
|
||||||
|
}
|
||||||
|
|
||||||
|
jboolean CanReadModule(jobject askingModule, jobject sourceModule) {
|
||||||
|
return functions->CanReadModule(this, askingModule, sourceModule);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -1989,7 +1989,48 @@ JNI_ENTRY_CHECKED(jint,
|
|||||||
return result;
|
return result;
|
||||||
JNI_END
|
JNI_END
|
||||||
|
|
||||||
|
JNI_ENTRY_CHECKED(jobject,
|
||||||
|
checked_jni_GetModule(JNIEnv *env,
|
||||||
|
jclass clazz))
|
||||||
|
functionEnter(thr);
|
||||||
|
IN_VM(
|
||||||
|
jniCheck::validate_class(thr, clazz, false);
|
||||||
|
)
|
||||||
|
jobject result = UNCHECKED()->GetModule(env,clazz);
|
||||||
|
functionExit(thr);
|
||||||
|
return result;
|
||||||
|
JNI_END
|
||||||
|
|
||||||
|
JNI_ENTRY_CHECKED(void,
|
||||||
|
checked_jni_AddModuleReads(JNIEnv *env,
|
||||||
|
jobject fromModule,
|
||||||
|
jobject sourceModule))
|
||||||
|
functionEnter(thr);
|
||||||
|
IN_VM(
|
||||||
|
jniCheck::validate_object(thr, fromModule);
|
||||||
|
if (sourceModule != NULL) {
|
||||||
|
jniCheck::validate_object(thr, sourceModule);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
UNCHECKED()->AddModuleReads(env,fromModule,sourceModule);
|
||||||
|
functionExit(thr);
|
||||||
|
JNI_END
|
||||||
|
|
||||||
|
JNI_ENTRY_CHECKED(jboolean,
|
||||||
|
checked_jni_CanReadModule(JNIEnv *env,
|
||||||
|
jobject askingModule,
|
||||||
|
jobject sourceModule))
|
||||||
|
functionEnter(thr);
|
||||||
|
IN_VM(
|
||||||
|
jniCheck::validate_object(thr, askingModule);
|
||||||
|
if (sourceModule != NULL) {
|
||||||
|
jniCheck::validate_object(thr, sourceModule);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
jboolean result = UNCHECKED()->CanReadModule(env,askingModule,sourceModule);
|
||||||
|
functionExit(thr);
|
||||||
|
return result;
|
||||||
|
JNI_END
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Structure containing all checked jni functions
|
* Structure containing all checked jni functions
|
||||||
@ -2272,7 +2313,13 @@ struct JNINativeInterface_ checked_jni_NativeInterface = {
|
|||||||
|
|
||||||
// New 1.6 Features
|
// New 1.6 Features
|
||||||
|
|
||||||
checked_jni_GetObjectRefType
|
checked_jni_GetObjectRefType,
|
||||||
|
|
||||||
|
// Module Features
|
||||||
|
|
||||||
|
checked_jni_GetModule,
|
||||||
|
checked_jni_AddModuleReads,
|
||||||
|
checked_jni_CanReadModule
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -25,8 +25,12 @@
|
|||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/classFileStream.hpp"
|
#include "classfile/classFileStream.hpp"
|
||||||
#include "classfile/classLoader.hpp"
|
#include "classfile/classLoader.hpp"
|
||||||
|
#include "classfile/classLoaderData.inline.hpp"
|
||||||
#include "classfile/javaAssertions.hpp"
|
#include "classfile/javaAssertions.hpp"
|
||||||
#include "classfile/javaClasses.inline.hpp"
|
#include "classfile/javaClasses.inline.hpp"
|
||||||
|
#include "classfile/moduleEntry.hpp"
|
||||||
|
#include "classfile/modules.hpp"
|
||||||
|
#include "classfile/packageEntry.hpp"
|
||||||
#include "classfile/stringTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "classfile/vmSymbols.hpp"
|
#include "classfile/vmSymbols.hpp"
|
||||||
@ -1047,6 +1051,58 @@ JVM_ENTRY(jclass, JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name)
|
|||||||
(jclass) JNIHandles::make_local(env, k->java_mirror());
|
(jclass) JNIHandles::make_local(env, k->java_mirror());
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
// Module support //////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
JVM_ENTRY(void, JVM_DefineModule(JNIEnv *env, jobject module, jstring version, jstring location,
|
||||||
|
jobjectArray packages))
|
||||||
|
JVMWrapper("JVM_DefineModule");
|
||||||
|
Modules::define_module(module, version, location, packages, CHECK);
|
||||||
|
JVM_END
|
||||||
|
|
||||||
|
JVM_ENTRY(void, JVM_SetBootLoaderUnnamedModule(JNIEnv *env, jobject module))
|
||||||
|
JVMWrapper("JVM_SetBootLoaderUnnamedModule");
|
||||||
|
Modules::set_bootloader_unnamed_module(module, CHECK);
|
||||||
|
JVM_END
|
||||||
|
|
||||||
|
JVM_ENTRY(void, JVM_AddModuleExports(JNIEnv *env, jobject from_module, jstring package, jobject to_module))
|
||||||
|
JVMWrapper("JVM_AddModuleExports");
|
||||||
|
Modules::add_module_exports_qualified(from_module, package, to_module, CHECK);
|
||||||
|
JVM_END
|
||||||
|
|
||||||
|
JVM_ENTRY(void, JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, jstring package))
|
||||||
|
JVMWrapper("JVM_AddModuleExportsToAllUnnamed");
|
||||||
|
Modules::add_module_exports_to_all_unnamed(from_module, package, CHECK);
|
||||||
|
JVM_END
|
||||||
|
|
||||||
|
JVM_ENTRY(void, JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, jstring package))
|
||||||
|
JVMWrapper("JVM_AddModuleExportsToAll");
|
||||||
|
Modules::add_module_exports(from_module, package, NULL, CHECK);
|
||||||
|
JVM_END
|
||||||
|
|
||||||
|
JVM_ENTRY (void, JVM_AddReadsModule(JNIEnv *env, jobject from_module, jobject source_module))
|
||||||
|
JVMWrapper("JVM_AddReadsModule");
|
||||||
|
Modules::add_reads_module(from_module, source_module, CHECK);
|
||||||
|
JVM_END
|
||||||
|
|
||||||
|
JVM_ENTRY(jboolean, JVM_CanReadModule(JNIEnv *env, jobject asking_module, jobject source_module))
|
||||||
|
JVMWrapper("JVM_CanReadModule");
|
||||||
|
return Modules::can_read_module(asking_module, source_module, THREAD);
|
||||||
|
JVM_END
|
||||||
|
|
||||||
|
JVM_ENTRY(jboolean, JVM_IsExportedToModule(JNIEnv *env, jobject from_module, jstring package, jobject to_module))
|
||||||
|
JVMWrapper("JVM_IsExportedToModule");
|
||||||
|
return Modules::is_exported_to_module(from_module, package, to_module, THREAD);
|
||||||
|
JVM_END
|
||||||
|
|
||||||
|
JVM_ENTRY (void, JVM_AddModulePackage(JNIEnv *env, jobject module, jstring package))
|
||||||
|
JVMWrapper("JVM_AddModulePackage");
|
||||||
|
Modules::add_module_package(module, package, CHECK);
|
||||||
|
JVM_END
|
||||||
|
|
||||||
|
JVM_ENTRY (jobject, JVM_GetModuleByPackageName(JNIEnv *env, jobject loader, jstring package))
|
||||||
|
JVMWrapper("JVM_GetModuleByPackageName");
|
||||||
|
return Modules::get_module_by_package_name(loader, package, THREAD);
|
||||||
|
JVM_END
|
||||||
|
|
||||||
// Reflection support //////////////////////////////////////////////////////////////////////////////
|
// Reflection support //////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -416,6 +416,41 @@ JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader,
|
|||||||
const jbyte *buf, jsize len, jobject pd,
|
const jbyte *buf, jsize len, jobject pd,
|
||||||
const char *source);
|
const char *source);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Module support funcions
|
||||||
|
*/
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
JVM_DefineModule(JNIEnv *env, jobject module, jstring version, jstring location,
|
||||||
|
jobjectArray packages);
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
JVM_SetBootLoaderUnnamedModule(JNIEnv *env, jobject module);
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
JVM_AddModuleExports(JNIEnv *env, jobject from_module, jstring package, jobject to_module);
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, jstring package);
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, jstring package);
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
JVM_AddReadsModule(JNIEnv *env, jobject from_module, jobject source_module);
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL
|
||||||
|
JVM_CanReadModule(JNIEnv *env, jobject asking_module, jobject source_module);
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL
|
||||||
|
JVM_IsExportedToModule(JNIEnv *env, jobject from_module, jstring package, jobject to_module);
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
JVM_AddModulePackage(JNIEnv* env, jobject module, jstring package);
|
||||||
|
|
||||||
|
JNIEXPORT jobject JNICALL
|
||||||
|
JVM_GetModuleByPackageName(JNIEnv* env, jobject loader, jstring package);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reflection support functions
|
* Reflection support functions
|
||||||
*/
|
*/
|
||||||
@ -920,6 +955,7 @@ JVM_IsSameClassPackage(JNIEnv *env, jclass class1, jclass class2);
|
|||||||
#define JVM_ACC_SYNTHETIC 0x1000 /* compiler-generated class, method or field */
|
#define JVM_ACC_SYNTHETIC 0x1000 /* compiler-generated class, method or field */
|
||||||
#define JVM_ACC_ANNOTATION 0x2000 /* annotation type */
|
#define JVM_ACC_ANNOTATION 0x2000 /* annotation type */
|
||||||
#define JVM_ACC_ENUM 0x4000 /* field is declared as element of enum */
|
#define JVM_ACC_ENUM 0x4000 /* field is declared as element of enum */
|
||||||
|
#define JVM_ACC_MODULE 0x8000 /* module-info class file */
|
||||||
|
|
||||||
#define JVM_ACC_PUBLIC_BIT 0
|
#define JVM_ACC_PUBLIC_BIT 0
|
||||||
#define JVM_ACC_PRIVATE_BIT 1
|
#define JVM_ACC_PRIVATE_BIT 1
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
<?xml-stylesheet type="text/xsl" href="jvmti.xsl"?>
|
<?xml-stylesheet type="text/xsl" href="jvmti.xsl"?>
|
||||||
<!--
|
<!--
|
||||||
Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
|
Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
|
||||||
This code is free software; you can redistribute it and/or modify it
|
This code is free software; you can redistribute it and/or modify it
|
||||||
@ -21,7 +21,7 @@
|
|||||||
Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
or visit www.oracle.com if you need additional information or have any
|
or visit www.oracle.com if you need additional information or have any
|
||||||
questions.
|
questions.
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<!DOCTYPE specification [
|
<!DOCTYPE specification [
|
||||||
@ -356,9 +356,9 @@
|
|||||||
]>
|
]>
|
||||||
|
|
||||||
<specification label="JVM(TM) Tool Interface"
|
<specification label="JVM(TM) Tool Interface"
|
||||||
majorversion="1"
|
majorversion="9"
|
||||||
minorversion="2"
|
minorversion="0"
|
||||||
microversion="3">
|
microversion="0">
|
||||||
<title subtitle="Version">
|
<title subtitle="Version">
|
||||||
<tm>JVM</tm> Tool Interface
|
<tm>JVM</tm> Tool Interface
|
||||||
</title>
|
</title>
|
||||||
@ -863,6 +863,23 @@ Agent_OnUnload_L(JavaVM *vm)</example>
|
|||||||
to be instrumented by the use of wrapper methods.
|
to be instrumented by the use of wrapper methods.
|
||||||
</intro>
|
</intro>
|
||||||
|
|
||||||
|
<intro id="bcimodules" label="Bytecode Instrumentation of code in modules">
|
||||||
|
Agents that instrument code in named modules may need to arrange for those
|
||||||
|
modules to read other modules. If code is instrumented to invoke a method
|
||||||
|
in a support class in another module, then the module of the instrumented
|
||||||
|
code should read the module of the supporting class. Furthermore, the
|
||||||
|
supporting class will only be accessible to the instrumented code if
|
||||||
|
it is <code>public</code> and in a package that is exported by its module.
|
||||||
|
Agents can use the JNI functions <code>CanReadModule</code> and
|
||||||
|
<code>AddModuleReads</code> to test and update a module to read another.
|
||||||
|
<p/>
|
||||||
|
As an aid to agents that deploy supporting classes on the search path of
|
||||||
|
the bootstrap class loader, or the search path of the class loader that
|
||||||
|
loads the main class, the Java virtual machine arranges for the module
|
||||||
|
of classes transformed by the <eventlink id="ClassFileLoadHook"/> event to
|
||||||
|
read the unnamed module of both class loaders.
|
||||||
|
</intro>
|
||||||
|
|
||||||
<intro id="mUTF" label="Modified UTF-8 String Encoding">
|
<intro id="mUTF" label="Modified UTF-8 String Encoding">
|
||||||
<jvmti/> uses modified UTF-8 to encode character strings.
|
<jvmti/> uses modified UTF-8 to encode character strings.
|
||||||
This is the same encoding used by JNI.
|
This is the same encoding used by JNI.
|
||||||
@ -1880,10 +1897,6 @@ jvmtiEnv *jvmti;
|
|||||||
<outptr><struct>jvmtiThreadInfo</struct></outptr>
|
<outptr><struct>jvmtiThreadInfo</struct></outptr>
|
||||||
<description>
|
<description>
|
||||||
On return, filled with information describing the specified thread.
|
On return, filled with information describing the specified thread.
|
||||||
<p/>
|
|
||||||
For JDK 1.1 implementations that don't
|
|
||||||
recognize context class loaders,
|
|
||||||
the <code>context_class_loader</code> field will be NULL.
|
|
||||||
</description>
|
</description>
|
||||||
</param>
|
</param>
|
||||||
</parameters>
|
</parameters>
|
||||||
@ -6460,6 +6473,43 @@ class C2 extends C1 implements I2 {
|
|||||||
</function>
|
</function>
|
||||||
</category>
|
</category>
|
||||||
|
|
||||||
|
<category id="module" label="Module">
|
||||||
|
|
||||||
|
<intro>
|
||||||
|
</intro>
|
||||||
|
|
||||||
|
<function id="GetAllModules" num="3" since="9">
|
||||||
|
<synopsis>Get All Modules</synopsis>
|
||||||
|
<description>
|
||||||
|
Return an array of all modules loaded in the virtual machine.
|
||||||
|
The number of modules in the array is returned via
|
||||||
|
<code>module_count_ptr</code>, and the array itself via
|
||||||
|
<code>modules_ptr</code>.
|
||||||
|
<p/>
|
||||||
|
</description>
|
||||||
|
<origin>new</origin>
|
||||||
|
<capabilities>
|
||||||
|
</capabilities>
|
||||||
|
<parameters>
|
||||||
|
<param id="module_count_ptr">
|
||||||
|
<outptr><jint/></outptr>
|
||||||
|
<description>
|
||||||
|
On return, points to the number of returned modules.
|
||||||
|
</description>
|
||||||
|
</param>
|
||||||
|
<param id="modules_ptr">
|
||||||
|
<allocbuf outcount="module_count_ptr"><jobject/></allocbuf>
|
||||||
|
<description>
|
||||||
|
On return, points to an array of references, one
|
||||||
|
for each module.
|
||||||
|
</description>
|
||||||
|
</param>
|
||||||
|
</parameters>
|
||||||
|
<errors>
|
||||||
|
</errors>
|
||||||
|
</function>
|
||||||
|
</category>
|
||||||
|
|
||||||
<category id="class" label="Class">
|
<category id="class" label="Class">
|
||||||
|
|
||||||
<intro>
|
<intro>
|
||||||
@ -6508,9 +6558,6 @@ class C2 extends C1 implements I2 {
|
|||||||
either by defining it directly or by delegation to another class loader.
|
either by defining it directly or by delegation to another class loader.
|
||||||
See <vmspec chapter="5.3"/>.
|
See <vmspec chapter="5.3"/>.
|
||||||
<p/>
|
<p/>
|
||||||
For JDK version 1.1 implementations that don't
|
|
||||||
recognize the distinction between initiating and defining class loaders,
|
|
||||||
this function should return all classes loaded in the virtual machine.
|
|
||||||
The number of classes in the array is returned via
|
The number of classes in the array is returned via
|
||||||
<code>class_count_ptr</code>, and the array itself via
|
<code>class_count_ptr</code>, and the array itself via
|
||||||
<code>classes_ptr</code>.
|
<code>classes_ptr</code>.
|
||||||
@ -9941,6 +9988,12 @@ myInit() {
|
|||||||
See <eventlink id="ResourceExhausted"/>.
|
See <eventlink id="ResourceExhausted"/>.
|
||||||
</description>
|
</description>
|
||||||
</capabilityfield>
|
</capabilityfield>
|
||||||
|
<capabilityfield id="can_generate_early_vmstart" since="9">
|
||||||
|
<description>
|
||||||
|
Can generate the <code>VMStart</code> event early.
|
||||||
|
See <eventlink id="VMStart"/>.
|
||||||
|
</description>
|
||||||
|
</capabilityfield>
|
||||||
</capabilitiestypedef>
|
</capabilitiestypedef>
|
||||||
|
|
||||||
<function id="GetPotentialCapabilities" jkernel="yes" phase="onload" num="140">
|
<function id="GetPotentialCapabilities" jkernel="yes" phase="onload" num="140">
|
||||||
@ -12351,7 +12404,7 @@ myInit() {
|
|||||||
</parameters>
|
</parameters>
|
||||||
</event>
|
</event>
|
||||||
|
|
||||||
<event label="Class File Load Hook" phase="any"
|
<event label="Class File Load Hook" phase="start"
|
||||||
id="ClassFileLoadHook" const="JVMTI_EVENT_CLASS_FILE_LOAD_HOOK" num="54">
|
id="ClassFileLoadHook" const="JVMTI_EVENT_CLASS_FILE_LOAD_HOOK" num="54">
|
||||||
<description>
|
<description>
|
||||||
This event is sent when the VM obtains class file data,
|
This event is sent when the VM obtains class file data,
|
||||||
@ -12367,9 +12420,9 @@ myInit() {
|
|||||||
<internallink id="bci">bytecode instrumentation</internallink>
|
<internallink id="bci">bytecode instrumentation</internallink>
|
||||||
for usage information.
|
for usage information.
|
||||||
<p/>
|
<p/>
|
||||||
This event may be sent before the VM is initialized (the primordial
|
This event may be sent before the VM is initialized (the start
|
||||||
<functionlink id="GetPhase">phase</functionlink>). During this time
|
<functionlink id="GetPhase">phase</functionlink>).
|
||||||
no VM resources should be created. Some classes might not be compatible
|
Some classes might not be compatible
|
||||||
with the function (eg. ROMized classes) and this event will not be
|
with the function (eg. ROMized classes) and this event will not be
|
||||||
generated for these classes.
|
generated for these classes.
|
||||||
<p/>
|
<p/>
|
||||||
@ -12378,9 +12431,7 @@ myInit() {
|
|||||||
using the memory allocation function
|
using the memory allocation function
|
||||||
<functionlink id="Allocate"></functionlink> because the
|
<functionlink id="Allocate"></functionlink> because the
|
||||||
VM is responsible for freeing the new class file data buffer
|
VM is responsible for freeing the new class file data buffer
|
||||||
using <functionlink id="Deallocate"></functionlink>.
|
using <functionlink id="Deallocate"></functionlink>.
|
||||||
Note that <functionlink id="Allocate"></functionlink>
|
|
||||||
is permitted during the primordial phase.
|
|
||||||
<p/>
|
<p/>
|
||||||
If the agent wishes to modify the class file, it must set
|
If the agent wishes to modify the class file, it must set
|
||||||
<code>new_class_data</code> to point
|
<code>new_class_data</code> to point
|
||||||
@ -12427,8 +12478,6 @@ myInit() {
|
|||||||
</outptr>
|
</outptr>
|
||||||
<description>
|
<description>
|
||||||
The JNI environment of the event (current) thread.
|
The JNI environment of the event (current) thread.
|
||||||
Will be <code>NULL</code> if sent during the primordial
|
|
||||||
<functionlink id="GetPhase">phase</functionlink>.
|
|
||||||
</description>
|
</description>
|
||||||
</param>
|
</param>
|
||||||
<param id="class_being_redefined">
|
<param id="class_being_redefined">
|
||||||
@ -12496,9 +12545,28 @@ myInit() {
|
|||||||
The VM initialization event signals the start of the VM.
|
The VM initialization event signals the start of the VM.
|
||||||
At this time JNI is live but the VM is not yet fully initialized.
|
At this time JNI is live but the VM is not yet fully initialized.
|
||||||
Once this event is generated, the agent is free to call any JNI function.
|
Once this event is generated, the agent is free to call any JNI function.
|
||||||
This event signals the beginning of the start phase,
|
This event signals the beginning of the start phase,
|
||||||
<jvmti/> functions permitted in the start phase may be called.
|
<jvmti/> functions permitted in the start phase may be called.
|
||||||
<p/>
|
<p/>
|
||||||
|
The timing of this event may depend on whether the agent has added the
|
||||||
|
<internallink id="jvmtiCapabilities.can_generate_early_vmstart">
|
||||||
|
<code>can_generate_early_vmstart</code></internallink> capability or not.
|
||||||
|
If the capability has been added then the VM posts the event as early
|
||||||
|
as possible. The VM is capable of executing bytecode but it may not have
|
||||||
|
initialized to the point where it can load classes in modules other than
|
||||||
|
<code>java.base</code>. Agents that do load-time instrumentation in this
|
||||||
|
phase must take great care when instrumenting code that potentially
|
||||||
|
executes in this phase. Care should also be taken with JNI
|
||||||
|
<code>FindClass</code> as it may not be possible to load classes that are
|
||||||
|
not in the <code>java.base</code> module.
|
||||||
|
If the capability has not been added then the VM delays posting this
|
||||||
|
event until it is capable of loading classes in modules other than
|
||||||
|
<code>java.base</code> or the VM has completed its initialization.
|
||||||
|
Agents that create more than one JVM TI environment, where the
|
||||||
|
capability is added to some but not all environments, may observe the
|
||||||
|
start phase beginning earlier in the JVM TI environments that possess
|
||||||
|
the capabilty.
|
||||||
|
<p/>
|
||||||
In the case of VM start-up failure, this event will not be sent.
|
In the case of VM start-up failure, this event will not be sent.
|
||||||
</description>
|
</description>
|
||||||
<origin>jvmdi</origin>
|
<origin>jvmdi</origin>
|
||||||
@ -12576,7 +12644,7 @@ myInit() {
|
|||||||
</parameters>
|
</parameters>
|
||||||
</event>
|
</event>
|
||||||
|
|
||||||
<event label="Compiled Method Load"
|
<event label="Compiled Method Load" phase="start"
|
||||||
id="CompiledMethodLoad" const="JVMTI_EVENT_COMPILED_METHOD_LOAD" num="68">
|
id="CompiledMethodLoad" const="JVMTI_EVENT_COMPILED_METHOD_LOAD" num="68">
|
||||||
<description>
|
<description>
|
||||||
Sent when a method is compiled and loaded into memory by the VM.
|
Sent when a method is compiled and loaded into memory by the VM.
|
||||||
@ -12667,7 +12735,7 @@ myInit() {
|
|||||||
</parameters>
|
</parameters>
|
||||||
</event>
|
</event>
|
||||||
|
|
||||||
<event label="Compiled Method Unload"
|
<event label="Compiled Method Unload" phase="start"
|
||||||
id="CompiledMethodUnload" const="JVMTI_EVENT_COMPILED_METHOD_UNLOAD" num="69">
|
id="CompiledMethodUnload" const="JVMTI_EVENT_COMPILED_METHOD_UNLOAD" num="69">
|
||||||
<description>
|
<description>
|
||||||
Sent when a compiled method is unloaded from memory.
|
Sent when a compiled method is unloaded from memory.
|
||||||
@ -14340,6 +14408,17 @@ typedef void (JNICALL *jvmtiEventVMInit)
|
|||||||
<change date="19 June 2013" version="1.2.3">
|
<change date="19 June 2013" version="1.2.3">
|
||||||
Added support for statically linked agents.
|
Added support for statically linked agents.
|
||||||
</change>
|
</change>
|
||||||
|
<change date="20 January 2016" version="9.0.0">
|
||||||
|
Support for modules:
|
||||||
|
- The majorversion is 9 now
|
||||||
|
- The ClassFileLoadHook events are not sent during the primordial phase anymore.
|
||||||
|
- Add new function GetAllModules
|
||||||
|
</change>
|
||||||
|
<change date="17 February 2016" version="9.0.0">
|
||||||
|
Support for modules:
|
||||||
|
- Add new capability can_generate_early_vmstart
|
||||||
|
- Allow CompiledMethodLoad events at start phase
|
||||||
|
</change>
|
||||||
</changehistory>
|
</changehistory>
|
||||||
|
|
||||||
</specification>
|
</specification>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<!--
|
<!--
|
||||||
Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
|
Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
|
||||||
This code is free software; you can redistribute it and/or modify it
|
This code is free software; you can redistribute it and/or modify it
|
||||||
@ -1801,7 +1801,7 @@ typedef struct {
|
|||||||
<xsl:text>) (jvmtiEnv* env</xsl:text>
|
<xsl:text>) (jvmtiEnv* env</xsl:text>
|
||||||
<xsl:apply-templates select="$thisFunction/parameters" mode="signature">
|
<xsl:apply-templates select="$thisFunction/parameters" mode="signature">
|
||||||
<xsl:with-param name="comma">
|
<xsl:with-param name="comma">
|
||||||
<xsl:text>, 
 </xsl:text>
|
<xsl:text>,
 </xsl:text>
|
||||||
</xsl:with-param>
|
</xsl:with-param>
|
||||||
</xsl:apply-templates>
|
</xsl:apply-templates>
|
||||||
<xsl:text>);</xsl:text>
|
<xsl:text>);</xsl:text>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<!--
|
<!--
|
||||||
Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
|
Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
|
||||||
This code is free software; you can redistribute it and/or modify it
|
This code is free software; you can redistribute it and/or modify it
|
||||||
@ -517,7 +517,7 @@ static jvmtiError JNICALL
|
|||||||
}</xsl:text>
|
}</xsl:text>
|
||||||
</xsl:if>
|
</xsl:if>
|
||||||
<xsl:if test="contains(@phase,'start')">
|
<xsl:if test="contains(@phase,'start')">
|
||||||
<xsl:text> if(JvmtiEnv::get_phase()!=JVMTI_PHASE_START && JvmtiEnv::get_phase()!=JVMTI_PHASE_LIVE) {
|
<xsl:text> if(JvmtiEnv::get_phase(env)!=JVMTI_PHASE_START && JvmtiEnv::get_phase()!=JVMTI_PHASE_LIVE) {
|
||||||
</xsl:text>
|
</xsl:text>
|
||||||
<xsl:if test="$trace='Trace'">
|
<xsl:if test="$trace='Trace'">
|
||||||
<xsl:text> if (trace_flags) {
|
<xsl:text> if (trace_flags) {
|
||||||
|
@ -186,6 +186,20 @@ JvmtiEnv::GetThreadLocalStorage(jthread thread, void** data_ptr) {
|
|||||||
return JVMTI_ERROR_NONE;
|
return JVMTI_ERROR_NONE;
|
||||||
} /* end GetThreadLocalStorage */
|
} /* end GetThreadLocalStorage */
|
||||||
|
|
||||||
|
//
|
||||||
|
// Module functions
|
||||||
|
//
|
||||||
|
|
||||||
|
// module_count_ptr - pre-checked for NULL
|
||||||
|
// modules_ptr - pre-checked for NULL
|
||||||
|
jvmtiError
|
||||||
|
JvmtiEnv::GetAllModules(jint* module_count_ptr, jobject** modules_ptr) {
|
||||||
|
JvmtiModuleClosure jmc;
|
||||||
|
|
||||||
|
return jmc.get_all_modules(this, module_count_ptr, modules_ptr);
|
||||||
|
} /* end GetAllModules */
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Class functions
|
// Class functions
|
||||||
//
|
//
|
||||||
@ -563,7 +577,7 @@ JvmtiEnv::AddToSystemClassLoaderSearch(const char* segment) {
|
|||||||
// phase_ptr - pre-checked for NULL
|
// phase_ptr - pre-checked for NULL
|
||||||
jvmtiError
|
jvmtiError
|
||||||
JvmtiEnv::GetPhase(jvmtiPhase* phase_ptr) {
|
JvmtiEnv::GetPhase(jvmtiPhase* phase_ptr) {
|
||||||
*phase_ptr = get_phase();
|
*phase_ptr = phase();
|
||||||
return JVMTI_ERROR_NONE;
|
return JVMTI_ERROR_NONE;
|
||||||
} /* end GetPhase */
|
} /* end GetPhase */
|
||||||
|
|
||||||
@ -3489,7 +3503,7 @@ JvmtiEnv::SetSystemProperty(const char* property, const char* value_ptr) {
|
|||||||
|
|
||||||
for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) {
|
for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) {
|
||||||
if (strcmp(property, p->key()) == 0) {
|
if (strcmp(property, p->key()) == 0) {
|
||||||
if (p->set_value(value_ptr)) {
|
if (p->set_writeable_value(value_ptr)) {
|
||||||
err = JVMTI_ERROR_NONE;
|
err = JVMTI_ERROR_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -114,6 +114,17 @@ JvmtiEnvBase::initialize() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jvmtiPhase
|
||||||
|
JvmtiEnvBase::phase() {
|
||||||
|
// For the JVMTI environments possessed the can_generate_early_vmstart:
|
||||||
|
// replace JVMTI_PHASE_PRIMORDIAL with JVMTI_PHASE_START
|
||||||
|
if (_phase == JVMTI_PHASE_PRIMORDIAL &&
|
||||||
|
JvmtiExport::early_vmstart_recorded() &&
|
||||||
|
early_vmstart_env()) {
|
||||||
|
return JVMTI_PHASE_START;
|
||||||
|
}
|
||||||
|
return _phase; // Normal case
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
JvmtiEnvBase::is_valid() {
|
JvmtiEnvBase::is_valid() {
|
||||||
@ -1475,3 +1486,35 @@ JvmtiMonitorClosure::do_monitor(ObjectMonitor* mon) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GrowableArray<jobject>* JvmtiModuleClosure::_tbl = NULL;
|
||||||
|
|
||||||
|
jvmtiError
|
||||||
|
JvmtiModuleClosure::get_all_modules(JvmtiEnv* env, jint* module_count_ptr, jobject** modules_ptr) {
|
||||||
|
ResourceMark rm;
|
||||||
|
MutexLocker ml(Module_lock);
|
||||||
|
|
||||||
|
_tbl = new GrowableArray<jobject>(77);
|
||||||
|
if (_tbl == NULL) {
|
||||||
|
return JVMTI_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate over all the modules loaded to the system.
|
||||||
|
ClassLoaderDataGraph::modules_do(&do_module);
|
||||||
|
|
||||||
|
jint len = _tbl->length();
|
||||||
|
guarantee(len > 0, "at least one module must be present");
|
||||||
|
|
||||||
|
jobject* array = (jobject*)env->jvmtiMalloc((jlong)(len * sizeof(jobject)));
|
||||||
|
if (array == NULL) {
|
||||||
|
return JVMTI_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
for (jint idx = 0; idx < len; idx++) {
|
||||||
|
array[idx] = _tbl->at(idx);
|
||||||
|
}
|
||||||
|
_tbl = NULL;
|
||||||
|
*modules_ptr = array;
|
||||||
|
*module_count_ptr = len;
|
||||||
|
return JVMTI_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -75,6 +75,7 @@ class JvmtiEnvBase : public CHeapObj<mtInternal> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static jvmtiPhase get_phase() { return _phase; }
|
static jvmtiPhase get_phase() { return _phase; }
|
||||||
|
static jvmtiPhase get_phase(jvmtiEnv* env) { return ((JvmtiEnvBase*)JvmtiEnv_from_jvmti_env(env))->phase(); }
|
||||||
static void set_phase(jvmtiPhase phase) { _phase = phase; }
|
static void set_phase(jvmtiPhase phase) { _phase = phase; }
|
||||||
static bool is_vm_live() { return _phase == JVMTI_PHASE_LIVE; }
|
static bool is_vm_live() { return _phase == JVMTI_PHASE_LIVE; }
|
||||||
|
|
||||||
@ -140,6 +141,7 @@ class JvmtiEnvBase : public CHeapObj<mtInternal> {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
jvmtiPhase phase();
|
||||||
bool is_valid();
|
bool is_valid();
|
||||||
|
|
||||||
bool use_version_1_0_semantics(); // agent asked for version 1.0
|
bool use_version_1_0_semantics(); // agent asked for version 1.0
|
||||||
@ -160,6 +162,10 @@ class JvmtiEnvBase : public CHeapObj<mtInternal> {
|
|||||||
|
|
||||||
jvmtiCapabilities *get_prohibited_capabilities() { return &_prohibited_capabilities; }
|
jvmtiCapabilities *get_prohibited_capabilities() { return &_prohibited_capabilities; }
|
||||||
|
|
||||||
|
bool early_vmstart_env() {
|
||||||
|
return get_capabilities()->can_generate_early_vmstart != 0;
|
||||||
|
}
|
||||||
|
|
||||||
static char** get_all_native_method_prefixes(int* count_ptr);
|
static char** get_all_native_method_prefixes(int* count_ptr);
|
||||||
|
|
||||||
// This test will answer true when all environments have been disposed and some have
|
// This test will answer true when all environments have been disposed and some have
|
||||||
@ -689,4 +695,21 @@ class JvmtiMonitorClosure: public MonitorClosure {
|
|||||||
jvmtiError error() { return _error;}
|
jvmtiError error() { return _error;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Jvmti module closure to collect all modules loaded to the system.
|
||||||
|
class JvmtiModuleClosure : public StackObj {
|
||||||
|
private:
|
||||||
|
static GrowableArray<jobject> *_tbl; // Protected with Module_lock
|
||||||
|
|
||||||
|
static void do_module(ModuleEntry* entry) {
|
||||||
|
assert_locked_or_safepoint(Module_lock);
|
||||||
|
jobject module = entry->module();
|
||||||
|
guarantee(module != NULL, "module object is NULL");
|
||||||
|
_tbl->push(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
jvmtiError get_all_modules(JvmtiEnv* env, jint* module_count_ptr, jobject** modules_ptr);
|
||||||
|
};
|
||||||
|
|
||||||
#endif // SHARE_VM_PRIMS_JVMTIENVBASE_HPP
|
#endif // SHARE_VM_PRIMS_JVMTIENVBASE_HPP
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -98,6 +98,7 @@ static const jlong NEED_THREAD_LIFE_EVENTS = THREAD_FILTERED_EVENT_BITS | THREA
|
|||||||
static const jlong EARLY_EVENT_BITS = CLASS_FILE_LOAD_HOOK_BIT |
|
static const jlong EARLY_EVENT_BITS = CLASS_FILE_LOAD_HOOK_BIT |
|
||||||
VM_START_BIT | VM_INIT_BIT | VM_DEATH_BIT | NATIVE_METHOD_BIND_BIT |
|
VM_START_BIT | VM_INIT_BIT | VM_DEATH_BIT | NATIVE_METHOD_BIND_BIT |
|
||||||
THREAD_START_BIT | THREAD_END_BIT |
|
THREAD_START_BIT | THREAD_END_BIT |
|
||||||
|
COMPILED_METHOD_LOAD_BIT | COMPILED_METHOD_UNLOAD_BIT |
|
||||||
DYNAMIC_CODE_GENERATED_BIT;
|
DYNAMIC_CODE_GENERATED_BIT;
|
||||||
static const jlong GLOBAL_EVENT_BITS = ~THREAD_FILTERED_EVENT_BITS;
|
static const jlong GLOBAL_EVENT_BITS = ~THREAD_FILTERED_EVENT_BITS;
|
||||||
static const jlong SHOULD_POST_ON_EXCEPTIONS_BITS = EXCEPTION_BITS | METHOD_EXIT_BIT | FRAME_POP_BIT;
|
static const jlong SHOULD_POST_ON_EXCEPTIONS_BITS = EXCEPTION_BITS | METHOD_EXIT_BIT | FRAME_POP_BIT;
|
||||||
@ -409,7 +410,7 @@ JvmtiEventControllerPrivate::recompute_env_enabled(JvmtiEnvBase* env) {
|
|||||||
env->env_event_enable()->_event_callback_enabled.get_bits() &
|
env->env_event_enable()->_event_callback_enabled.get_bits() &
|
||||||
env->env_event_enable()->_event_user_enabled.get_bits();
|
env->env_event_enable()->_event_user_enabled.get_bits();
|
||||||
|
|
||||||
switch (JvmtiEnv::get_phase()) {
|
switch (env->phase()) {
|
||||||
case JVMTI_PHASE_PRIMORDIAL:
|
case JVMTI_PHASE_PRIMORDIAL:
|
||||||
case JVMTI_PHASE_ONLOAD:
|
case JVMTI_PHASE_ONLOAD:
|
||||||
// only these events allowed in primordial or onload phase
|
// only these events allowed in primordial or onload phase
|
||||||
@ -576,8 +577,6 @@ JvmtiEventControllerPrivate::recompute_enabled() {
|
|||||||
// filtered events and there weren't last time
|
// filtered events and there weren't last time
|
||||||
if ( (any_env_thread_enabled & THREAD_FILTERED_EVENT_BITS) != 0 &&
|
if ( (any_env_thread_enabled & THREAD_FILTERED_EVENT_BITS) != 0 &&
|
||||||
(was_any_env_thread_enabled & THREAD_FILTERED_EVENT_BITS) == 0) {
|
(was_any_env_thread_enabled & THREAD_FILTERED_EVENT_BITS) == 0) {
|
||||||
assert(JvmtiEnv::is_vm_live() || (JvmtiEnv::get_phase()==JVMTI_PHASE_START),
|
|
||||||
"thread filtered events should not be enabled when VM not in start or live phase");
|
|
||||||
{
|
{
|
||||||
MutexLocker mu(Threads_lock); //hold the Threads_lock for the iteration
|
MutexLocker mu(Threads_lock); //hold the Threads_lock for the iteration
|
||||||
for (JavaThread *tp = Threads::first(); tp != NULL; tp = tp->next()) {
|
for (JavaThread *tp = Threads::first(); tp != NULL; tp = tp->next()) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -46,6 +46,7 @@
|
|||||||
#include "runtime/arguments.hpp"
|
#include "runtime/arguments.hpp"
|
||||||
#include "runtime/handles.hpp"
|
#include "runtime/handles.hpp"
|
||||||
#include "runtime/interfaceSupport.hpp"
|
#include "runtime/interfaceSupport.hpp"
|
||||||
|
#include "runtime/javaCalls.hpp"
|
||||||
#include "runtime/objectMonitor.hpp"
|
#include "runtime/objectMonitor.hpp"
|
||||||
#include "runtime/objectMonitor.inline.hpp"
|
#include "runtime/objectMonitor.inline.hpp"
|
||||||
#include "runtime/os.inline.hpp"
|
#include "runtime/os.inline.hpp"
|
||||||
@ -369,6 +370,14 @@ JvmtiExport::get_jvmti_interface(JavaVM *jvm, void **penv, jint version) {
|
|||||||
return JNI_EVERSION; // unsupported minor version number
|
return JNI_EVERSION; // unsupported minor version number
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 9:
|
||||||
|
switch (minor) {
|
||||||
|
case 0: // version 9.0.<micro> is recognized
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return JNI_EVERSION; // unsupported minor version number
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return JNI_EVERSION; // unsupported major version number
|
return JNI_EVERSION; // unsupported major version number
|
||||||
}
|
}
|
||||||
@ -397,6 +406,28 @@ JvmtiExport::get_jvmti_interface(JavaVM *jvm, void **penv, jint version) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
JvmtiExport::add_default_read_edges(Handle h_module, TRAPS) {
|
||||||
|
if (!Universe::is_module_initialized()) {
|
||||||
|
return; // extra safety
|
||||||
|
}
|
||||||
|
assert(!h_module.is_null(), "module should always be set");
|
||||||
|
|
||||||
|
// Invoke the transformedByAgent method
|
||||||
|
JavaValue result(T_VOID);
|
||||||
|
JavaCalls::call_static(&result,
|
||||||
|
SystemDictionary::module_Modules_klass(),
|
||||||
|
vmSymbols::transformedByAgent_name(),
|
||||||
|
vmSymbols::transformedByAgent_signature(),
|
||||||
|
h_module,
|
||||||
|
THREAD);
|
||||||
|
|
||||||
|
if (HAS_PENDING_EXCEPTION) {
|
||||||
|
java_lang_Throwable::print(PENDING_EXCEPTION, tty);
|
||||||
|
CLEAR_PENDING_EXCEPTION;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
JvmtiExport::decode_version_values(jint version, int * major, int * minor,
|
JvmtiExport::decode_version_values(jint version, int * major, int * minor,
|
||||||
@ -410,6 +441,11 @@ void JvmtiExport::enter_primordial_phase() {
|
|||||||
JvmtiEnvBase::set_phase(JVMTI_PHASE_PRIMORDIAL);
|
JvmtiEnvBase::set_phase(JVMTI_PHASE_PRIMORDIAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JvmtiExport::enter_early_start_phase() {
|
||||||
|
JvmtiManageCapabilities::recompute_always_capabilities();
|
||||||
|
set_early_vmstart_recorded(true);
|
||||||
|
}
|
||||||
|
|
||||||
void JvmtiExport::enter_start_phase() {
|
void JvmtiExport::enter_start_phase() {
|
||||||
JvmtiManageCapabilities::recompute_always_capabilities();
|
JvmtiManageCapabilities::recompute_always_capabilities();
|
||||||
JvmtiEnvBase::set_phase(JVMTI_PHASE_START);
|
JvmtiEnvBase::set_phase(JVMTI_PHASE_START);
|
||||||
@ -428,6 +464,28 @@ void JvmtiExport::enter_live_phase() {
|
|||||||
// and call the agent's premain() for java.lang.instrument.
|
// and call the agent's premain() for java.lang.instrument.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
void JvmtiExport::post_early_vm_start() {
|
||||||
|
EVT_TRIG_TRACE(JVMTI_EVENT_VM_START, ("JVMTI Trg Early VM start event triggered" ));
|
||||||
|
|
||||||
|
// can now enable some events
|
||||||
|
JvmtiEventController::vm_start();
|
||||||
|
|
||||||
|
JvmtiEnvIterator it;
|
||||||
|
for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
||||||
|
// Only early vmstart envs post early VMStart event
|
||||||
|
if (env->early_vmstart_env() && env->is_enabled(JVMTI_EVENT_VM_START)) {
|
||||||
|
EVT_TRACE(JVMTI_EVENT_VM_START, ("JVMTI Evt Early VM start event sent" ));
|
||||||
|
JavaThread *thread = JavaThread::current();
|
||||||
|
JvmtiThreadEventMark jem(thread);
|
||||||
|
JvmtiJavaThreadEventTransition jet(thread);
|
||||||
|
jvmtiEventVMStart callback = env->callbacks()->VMStart;
|
||||||
|
if (callback != NULL) {
|
||||||
|
(*callback)(env->jvmti_external(), jem.jni_env());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void JvmtiExport::post_vm_start() {
|
void JvmtiExport::post_vm_start() {
|
||||||
EVT_TRIG_TRACE(JVMTI_EVENT_VM_START, ("JVMTI Trg VM start event triggered" ));
|
EVT_TRIG_TRACE(JVMTI_EVENT_VM_START, ("JVMTI Trg VM start event triggered" ));
|
||||||
|
|
||||||
@ -436,7 +494,8 @@ void JvmtiExport::post_vm_start() {
|
|||||||
|
|
||||||
JvmtiEnvIterator it;
|
JvmtiEnvIterator it;
|
||||||
for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
||||||
if (env->is_enabled(JVMTI_EVENT_VM_START)) {
|
// Early vmstart envs do not post normal VMStart event
|
||||||
|
if (!env->early_vmstart_env() && env->is_enabled(JVMTI_EVENT_VM_START)) {
|
||||||
EVT_TRACE(JVMTI_EVENT_VM_START, ("JVMTI Evt VM start event sent" ));
|
EVT_TRACE(JVMTI_EVENT_VM_START, ("JVMTI Evt VM start event sent" ));
|
||||||
|
|
||||||
JavaThread *thread = JavaThread::current();
|
JavaThread *thread = JavaThread::current();
|
||||||
@ -544,6 +603,21 @@ class JvmtiClassFileLoadHookPoster : public StackObj {
|
|||||||
if (_state != NULL) {
|
if (_state != NULL) {
|
||||||
_h_class_being_redefined = _state->get_class_being_redefined();
|
_h_class_being_redefined = _state->get_class_being_redefined();
|
||||||
_load_kind = _state->get_class_load_kind();
|
_load_kind = _state->get_class_load_kind();
|
||||||
|
Klass* klass = (_h_class_being_redefined == NULL) ? NULL : (*_h_class_being_redefined)();
|
||||||
|
if (_load_kind != jvmti_class_load_kind_load && klass != NULL) {
|
||||||
|
ModuleEntry* module_entry = InstanceKlass::cast(klass)->module();
|
||||||
|
assert(module_entry != NULL, "module_entry should always be set");
|
||||||
|
if (module_entry->is_named() &&
|
||||||
|
module_entry->module() != NULL &&
|
||||||
|
!module_entry->has_default_read_edges()) {
|
||||||
|
if (!module_entry->set_has_default_read_edges()) {
|
||||||
|
// We won a potential race.
|
||||||
|
// Add read edges to the unnamed modules of the bootstrap and app class loaders
|
||||||
|
Handle class_module(_thread, JNIHandles::resolve(module_entry->module())); // Obtain j.l.r.Module
|
||||||
|
JvmtiExport::add_default_read_edges(class_module, _thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// Clear class_being_redefined flag here. The action
|
// Clear class_being_redefined flag here. The action
|
||||||
// from agent handler could generate a new class file load
|
// from agent handler could generate a new class file load
|
||||||
// hook event and if it is not cleared the new event generated
|
// hook event and if it is not cleared the new event generated
|
||||||
@ -591,6 +665,9 @@ class JvmtiClassFileLoadHookPoster : public StackObj {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void post_to_env(JvmtiEnv* env, bool caching_needed) {
|
void post_to_env(JvmtiEnv* env, bool caching_needed) {
|
||||||
|
if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
unsigned char *new_data = NULL;
|
unsigned char *new_data = NULL;
|
||||||
jint new_len = 0;
|
jint new_len = 0;
|
||||||
// EVT_TRACE(JVMTI_EVENT_CLASS_FILE_LOAD_HOOK,
|
// EVT_TRACE(JVMTI_EVENT_CLASS_FILE_LOAD_HOOK,
|
||||||
@ -602,11 +679,9 @@ class JvmtiClassFileLoadHookPoster : public StackObj {
|
|||||||
_h_protection_domain,
|
_h_protection_domain,
|
||||||
_h_class_being_redefined);
|
_h_class_being_redefined);
|
||||||
JvmtiJavaThreadEventTransition jet(_thread);
|
JvmtiJavaThreadEventTransition jet(_thread);
|
||||||
JNIEnv* jni_env = (JvmtiEnv::get_phase() == JVMTI_PHASE_PRIMORDIAL)?
|
|
||||||
NULL : jem.jni_env();
|
|
||||||
jvmtiEventClassFileLoadHook callback = env->callbacks()->ClassFileLoadHook;
|
jvmtiEventClassFileLoadHook callback = env->callbacks()->ClassFileLoadHook;
|
||||||
if (callback != NULL) {
|
if (callback != NULL) {
|
||||||
(*callback)(env->jvmti_external(), jni_env,
|
(*callback)(env->jvmti_external(), jem.jni_env(),
|
||||||
jem.class_being_redefined(),
|
jem.class_being_redefined(),
|
||||||
jem.jloader(), jem.class_name(),
|
jem.jloader(), jem.class_name(),
|
||||||
jem.protection_domain(),
|
jem.protection_domain(),
|
||||||
@ -668,6 +743,10 @@ void JvmtiExport::post_class_file_load_hook(Symbol* h_name,
|
|||||||
unsigned char **data_ptr,
|
unsigned char **data_ptr,
|
||||||
unsigned char **end_ptr,
|
unsigned char **end_ptr,
|
||||||
JvmtiCachedClassFileData **cache_ptr) {
|
JvmtiCachedClassFileData **cache_ptr) {
|
||||||
|
if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
JvmtiClassFileLoadHookPoster poster(h_name, class_loader,
|
JvmtiClassFileLoadHookPoster poster(h_name, class_loader,
|
||||||
h_protection_domain,
|
h_protection_domain,
|
||||||
data_ptr, end_ptr,
|
data_ptr, end_ptr,
|
||||||
@ -756,6 +835,9 @@ public:
|
|||||||
|
|
||||||
void JvmtiExport::post_compiled_method_unload(
|
void JvmtiExport::post_compiled_method_unload(
|
||||||
jmethodID method, const void *code_begin) {
|
jmethodID method, const void *code_begin) {
|
||||||
|
if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
JavaThread* thread = JavaThread::current();
|
JavaThread* thread = JavaThread::current();
|
||||||
EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD,
|
EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD,
|
||||||
("JVMTI [%s] method compile unload event triggered",
|
("JVMTI [%s] method compile unload event triggered",
|
||||||
@ -765,7 +847,9 @@ void JvmtiExport::post_compiled_method_unload(
|
|||||||
JvmtiEnvIterator it;
|
JvmtiEnvIterator it;
|
||||||
for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
||||||
if (env->is_enabled(JVMTI_EVENT_COMPILED_METHOD_UNLOAD)) {
|
if (env->is_enabled(JVMTI_EVENT_COMPILED_METHOD_UNLOAD)) {
|
||||||
|
if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
EVT_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD,
|
EVT_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD,
|
||||||
("JVMTI [%s] class compile method unload event sent jmethodID " PTR_FORMAT,
|
("JVMTI [%s] class compile method unload event sent jmethodID " PTR_FORMAT,
|
||||||
JvmtiTrace::safe_get_thread_name(thread), p2i(method)));
|
JvmtiTrace::safe_get_thread_name(thread), p2i(method)));
|
||||||
@ -838,6 +922,8 @@ bool JvmtiExport::_can_post_method_exit = fals
|
|||||||
bool JvmtiExport::_can_pop_frame = false;
|
bool JvmtiExport::_can_pop_frame = false;
|
||||||
bool JvmtiExport::_can_force_early_return = false;
|
bool JvmtiExport::_can_force_early_return = false;
|
||||||
|
|
||||||
|
bool JvmtiExport::_early_vmstart_recorded = false;
|
||||||
|
|
||||||
bool JvmtiExport::_should_post_single_step = false;
|
bool JvmtiExport::_should_post_single_step = false;
|
||||||
bool JvmtiExport::_should_post_field_access = false;
|
bool JvmtiExport::_should_post_field_access = false;
|
||||||
bool JvmtiExport::_should_post_field_modification = false;
|
bool JvmtiExport::_should_post_field_modification = false;
|
||||||
@ -912,6 +998,9 @@ bool JvmtiExport::hide_single_stepping(JavaThread *thread) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JvmtiExport::post_class_load(JavaThread *thread, Klass* klass) {
|
void JvmtiExport::post_class_load(JavaThread *thread, Klass* klass) {
|
||||||
|
if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
HandleMark hm(thread);
|
HandleMark hm(thread);
|
||||||
KlassHandle kh(thread, klass);
|
KlassHandle kh(thread, klass);
|
||||||
|
|
||||||
@ -924,11 +1013,13 @@ void JvmtiExport::post_class_load(JavaThread *thread, Klass* klass) {
|
|||||||
JvmtiEnvThreadStateIterator it(state);
|
JvmtiEnvThreadStateIterator it(state);
|
||||||
for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
|
for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
|
||||||
if (ets->is_enabled(JVMTI_EVENT_CLASS_LOAD)) {
|
if (ets->is_enabled(JVMTI_EVENT_CLASS_LOAD)) {
|
||||||
|
JvmtiEnv *env = ets->get_env();
|
||||||
|
if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
EVT_TRACE(JVMTI_EVENT_CLASS_LOAD, ("JVMTI [%s] Evt Class Load sent %s",
|
EVT_TRACE(JVMTI_EVENT_CLASS_LOAD, ("JVMTI [%s] Evt Class Load sent %s",
|
||||||
JvmtiTrace::safe_get_thread_name(thread),
|
JvmtiTrace::safe_get_thread_name(thread),
|
||||||
kh()==NULL? "NULL" : kh()->external_name() ));
|
kh()==NULL? "NULL" : kh()->external_name() ));
|
||||||
|
|
||||||
JvmtiEnv *env = ets->get_env();
|
|
||||||
JvmtiClassEventMark jem(thread, kh());
|
JvmtiClassEventMark jem(thread, kh());
|
||||||
JvmtiJavaThreadEventTransition jet(thread);
|
JvmtiJavaThreadEventTransition jet(thread);
|
||||||
jvmtiEventClassLoad callback = env->callbacks()->ClassLoad;
|
jvmtiEventClassLoad callback = env->callbacks()->ClassLoad;
|
||||||
@ -941,6 +1032,9 @@ void JvmtiExport::post_class_load(JavaThread *thread, Klass* klass) {
|
|||||||
|
|
||||||
|
|
||||||
void JvmtiExport::post_class_prepare(JavaThread *thread, Klass* klass) {
|
void JvmtiExport::post_class_prepare(JavaThread *thread, Klass* klass) {
|
||||||
|
if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
HandleMark hm(thread);
|
HandleMark hm(thread);
|
||||||
KlassHandle kh(thread, klass);
|
KlassHandle kh(thread, klass);
|
||||||
|
|
||||||
@ -953,11 +1047,13 @@ void JvmtiExport::post_class_prepare(JavaThread *thread, Klass* klass) {
|
|||||||
JvmtiEnvThreadStateIterator it(state);
|
JvmtiEnvThreadStateIterator it(state);
|
||||||
for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
|
for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
|
||||||
if (ets->is_enabled(JVMTI_EVENT_CLASS_PREPARE)) {
|
if (ets->is_enabled(JVMTI_EVENT_CLASS_PREPARE)) {
|
||||||
|
JvmtiEnv *env = ets->get_env();
|
||||||
|
if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
EVT_TRACE(JVMTI_EVENT_CLASS_PREPARE, ("JVMTI [%s] Evt Class Prepare sent %s",
|
EVT_TRACE(JVMTI_EVENT_CLASS_PREPARE, ("JVMTI [%s] Evt Class Prepare sent %s",
|
||||||
JvmtiTrace::safe_get_thread_name(thread),
|
JvmtiTrace::safe_get_thread_name(thread),
|
||||||
kh()==NULL? "NULL" : kh()->external_name() ));
|
kh()==NULL? "NULL" : kh()->external_name() ));
|
||||||
|
|
||||||
JvmtiEnv *env = ets->get_env();
|
|
||||||
JvmtiClassEventMark jem(thread, kh());
|
JvmtiClassEventMark jem(thread, kh());
|
||||||
JvmtiJavaThreadEventTransition jet(thread);
|
JvmtiJavaThreadEventTransition jet(thread);
|
||||||
jvmtiEventClassPrepare callback = env->callbacks()->ClassPrepare;
|
jvmtiEventClassPrepare callback = env->callbacks()->ClassPrepare;
|
||||||
@ -969,6 +1065,9 @@ void JvmtiExport::post_class_prepare(JavaThread *thread, Klass* klass) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JvmtiExport::post_class_unload(Klass* klass) {
|
void JvmtiExport::post_class_unload(Klass* klass) {
|
||||||
|
if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
Thread *thread = Thread::current();
|
Thread *thread = Thread::current();
|
||||||
HandleMark hm(thread);
|
HandleMark hm(thread);
|
||||||
KlassHandle kh(thread, klass);
|
KlassHandle kh(thread, klass);
|
||||||
@ -983,6 +1082,9 @@ void JvmtiExport::post_class_unload(Klass* klass) {
|
|||||||
|
|
||||||
JvmtiEnvIterator it;
|
JvmtiEnvIterator it;
|
||||||
for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
||||||
|
if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (env->is_enabled((jvmtiEvent)EXT_EVENT_CLASS_UNLOAD)) {
|
if (env->is_enabled((jvmtiEvent)EXT_EVENT_CLASS_UNLOAD)) {
|
||||||
EVT_TRACE(EXT_EVENT_CLASS_UNLOAD, ("JVMTI [?] Evt Class Unload sent %s",
|
EVT_TRACE(EXT_EVENT_CLASS_UNLOAD, ("JVMTI [?] Evt Class Unload sent %s",
|
||||||
kh()==NULL? "NULL" : kh()->external_name() ));
|
kh()==NULL? "NULL" : kh()->external_name() ));
|
||||||
@ -1018,6 +1120,9 @@ void JvmtiExport::post_class_unload(Klass* klass) {
|
|||||||
|
|
||||||
|
|
||||||
void JvmtiExport::post_thread_start(JavaThread *thread) {
|
void JvmtiExport::post_thread_start(JavaThread *thread) {
|
||||||
|
if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
assert(thread->thread_state() == _thread_in_vm, "must be in vm state");
|
assert(thread->thread_state() == _thread_in_vm, "must be in vm state");
|
||||||
|
|
||||||
EVT_TRIG_TRACE(JVMTI_EVENT_THREAD_START, ("JVMTI [%s] Trg Thread Start event triggered",
|
EVT_TRIG_TRACE(JVMTI_EVENT_THREAD_START, ("JVMTI [%s] Trg Thread Start event triggered",
|
||||||
@ -1031,6 +1136,9 @@ void JvmtiExport::post_thread_start(JavaThread *thread) {
|
|||||||
!thread->is_hidden_from_external_view()) {
|
!thread->is_hidden_from_external_view()) {
|
||||||
JvmtiEnvIterator it;
|
JvmtiEnvIterator it;
|
||||||
for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
||||||
|
if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (env->is_enabled(JVMTI_EVENT_THREAD_START)) {
|
if (env->is_enabled(JVMTI_EVENT_THREAD_START)) {
|
||||||
EVT_TRACE(JVMTI_EVENT_THREAD_START, ("JVMTI [%s] Evt Thread Start event sent",
|
EVT_TRACE(JVMTI_EVENT_THREAD_START, ("JVMTI [%s] Evt Thread Start event sent",
|
||||||
JvmtiTrace::safe_get_thread_name(thread) ));
|
JvmtiTrace::safe_get_thread_name(thread) ));
|
||||||
@ -1048,6 +1156,9 @@ void JvmtiExport::post_thread_start(JavaThread *thread) {
|
|||||||
|
|
||||||
|
|
||||||
void JvmtiExport::post_thread_end(JavaThread *thread) {
|
void JvmtiExport::post_thread_end(JavaThread *thread) {
|
||||||
|
if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
EVT_TRIG_TRACE(JVMTI_EVENT_THREAD_END, ("JVMTI [%s] Trg Thread End event triggered",
|
EVT_TRIG_TRACE(JVMTI_EVENT_THREAD_END, ("JVMTI [%s] Trg Thread End event triggered",
|
||||||
JvmtiTrace::safe_get_thread_name(thread)));
|
JvmtiTrace::safe_get_thread_name(thread)));
|
||||||
|
|
||||||
@ -1063,10 +1174,13 @@ void JvmtiExport::post_thread_end(JavaThread *thread) {
|
|||||||
JvmtiEnvThreadStateIterator it(state);
|
JvmtiEnvThreadStateIterator it(state);
|
||||||
for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
|
for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
|
||||||
if (ets->is_enabled(JVMTI_EVENT_THREAD_END)) {
|
if (ets->is_enabled(JVMTI_EVENT_THREAD_END)) {
|
||||||
|
JvmtiEnv *env = ets->get_env();
|
||||||
|
if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
EVT_TRACE(JVMTI_EVENT_THREAD_END, ("JVMTI [%s] Evt Thread End event sent",
|
EVT_TRACE(JVMTI_EVENT_THREAD_END, ("JVMTI [%s] Evt Thread End event sent",
|
||||||
JvmtiTrace::safe_get_thread_name(thread) ));
|
JvmtiTrace::safe_get_thread_name(thread) ));
|
||||||
|
|
||||||
JvmtiEnv *env = ets->get_env();
|
|
||||||
JvmtiThreadEventMark jem(thread);
|
JvmtiThreadEventMark jem(thread);
|
||||||
JvmtiJavaThreadEventTransition jet(thread);
|
JvmtiJavaThreadEventTransition jet(thread);
|
||||||
jvmtiEventThreadEnd callback = env->callbacks()->ThreadEnd;
|
jvmtiEventThreadEnd callback = env->callbacks()->ThreadEnd;
|
||||||
@ -1705,7 +1819,7 @@ void JvmtiExport::post_native_method_bind(Method* method, address* function_ptr)
|
|||||||
|
|
||||||
JvmtiMethodEventMark jem(thread, mh);
|
JvmtiMethodEventMark jem(thread, mh);
|
||||||
JvmtiJavaThreadEventTransition jet(thread);
|
JvmtiJavaThreadEventTransition jet(thread);
|
||||||
JNIEnv* jni_env = JvmtiEnv::get_phase() == JVMTI_PHASE_PRIMORDIAL? NULL : jem.jni_env();
|
JNIEnv* jni_env = (env->phase() == JVMTI_PHASE_PRIMORDIAL) ? NULL : jem.jni_env();
|
||||||
jvmtiEventNativeMethodBind callback = env->callbacks()->NativeMethodBind;
|
jvmtiEventNativeMethodBind callback = env->callbacks()->NativeMethodBind;
|
||||||
if (callback != NULL) {
|
if (callback != NULL) {
|
||||||
(*callback)(env->jvmti_external(), jni_env, jem.jni_thread(),
|
(*callback)(env->jvmti_external(), jni_env, jem.jni_thread(),
|
||||||
@ -1758,6 +1872,9 @@ jvmtiCompiledMethodLoadInlineRecord* create_inline_record(nmethod* nm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JvmtiExport::post_compiled_method_load(nmethod *nm) {
|
void JvmtiExport::post_compiled_method_load(nmethod *nm) {
|
||||||
|
if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
JavaThread* thread = JavaThread::current();
|
JavaThread* thread = JavaThread::current();
|
||||||
|
|
||||||
EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD,
|
EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD,
|
||||||
@ -1767,7 +1884,9 @@ void JvmtiExport::post_compiled_method_load(nmethod *nm) {
|
|||||||
JvmtiEnvIterator it;
|
JvmtiEnvIterator it;
|
||||||
for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
||||||
if (env->is_enabled(JVMTI_EVENT_COMPILED_METHOD_LOAD)) {
|
if (env->is_enabled(JVMTI_EVENT_COMPILED_METHOD_LOAD)) {
|
||||||
|
if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
EVT_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD,
|
EVT_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD,
|
||||||
("JVMTI [%s] class compile method load event sent %s.%s ",
|
("JVMTI [%s] class compile method load event sent %s.%s ",
|
||||||
JvmtiTrace::safe_get_thread_name(thread),
|
JvmtiTrace::safe_get_thread_name(thread),
|
||||||
@ -1797,6 +1916,9 @@ void JvmtiExport::post_compiled_method_load(JvmtiEnv* env, const jmethodID metho
|
|||||||
const void *code_begin, const jint map_length,
|
const void *code_begin, const jint map_length,
|
||||||
const jvmtiAddrLocationMap* map)
|
const jvmtiAddrLocationMap* map)
|
||||||
{
|
{
|
||||||
|
if (env->phase() <= JVMTI_PHASE_PRIMORDIAL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
JavaThread* thread = JavaThread::current();
|
JavaThread* thread = JavaThread::current();
|
||||||
EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD,
|
EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD,
|
||||||
("JVMTI [%s] method compile load event triggered (by GenerateEvents)",
|
("JVMTI [%s] method compile load event triggered (by GenerateEvents)",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1998, 2013, 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -91,6 +91,8 @@ class JvmtiExport : public AllStatic {
|
|||||||
JVMTI_SUPPORT_FLAG(can_pop_frame)
|
JVMTI_SUPPORT_FLAG(can_pop_frame)
|
||||||
JVMTI_SUPPORT_FLAG(can_force_early_return)
|
JVMTI_SUPPORT_FLAG(can_force_early_return)
|
||||||
|
|
||||||
|
JVMTI_SUPPORT_FLAG(early_vmstart_recorded)
|
||||||
|
|
||||||
friend class JvmtiEventControllerPrivate; // should only modify these flags
|
friend class JvmtiEventControllerPrivate; // should only modify these flags
|
||||||
JVMTI_SUPPORT_FLAG(should_post_single_step)
|
JVMTI_SUPPORT_FLAG(should_post_single_step)
|
||||||
JVMTI_SUPPORT_FLAG(should_post_field_access)
|
JVMTI_SUPPORT_FLAG(should_post_field_access)
|
||||||
@ -213,6 +215,8 @@ class JvmtiExport : public AllStatic {
|
|||||||
_all_dependencies_are_recorded = (on != 0);
|
_all_dependencies_are_recorded = (on != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add read edges to the unnamed modules of the bootstrap and app class loaders
|
||||||
|
static void add_default_read_edges(Handle h_module, TRAPS) NOT_JVMTI_RETURN;
|
||||||
|
|
||||||
// let JVMTI know that the JVM_OnLoad code is running
|
// let JVMTI know that the JVM_OnLoad code is running
|
||||||
static void enter_onload_phase() NOT_JVMTI_RETURN;
|
static void enter_onload_phase() NOT_JVMTI_RETURN;
|
||||||
@ -221,6 +225,7 @@ class JvmtiExport : public AllStatic {
|
|||||||
static void enter_primordial_phase() NOT_JVMTI_RETURN;
|
static void enter_primordial_phase() NOT_JVMTI_RETURN;
|
||||||
|
|
||||||
// let JVMTI know that the VM isn't up yet but JNI is live
|
// let JVMTI know that the VM isn't up yet but JNI is live
|
||||||
|
static void enter_early_start_phase() NOT_JVMTI_RETURN;
|
||||||
static void enter_start_phase() NOT_JVMTI_RETURN;
|
static void enter_start_phase() NOT_JVMTI_RETURN;
|
||||||
|
|
||||||
// let JVMTI know that the VM is fully up and running now
|
// let JVMTI know that the VM is fully up and running now
|
||||||
@ -270,6 +275,7 @@ class JvmtiExport : public AllStatic {
|
|||||||
static bool hide_single_stepping(JavaThread *thread) NOT_JVMTI_RETURN_(false);
|
static bool hide_single_stepping(JavaThread *thread) NOT_JVMTI_RETURN_(false);
|
||||||
|
|
||||||
// Methods that notify the debugger that something interesting has happened in the VM.
|
// Methods that notify the debugger that something interesting has happened in the VM.
|
||||||
|
static void post_early_vm_start () NOT_JVMTI_RETURN;
|
||||||
static void post_vm_start () NOT_JVMTI_RETURN;
|
static void post_vm_start () NOT_JVMTI_RETURN;
|
||||||
static void post_vm_initialized () NOT_JVMTI_RETURN;
|
static void post_vm_initialized () NOT_JVMTI_RETURN;
|
||||||
static void post_vm_death () NOT_JVMTI_RETURN;
|
static void post_vm_death () NOT_JVMTI_RETURN;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
<!--
|
||||||
Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
|
Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
|
||||||
This code is free software; you can redistribute it and/or modify it
|
This code is free software; you can redistribute it and/or modify it
|
||||||
@ -113,6 +113,7 @@ enum {
|
|||||||
JVMTI_VERSION_1_0 = 0x30010000,
|
JVMTI_VERSION_1_0 = 0x30010000,
|
||||||
JVMTI_VERSION_1_1 = 0x30010100,
|
JVMTI_VERSION_1_1 = 0x30010100,
|
||||||
JVMTI_VERSION_1_2 = 0x30010200,
|
JVMTI_VERSION_1_2 = 0x30010200,
|
||||||
|
JVMTI_VERSION_9 = 0x30090000,
|
||||||
|
|
||||||
JVMTI_VERSION = 0x30000000 + (</xsl:text>
|
JVMTI_VERSION = 0x30000000 + (</xsl:text>
|
||||||
<xsl:value-of select="//specification/@majorversion"/>
|
<xsl:value-of select="//specification/@majorversion"/>
|
||||||
@ -137,21 +138,21 @@ enum {
|
|||||||
<xsl:text> */
|
<xsl:text> */
|
||||||
};
|
};
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL
|
JNIEXPORT jint JNICALL
|
||||||
Agent_OnLoad(JavaVM *vm, char *options, void *reserved);
|
Agent_OnLoad(JavaVM *vm, char *options, void *reserved);
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL
|
JNIEXPORT jint JNICALL
|
||||||
Agent_OnAttach(JavaVM* vm, char* options, void* reserved);
|
Agent_OnAttach(JavaVM* vm, char* options, void* reserved);
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Agent_OnUnload(JavaVM *vm);
|
Agent_OnUnload(JavaVM *vm);
|
||||||
|
|
||||||
/* Forward declaration of the environment */
|
/* Forward declaration of the environment */
|
||||||
|
|
||||||
struct _jvmtiEnv;
|
struct _jvmtiEnv;
|
||||||
|
|
||||||
struct jvmtiInterface_1_;
|
struct jvmtiInterface_1_;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
typedef _jvmtiEnv jvmtiEnv;
|
typedef _jvmtiEnv jvmtiEnv;
|
||||||
#else
|
#else
|
||||||
@ -169,7 +170,6 @@ typedef const struct jvmtiInterface_1_ *jvmtiEnv;
|
|||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif /* !_JAVA_JVMTI_H_ */
|
#endif /* !_JAVA_JVMTI_H_ */
|
||||||
|
|
||||||
</xsl:text>
|
</xsl:text>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
@ -238,7 +238,7 @@ typedef void (JNICALL *jvmtiEvent</xsl:text>
|
|||||||
(jvmtiEnv *jvmti_env</xsl:text>
|
(jvmtiEnv *jvmti_env</xsl:text>
|
||||||
<xsl:apply-templates select="parameters" mode="signature">
|
<xsl:apply-templates select="parameters" mode="signature">
|
||||||
<xsl:with-param name="comma">
|
<xsl:with-param name="comma">
|
||||||
<xsl:text>,
|
<xsl:text>,
|
||||||
</xsl:text>
|
</xsl:text>
|
||||||
</xsl:with-param>
|
</xsl:with-param>
|
||||||
</xsl:apply-templates>
|
</xsl:apply-templates>
|
||||||
@ -250,7 +250,7 @@ typedef void (JNICALL *jvmtiEvent</xsl:text>
|
|||||||
<xsl:text>
|
<xsl:text>
|
||||||
|
|
||||||
/* Function Interface */
|
/* Function Interface */
|
||||||
|
|
||||||
typedef struct jvmtiInterface_1_ {
|
typedef struct jvmtiInterface_1_ {
|
||||||
|
|
||||||
</xsl:text>
|
</xsl:text>
|
||||||
@ -290,7 +290,7 @@ struct _jvmtiEnv {
|
|||||||
<xsl:text>) (jvmtiEnv* env</xsl:text>
|
<xsl:text>) (jvmtiEnv* env</xsl:text>
|
||||||
<xsl:apply-templates select="$thisFunction/parameters" mode="signature">
|
<xsl:apply-templates select="$thisFunction/parameters" mode="signature">
|
||||||
<xsl:with-param name="comma">
|
<xsl:with-param name="comma">
|
||||||
<xsl:text>,
|
<xsl:text>,
|
||||||
</xsl:text>
|
</xsl:text>
|
||||||
</xsl:with-param>
|
</xsl:with-param>
|
||||||
</xsl:apply-templates>
|
</xsl:apply-templates>
|
||||||
@ -365,7 +365,7 @@ struct _jvmtiEnv {
|
|||||||
|
|
||||||
/* </xsl:text>
|
/* </xsl:text>
|
||||||
<xsl:value-of select="@label"/>
|
<xsl:value-of select="@label"/>
|
||||||
<xsl:text> */
|
<xsl:text> */
|
||||||
</xsl:text>
|
</xsl:text>
|
||||||
<xsl:choose>
|
<xsl:choose>
|
||||||
<xsl:when test="@kind='enum'">
|
<xsl:when test="@kind='enum'">
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!--
|
<!--
|
||||||
|
|
||||||
Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
|
Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
|
||||||
This code is free software; you can redistribute it and/or modify it
|
This code is free software; you can redistribute it and/or modify it
|
||||||
@ -44,20 +44,20 @@
|
|||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
<xsl:template name="copyrightComment">
|
<xsl:template name="copyrightComment">
|
||||||
<xsl:text>/* </xsl:text>
|
<xsl:text>/*</xsl:text>
|
||||||
<!-- Copy the Copyright comment from jvmti.xml -->
|
<!-- Copy the Copyright comment from jvmti.xml -->
|
||||||
<xsl:value-of select="/comment()[position()=1]"/>
|
<xsl:value-of select="/comment()[position()=1]"/>
|
||||||
<xsl:text> */ 

</xsl:text>
|
<xsl:text> */

</xsl:text>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
<xsl:template name="includeHeader">
|
<xsl:template name="includeHeader">
|
||||||
<xsl:call-template name="copyrightComment"/>
|
<xsl:call-template name="copyrightComment"/>
|
||||||
<xsl:text> /* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */ 
</xsl:text>
|
<xsl:text> /* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */
</xsl:text>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
<xsl:template name="sourceHeader">
|
<xsl:template name="sourceHeader">
|
||||||
<xsl:call-template name="copyrightComment"/>
|
<xsl:call-template name="copyrightComment"/>
|
||||||
<xsl:text> // AUTOMATICALLY GENERATED FILE - DO NOT EDIT 
</xsl:text>
|
<xsl:text> // AUTOMATICALLY GENERATED FILE - DO NOT EDIT
</xsl:text>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -133,9 +133,7 @@ jvmtiCapabilities JvmtiManageCapabilities::init_onload_capabilities() {
|
|||||||
jc.can_get_owned_monitor_info = 1;
|
jc.can_get_owned_monitor_info = 1;
|
||||||
jc.can_get_owned_monitor_stack_depth_info = 1;
|
jc.can_get_owned_monitor_stack_depth_info = 1;
|
||||||
jc.can_get_current_contended_monitor = 1;
|
jc.can_get_current_contended_monitor = 1;
|
||||||
// jc.can_get_monitor_info = 1;
|
jc.can_generate_early_vmstart = 1;
|
||||||
jc.can_tag_objects = 1; // TODO: this should have been removed
|
|
||||||
jc.can_generate_object_free_events = 1; // TODO: this should have been removed
|
|
||||||
return jc;
|
return jc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -454,6 +452,8 @@ void JvmtiManageCapabilities:: print(const jvmtiCapabilities* cap) {
|
|||||||
tty->print_cr("can_generate_resource_exhaustion_heap_events");
|
tty->print_cr("can_generate_resource_exhaustion_heap_events");
|
||||||
if (cap->can_generate_resource_exhaustion_threads_events)
|
if (cap->can_generate_resource_exhaustion_threads_events)
|
||||||
tty->print_cr("can_generate_resource_exhaustion_threads_events");
|
tty->print_cr("can_generate_resource_exhaustion_threads_events");
|
||||||
|
if (cap->can_generate_early_vmstart)
|
||||||
|
tty->print_cr("can_generate_early_vmstart");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1177,9 +1177,9 @@ JVM_ENTRY(jobject, MHN_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh,
|
|||||||
if (reference_klass != NULL && reference_klass->is_instance_klass()) {
|
if (reference_klass != NULL && reference_klass->is_instance_klass()) {
|
||||||
// Emulate LinkResolver::check_klass_accessability.
|
// Emulate LinkResolver::check_klass_accessability.
|
||||||
Klass* caller = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(caller_jh));
|
Klass* caller = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(caller_jh));
|
||||||
if (!Reflection::verify_class_access(caller,
|
if (Reflection::verify_class_access(caller,
|
||||||
reference_klass,
|
reference_klass,
|
||||||
true)) {
|
true) != Reflection::ACCESS_OK) {
|
||||||
THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), reference_klass->external_name());
|
THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), reference_klass->external_name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,9 @@
|
|||||||
#include "runtime/sharedRuntime.hpp"
|
#include "runtime/sharedRuntime.hpp"
|
||||||
#include "runtime/signature.hpp"
|
#include "runtime/signature.hpp"
|
||||||
#include "utilities/macros.hpp"
|
#include "utilities/macros.hpp"
|
||||||
|
#if INCLUDE_TRACE
|
||||||
|
#include "trace/traceMacros.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
static void mangle_name_on(outputStream* st, Symbol* name, int begin, int end) {
|
static void mangle_name_on(outputStream* st, Symbol* name, int begin, int end) {
|
||||||
char* bytes = (char*)name->bytes() + begin;
|
char* bytes = (char*)name->bytes() + begin;
|
||||||
@ -131,6 +133,9 @@ static JNINativeMethod lookup_special_native_methods[] = {
|
|||||||
{ CC"Java_jdk_vm_ci_runtime_JVMCI_initializeRuntime", NULL, FN_PTR(JVM_GetJVMCIRuntime) },
|
{ CC"Java_jdk_vm_ci_runtime_JVMCI_initializeRuntime", NULL, FN_PTR(JVM_GetJVMCIRuntime) },
|
||||||
{ CC"Java_jdk_vm_ci_hotspot_CompilerToVM_registerNatives", NULL, FN_PTR(JVM_RegisterJVMCINatives) },
|
{ CC"Java_jdk_vm_ci_hotspot_CompilerToVM_registerNatives", NULL, FN_PTR(JVM_RegisterJVMCINatives) },
|
||||||
#endif
|
#endif
|
||||||
|
#if INCLUDE_TRACE
|
||||||
|
{ CC"Java_jdk_jfr_internal_JVM_registerNatives", NULL, TRACE_REGISTER_NATIVES },
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static address lookup_special_native(char* jni_name) {
|
static address lookup_special_native(char* jni_name) {
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
#include "classfile/classLoaderData.hpp"
|
#include "classfile/classLoaderData.hpp"
|
||||||
|
#include "classfile/modules.hpp"
|
||||||
#include "classfile/stringTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
#include "compiler/methodMatcher.hpp"
|
#include "compiler/methodMatcher.hpp"
|
||||||
@ -1250,6 +1251,43 @@ WB_ENTRY(void, WB_FreeMetaspace(JNIEnv* env, jobject wb, jobject class_loader, j
|
|||||||
MetadataFactory::free_array(cld, (Array<u1>*)(uintptr_t)addr);
|
MetadataFactory::free_array(cld, (Array<u1>*)(uintptr_t)addr);
|
||||||
WB_END
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(void, WB_DefineModule(JNIEnv* env, jobject o, jobject module, jstring version, jstring location,
|
||||||
|
jobjectArray packages))
|
||||||
|
Modules::define_module(module, version, location, packages, CHECK);
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(void, WB_AddModuleExports(JNIEnv* env, jobject o, jobject from_module, jstring package, jobject to_module))
|
||||||
|
Modules::add_module_exports_qualified(from_module, package, to_module, CHECK);
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(void, WB_AddModuleExportsToAllUnnamed(JNIEnv* env, jobject o, jclass module, jstring package))
|
||||||
|
Modules::add_module_exports_to_all_unnamed(module, package, CHECK);
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(void, WB_AddModuleExportsToAll(JNIEnv* env, jobject o, jclass module, jstring package))
|
||||||
|
Modules::add_module_exports(module, package, NULL, CHECK);
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(void, WB_AddReadsModule(JNIEnv* env, jobject o, jobject from_module, jobject source_module))
|
||||||
|
Modules::add_reads_module(from_module, source_module, CHECK);
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jboolean, WB_CanReadModule(JNIEnv* env, jobject o, jobject asking_module, jobject source_module))
|
||||||
|
return Modules::can_read_module(asking_module, source_module, THREAD);
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jboolean, WB_IsExportedToModule(JNIEnv* env, jobject o, jobject from_module, jstring package, jobject to_module))
|
||||||
|
return Modules::is_exported_to_module(from_module, package, to_module, THREAD);
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(void, WB_AddModulePackage(JNIEnv* env, jobject o, jclass module, jstring package))
|
||||||
|
Modules::add_module_package(module, package, CHECK);
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jobject, WB_GetModuleByPackageName(JNIEnv* env, jobject o, jobject loader, jstring package))
|
||||||
|
return Modules::get_module_by_package_name(loader, package, THREAD);
|
||||||
|
WB_END
|
||||||
|
|
||||||
WB_ENTRY(jlong, WB_IncMetaspaceCapacityUntilGC(JNIEnv* env, jobject wb, jlong inc))
|
WB_ENTRY(jlong, WB_IncMetaspaceCapacityUntilGC(JNIEnv* env, jobject wb, jlong inc))
|
||||||
if (inc < 0) {
|
if (inc < 0) {
|
||||||
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
|
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
|
||||||
@ -1278,7 +1316,6 @@ WB_ENTRY(jlong, WB_MetaspaceCapacityUntilGC(JNIEnv* env, jobject wb))
|
|||||||
WB_END
|
WB_END
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
WB_ENTRY(void, WB_AssertMatchingSafepointCalls(JNIEnv* env, jobject o, jboolean mutexSafepointValue, jboolean attemptedNoSafepointValue))
|
WB_ENTRY(void, WB_AssertMatchingSafepointCalls(JNIEnv* env, jobject o, jboolean mutexSafepointValue, jboolean attemptedNoSafepointValue))
|
||||||
Monitor::SafepointCheckRequired sfpt_check_required = mutexSafepointValue ?
|
Monitor::SafepointCheckRequired sfpt_check_required = mutexSafepointValue ?
|
||||||
Monitor::_safepoint_check_always :
|
Monitor::_safepoint_check_always :
|
||||||
@ -1287,10 +1324,6 @@ WB_ENTRY(void, WB_AssertMatchingSafepointCalls(JNIEnv* env, jobject o, jboolean
|
|||||||
attemptedNoSafepointValue == JNI_TRUE);
|
attemptedNoSafepointValue == JNI_TRUE);
|
||||||
WB_END
|
WB_END
|
||||||
|
|
||||||
WB_ENTRY(jboolean, WB_IsSharedClass(JNIEnv* env, jobject wb, jclass clazz))
|
|
||||||
return (jboolean)MetaspaceShared::is_in_shared_space(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
|
|
||||||
WB_END
|
|
||||||
|
|
||||||
WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj))
|
WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj))
|
||||||
oop obj_oop = JNIHandles::resolve(obj);
|
oop obj_oop = JNIHandles::resolve(obj);
|
||||||
return (jboolean) obj_oop->mark()->has_monitor();
|
return (jboolean) obj_oop->mark()->has_monitor();
|
||||||
@ -1417,6 +1450,10 @@ WB_ENTRY(jboolean, WB_IsShared(JNIEnv* env, jobject wb, jobject obj))
|
|||||||
return MetaspaceShared::is_in_shared_space((void*)obj_oop);
|
return MetaspaceShared::is_in_shared_space((void*)obj_oop);
|
||||||
WB_END
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jboolean, WB_IsSharedClass(JNIEnv* env, jobject wb, jclass clazz))
|
||||||
|
return (jboolean)MetaspaceShared::is_in_shared_space(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
|
||||||
|
WB_END
|
||||||
|
|
||||||
WB_ENTRY(jboolean, WB_AreSharedStringsIgnored(JNIEnv* env))
|
WB_ENTRY(jboolean, WB_AreSharedStringsIgnored(JNIEnv* env))
|
||||||
return StringTable::shared_string_ignored();
|
return StringTable::shared_string_ignored();
|
||||||
WB_END
|
WB_END
|
||||||
@ -1528,10 +1565,9 @@ static JNINativeMethod methods[] = {
|
|||||||
{CC"runMemoryUnitTests", CC"()V", (void*)&WB_RunMemoryUnitTests},
|
{CC"runMemoryUnitTests", CC"()V", (void*)&WB_RunMemoryUnitTests},
|
||||||
{CC"readFromNoaccessArea",CC"()V", (void*)&WB_ReadFromNoaccessArea},
|
{CC"readFromNoaccessArea",CC"()V", (void*)&WB_ReadFromNoaccessArea},
|
||||||
{CC"stressVirtualSpaceResize",CC"(JJJ)I", (void*)&WB_StressVirtualSpaceResize},
|
{CC"stressVirtualSpaceResize",CC"(JJJ)I", (void*)&WB_StressVirtualSpaceResize},
|
||||||
{CC"isSharedClass", CC"(Ljava/lang/Class;)Z", (void*)&WB_IsSharedClass },
|
|
||||||
#if INCLUDE_ALL_GCS
|
#if INCLUDE_ALL_GCS
|
||||||
{CC"g1InConcurrentMark", CC"()Z", (void*)&WB_G1InConcurrentMark},
|
{CC"g1InConcurrentMark", CC"()Z", (void*)&WB_G1InConcurrentMark},
|
||||||
{CC"g1IsHumongous0", CC"(Ljava/lang/Object;)Z",(void*)&WB_G1IsHumongous },
|
{CC"g1IsHumongous0", CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous },
|
||||||
{CC"g1BelongsToHumongousRegion0", CC"(J)Z", (void*)&WB_G1BelongsToHumongousRegion},
|
{CC"g1BelongsToHumongousRegion0", CC"(J)Z", (void*)&WB_G1BelongsToHumongousRegion},
|
||||||
{CC"g1BelongsToFreeRegion0", CC"(J)Z", (void*)&WB_G1BelongsToFreeRegion},
|
{CC"g1BelongsToFreeRegion0", CC"(J)Z", (void*)&WB_G1BelongsToFreeRegion},
|
||||||
{CC"g1NumMaxRegions", CC"()J", (void*)&WB_G1NumMaxRegions },
|
{CC"g1NumMaxRegions", CC"()J", (void*)&WB_G1NumMaxRegions },
|
||||||
@ -1649,6 +1685,24 @@ static JNINativeMethod methods[] = {
|
|||||||
{CC"getCodeBlob", CC"(J)[Ljava/lang/Object;",(void*)&WB_GetCodeBlob },
|
{CC"getCodeBlob", CC"(J)[Ljava/lang/Object;",(void*)&WB_GetCodeBlob },
|
||||||
{CC"getThreadStackSize", CC"()J", (void*)&WB_GetThreadStackSize },
|
{CC"getThreadStackSize", CC"()J", (void*)&WB_GetThreadStackSize },
|
||||||
{CC"getThreadRemainingStackSize", CC"()J", (void*)&WB_GetThreadRemainingStackSize },
|
{CC"getThreadRemainingStackSize", CC"()J", (void*)&WB_GetThreadRemainingStackSize },
|
||||||
|
{CC"DefineModule", CC"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V",
|
||||||
|
(void*)&WB_DefineModule },
|
||||||
|
{CC"AddModuleExports", CC"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V",
|
||||||
|
(void*)&WB_AddModuleExports },
|
||||||
|
{CC"AddReadsModule", CC"(Ljava/lang/Object;Ljava/lang/Object;)V",
|
||||||
|
(void*)&WB_AddReadsModule },
|
||||||
|
{CC"CanReadModule", CC"(Ljava/lang/Object;Ljava/lang/Object;)Z",
|
||||||
|
(void*)&WB_CanReadModule },
|
||||||
|
{CC"IsExportedToModule", CC"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Z",
|
||||||
|
(void*)&WB_IsExportedToModule },
|
||||||
|
{CC"AddModulePackage", CC"(Ljava/lang/Object;Ljava/lang/String;)V",
|
||||||
|
(void*)&WB_AddModulePackage },
|
||||||
|
{CC"GetModuleByPackageName", CC"(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;",
|
||||||
|
(void*)&WB_GetModuleByPackageName },
|
||||||
|
{CC"AddModuleExportsToAllUnnamed", CC"(Ljava/lang/Object;Ljava/lang/String;)V",
|
||||||
|
(void*)&WB_AddModuleExportsToAllUnnamed },
|
||||||
|
{CC"AddModuleExportsToAll", CC"(Ljava/lang/Object;Ljava/lang/String;)V",
|
||||||
|
(void*)&WB_AddModuleExportsToAll },
|
||||||
{CC"assertMatchingSafepointCalls", CC"(ZZ)V", (void*)&WB_AssertMatchingSafepointCalls },
|
{CC"assertMatchingSafepointCalls", CC"(ZZ)V", (void*)&WB_AssertMatchingSafepointCalls },
|
||||||
{CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated },
|
{CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated },
|
||||||
{CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint },
|
{CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint },
|
||||||
@ -1675,6 +1729,7 @@ static JNINativeMethod methods[] = {
|
|||||||
CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/String;",
|
CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/String;",
|
||||||
(void*)&WB_GetMethodStringOption},
|
(void*)&WB_GetMethodStringOption},
|
||||||
{CC"isShared", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsShared },
|
{CC"isShared", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsShared },
|
||||||
|
{CC"isSharedClass", CC"(Ljava/lang/Class;)Z", (void*)&WB_IsSharedClass },
|
||||||
{CC"areSharedStringsIgnored", CC"()Z", (void*)&WB_AreSharedStringsIgnored },
|
{CC"areSharedStringsIgnored", CC"()Z", (void*)&WB_AreSharedStringsIgnored },
|
||||||
{CC"clearInlineCaches", CC"()V", (void*)&WB_ClearInlineCaches },
|
{CC"clearInlineCaches", CC"()V", (void*)&WB_ClearInlineCaches },
|
||||||
};
|
};
|
||||||
|
@ -94,6 +94,9 @@ const char* Arguments::_java_vendor_url_bug = DEFAULT_VENDOR_URL_BUG;
|
|||||||
const char* Arguments::_sun_java_launcher = DEFAULT_JAVA_LAUNCHER;
|
const char* Arguments::_sun_java_launcher = DEFAULT_JAVA_LAUNCHER;
|
||||||
int Arguments::_sun_java_launcher_pid = -1;
|
int Arguments::_sun_java_launcher_pid = -1;
|
||||||
bool Arguments::_sun_java_launcher_is_altjvm = false;
|
bool Arguments::_sun_java_launcher_is_altjvm = false;
|
||||||
|
int Arguments::_patch_dirs_count = 0;
|
||||||
|
char** Arguments::_patch_dirs = NULL;
|
||||||
|
int Arguments::_bootclassloader_append_index = -1;
|
||||||
|
|
||||||
// These parameters are reset in method parse_vm_init_args()
|
// These parameters are reset in method parse_vm_init_args()
|
||||||
bool Arguments::_AlwaysCompileLoopMethods = AlwaysCompileLoopMethods;
|
bool Arguments::_AlwaysCompileLoopMethods = AlwaysCompileLoopMethods;
|
||||||
@ -117,7 +120,9 @@ SystemProperty *Arguments::_sun_boot_library_path = NULL;
|
|||||||
SystemProperty *Arguments::_java_library_path = NULL;
|
SystemProperty *Arguments::_java_library_path = NULL;
|
||||||
SystemProperty *Arguments::_java_home = NULL;
|
SystemProperty *Arguments::_java_home = NULL;
|
||||||
SystemProperty *Arguments::_java_class_path = NULL;
|
SystemProperty *Arguments::_java_class_path = NULL;
|
||||||
SystemProperty *Arguments::_sun_boot_class_path = NULL;
|
SystemProperty *Arguments::_jdk_boot_class_path_append = NULL;
|
||||||
|
|
||||||
|
PathString *Arguments::_system_boot_class_path = NULL;
|
||||||
|
|
||||||
char* Arguments::_ext_dirs = NULL;
|
char* Arguments::_ext_dirs = NULL;
|
||||||
|
|
||||||
@ -195,6 +200,12 @@ void Arguments::process_sun_java_launcher_properties(JavaVMInitArgs* args) {
|
|||||||
|
|
||||||
// Initialize system properties key and value.
|
// Initialize system properties key and value.
|
||||||
void Arguments::init_system_properties() {
|
void Arguments::init_system_properties() {
|
||||||
|
|
||||||
|
// Set up _system_boot_class_path which is not a property but
|
||||||
|
// relies heavily on argument processing and the jdk.boot.class.path.append
|
||||||
|
// property. It is used to store the underlying system boot class path.
|
||||||
|
_system_boot_class_path = new PathString(NULL);
|
||||||
|
|
||||||
PropertyList_add(&_system_properties, new SystemProperty("java.vm.specification.name",
|
PropertyList_add(&_system_properties, new SystemProperty("java.vm.specification.name",
|
||||||
"Java Virtual Machine Specification", false));
|
"Java Virtual Machine Specification", false));
|
||||||
PropertyList_add(&_system_properties, new SystemProperty("java.vm.version", VM_Version::vm_release(), false));
|
PropertyList_add(&_system_properties, new SystemProperty("java.vm.version", VM_Version::vm_release(), false));
|
||||||
@ -208,16 +219,19 @@ void Arguments::init_system_properties() {
|
|||||||
_sun_boot_library_path = new SystemProperty("sun.boot.library.path", NULL, true);
|
_sun_boot_library_path = new SystemProperty("sun.boot.library.path", NULL, true);
|
||||||
_java_library_path = new SystemProperty("java.library.path", NULL, true);
|
_java_library_path = new SystemProperty("java.library.path", NULL, true);
|
||||||
_java_home = new SystemProperty("java.home", NULL, true);
|
_java_home = new SystemProperty("java.home", NULL, true);
|
||||||
_sun_boot_class_path = new SystemProperty("sun.boot.class.path", NULL, true);
|
|
||||||
|
|
||||||
_java_class_path = new SystemProperty("java.class.path", "", true);
|
_java_class_path = new SystemProperty("java.class.path", "", true);
|
||||||
|
// jdk.boot.class.path.append is a non-writeable, internal property.
|
||||||
|
// It can only be set by either:
|
||||||
|
// - -Xbootclasspath/a:
|
||||||
|
// - AddToBootstrapClassLoaderSearch during JVMTI OnLoad phase
|
||||||
|
_jdk_boot_class_path_append = new SystemProperty("jdk.boot.class.path.append", "", false, true);
|
||||||
|
|
||||||
// Add to System Property list.
|
// Add to System Property list.
|
||||||
PropertyList_add(&_system_properties, _sun_boot_library_path);
|
PropertyList_add(&_system_properties, _sun_boot_library_path);
|
||||||
PropertyList_add(&_system_properties, _java_library_path);
|
PropertyList_add(&_system_properties, _java_library_path);
|
||||||
PropertyList_add(&_system_properties, _java_home);
|
PropertyList_add(&_system_properties, _java_home);
|
||||||
PropertyList_add(&_system_properties, _java_class_path);
|
PropertyList_add(&_system_properties, _java_class_path);
|
||||||
PropertyList_add(&_system_properties, _sun_boot_class_path);
|
PropertyList_add(&_system_properties, _jdk_boot_class_path_append);
|
||||||
|
|
||||||
// Set OS specific system properties values
|
// Set OS specific system properties values
|
||||||
os::init_system_properties_values();
|
os::init_system_properties_values();
|
||||||
@ -542,19 +556,19 @@ static bool verify_special_jvm_flags() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Constructs the system class path (aka boot class path) from the following
|
// Constructs the system boot class path from the following components, in order:
|
||||||
// components, in order:
|
|
||||||
//
|
//
|
||||||
// prefix // from -Xbootclasspath/p:...
|
// prefix // from -Xpatch:...
|
||||||
// base // from os::get_system_properties() or -Xbootclasspath=
|
// base // from os::get_system_properties()
|
||||||
// suffix // from -Xbootclasspath/a:...
|
// suffix // from -Xbootclasspath/a:...
|
||||||
//
|
//
|
||||||
// This could be AllStatic, but it isn't needed after argument processing is
|
// This could be AllStatic, but it isn't needed after argument processing is
|
||||||
// complete.
|
// complete. After argument processing, the combined components are copied
|
||||||
class SysClassPath: public StackObj {
|
// to Arguments::_system_boot_class_path via a call to Arguments::set_sysclasspath.
|
||||||
|
class ArgumentBootClassPath: public StackObj {
|
||||||
public:
|
public:
|
||||||
SysClassPath(const char* base);
|
ArgumentBootClassPath(const char* base);
|
||||||
~SysClassPath();
|
~ArgumentBootClassPath();
|
||||||
|
|
||||||
inline void set_base(const char* base);
|
inline void set_base(const char* base);
|
||||||
inline void add_prefix(const char* prefix);
|
inline void add_prefix(const char* prefix);
|
||||||
@ -562,9 +576,9 @@ public:
|
|||||||
inline void add_suffix(const char* suffix);
|
inline void add_suffix(const char* suffix);
|
||||||
inline void reset_path(const char* base);
|
inline void reset_path(const char* base);
|
||||||
|
|
||||||
inline const char* get_base() const { return _items[_scp_base]; }
|
inline const char* get_base() const { return _items[_bcp_base]; }
|
||||||
inline const char* get_prefix() const { return _items[_scp_prefix]; }
|
inline const char* get_prefix() const { return _items[_bcp_prefix]; }
|
||||||
inline const char* get_suffix() const { return _items[_scp_suffix]; }
|
inline const char* get_suffix() const { return _items[_bcp_suffix]; }
|
||||||
|
|
||||||
// Combine all the components into a single c-heap-allocated string; caller
|
// Combine all the components into a single c-heap-allocated string; caller
|
||||||
// must free the string if/when no longer needed.
|
// must free the string if/when no longer needed.
|
||||||
@ -580,55 +594,55 @@ private:
|
|||||||
// Array indices for the items that make up the sysclasspath. All except the
|
// Array indices for the items that make up the sysclasspath. All except the
|
||||||
// base are allocated in the C heap and freed by this class.
|
// base are allocated in the C heap and freed by this class.
|
||||||
enum {
|
enum {
|
||||||
_scp_prefix, // from -Xbootclasspath/p:...
|
_bcp_prefix, // was -Xpatch:...
|
||||||
_scp_base, // the default sysclasspath
|
_bcp_base, // the default system boot class path
|
||||||
_scp_suffix, // from -Xbootclasspath/a:...
|
_bcp_suffix, // from -Xbootclasspath/a:...
|
||||||
_scp_nitems // the number of items, must be last.
|
_bcp_nitems // the number of items, must be last.
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* _items[_scp_nitems];
|
const char* _items[_bcp_nitems];
|
||||||
};
|
};
|
||||||
|
|
||||||
SysClassPath::SysClassPath(const char* base) {
|
ArgumentBootClassPath::ArgumentBootClassPath(const char* base) {
|
||||||
memset(_items, 0, sizeof(_items));
|
memset(_items, 0, sizeof(_items));
|
||||||
_items[_scp_base] = base;
|
_items[_bcp_base] = base;
|
||||||
}
|
}
|
||||||
|
|
||||||
SysClassPath::~SysClassPath() {
|
ArgumentBootClassPath::~ArgumentBootClassPath() {
|
||||||
// Free everything except the base.
|
// Free everything except the base.
|
||||||
for (int i = 0; i < _scp_nitems; ++i) {
|
for (int i = 0; i < _bcp_nitems; ++i) {
|
||||||
if (i != _scp_base) reset_item_at(i);
|
if (i != _bcp_base) reset_item_at(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SysClassPath::set_base(const char* base) {
|
inline void ArgumentBootClassPath::set_base(const char* base) {
|
||||||
_items[_scp_base] = base;
|
_items[_bcp_base] = base;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SysClassPath::add_prefix(const char* prefix) {
|
inline void ArgumentBootClassPath::add_prefix(const char* prefix) {
|
||||||
_items[_scp_prefix] = add_to_path(_items[_scp_prefix], prefix, true);
|
_items[_bcp_prefix] = add_to_path(_items[_bcp_prefix], prefix, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SysClassPath::add_suffix_to_prefix(const char* suffix) {
|
inline void ArgumentBootClassPath::add_suffix_to_prefix(const char* suffix) {
|
||||||
_items[_scp_prefix] = add_to_path(_items[_scp_prefix], suffix, false);
|
_items[_bcp_prefix] = add_to_path(_items[_bcp_prefix], suffix, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SysClassPath::add_suffix(const char* suffix) {
|
inline void ArgumentBootClassPath::add_suffix(const char* suffix) {
|
||||||
_items[_scp_suffix] = add_to_path(_items[_scp_suffix], suffix, false);
|
_items[_bcp_suffix] = add_to_path(_items[_bcp_suffix], suffix, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SysClassPath::reset_item_at(int index) {
|
inline void ArgumentBootClassPath::reset_item_at(int index) {
|
||||||
assert(index < _scp_nitems && index != _scp_base, "just checking");
|
assert(index < _bcp_nitems && index != _bcp_base, "just checking");
|
||||||
if (_items[index] != NULL) {
|
if (_items[index] != NULL) {
|
||||||
FREE_C_HEAP_ARRAY(char, _items[index]);
|
FREE_C_HEAP_ARRAY(char, _items[index]);
|
||||||
_items[index] = NULL;
|
_items[index] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SysClassPath::reset_path(const char* base) {
|
inline void ArgumentBootClassPath::reset_path(const char* base) {
|
||||||
// Clear the prefix and suffix.
|
// Clear the prefix and suffix.
|
||||||
reset_item_at(_scp_prefix);
|
reset_item_at(_bcp_prefix);
|
||||||
reset_item_at(_scp_suffix);
|
reset_item_at(_bcp_suffix);
|
||||||
set_base(base);
|
set_base(base);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -637,17 +651,21 @@ inline void SysClassPath::reset_path(const char* base) {
|
|||||||
|
|
||||||
// Combine the bootclasspath elements, some of which may be null, into a single
|
// Combine the bootclasspath elements, some of which may be null, into a single
|
||||||
// c-heap-allocated string.
|
// c-heap-allocated string.
|
||||||
char* SysClassPath::combined_path() {
|
char* ArgumentBootClassPath::combined_path() {
|
||||||
assert(_items[_scp_base] != NULL, "empty default sysclasspath");
|
assert(_items[_bcp_base] != NULL, "empty default sysclasspath");
|
||||||
|
|
||||||
size_t lengths[_scp_nitems];
|
size_t lengths[_bcp_nitems];
|
||||||
size_t total_len = 0;
|
size_t total_len = 0;
|
||||||
|
|
||||||
const char separator = *os::path_separator();
|
const char separator = *os::path_separator();
|
||||||
|
|
||||||
// Get the lengths.
|
// Get the lengths.
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < _scp_nitems; ++i) {
|
for (i = 0; i < _bcp_nitems; ++i) {
|
||||||
|
if (i == _bcp_suffix) {
|
||||||
|
// Record index of boot loader's append path.
|
||||||
|
Arguments::set_bootclassloader_append_index((int)total_len);
|
||||||
|
}
|
||||||
if (_items[i] != NULL) {
|
if (_items[i] != NULL) {
|
||||||
lengths[i] = strlen(_items[i]);
|
lengths[i] = strlen(_items[i]);
|
||||||
// Include space for the separator char (or a NULL for the last item).
|
// Include space for the separator char (or a NULL for the last item).
|
||||||
@ -659,7 +677,7 @@ char* SysClassPath::combined_path() {
|
|||||||
// Copy the _items to a single string.
|
// Copy the _items to a single string.
|
||||||
char* cp = NEW_C_HEAP_ARRAY(char, total_len, mtInternal);
|
char* cp = NEW_C_HEAP_ARRAY(char, total_len, mtInternal);
|
||||||
char* cp_tmp = cp;
|
char* cp_tmp = cp;
|
||||||
for (i = 0; i < _scp_nitems; ++i) {
|
for (i = 0; i < _bcp_nitems; ++i) {
|
||||||
if (_items[i] != NULL) {
|
if (_items[i] != NULL) {
|
||||||
memcpy(cp_tmp, _items[i], lengths[i]);
|
memcpy(cp_tmp, _items[i], lengths[i]);
|
||||||
cp_tmp += lengths[i];
|
cp_tmp += lengths[i];
|
||||||
@ -672,7 +690,7 @@ char* SysClassPath::combined_path() {
|
|||||||
|
|
||||||
// Note: path must be c-heap-allocated (or NULL); it is freed if non-null.
|
// Note: path must be c-heap-allocated (or NULL); it is freed if non-null.
|
||||||
char*
|
char*
|
||||||
SysClassPath::add_to_path(const char* path, const char* str, bool prepend) {
|
ArgumentBootClassPath::add_to_path(const char* path, const char* str, bool prepend) {
|
||||||
char *cp;
|
char *cp;
|
||||||
|
|
||||||
assert(str != NULL, "just checking");
|
assert(str != NULL, "just checking");
|
||||||
@ -706,7 +724,7 @@ SysClassPath::add_to_path(const char* path, const char* str, bool prepend) {
|
|||||||
|
|
||||||
// Scan the directory and append any jar or zip files found to path.
|
// Scan the directory and append any jar or zip files found to path.
|
||||||
// Note: path must be c-heap-allocated (or NULL); it is freed if non-null.
|
// Note: path must be c-heap-allocated (or NULL); it is freed if non-null.
|
||||||
char* SysClassPath::add_jars_to_path(char* path, const char* directory) {
|
char* ArgumentBootClassPath::add_jars_to_path(char* path, const char* directory) {
|
||||||
DIR* dir = os::opendir(directory);
|
DIR* dir = os::opendir(directory);
|
||||||
if (dir == NULL) return path;
|
if (dir == NULL) return path;
|
||||||
|
|
||||||
@ -1375,6 +1393,54 @@ bool Arguments::add_property(const char* prop) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sets or adds a module name to the jdk.launcher.addmods property
|
||||||
|
bool Arguments::append_to_addmods_property(const char* module_name) {
|
||||||
|
const char* key = "jdk.launcher.addmods";
|
||||||
|
const char* old_value = Arguments::get_property(key);
|
||||||
|
size_t buf_len = strlen(key) + strlen(module_name) + 2;
|
||||||
|
if (old_value != NULL) {
|
||||||
|
buf_len += strlen(old_value) + 1;
|
||||||
|
}
|
||||||
|
char* new_value = AllocateHeap(buf_len, mtInternal);
|
||||||
|
if (new_value == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (old_value == NULL) {
|
||||||
|
jio_snprintf(new_value, buf_len, "%s=%s", key, module_name);
|
||||||
|
} else {
|
||||||
|
jio_snprintf(new_value, buf_len, "%s=%s,%s", key, old_value, module_name);
|
||||||
|
}
|
||||||
|
bool added = add_property(new_value);
|
||||||
|
FreeHeap(new_value);
|
||||||
|
return added;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if INCLUDE_CDS
|
||||||
|
void Arguments::check_unsupported_dumping_properties() {
|
||||||
|
assert(DumpSharedSpaces, "this function is only used with -Xshare:dump");
|
||||||
|
const char* unsupported_properties[5] = { "jdk.module.main",
|
||||||
|
"jdk.module.path",
|
||||||
|
"jdk.upgrade.module.path",
|
||||||
|
"jdk.launcher.addmods",
|
||||||
|
"jdk.launcher.limitmods" };
|
||||||
|
const char* unsupported_options[5] = { "-m",
|
||||||
|
"-modulepath",
|
||||||
|
"-upgrademodulepath",
|
||||||
|
"-addmods",
|
||||||
|
"-limitmods" };
|
||||||
|
SystemProperty* sp = system_properties();
|
||||||
|
while (sp != NULL) {
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
if (strcmp(sp->key(), unsupported_properties[i]) == 0) {
|
||||||
|
vm_exit_during_initialization(
|
||||||
|
"Cannot use the following option when dumping the shared archive", unsupported_options[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sp = sp->next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//===========================================================================================================
|
//===========================================================================================================
|
||||||
// Setting int/mixed/comp mode flags
|
// Setting int/mixed/comp mode flags
|
||||||
|
|
||||||
@ -2553,8 +2619,8 @@ jint Arguments::parse_vm_init_args(const JavaVMInitArgs *java_tool_options_args,
|
|||||||
const JavaVMInitArgs *java_options_args,
|
const JavaVMInitArgs *java_options_args,
|
||||||
const JavaVMInitArgs *cmd_line_args) {
|
const JavaVMInitArgs *cmd_line_args) {
|
||||||
// For components of the system classpath.
|
// For components of the system classpath.
|
||||||
SysClassPath scp(Arguments::get_sysclasspath());
|
ArgumentBootClassPath bcp(Arguments::get_sysclasspath());
|
||||||
bool scp_assembly_required = false;
|
bool bcp_assembly_required = false;
|
||||||
|
|
||||||
// Save default settings for some mode flags
|
// Save default settings for some mode flags
|
||||||
Arguments::_AlwaysCompileLoopMethods = AlwaysCompileLoopMethods;
|
Arguments::_AlwaysCompileLoopMethods = AlwaysCompileLoopMethods;
|
||||||
@ -2572,13 +2638,13 @@ jint Arguments::parse_vm_init_args(const JavaVMInitArgs *java_tool_options_args,
|
|||||||
// Parse args structure generated from JAVA_TOOL_OPTIONS environment
|
// Parse args structure generated from JAVA_TOOL_OPTIONS environment
|
||||||
// variable (if present).
|
// variable (if present).
|
||||||
jint result = parse_each_vm_init_arg(
|
jint result = parse_each_vm_init_arg(
|
||||||
java_tool_options_args, &scp, &scp_assembly_required, Flag::ENVIRON_VAR);
|
java_tool_options_args, &bcp, &bcp_assembly_required, Flag::ENVIRON_VAR);
|
||||||
if (result != JNI_OK) {
|
if (result != JNI_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse args structure generated from the command line flags.
|
// Parse args structure generated from the command line flags.
|
||||||
result = parse_each_vm_init_arg(cmd_line_args, &scp, &scp_assembly_required,
|
result = parse_each_vm_init_arg(cmd_line_args, &bcp, &bcp_assembly_required,
|
||||||
Flag::COMMAND_LINE);
|
Flag::COMMAND_LINE);
|
||||||
if (result != JNI_OK) {
|
if (result != JNI_OK) {
|
||||||
return result;
|
return result;
|
||||||
@ -2587,13 +2653,13 @@ jint Arguments::parse_vm_init_args(const JavaVMInitArgs *java_tool_options_args,
|
|||||||
// Parse args structure generated from the _JAVA_OPTIONS environment
|
// Parse args structure generated from the _JAVA_OPTIONS environment
|
||||||
// variable (if present) (mimics classic VM)
|
// variable (if present) (mimics classic VM)
|
||||||
result = parse_each_vm_init_arg(
|
result = parse_each_vm_init_arg(
|
||||||
java_options_args, &scp, &scp_assembly_required, Flag::ENVIRON_VAR);
|
java_options_args, &bcp, &bcp_assembly_required, Flag::ENVIRON_VAR);
|
||||||
if (result != JNI_OK) {
|
if (result != JNI_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do final processing now that all arguments have been parsed
|
// Do final processing now that all arguments have been parsed
|
||||||
result = finalize_vm_init_args(&scp, scp_assembly_required);
|
result = finalize_vm_init_args(&bcp, bcp_assembly_required);
|
||||||
if (result != JNI_OK) {
|
if (result != JNI_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -2647,8 +2713,8 @@ bool valid_jdwp_agent(char *name, bool is_path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||||
SysClassPath* scp_p,
|
ArgumentBootClassPath* bcp_p,
|
||||||
bool* scp_assembly_required_p,
|
bool* bcp_assembly_required_p,
|
||||||
Flag::Flags origin) {
|
Flag::Flags origin) {
|
||||||
// For match_option to return remaining or value part of option string
|
// For match_option to return remaining or value part of option string
|
||||||
const char* tail;
|
const char* tail;
|
||||||
@ -2700,16 +2766,18 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
|||||||
JavaAssertions::setSystemClassDefault(enable);
|
JavaAssertions::setSystemClassDefault(enable);
|
||||||
// -bootclasspath:
|
// -bootclasspath:
|
||||||
} else if (match_option(option, "-Xbootclasspath:", &tail)) {
|
} else if (match_option(option, "-Xbootclasspath:", &tail)) {
|
||||||
scp_p->reset_path(tail);
|
jio_fprintf(defaultStream::output_stream(),
|
||||||
*scp_assembly_required_p = true;
|
"-Xbootclasspath is no longer a supported option.\n");
|
||||||
|
return JNI_EINVAL;
|
||||||
// -bootclasspath/a:
|
// -bootclasspath/a:
|
||||||
} else if (match_option(option, "-Xbootclasspath/a:", &tail)) {
|
} else if (match_option(option, "-Xbootclasspath/a:", &tail)) {
|
||||||
scp_p->add_suffix(tail);
|
bcp_p->add_suffix(tail);
|
||||||
*scp_assembly_required_p = true;
|
*bcp_assembly_required_p = true;
|
||||||
// -bootclasspath/p:
|
// -bootclasspath/p:
|
||||||
} else if (match_option(option, "-Xbootclasspath/p:", &tail)) {
|
} else if (match_option(option, "-Xbootclasspath/p:", &tail)) {
|
||||||
scp_p->add_prefix(tail);
|
jio_fprintf(defaultStream::output_stream(),
|
||||||
*scp_assembly_required_p = true;
|
"-Xbootclasspath/p is no longer a supported option.\n");
|
||||||
|
return JNI_EINVAL;
|
||||||
// -Xrun
|
// -Xrun
|
||||||
} else if (match_option(option, "-Xrun", &tail)) {
|
} else if (match_option(option, "-Xrun", &tail)) {
|
||||||
if (tail != NULL) {
|
if (tail != NULL) {
|
||||||
@ -2761,9 +2829,14 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
|||||||
"Instrumentation agents are not supported in this VM\n");
|
"Instrumentation agents are not supported in this VM\n");
|
||||||
return JNI_ERR;
|
return JNI_ERR;
|
||||||
#else
|
#else
|
||||||
if(tail != NULL) {
|
if (tail != NULL) {
|
||||||
char *options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(tail) + 1, mtInternal), tail);
|
char *options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(tail) + 1, mtInternal), tail);
|
||||||
add_init_agent("instrument", options, false);
|
add_init_agent("instrument", options, false);
|
||||||
|
// java agents need module java.instrument. Also -addmods ALL-SYSTEM because
|
||||||
|
// the java agent is in the unmamed module of the application class loader
|
||||||
|
if (!Arguments::append_to_addmods_property("java.instrument,ALL-SYSTEM")) {
|
||||||
|
return JNI_ENOMEM;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif // !INCLUDE_JVMTI
|
#endif // !INCLUDE_JVMTI
|
||||||
// -Xnoclassgc
|
// -Xnoclassgc
|
||||||
@ -3029,12 +3102,50 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
|||||||
if (FLAG_SET_CMDLINE(bool, ManagementServer, true) != Flag::SUCCESS) {
|
if (FLAG_SET_CMDLINE(bool, ManagementServer, true) != Flag::SUCCESS) {
|
||||||
return JNI_EINVAL;
|
return JNI_EINVAL;
|
||||||
}
|
}
|
||||||
|
// management agent in module java.management
|
||||||
|
if (!Arguments::append_to_addmods_property("java.management")) {
|
||||||
|
return JNI_ENOMEM;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
jio_fprintf(defaultStream::output_stream(),
|
jio_fprintf(defaultStream::output_stream(),
|
||||||
"-Dcom.sun.management is not supported in this VM.\n");
|
"-Dcom.sun.management is not supported in this VM.\n");
|
||||||
return JNI_ERR;
|
return JNI_ERR;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
if (match_option(option, "-Djdk.launcher.patch.0=", &tail)) {
|
||||||
|
// -Xpatch
|
||||||
|
int dir_count;
|
||||||
|
char** patch_dirs = os::split_path(tail, &dir_count);
|
||||||
|
if (patch_dirs == NULL) {
|
||||||
|
jio_fprintf(defaultStream::output_stream(),
|
||||||
|
"Bad value for -Xpatch.\n");
|
||||||
|
return JNI_ERR;
|
||||||
|
}
|
||||||
|
set_patch_dirs(patch_dirs);
|
||||||
|
set_patch_dirs_count(dir_count);
|
||||||
|
|
||||||
|
// Create a path for each patch dir consisting of dir/java.base.
|
||||||
|
char file_sep = os::file_separator()[0];
|
||||||
|
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 += 11; // file_sep + "java.base" + null terminator.
|
||||||
|
char* dir = NEW_C_HEAP_ARRAY(char, len, mtInternal);
|
||||||
|
jio_snprintf(dir, len, "%s%cjava.base", patch_dirs[x], file_sep);
|
||||||
|
|
||||||
|
// See if Xpatch module path exists.
|
||||||
|
struct stat st;
|
||||||
|
if ((os::stat(dir, &st) == 0)) {
|
||||||
|
bcp_p->add_prefix(dir);
|
||||||
|
*bcp_assembly_required_p = true;
|
||||||
|
}
|
||||||
|
FREE_C_HEAP_ARRAY(char, dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// -Xint
|
// -Xint
|
||||||
} else if (match_option(option, "-Xint")) {
|
} else if (match_option(option, "-Xint")) {
|
||||||
set_mode_flags(_int);
|
set_mode_flags(_int);
|
||||||
@ -3294,6 +3405,18 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
|||||||
return JNI_OK;
|
return JNI_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set property jdk.boot.class.path.append to the contents of the bootclasspath
|
||||||
|
// that follows either the jimage file or exploded module directories. The
|
||||||
|
// property will contain -Xbootclasspath/a and/or jvmti appended additions.
|
||||||
|
void Arguments::set_jdkbootclasspath_append() {
|
||||||
|
char *sysclasspath = get_sysclasspath();
|
||||||
|
assert(sysclasspath != NULL, "NULL sysclasspath");
|
||||||
|
int bcp_a_idx = bootclassloader_append_index();
|
||||||
|
if (bcp_a_idx != -1 && bcp_a_idx < (int)strlen(sysclasspath)) {
|
||||||
|
_jdk_boot_class_path_append->set_value(sysclasspath + bcp_a_idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Remove all empty paths from the app classpath (if IgnoreEmptyClassPaths is enabled)
|
// Remove all empty paths from the app classpath (if IgnoreEmptyClassPaths is enabled)
|
||||||
//
|
//
|
||||||
// This is necessary because some apps like to specify classpath like -cp foo.jar:${XYZ}:bar.jar
|
// This is necessary because some apps like to specify classpath like -cp foo.jar:${XYZ}:bar.jar
|
||||||
@ -3329,7 +3452,7 @@ void Arguments::fix_appclasspath() {
|
|||||||
// Keep replacing ";;" -> ";" until we have no more ";;" (windows)
|
// Keep replacing ";;" -> ";" until we have no more ";;" (windows)
|
||||||
}
|
}
|
||||||
|
|
||||||
_java_class_path->set_value(copy);
|
_java_class_path->set_writeable_value(copy);
|
||||||
FreeHeap(copy); // a copy was made by set_value, so don't need this anymore
|
FreeHeap(copy); // a copy was made by set_value, so don't need this anymore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3380,7 +3503,7 @@ static int check_non_empty_dirs(const char* path) {
|
|||||||
return nonEmptyDirs;
|
return nonEmptyDirs;
|
||||||
}
|
}
|
||||||
|
|
||||||
jint Arguments::finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_required) {
|
jint Arguments::finalize_vm_init_args(ArgumentBootClassPath* bcp_p, bool bcp_assembly_required) {
|
||||||
// check if the default lib/endorsed directory exists; if so, error
|
// check if the default lib/endorsed directory exists; if so, error
|
||||||
char path[JVM_MAXPATHLEN];
|
char path[JVM_MAXPATHLEN];
|
||||||
const char* fileSep = os::file_separator();
|
const char* fileSep = os::file_separator();
|
||||||
@ -3416,11 +3539,16 @@ jint Arguments::finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_req
|
|||||||
return JNI_ERR;
|
return JNI_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scp_assembly_required) {
|
if (bcp_assembly_required) {
|
||||||
// Assemble the bootclasspath elements into the final path.
|
// Assemble the bootclasspath elements into the final path.
|
||||||
char *combined_path = scp_p->combined_path();
|
char *combined_path = bcp_p->combined_path();
|
||||||
Arguments::set_sysclasspath(combined_path);
|
Arguments::set_sysclasspath(combined_path);
|
||||||
FREE_C_HEAP_ARRAY(char, combined_path);
|
FREE_C_HEAP_ARRAY(char, combined_path);
|
||||||
|
} else {
|
||||||
|
// At this point in sysclasspath processing anything
|
||||||
|
// added would be considered in the boot loader's append path.
|
||||||
|
// Record this index, including +1 for the file separator character.
|
||||||
|
Arguments::set_bootclassloader_append_index(((int)strlen(Arguments::get_sysclasspath()))+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This must be done after all arguments have been processed.
|
// This must be done after all arguments have been processed.
|
||||||
@ -3766,6 +3894,11 @@ jint Arguments::parse_options_buffer(const char* name, char* buffer, const size_
|
|||||||
|
|
||||||
void Arguments::set_shared_spaces_flags() {
|
void Arguments::set_shared_spaces_flags() {
|
||||||
if (DumpSharedSpaces) {
|
if (DumpSharedSpaces) {
|
||||||
|
if (Arguments::patch_dirs() != NULL) {
|
||||||
|
vm_exit_during_initialization(
|
||||||
|
"Cannot use the following option when dumping the shared archive", "-Xpatch");
|
||||||
|
}
|
||||||
|
|
||||||
if (RequireSharedSpaces) {
|
if (RequireSharedSpaces) {
|
||||||
warning("Cannot dump shared archive while using shared archive");
|
warning("Cannot dump shared archive while using shared archive");
|
||||||
}
|
}
|
||||||
@ -4455,7 +4588,7 @@ void Arguments::PropertyList_unique_add(SystemProperty** plist, const char* k, c
|
|||||||
if (append) {
|
if (append) {
|
||||||
prop->append_value(v);
|
prop->append_value(v);
|
||||||
} else {
|
} else {
|
||||||
prop->set_value(v);
|
prop->set_writeable_value(v);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user