This commit is contained in:
Phil Race 2018-02-20 13:30:49 -08:00
commit 89cb6a90d2
43 changed files with 949 additions and 575 deletions

View File

@ -134,18 +134,22 @@ $(JDK_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \
$(call DependOnVariable, JDK_MODULES_LIST) $(BASE_RELEASE_FILE) $(call DependOnVariable, JDK_MODULES_LIST) $(BASE_RELEASE_FILE)
$(ECHO) Creating jdk jimage $(ECHO) Creating jdk jimage
$(RM) -r $(JDK_IMAGE_DIR) $(RM) -r $(JDK_IMAGE_DIR)
$(call ExecuteWithLog, $(SUPPORT_OUTPUTDIR)/images/jdk, \
$(JLINK_TOOL) --add-modules $(JDK_MODULES_LIST) \ $(JLINK_TOOL) --add-modules $(JDK_MODULES_LIST) \
$(JLINK_JDK_EXTRA_OPTS) \ $(JLINK_JDK_EXTRA_OPTS) \
--output $(JDK_IMAGE_DIR) --output $(JDK_IMAGE_DIR) \
)
$(TOUCH) $@ $(TOUCH) $@
$(JRE_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \ $(JRE_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \
$(call DependOnVariable, JRE_MODULES_LIST) $(BASE_RELEASE_FILE) $(call DependOnVariable, JRE_MODULES_LIST) $(BASE_RELEASE_FILE)
$(ECHO) Creating jre jimage $(ECHO) Creating jre jimage
$(RM) -r $(JRE_IMAGE_DIR) $(RM) -r $(JRE_IMAGE_DIR)
$(call ExecuteWithLog, $(SUPPORT_OUTPUTDIR)/images/jre, \
$(JLINK_TOOL) --add-modules $(JRE_MODULES_LIST) \ $(JLINK_TOOL) --add-modules $(JRE_MODULES_LIST) \
$(JLINK_JRE_EXTRA_OPTS) \ $(JLINK_JRE_EXTRA_OPTS) \
--output $(JRE_IMAGE_DIR) --output $(JRE_IMAGE_DIR) \
)
$(TOUCH) $@ $(TOUCH) $@
@ -153,27 +157,33 @@ $(JRE_COMPACT1_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \
$(call DependOnVariable, JRE_COMPACT1_MODULES_LIST) $(BASE_RELEASE_FILE) $(call DependOnVariable, JRE_COMPACT1_MODULES_LIST) $(BASE_RELEASE_FILE)
$(ECHO) Creating jre compact1 jimage $(ECHO) Creating jre compact1 jimage
$(RM) -r $(JRE_COMPACT1_IMAGE_DIR) $(RM) -r $(JRE_COMPACT1_IMAGE_DIR)
$(call ExecuteWithLog, $(SUPPORT_OUTPUTDIR)/images/jre_compact1, \
$(JLINK_TOOL) --add-modules $(JRE_COMPACT1_MODULES_LIST) \ $(JLINK_TOOL) --add-modules $(JRE_COMPACT1_MODULES_LIST) \
$(JLINK_JRE_EXTRA_OPTS) \ $(JLINK_JRE_EXTRA_OPTS) \
--output $(JRE_COMPACT1_IMAGE_DIR) --output $(JRE_COMPACT1_IMAGE_DIR) \
)
$(TOUCH) $@ $(TOUCH) $@
$(JRE_COMPACT2_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \ $(JRE_COMPACT2_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \
$(call DependOnVariable, JRE_COMPACT2_MODULES_LIST) $(BASE_RELEASE_FILE) $(call DependOnVariable, JRE_COMPACT2_MODULES_LIST) $(BASE_RELEASE_FILE)
$(ECHO) Creating jre compact2 jimage $(ECHO) Creating jre compact2 jimage
$(RM) -r $(JRE_COMPACT2_IMAGE_DIR) $(RM) -r $(JRE_COMPACT2_IMAGE_DIR)
$(call ExecuteWithLog, $(SUPPORT_OUTPUTDIR)/images/jre_compact2, \
$(JLINK_TOOL) --add-modules $(JRE_COMPACT2_MODULES_LIST) \ $(JLINK_TOOL) --add-modules $(JRE_COMPACT2_MODULES_LIST) \
$(JLINK_JRE_EXTRA_OPTS) \ $(JLINK_JRE_EXTRA_OPTS) \
--output $(JRE_COMPACT2_IMAGE_DIR) --output $(JRE_COMPACT2_IMAGE_DIR) \
)
$(TOUCH) $@ $(TOUCH) $@
$(JRE_COMPACT3_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \ $(JRE_COMPACT3_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \
$(call DependOnVariable, JRE_COMPACT3_MODULES_LIST) $(BASE_RELEASE_FILE) $(call DependOnVariable, JRE_COMPACT3_MODULES_LIST) $(BASE_RELEASE_FILE)
$(ECHO) Creating jre compact3 jimage $(ECHO) Creating jre compact3 jimage
$(RM) -r $(JRE_COMPACT3_IMAGE_DIR) $(RM) -r $(JRE_COMPACT3_IMAGE_DIR)
$(call ExecuteWithLog, $(SUPPORT_OUTPUTDIR)/images/jre_compact3, \
$(JLINK_TOOL) --add-modules $(JRE_COMPACT3_MODULES_LIST) \ $(JLINK_TOOL) --add-modules $(JRE_COMPACT3_MODULES_LIST) \
$(JLINK_JRE_EXTRA_OPTS) \ $(JLINK_JRE_EXTRA_OPTS) \
--output $(JRE_COMPACT3_IMAGE_DIR) --output $(JRE_COMPACT3_IMAGE_DIR) \
)
$(TOUCH) $@ $(TOUCH) $@
TOOL_JRE_TARGETS := $(JRE_IMAGE_DIR)/$(JIMAGE_TARGET_FILE) TOOL_JRE_TARGETS := $(JRE_IMAGE_DIR)/$(JIMAGE_TARGET_FILE)

View File

@ -641,8 +641,11 @@ else
generate-exported-symbols: java.base-libs jdk.jdwp.agent-libs generate-exported-symbols: java.base-libs jdk.jdwp.agent-libs
# If not already set, set the JVM variant target so that the JVM will be built.
JVM_MAIN_LIB_TARGETS ?= hotspot-$(JVM_VARIANT_MAIN)-libs
# Building one JVM variant is enough to start building the other libs # Building one JVM variant is enough to start building the other libs
$(LIBS_TARGETS): hotspot-$(JVM_VARIANT_MAIN)-libs $(LIBS_TARGETS): $(JVM_MAIN_LIB_TARGETS)
$(LAUNCHER_TARGETS): java.base-libs $(LAUNCHER_TARGETS): java.base-libs
@ -719,8 +722,11 @@ else
java.base-jmod: jrtfs-jar $(filter-out java.base-jmod, $(JMOD_TARGETS)) java.base-jmod: jrtfs-jar $(filter-out java.base-jmod, $(JMOD_TARGETS))
endif endif
# Building java.base-jmod requires all of hotspot to be built. # If not already set, set the JVM target so that the JVM will be built.
java.base-jmod: hotspot JVM_MAIN_TARGETS ?= hotspot
# Building java.base-jmod requires all of VM (ie hotspot) to be built.
java.base-jmod: $(JVM_MAIN_TARGETS)
# Declare dependencies from <module>-jmod to all other module targets # Declare dependencies from <module>-jmod to all other module targets
# When creating a BUILDJDK, the java compilation has already been done by the # When creating a BUILDJDK, the java compilation has already been done by the
@ -746,7 +752,7 @@ else
# in java.base-copy) and tzdb.dat (done in java.base-gendata) to the # in java.base-copy) and tzdb.dat (done in java.base-gendata) to the
# appropriate location otherwise jimage, jlink and jmod won't start. This # appropriate location otherwise jimage, jlink and jmod won't start. This
# also applies when creating the buildjdk. # also applies when creating the buildjdk.
DEFAULT_JMOD_DEPS := java.base-libs java.base-copy java.base-gendata \ DEFAULT_JMOD_DEPS += java.base-libs java.base-copy java.base-gendata \
jdk.jlink-launchers jdk.jlink-launchers
# When cross compiling and buildjdk is to be created, depend on creating the # When cross compiling and buildjdk is to be created, depend on creating the
# buildjdk instead of the default dependencies. # buildjdk instead of the default dependencies.
@ -822,8 +828,11 @@ else
docs-reference-api-modulegraph: exploded-image buildtools-modules docs-reference-api-modulegraph: exploded-image buildtools-modules
# If not already set, then set the JVM specific docs targets
JVM_DOCS_TARGETS ?= hotspot-$(JVM_VARIANT_MAIN)-gensrc
# The gensrc steps for hotspot and jdk.jdi create html spec files. # The gensrc steps for hotspot and jdk.jdi create html spec files.
docs-jdk-specs: hotspot-$(JVM_VARIANT_MAIN)-gensrc jdk.jdi-gensrc \ docs-jdk-specs: $(JVM_DOCS_TARGETS) jdk.jdi-gensrc \
docs-jdk-index docs-jdk-index
docs-jdk-index: exploded-image buildtools-modules docs-jdk-index: exploded-image buildtools-modules
@ -890,8 +899,10 @@ endif
################################################################################ ################################################################################
# Virtual targets without recipes # Virtual targets without recipes
# If not already set, set the JVM specific tools targets
JVM_TOOLS_TARGETS ?= buildtools-hotspot
buildtools: buildtools-langtools interim-langtools interim-rmic \ buildtools: buildtools-langtools interim-langtools interim-rmic \
buildtools-jdk buildtools-hotspot buildtools-jdk $(JVM_TOOLS_TARGETS)
hotspot: $(HOTSPOT_VARIANT_TARGETS) hotspot-jsig hotspot: $(HOTSPOT_VARIANT_TARGETS) hotspot-jsig
@ -934,7 +945,7 @@ $(foreach m, $(LAUNCHER_MODULES), $(eval $m: $m-launchers))
$(foreach m, $(ALL_COPY_MODULES), $(eval $m: $m-copy)) $(foreach m, $(ALL_COPY_MODULES), $(eval $m: $m-copy))
# Building java.base includes building all of hotspot. # Building java.base includes building all of hotspot.
java.base: hotspot java.base: $(JVM_MAIN_TARGETS)
demos: demos-jdk demos: demos-jdk
@ -1001,10 +1012,15 @@ endif
# This target builds the documentation image # This target builds the documentation image
docs-image: docs-jdk docs-image: docs-jdk
# If not already set, set the JVM specific targets to build the test image
JVM_TEST_IMAGE_TARGETS ?= test-image-hotspot-jtreg-native test-image-hotspot-gtest
# This target builds the test image # This target builds the test image
test-image: prepare-test-image test-image-hotspot-jtreg-native \ test-image: prepare-test-image \
test-image-jdk-jtreg-native test-image-failure-handler test-image-hotspot-gtest \ test-image-jdk-jtreg-native test-image-failure-handler \
test-image-demos-jdk test-image-demos-jdk $(JVM_TEST_IMAGE_TARGETS)
################################################################################
# all-images builds all our deliverables as images. # all-images builds all our deliverables as images.
all-images: product-images test-image docs-image all-images: product-images test-image docs-image
@ -1143,6 +1159,8 @@ create-main-targets-include:
$(MAKESUPPORT_OUTPUTDIR)/main-targets.gmk $(MAKESUPPORT_OUTPUTDIR)/main-targets.gmk
################################################################################ ################################################################################
# Hook to include the corresponding custom file, if present.
$(eval $(call IncludeCustomExtension, Main-post.gmk))
.PHONY: $(ALL_TARGETS) .PHONY: $(ALL_TARGETS)

View File

@ -258,16 +258,12 @@ AC_DEFUN([BASIC_REMOVE_SYMBOLIC_LINKS],
if test "x$READLINK_TESTED" != yes; then if test "x$READLINK_TESTED" != yes; then
# On MacOSX there is a readlink tool with a different # On MacOSX there is a readlink tool with a different
# purpose than the GNU readlink tool. Check the found readlink. # purpose than the GNU readlink tool. Check the found readlink.
ISGNU=`$READLINK --version 2>&1 | $GREP GNU` READLINK_ISGNU=`$READLINK --version 2>&1 | $GREP GNU`
if test "x$ISGNU" = x; then # If READLINK_ISGNU is empty, then it's a non-GNU readlink. Don't use it.
# A readlink that we do not know how to use.
# Are there other non-GNU readlinks out there?
READLINK_TESTED=yes READLINK_TESTED=yes
READLINK=
fi
fi fi
if test "x$READLINK" != x; then if test "x$READLINK" != x && "x$READLINK_ISGNU" != x; then
$1=`$READLINK -f [$]$1` $1=`$READLINK -f [$]$1`
else else
# Save the current directory for restoring afterwards # Save the current directory for restoring afterwards
@ -494,6 +490,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_FUNDAMENTAL_TOOLS],
BASIC_REQUIRE_PROGS(MV, mv) BASIC_REQUIRE_PROGS(MV, mv)
BASIC_REQUIRE_PROGS(NAWK, [nawk gawk awk]) BASIC_REQUIRE_PROGS(NAWK, [nawk gawk awk])
BASIC_REQUIRE_PROGS(PRINTF, printf) BASIC_REQUIRE_PROGS(PRINTF, printf)
BASIC_REQUIRE_PROGS(READLINK, [greadlink readlink])
BASIC_REQUIRE_PROGS(RM, rm) BASIC_REQUIRE_PROGS(RM, rm)
BASIC_REQUIRE_PROGS(RMDIR, rmdir) BASIC_REQUIRE_PROGS(RMDIR, rmdir)
BASIC_REQUIRE_PROGS(SH, sh) BASIC_REQUIRE_PROGS(SH, sh)
@ -525,7 +522,6 @@ AC_DEFUN_ONCE([BASIC_SETUP_FUNDAMENTAL_TOOLS],
# These are not required on all platforms # These are not required on all platforms
BASIC_PATH_PROGS(CYGPATH, cygpath) BASIC_PATH_PROGS(CYGPATH, cygpath)
BASIC_PATH_PROGS(READLINK, [greadlink readlink])
BASIC_PATH_PROGS(DF, df) BASIC_PATH_PROGS(DF, df)
BASIC_PATH_PROGS(CPIO, [cpio bsdcpio]) BASIC_PATH_PROGS(CPIO, [cpio bsdcpio])
BASIC_PATH_PROGS(NICE, nice) BASIC_PATH_PROGS(NICE, nice)

View File

@ -685,6 +685,7 @@ NICE:=@NICE@
PANDOC:=@FIXPATH@ @PANDOC@ PANDOC:=@FIXPATH@ @PANDOC@
PATCH:=@PATCH@ PATCH:=@PATCH@
PRINTF:=@PRINTF@ PRINTF:=@PRINTF@
READLINK:=@READLINK@
RM:=@RM@ RM:=@RM@
RMDIR:=@RMDIR@ RMDIR:=@RMDIR@
SED:=@SED@ SED:=@SED@

View File

@ -1,5 +1,5 @@
# #
# Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2011, 2018, 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
@ -545,8 +545,18 @@ else ifeq ($(OPENJDK_TARGET_OS),macosx)
define install-file define install-file
$(call MakeTargetDir) $(call MakeTargetDir)
$(RM) '$(call DecodeSpace, $@)' $(RM) '$(call DecodeSpace, $@)'
$(CP) -fRP '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)' # Work around a weirdness with cp on Macosx. When copying a symlink, if
if [ -n "`$(XATTR) -ls '$(call DecodeSpace, $@)'`" ]; then $(XATTR) -cs '$(call DecodeSpace, $@)'; fi # the target of the link is write protected (e.g. 444), cp will add
# write permission for the user on the target file (644). Avoid this by
# using ln to create a new link instead.
if [ -h '$(call DecodeSpace, $<)' ]; then \
$(LN) -s "`$(READLINK) '$(call DecodeSpace, $<)'`" '$(call DecodeSpace, $@)'; \
else \
$(CP) -fRP '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)'; \
fi
if [ -n "`$(XATTR) -ls '$(call DecodeSpace, $@)'`" ]; then \
$(XATTR) -cs '$(call DecodeSpace, $@)'; \
fi
endef endef
else else
define install-file define install-file
@ -1000,6 +1010,7 @@ endif
# Param 2 - The command to run # Param 2 - The command to run
ExecuteWithLog = \ ExecuteWithLog = \
$(call LogCmdlines, Exececuting: [$(strip $2)]) \ $(call LogCmdlines, Exececuting: [$(strip $2)]) \
$(call MakeDir, $(dir $(strip $1))) \
$(call WriteFile, $2, $(strip $1).cmdline) \ $(call WriteFile, $2, $(strip $1).cmdline) \
( $(strip $2) > >($(TEE) $(strip $1).log) 2> >($(TEE) $(strip $1).log >&2) || \ ( $(strip $2) > >($(TEE) $(strip $1).log) 2> >($(TEE) $(strip $1).log >&2) || \
( exitcode=$(DOLLAR)? && \ ( exitcode=$(DOLLAR)? && \

View File

@ -0,0 +1,167 @@
#!/bin/bash
#
# Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute 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 script creates a devkit for building OpenJDK on Solaris by copying
# part of a Solaris Studio installation and cretaing a sysroot by installing
# a limited set of system packages. It is assumed that a suitable pkg
# publisher is configured for the system where the script is executed.
#
# Note that you will need to be able to sudo to root to run the pkg install
# part of this script. It should not affect the running system, but only
# install in a separate temporary image.
#
# The Solaris Studio installation must contain at least these packages:
# developer/developerstudio-126/backend 12.6-1.0.0.0 i--
# developer/developerstudio-126/c++ 12.6-1.0.0.0 i--
# developer/developerstudio-126/cc 12.6-1.0.0.0 i--
# developer/developerstudio-126/dbx (solarisstudio) 12.6-1.0.0.0 i--
# developer/developerstudio-126/library/c++-libs 12.6-1.0.0.0 i--
# developer/developerstudio-126/library/math-libs 12.6-1.0.0.0 i--
# developer/developerstudio-126/library/c-libs 12.6-1.0.0.0 i--
# developer/developerstudio-126/library/studio-gccrt 12.6-1.0.0.0 i--
# developer/developerstudio-126/studio-common 12.6-1.0.0.0 i--
# developer/developerstudio-126/studio-ja 12.6-1.0.0.0 i--
# developer/developerstudio-126/studio-legal 12.6-1.0.0.0 i--
# developer/developerstudio-126/studio-zhCN 12.6-1.0.0.0 i--
#
# erik.joelsson@oracle.com
USAGE="$0 <Solaris Studio installation>"
if [ "$1" = "" ]; then
echo $USAGE
exit 1
fi
SOLARIS_STUDIO_VERSION=12u6
SOLARIS_VERSION=11u3
SOLARIS_ENTIRE_VERSION=0.5.11-0.175.3.20.0.6.0
case `uname -p` in
i*)
ARCH=x86
;;
sparc*)
ARCH=sparc
;;
esac
SOLARIS_STUDIO_SRC=$1
SCRIPT_DIR="$(cd "$(dirname $0)" > /dev/null && pwd)"
BUILD_DIR="${SCRIPT_DIR}/../../build/devkit"
DEVKIT_NAME=SS${SOLARIS_STUDIO_VERSION}-Solaris${SOLARIS_VERSION}
DEVKIT_ROOT=${BUILD_DIR}/${DEVKIT_NAME}
BUNDLE_NAME=${DEVKIT_NAME}.tar.gz
BUNDLE=${BUILD_DIR}/${BUNDLE_NAME}
INSTALL_ROOT=${BUILD_DIR}/install-root-$SOLARIS_VERSION
SYSROOT=${DEVKIT_ROOT}/sysroot
SOLARIS_STUDIO_SUBDIR=SS${SOLARIS_STUDIO_VERSION}
SOLARIS_STUDIO_DIR=${DEVKIT_ROOT}/${SOLARIS_STUDIO_SUBDIR}
# Extract the publisher from the system
if [ -z "${PUBLISHER_URI}" ]; then
PUBLISHER_URI="$(pkg publisher solaris | grep URI | awk '{ print $3 }')"
fi
if [ ! -d $INSTALL_ROOT ]; then
echo "Creating $INSTALL_ROOT and installing packages"
pkg image-create $INSTALL_ROOT
pkg -R $INSTALL_ROOT set-publisher -P -g ${PUBLISHER_URI} solaris
sudo pkg -R $INSTALL_ROOT install --accept entire@$SOLARIS_ENTIRE_VERSION \
system/install developer/gnu-binutils system/library/mmheap system/picl \
developer/assembler
else
echo "Skipping installing packages"
fi
if [ ! -d $SYSROOT ]; then
echo "Copying from $INSTALL_ROOT to $SYSROOT"
mkdir -p $SYSROOT
cp -rH $INSTALL_ROOT/lib $SYSROOT/
mkdir $SYSROOT/usr
cp -rH $INSTALL_ROOT/usr/lib $SYSROOT/usr/
cp -rH $INSTALL_ROOT/usr/include $SYSROOT/usr/
pkg -R $INSTALL_ROOT list > $SYSROOT/pkg-list.txt
else
echo "Skipping copying to $SYSROOT"
fi
if [ ! -d $DEVKIT_ROOT/tools ]; then
# Some of the tools in sysroot are needed in the OpenJDK build. We need
# to copy them into a tools dir, including their specific libraries.
mkdir -p $DEVKIT_ROOT/tools/usr/bin $DEVKIT_ROOT/tools/lib/sparcv9 \
$DEVKIT_ROOT/tools/usr/gnu/bin $DEVKIT_ROOT/tools/usr/bin/sparcv9
cp $INSTALL_ROOT/usr/bin/{as,ar,nm,strip,ld,pigz,ldd} \
$DEVKIT_ROOT/tools/usr/bin/
cp $INSTALL_ROOT/usr/sbin/dtrace $DEVKIT_ROOT/tools/usr/bin/
cp $INSTALL_ROOT/usr/sbin/sparcv9/dtrace $DEVKIT_ROOT/tools/usr/bin/sparcv9/
cp -rH $INSTALL_ROOT/usr/gnu/bin/* $DEVKIT_ROOT/tools/usr/gnu/bin/
cp $INSTALL_ROOT/lib/sparcv9/{libelf.so*,libld.so*,liblddbg.so*} $DEVKIT_ROOT/tools/lib/sparcv9/
for t in $(ls $DEVKIT_ROOT/tools/usr/gnu/bin); do
if [ -f $DEVKIT_ROOT/tools/usr/gnu/bin/$t ]; then
ln -s ../gnu/bin/$t $DEVKIT_ROOT/tools/usr/bin/g$t
fi
done
else
echo "Skipping copying to tools dir $DEVKIT_ROOT/tools"
fi
if [ ! -d $SOLARIS_STUDIO_DIR ]; then
echo "Copying Solaris Studio from $SOLARIS_STUDIO_SRC"
mkdir -p ${SOLARIS_STUDIO_DIR}
cp -rH $SOLARIS_STUDIO_SRC/. ${SOLARIS_STUDIO_DIR}/
# Solaris Studio 12.6 requires libmmheap.so.1 and libsunmath.so.1 to run, but
# these libs are not installed by default on all Solaris systems.
# Sneak them in from the sysroot to make it run OOTB on more systems.
cp $SYSROOT/lib/libsunmath.so.1 $SOLARIS_STUDIO_DIR/lib/compilers/sys/
cp $SYSROOT/lib/sparcv9/libsunmath.so.1 $SOLARIS_STUDIO_DIR/lib/compilers/sys/sparcv9/
cp $SYSROOT/lib/libmmheap.so.1 $SOLARIS_STUDIO_DIR/lib/compilers/sys/
cp $SYSROOT/lib/sparcv9/libmmheap.so.1 $SOLARIS_STUDIO_DIR/lib/compilers/sys/sparcv9/
else
echo "Skipping copying of Solaris Studio"
fi
# Create the devkit.info file
echo Creating devkit.info
INFO_FILE=$DEVKIT_ROOT/devkit.info
rm -f $INFO_FILE
echo "# This file describes to configure how to interpret the contents of this devkit" >> $INFO_FILE
echo "DEVKIT_NAME=\"Solaris Studio $SOLARIS_STUDIO_VERSION - Solaris $SOLARIS_VERSION - $ARCH\"" >> $INFO_FILE
echo "DEVKIT_TOOLCHAIN_PATH=\"\$DEVKIT_ROOT/$SOLARIS_STUDIO_SUBDIR/bin:\$DEVKIT_ROOT/bin\"" >> $INFO_FILE
echo "DEVKIT_EXTRA_PATH=\"\$DEVKIT_ROOT/tools/usr/bin\"" >> $INFO_FILE
echo "DEVKIT_SYSROOT=\"\$DEVKIT_ROOT/sysroot\"" >> $INFO_FILE
if [ ! -e $BUNDLE ]; then
GZIP=$(command -v pigz)
if [ -z "$GZIP" ]; then
GZIP="gzip"
fi
echo "Creating $BUNDLE from $DEVKIT_ROOT"
(cd $DEVKIT_ROOT && tar cf - . | $GZIP - > "$BUNDLE")
else
echo "Skipping creation of $BUNDLE"
fi

View File

@ -123,7 +123,7 @@ TARGETS += $(GENSRC_DIR)/_gensrc_proc_done
$(GENSRC_DIR)/module-info.java.extra: $(GENSRC_DIR)/_gensrc_proc_done $(GENSRC_DIR)/module-info.java.extra: $(GENSRC_DIR)/_gensrc_proc_done
($(CD) $(GENSRC_DIR)/META-INF/providers && \ ($(CD) $(GENSRC_DIR)/META-INF/providers && \
p=""; \ p=""; \
for i in $$($(LS)); do \ for i in $$($(LS) | $(SORT)); do \
c=$$($(CAT) $$i | $(TR) -d '\n\r'); \ c=$$($(CAT) $$i | $(TR) -d '\n\r'); \
if test x$$p != x$$c; then \ if test x$$p != x$$c; then \
if test x$$p != x; then \ if test x$$p != x; then \
@ -137,7 +137,7 @@ $(GENSRC_DIR)/module-info.java.extra: $(GENSRC_DIR)/_gensrc_proc_done
$(ECHO) " ;" >> $@; \ $(ECHO) " ;" >> $@; \
$(ECHO) "uses org.graalvm.compiler.options.OptionDescriptors;" >> $@; \ $(ECHO) "uses org.graalvm.compiler.options.OptionDescriptors;" >> $@; \
$(ECHO) "provides org.graalvm.compiler.options.OptionDescriptors with" >> $@; \ $(ECHO) "provides org.graalvm.compiler.options.OptionDescriptors with" >> $@; \
for i in $$($(FIND) $(GENSRC_DIR) -name '*_OptionDescriptors.java'); do \ for i in $$($(FIND) $(GENSRC_DIR) -name '*_OptionDescriptors.java' | $(SORT)); do \
c=$$($(ECHO) $$i | $(SED) 's:.*/jdk\.internal\.vm\.compiler/\(.*\)\.java:\1:' | $(TR) '/' '.'); \ c=$$($(ECHO) $$i | $(SED) 's:.*/jdk\.internal\.vm\.compiler/\(.*\)\.java:\1:' | $(TR) '/' '.'); \
$(ECHO) " $$c," >> $@; \ $(ECHO) " $$c," >> $@; \
done; \ done; \

View File

@ -203,7 +203,6 @@ SUNWprivate_1.1 {
Java_java_lang_Runtime_freeMemory; Java_java_lang_Runtime_freeMemory;
Java_java_lang_Runtime_maxMemory; Java_java_lang_Runtime_maxMemory;
Java_java_lang_Runtime_gc; Java_java_lang_Runtime_gc;
Java_java_lang_Runtime_runFinalization0;
Java_java_lang_Runtime_totalMemory; Java_java_lang_Runtime_totalMemory;
Java_java_lang_Runtime_availableProcessors; Java_java_lang_Runtime_availableProcessors;
Java_java_lang_SecurityManager_getClassContext; Java_java_lang_SecurityManager_getClassContext;

View File

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
# #
# Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2012, 2018, 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
@ -94,7 +94,7 @@ diff_text() {
$SED -e '/[<>] \* from.*\.idl/d' \ $SED -e '/[<>] \* from.*\.idl/d' \
-e '/[<>] .*[0-9]\{4\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}-b[0-9]\{2\}.*/d' \ -e '/[<>] .*[0-9]\{4\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}-b[0-9]\{2\}.*/d' \
-e '/[<>] .*[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}.*/d' \ -e '/[<>] .*[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}.*/d' \
-e '/[<>] \*.*[0-9]\{4\} [0-9][0-9]*:[0-9]\{2\}:[0-9]\{2\}.*/d' \ -e '/[<>] \*.*[0-9]\{4\} \(at \)*[0-9][0-9]*:[0-9]\{2\}:[0-9]\{2\}.*/d' \
-e '/\/\/ Generated from input file.*/d' \ -e '/\/\/ Generated from input file.*/d' \
-e '/\/\/ This file was generated AUTOMATICALLY from a template file.*/d' \ -e '/\/\/ This file was generated AUTOMATICALLY from a template file.*/d' \
-e '/\/\/ java GenerateCharacter.*/d') -e '/\/\/ java GenerateCharacter.*/d')
@ -102,9 +102,12 @@ diff_text() {
# Ignore date strings in class files. # Ignore date strings in class files.
# Anonymous lambda classes get randomly assigned counters in their names. # Anonymous lambda classes get randomly assigned counters in their names.
if test "x$SUFFIX" = "xclass"; then if test "x$SUFFIX" = "xclass"; then
if [ "$NAME" = "SystemModules.class" ]; then if [ "$NAME" = "SystemModules\$all.class" ] \
# The SystemModules.class is not comparable. The way it is generated is || [ "$NAME" = "SystemModules\$default.class" ]; then
# too random. It can even be of different size for no apparent reason. # The SystemModules\$*.classes are not comparable as they contain the
# module hashes which would require a whole other level of
# reproducible builds to get reproducible. There is also random
# order of map initialization.
TMP="" TMP=""
elif [ "$NAME" = "module-info.class" ]; then elif [ "$NAME" = "module-info.class" ]; then
# The module-info.class have several issues with random ordering of # The module-info.class have several issues with random ordering of
@ -654,7 +657,6 @@ compare_bin_file() {
# pdb files. # pdb files.
PDB_DIRS="$(ls -d \ PDB_DIRS="$(ls -d \
{$OTHER,$THIS}/support/modules_{cmds,libs}/{*,*/*} \ {$OTHER,$THIS}/support/modules_{cmds,libs}/{*,*/*} \
{$OTHER,$THIS}/support/demos/image/jvmti/*/lib \
{$OTHER,$THIS}/support/native/java.base/java_objs \ {$OTHER,$THIS}/support/native/java.base/java_objs \
)" )"
export _NT_SYMBOL_PATH="$(echo $PDB_DIRS | tr ' ' ';')" export _NT_SYMBOL_PATH="$(echo $PDB_DIRS | tr ' ' ';')"
@ -1001,6 +1003,12 @@ compare_all_libs() {
-o -name '*.dll' -o -name '*.obj' -o -name '*.o' -o -name '*.a' \ -o -name '*.dll' -o -name '*.obj' -o -name '*.o' -o -name '*.a' \
-o -name '*.cpl' \) | $SORT | $FILTER) -o -name '*.cpl' \) | $SORT | $FILTER)
# On macos, filter out the dSYM debug symbols files as they are also
# named *.dylib.
if [ "$OPENJDK_TARGET_OS" = "macosx" ]; then
LIBS=$(echo "$LIBS" | $GREP -v '\.dSYM/')
fi
if [ -n "$LIBS" ]; then if [ -n "$LIBS" ]; then
echo Libraries... echo Libraries...
print_binary_diff_header print_binary_diff_header
@ -1041,7 +1049,7 @@ compare_all_execs() {
-o -name '*.jfc' -o -name '*.dat' -o -name 'release' -o -name '*.dir'\ -o -name '*.jfc' -o -name '*.dat' -o -name 'release' -o -name '*.dir'\
-o -name '*.sym' -o -name '*.idl' -o -name '*.h' -o -name '*.access' \ -o -name '*.sym' -o -name '*.idl' -o -name '*.h' -o -name '*.access' \
-o -name '*.template' -o -name '*.policy' -o -name '*.security' \ -o -name '*.template' -o -name '*.policy' -o -name '*.security' \
-o -name 'COPYRIGHT' -o -name '*.1' \ -o -name 'COPYRIGHT' -o -name '*.1' -o -name '*.debuginfo' \
-o -name 'classlist' \) | $SORT | $FILTER) -o -name 'classlist' \) | $SORT | $FILTER)
fi fi
@ -1219,7 +1227,7 @@ if [ "$STRIP_ALL" = "true" ] && [ -z "$STRIP" ]; then
STRIP_ALL=false STRIP_ALL=false
fi fi
COMPARE_ROOT=/tmp/cimages.$USER COMPARE_ROOT=$OUTPUTDIR/compare-support
if [ "$CLEAN_OUTPUT" = "true" ]; then if [ "$CLEAN_OUTPUT" = "true" ]; then
echo Cleaning old output in $COMPARE_ROOT. echo Cleaning old output in $COMPARE_ROOT.
$RM -rf $COMPARE_ROOT $RM -rf $COMPARE_ROOT

View File

@ -428,8 +428,13 @@ if [ "$OPENJDK_TARGET_OS" = "windows" ]; then
./bin/xjc.exe ./bin/xjc.exe
" "
SORT_SYMBOLS="
./bin/fontmanager.dll
"
ACCEPTED_DIS_DIFF=" ACCEPTED_DIS_DIFF="
./bin/jabswitch.exe ./bin/jabswitch.exe
./bin/fontmanager.dll
" "
if [ "$OPENJDK_TARGET_CPU" = "x86" ]; then if [ "$OPENJDK_TARGET_CPU" = "x86" ]; then

View File

@ -35,6 +35,8 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection; import jdk.internal.reflect.Reflection;
@ -702,9 +704,6 @@ public class Runtime {
*/ */
public native void gc(); public native void gc();
/* Wormhole for calling java.lang.ref.Finalizer.runFinalization */
private static native void runFinalization0();
/** /**
* Runs the finalization methods of any objects pending finalization. * Runs the finalization methods of any objects pending finalization.
* Calling this method suggests that the Java virtual machine expend * Calling this method suggests that the Java virtual machine expend
@ -724,7 +723,7 @@ public class Runtime {
* @see java.lang.Object#finalize() * @see java.lang.Object#finalize()
*/ */
public void runFinalization() { public void runFinalization() {
runFinalization0(); SharedSecrets.getJavaLangRefAccess().runFinalization();
} }
/** /**

View File

@ -116,8 +116,24 @@ final class BootstrapMethodInvoker {
argv[0], argv[1]); argv[0], argv[1]);
break; break;
case 3: case 3:
// Special case the LambdaMetafactory::metafactory BSM
//
// By invoking exactly, we can avoid generating a number of
// classes on first (and subsequent) lambda initialization,
// most of which won't be shared with other invoke uses.
MethodType bsmType = bootstrapMethod.type();
if (isLambdaMetafactoryIndyBSM(bsmType)) {
result = (CallSite)bootstrapMethod
.invokeExact(caller, name, (MethodType)type, (MethodType)argv[0],
(MethodHandle)argv[1], (MethodType)argv[2]);
} else if (isLambdaMetafactoryCondyBSM(bsmType)) {
result = bootstrapMethod
.invokeExact(caller, name, (Class<?>)type, (MethodType)argv[0],
(MethodHandle)argv[1], (MethodType)argv[2]);
} else {
result = bootstrapMethod.invoke(caller, name, type, result = bootstrapMethod.invoke(caller, name, type,
argv[0], argv[1], argv[2]); argv[0], argv[1], argv[2]);
}
break; break;
case 4: case 4:
result = bootstrapMethod.invoke(caller, name, type, result = bootstrapMethod.invoke(caller, name, type,
@ -175,6 +191,30 @@ final class BootstrapMethodInvoker {
} }
} }
private static final MethodType LMF_INDY_MT = MethodType.methodType(CallSite.class,
Lookup.class, String.class, MethodType.class, MethodType.class, MethodHandle.class, MethodType.class);
private static final MethodType LMF_CONDY_MT = MethodType.methodType(Object.class,
Lookup.class, String.class, Class.class, MethodType.class, MethodHandle.class, MethodType.class);
/**
* @return true iff the BSM method type exactly matches
* {@see java.lang.invoke.LambdaMetafactory#metafactory(
* MethodHandles.Lookup,String,Class,MethodType,MethodHandle,MethodType)}
*/
private static boolean isLambdaMetafactoryCondyBSM(MethodType bsmType) {
return bsmType == LMF_CONDY_MT;
}
/**
* @return true iff the BSM method type exactly matches
* {@see java.lang.invoke.LambdaMetafactory#metafactory(
* MethodHandles.Lookup,String,MethodType,MethodType,MethodHandle,MethodType)}
*/
private static boolean isLambdaMetafactoryIndyBSM(MethodType bsmType) {
return bsmType == LMF_INDY_MT;
}
/** The JVM produces java.lang.Integer values to box /** The JVM produces java.lang.Integer values to box
* CONSTANT_Integer boxes but does not intern them. * CONSTANT_Integer boxes but does not intern them.
* Let's intern them. This is slightly wrong for * Let's intern them. This is slightly wrong for

View File

@ -242,6 +242,12 @@ public final class LambdaMetafactory {
private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0]; private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
private static final MethodType[] EMPTY_MT_ARRAY = new MethodType[0]; private static final MethodType[] EMPTY_MT_ARRAY = new MethodType[0];
// LambdaMetafactory bootstrap methods are startup sensitive, and may be
// special cased in java.lang.invokeBootstrapMethodInvoker to ensure
// methods are invoked with exact type information to avoid generating
// code for runtime checks. Take care any changes or additions here are
// reflected there as appropriate.
/** /**
* Facilitates the creation of simple "function objects" that implement one * Facilitates the creation of simple "function objects" that implement one
* or more interfaces by delegation to a provided {@link MethodHandle}, * or more interfaces by delegation to a provided {@link MethodHandle},

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2018, 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
@ -235,6 +235,11 @@ public abstract class Reference<T> {
{ {
return Reference.waitForReferenceProcessing(); return Reference.waitForReferenceProcessing();
} }
@Override
public void runFinalization() {
Finalizer.runFinalization();
}
}); });
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2018, 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
@ -1946,9 +1946,10 @@ public final class Locale implements Cloneable, Serializable {
* script (country(, extension)*)<br> * script (country(, extension)*)<br>
* country (extension)*<br> * country (extension)*<br>
* </blockquote> * </blockquote>
* depending on which fields are specified in the locale. If the * depending on which fields are specified in the locale. The field
* language, script, country, and variant fields are all empty, * separator in the above parentheses, denoted as a comma character, may
* this function returns the empty string. * be localized depending on the locale. If the language, script, country,
* and variant fields are all empty, this function returns the empty string.
* *
* @return The name of the locale appropriate to display. * @return The name of the locale appropriate to display.
*/ */
@ -1971,9 +1972,10 @@ public final class Locale implements Cloneable, Serializable {
* script (country(, extension)*)<br> * script (country(, extension)*)<br>
* country (extension)*<br> * country (extension)*<br>
* </blockquote> * </blockquote>
* depending on which fields are specified in the locale. If the * depending on which fields are specified in the locale. The field
* language, script, country, and variant fields are all empty, * separator in the above parentheses, denoted as a comma character, may
* this function returns the empty string. * be localized depending on the locale. If the language, script, country,
* and variant fields are all empty, this function returns the empty string.
* *
* @param inLocale The locale for which to retrieve the display name. * @param inLocale The locale for which to retrieve the display name.
* @return The name of the locale appropriate to display. * @return The name of the locale appropriate to display.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2018, 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
@ -36,4 +36,11 @@ public interface JavaLangRefAccess {
* {@link java.lang.ref.Reference}s, {@code false} otherwise. * {@link java.lang.ref.Reference}s, {@code false} otherwise.
*/ */
boolean waitForReferenceProcessing() throws InterruptedException; boolean waitForReferenceProcessing() throws InterruptedException;
/**
* Runs the finalization methods of any objects pending finalization.
*
* Invoked by Runtime.runFinalization()
*/
void runFinalization();
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1994, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1994, 2018, 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
@ -65,19 +65,6 @@ Java_java_lang_Runtime_gc(JNIEnv *env, jobject this)
JVM_GC(); JVM_GC();
} }
JNIEXPORT void JNICALL
Java_java_lang_Runtime_runFinalization0(JNIEnv *env, jobject this)
{
jclass cl;
jmethodID mid;
if ((cl = (*env)->FindClass(env, "java/lang/ref/Finalizer"))
&& (mid = (*env)->GetStaticMethodID(env, cl,
"runFinalization", "()V"))) {
(*env)->CallStaticVoidMethod(env, cl, mid);
}
}
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Java_java_lang_Runtime_availableProcessors(JNIEnv *env, jobject this) Java_java_lang_Runtime_availableProcessors(JNIEnv *env, jobject this)
{ {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2007, 2018, 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
@ -29,42 +29,13 @@ import java.io.FileDescriptor;
import sun.net.ResourceManager; import sun.net.ResourceManager;
/* /*
* This class defines the plain SocketImpl that is used for all * This class defines the plain SocketImpl that is used when
* Windows version lower than Vista. It adds support for IPv6 on * the System property java.net.preferIPv4Stack is set to true.
* these platforms where available.
*
* For backward compatibility Windows platforms that do not have IPv6
* support also use this implementation, and fd1 gets set to null
* during socket creation.
* *
* @author Chris Hegarty * @author Chris Hegarty
*/ */
class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl {
{
/* second fd, used for ipv6 on windows only.
* fd1 is used for listeners and for client sockets at initialization
* until the socket is connected. Up to this point fd always refers
* to the ipv4 socket and fd1 to the ipv6 socket. After the socket
* becomes connected, fd always refers to the connected socket
* (either v4 or v6) and fd1 is closed.
*
* For ServerSockets, fd always refers to the v4 listener and
* fd1 the v6 listener.
*/
private FileDescriptor fd1;
/*
* Needed for ipv6 on windows because we need to know
* if the socket is bound to ::0 or 0.0.0.0, when a caller
* asks for it. Otherwise we don't know which socket to ask.
*/
private InetAddress anyLocalBoundAddr = null;
/* to prevent starvation when listening on two sockets, this is
* is used to hold the id of the last socket we accepted on.
*/
private int lastfd = -1;
// true if this socket is exclusively bound // true if this socket is exclusively bound
private final boolean exclusiveBind; private final boolean exclusiveBind;
@ -85,43 +56,11 @@ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl
exclusiveBind = exclBind; exclusiveBind = exclBind;
} }
/**
* Creates a socket with a boolean that specifies whether this
* is a stream socket (true) or an unconnected UDP socket (false).
*/
protected synchronized void create(boolean stream) throws IOException {
fd1 = new FileDescriptor();
try {
super.create(stream);
} catch (IOException e) {
fd1 = null;
throw e;
}
}
/**
* Binds the socket to the specified address of the specified local port.
* @param address the address
* @param port the port
*/
protected synchronized void bind(InetAddress address, int lport)
throws IOException
{
super.bind(address, lport);
if (address.isAnyLocalAddress()) {
anyLocalBoundAddr = address;
}
}
public Object getOption(int opt) throws SocketException { public Object getOption(int opt) throws SocketException {
if (isClosedOrPending()) { if (isClosedOrPending()) {
throw new SocketException("Socket Closed"); throw new SocketException("Socket Closed");
} }
if (opt == SO_BINDADDR) { if (opt == SO_BINDADDR) {
if (fd != null && fd1 != null ) {
/* must be unbound or else bound to anyLocal */
return anyLocalBoundAddr;
}
InetAddressContainer in = new InetAddressContainer(); InetAddressContainer in = new InetAddressContainer();
socketGetOption(opt, in); socketGetOption(opt, in);
return in.addr; return in.addr;
@ -161,7 +100,7 @@ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl
@Override @Override
protected void close() throws IOException { protected void close() throws IOException {
synchronized(fdLock) { synchronized(fdLock) {
if (fd != null || fd1 != null) { if (fd != null) {
if (!stream) { if (!stream) {
ResourceManager.afterUdpClose(); ResourceManager.afterUdpClose();
} }
@ -172,7 +111,6 @@ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl
closePending = true; closePending = true;
socketClose(); socketClose();
fd = null; fd = null;
fd1 = null;
return; return;
} else { } else {
/* /*
@ -191,39 +129,11 @@ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl
} }
} }
@Override
void reset() throws IOException {
if (fd != null || fd1 != null) {
socketClose();
}
fd = null;
fd1 = null;
super.reset();
}
/*
* Return true if already closed or close is pending
*/
@Override
public boolean isClosedOrPending() {
/*
* Lock on fdLock to ensure that we wait if a
* close is in progress.
*/
synchronized (fdLock) {
if (closePending || (fd == null && fd1 == null)) {
return true;
} else {
return false;
}
}
}
/* Native methods */ /* Native methods */
static native void initProto(); static native void initProto();
native void socketCreate(boolean isServer) throws IOException; native void socketCreate(boolean stream) throws IOException;
native void socketConnect(InetAddress address, int port, int timeout) native void socketConnect(InetAddress address, int port, int timeout)
throws IOException; throws IOException;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2018, 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
@ -37,14 +37,12 @@
static jfieldID IO_fd_fdID; static jfieldID IO_fd_fdID;
jfieldID psi_fdID; jfieldID psi_fdID;
jfieldID psi_fd1ID;
jfieldID psi_addressID; jfieldID psi_addressID;
jfieldID psi_portID; jfieldID psi_portID;
jfieldID psi_localportID; jfieldID psi_localportID;
jfieldID psi_timeoutID; jfieldID psi_timeoutID;
jfieldID psi_trafficClassID; jfieldID psi_trafficClassID;
jfieldID psi_serverSocketID; jfieldID psi_serverSocketID;
jfieldID psi_lastfdID;
/* /*
* the level of the TCP protocol for setsockopt and getsockopt * the level of the TCP protocol for setsockopt and getsockopt
@ -62,15 +60,6 @@ static int getFD(JNIEnv *env, jobject this) {
return (*env)->GetIntField(env, fdObj, IO_fd_fdID); return (*env)->GetIntField(env, fdObj, IO_fd_fdID);
} }
static int getFD1(JNIEnv *env, jobject this) {
jobject fdObj = (*env)->GetObjectField(env, this, psi_fd1ID);
if (fdObj == NULL) {
return -1;
}
return (*env)->GetIntField(env, fdObj, IO_fd_fdID);
}
/* /*
* The initProto function is called whenever TwoStacksPlainSocketImpl is * The initProto function is called whenever TwoStacksPlainSocketImpl is
@ -90,15 +79,11 @@ Java_java_net_TwoStacksPlainSocketImpl_initProto(JNIEnv *env, jclass cls) {
psi_fdID = (*env)->GetFieldID(env, cls , "fd", "Ljava/io/FileDescriptor;"); psi_fdID = (*env)->GetFieldID(env, cls , "fd", "Ljava/io/FileDescriptor;");
CHECK_NULL(psi_fdID); CHECK_NULL(psi_fdID);
psi_fd1ID =(*env)->GetFieldID(env, cls , "fd1", "Ljava/io/FileDescriptor;");
CHECK_NULL(psi_fd1ID);
psi_addressID = (*env)->GetFieldID(env, cls, "address", psi_addressID = (*env)->GetFieldID(env, cls, "address",
"Ljava/net/InetAddress;"); "Ljava/net/InetAddress;");
CHECK_NULL(psi_addressID); CHECK_NULL(psi_addressID);
psi_portID = (*env)->GetFieldID(env, cls, "port", "I"); psi_portID = (*env)->GetFieldID(env, cls, "port", "I");
CHECK_NULL(psi_portID); CHECK_NULL(psi_portID);
psi_lastfdID = (*env)->GetFieldID(env, cls, "lastfd", "I");
CHECK_NULL(psi_lastfdID);
psi_localportID = (*env)->GetFieldID(env, cls, "localport", "I"); psi_localportID = (*env)->GetFieldID(env, cls, "localport", "I");
CHECK_NULL(psi_localportID); CHECK_NULL(psi_localportID);
psi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I"); psi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I");
@ -120,8 +105,8 @@ Java_java_net_TwoStacksPlainSocketImpl_initProto(JNIEnv *env, jclass cls) {
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_java_net_TwoStacksPlainSocketImpl_socketCreate(JNIEnv *env, jobject this, Java_java_net_TwoStacksPlainSocketImpl_socketCreate(JNIEnv *env, jobject this,
jboolean stream) { jboolean stream) {
jobject fdObj, fd1Obj; jobject fdObj;
int fd, fd1; int fd;
fdObj = (*env)->GetObjectField(env, this, psi_fdID); fdObj = (*env)->GetObjectField(env, this, psi_fdID);
@ -139,30 +124,6 @@ Java_java_net_TwoStacksPlainSocketImpl_socketCreate(JNIEnv *env, jobject this,
SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE); SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE);
(*env)->SetIntField(env, fdObj, IO_fd_fdID, (int)fd); (*env)->SetIntField(env, fdObj, IO_fd_fdID, (int)fd);
} }
if (ipv6_available()) {
fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
if (IS_NULL(fd1Obj)) {
(*env)->SetIntField(env, fdObj, IO_fd_fdID, -1);
NET_SocketClose(fd);
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"null fd1 object");
return;
}
fd1 = socket(AF_INET6, (stream ? SOCK_STREAM: SOCK_DGRAM), 0);
if (fd1 == -1) {
(*env)->SetIntField(env, fdObj, IO_fd_fdID, -1);
NET_SocketClose(fd);
NET_ThrowCurrent(env, "create");
return;
} else {
/* Set socket attribute so it is not passed to any child process */
SetHandleInformation((HANDLE)(UINT_PTR)fd1, HANDLE_FLAG_INHERIT, FALSE);
(*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1);
}
} else {
(*env)->SetObjectField(env, this, psi_fd1ID, NULL);
}
} }
/* /*
@ -182,16 +143,10 @@ Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
/* family and localport are int fields of iaObj */ /* family and localport are int fields of iaObj */
int family; int family;
jint fd = -1, fd1 = -1; jint fd = -1;
jint len; jint len;
int ipv6_supported = ipv6_available();
/* fd initially points to the IPv4 socket and fd1 to the IPv6 socket
* If we want to connect to IPv6 then we swap the two sockets/objects
* This way, fd is always the connected socket, and fd1 always gets closed.
*/
jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
SOCKETADDRESS sa; SOCKETADDRESS sa;
@ -203,10 +158,6 @@ Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
} }
if (ipv6_supported && !IS_NULL(fd1Obj)) {
fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
}
if (IS_NULL(iaObj)) { if (IS_NULL(iaObj)) {
JNU_ThrowNullPointerException(env, "inet address argument is null."); JNU_ThrowNullPointerException(env, "inet address argument is null.");
return; return;
@ -218,35 +169,15 @@ Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
} }
family = sa.sa.sa_family; family = sa.sa.sa_family;
if (family == AF_INET6) { if (family != AF_INET) {
if (!ipv6_supported) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Protocol family not supported"); "Protocol family not supported");
return;
} else {
if (fd1 == -1) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Destination unreachable");
return;
}
/* close the v4 socket, and set fd to be the v6 socket */
(*env)->SetObjectField(env, this, psi_fdID, fd1Obj);
(*env)->SetObjectField(env, this, psi_fd1ID, NULL);
NET_SocketClose(fd);
fd = fd1; fdObj = fd1Obj;
}
} else {
if (fd1 != -1) {
(*env)->SetIntField(env, fd1Obj, IO_fd_fdID, -1);
NET_SocketClose(fd1);
} }
if (fd == -1) { if (fd == -1) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Destination unreachable"); "Destination unreachable");
return; return;
} }
}
(*env)->SetObjectField(env, this, psi_fd1ID, NULL);
if (timeout <= 0) { if (timeout <= 0) {
connect_res = connect(fd, &sa.sa, sizeof(SOCKETADDRESS)); connect_res = connect(fd, &sa.sa, sizeof(SOCKETADDRESS));
@ -388,10 +319,9 @@ Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this,
jboolean exclBind) { jboolean exclBind) {
/* fdObj is the FileDescriptor field on this */ /* fdObj is the FileDescriptor field on this */
jobject fdObj, fd1Obj; jobject fdObj;
/* fd is an int field on fdObj */ /* fd is an int field on fdObj */
int fd, fd1 = -1, len = 0; int fd, len = 0;
int ipv6_supported = ipv6_available();
/* family is an int field of iaObj */ /* family is an int field of iaObj */
int family; int family;
@ -400,25 +330,21 @@ Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this,
SOCKETADDRESS sa; SOCKETADDRESS sa;
fdObj = (*env)->GetObjectField(env, this, psi_fdID); fdObj = (*env)->GetObjectField(env, this, psi_fdID);
fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
family = getInetAddress_family(env, iaObj); family = getInetAddress_family(env, iaObj);
if (family == java_net_InetAddress_IPv6 && !ipv6_supported) { if (family != java_net_InetAddress_IPv4) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Protocol family not supported"); "Protocol family not supported");
return; return;
} }
if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) { if (IS_NULL(fdObj)) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Socket closed"); "Socket closed");
return; return;
} else { } else {
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
if (ipv6_supported) {
fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
}
} }
if (IS_NULL(iaObj)) { if (IS_NULL(iaObj)) {
JNU_ThrowNullPointerException(env, "inet address argument"); JNU_ThrowNullPointerException(env, "inet address argument");
@ -429,42 +355,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this,
JNI_FALSE) != 0) { JNI_FALSE) != 0) {
return; return;
} }
if (ipv6_supported) {
struct ipv6bind v6bind;
v6bind.addr = &sa.sa;
v6bind.ipv4_fd = fd;
v6bind.ipv6_fd = fd1;
rv = NET_BindV6(&v6bind, exclBind);
if (rv != -1) {
/* check if the fds have changed */
if (v6bind.ipv4_fd != fd) {
fd = v6bind.ipv4_fd;
if (fd == -1) {
/* socket is closed. */
(*env)->SetObjectField(env, this, psi_fdID, NULL);
} else {
/* socket was re-created */
(*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
}
}
if (v6bind.ipv6_fd != fd1) {
fd1 = v6bind.ipv6_fd;
if (fd1 == -1) {
/* socket is closed. */
(*env)->SetObjectField(env, this, psi_fd1ID, NULL);
} else {
/* socket was re-created */
(*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1);
}
}
} else {
/* NET_BindV6() closes both sockets upon a failure */
(*env)->SetObjectField(env, this, psi_fdID, NULL);
(*env)->SetObjectField(env, this, psi_fd1ID, NULL);
}
} else {
rv = NET_WinBind(fd, &sa, len, exclBind); rv = NET_WinBind(fd, &sa, len, exclBind);
}
if (rv == -1) { if (rv == -1) {
NET_ThrowCurrent(env, "NET_Bind"); NET_ThrowCurrent(env, "NET_Bind");
@ -482,7 +373,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this,
int len = sizeof(SOCKETADDRESS); int len = sizeof(SOCKETADDRESS);
u_short port; u_short port;
if (getsockname(sa.sa.sa_family == AF_INET ? fd : fd1, &sa.sa, &len) == -1) { if (getsockname(fd, &sa.sa, &len) == -1) {
NET_ThrowCurrent(env, "getsockname in plain socketBind"); NET_ThrowCurrent(env, "getsockname in plain socketBind");
return; return;
} }
@ -505,14 +396,13 @@ Java_java_net_TwoStacksPlainSocketImpl_socketListen
{ {
/* this FileDescriptor fd field */ /* this FileDescriptor fd field */
jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
jobject address; jobject address;
/* fdObj's int fd field */ /* fdObj's int fd field */
int fd = INVALID_SOCKET, fd1 = INVALID_SOCKET; int fd = INVALID_SOCKET;
SOCKETADDRESS addr; SOCKETADDRESS addr;
int addrlen; int addrlen;
if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { if (IS_NULL(fdObj)) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"socket closed"); "socket closed");
return; return;
@ -521,10 +411,6 @@ Java_java_net_TwoStacksPlainSocketImpl_socketListen
if (!IS_NULL(fdObj)) { if (!IS_NULL(fdObj)) {
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
} }
/* Listen on V4 if address type is v4 or if v6 and address is ::0.
* Listen on V6 if address type is v6 or if v4 and address is 0.0.0.0.
* In cases, where we listen on one space only, we close the other socket.
*/
address = (*env)->GetObjectField(env, this, psi_addressID); address = (*env)->GetObjectField(env, this, psi_addressID);
if (IS_NULL(address)) { if (IS_NULL(address)) {
JNU_ThrowNullPointerException(env, "socket address"); JNU_ThrowNullPointerException(env, "socket address");
@ -535,7 +421,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketListen
return; return;
} }
if (addr.sa.sa_family == AF_INET || IN6ADDR_ISANY(&addr.sa6)) { if (addr.sa.sa_family == AF_INET) {
/* listen on v4 */ /* listen on v4 */
if (listen(fd, count) == -1) { if (listen(fd, count) == -1) {
NET_ThrowCurrent(env, "listen failed"); NET_ThrowCurrent(env, "listen failed");
@ -544,18 +430,6 @@ Java_java_net_TwoStacksPlainSocketImpl_socketListen
NET_SocketClose(fd); NET_SocketClose(fd);
(*env)->SetObjectField(env, this, psi_fdID, NULL); (*env)->SetObjectField(env, this, psi_fdID, NULL);
} }
if (ipv6_available() && !IS_NULL(fd1Obj)) {
fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
if (addr.sa.sa_family == AF_INET6 || addr.sa4.sin_addr.s_addr == INADDR_ANY) {
/* listen on v6 */
if (listen(fd1, count) == -1) {
NET_ThrowCurrent(env, "listen failed");
}
} else {
NET_SocketClose (fd1);
(*env)->SetObjectField(env, this, psi_fd1ID, NULL);
}
}
} }
/* /*
@ -571,35 +445,31 @@ Java_java_net_TwoStacksPlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
jint port; jint port;
jint timeout = (*env)->GetIntField(env, this, psi_timeoutID); jint timeout = (*env)->GetIntField(env, this, psi_timeoutID);
jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
/* the FileDescriptor field on socket */ /* the FileDescriptor field on socket */
jobject socketFdObj; jobject socketFdObj;
/* cache the Inet4/6Address classes */ /* cache the Inet4 class */
static jclass inet4Cls; static jclass inet4Cls;
static jclass inet6Cls;
/* the InetAddress field on socket */ /* the InetAddress field on socket */
jobject socketAddressObj; jobject socketAddressObj;
/* the fd int field on fdObj */ /* the fd int field on fdObj */
jint fd=-1, fd1=-1; jint fd=-1;
SOCKETADDRESS sa; SOCKETADDRESS sa;
jint len; jint len;
int ret;
if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { if (IS_NULL(fdObj)) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Socket closed"); "Socket closed");
return; return;
} }
if (!IS_NULL(fdObj)) {
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
}
if (!IS_NULL(fd1Obj)) {
fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
}
if (IS_NULL(socket)) { if (IS_NULL(socket)) {
JNU_ThrowNullPointerException(env, "socket is null"); JNU_ThrowNullPointerException(env, "socket is null");
return; return;
@ -611,54 +481,8 @@ Java_java_net_TwoStacksPlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
JNU_ThrowNullPointerException(env, "socket address or fd obj"); JNU_ThrowNullPointerException(env, "socket address or fd obj");
return; return;
} }
if (fd != -1 && fd1 != -1) {
fd_set rfds;
struct timeval t, *tP=&t;
int lastfd, res, fd2;
FD_ZERO(&rfds);
FD_SET(fd,&rfds);
FD_SET(fd1,&rfds);
if (timeout) {
t.tv_sec = timeout/1000;
t.tv_usec = (timeout%1000)*1000;
} else {
tP = NULL;
}
res = select (fd, &rfds, NULL, NULL, tP);
if (res == 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
"Accept timed out");
return;
} else if (res == 1) {
fd2 = FD_ISSET(fd, &rfds)? fd: fd1;
} else if (res == 2) {
/* avoid starvation */
lastfd = (*env)->GetIntField(env, this, psi_lastfdID);
if (lastfd != -1) {
fd2 = lastfd==fd? fd1: fd;
} else {
fd2 = fd;
}
(*env)->SetIntField(env, this, psi_lastfdID, fd2);
} else {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"select failed");
return;
}
if (fd2 == fd) { /* v4 */
len = sizeof(struct sockaddr_in); len = sizeof(struct sockaddr_in);
} else {
len = sizeof(struct sockaddr_in6);
}
fd = fd2;
} else {
int ret;
if (fd1 != -1) {
fd = fd1;
len = sizeof(struct sockaddr_in6);
} else {
len = sizeof(struct sockaddr_in);
}
if (timeout) { if (timeout) {
ret = NET_Timeout(fd, timeout); ret = NET_Timeout(fd, timeout);
if (ret == 0) { if (ret == 0) {
@ -676,7 +500,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
return; return;
} }
} }
}
fd = accept(fd, &sa.sa, &len); fd = accept(fd, &sa.sa, &len);
if (fd < 0) { if (fd < 0) {
/* REMIND: SOCKET CLOSED PROBLEM */ /* REMIND: SOCKET CLOSED PROBLEM */
@ -692,7 +516,12 @@ Java_java_net_TwoStacksPlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, 0); SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, 0);
(*env)->SetIntField(env, socketFdObj, IO_fd_fdID, fd); (*env)->SetIntField(env, socketFdObj, IO_fd_fdID, fd);
if (sa.sa.sa_family == AF_INET) { if (sa.sa.sa_family != AF_INET) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Protocol family not supported");
return;
}
if (inet4Cls == NULL) { if (inet4Cls == NULL) {
jclass c = (*env)->FindClass(env, "java/net/Inet4Address"); jclass c = (*env)->FindClass(env, "java/net/Inet4Address");
if (c != NULL) { if (c != NULL) {
@ -712,7 +541,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
if (socketAddressObj == NULL) { if (socketAddressObj == NULL) {
/* /*
* FindClass or NewObject failed so close connection and * FindClass or NewObject failed so close connection and
* exist (there will be a pending exception). * exit (there will be a pending exception).
*/ */
NET_SocketClose(fd); NET_SocketClose(fd);
return; return;
@ -721,36 +550,6 @@ Java_java_net_TwoStacksPlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
setInetAddress_addr(env, socketAddressObj, ntohl(sa.sa4.sin_addr.s_addr)); setInetAddress_addr(env, socketAddressObj, ntohl(sa.sa4.sin_addr.s_addr));
setInetAddress_family(env, socketAddressObj, java_net_InetAddress_IPv4); setInetAddress_family(env, socketAddressObj, java_net_InetAddress_IPv4);
(*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj); (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj);
} else {
/* AF_INET6 -> Inet6Address */
if (inet6Cls == 0) {
jclass c = (*env)->FindClass(env, "java/net/Inet6Address");
if (c != NULL) {
inet6Cls = (*env)->NewGlobalRef(env, c);
(*env)->DeleteLocalRef(env, c);
}
}
if (inet6Cls != NULL) {
socketAddressObj = (*env)->NewObject(env, inet6Cls, ia6_ctrID);
} else {
socketAddressObj = NULL;
}
if (socketAddressObj == NULL) {
/*
* FindClass or NewObject failed so close connection and
* exist (there will be a pending exception).
*/
NET_SocketClose(fd);
return;
}
setInet6Address_ipaddress(env, socketAddressObj, (char *)&sa.sa6.sin6_addr);
setInetAddress_family(env, socketAddressObj, java_net_InetAddress_IPv6);
setInet6Address_scopeid(env, socketAddressObj, sa.sa6.sin6_scope_id);
}
/* fields common to AF_INET and AF_INET6 */
port = ntohs ((u_short)GET_PORT(&sa)); port = ntohs ((u_short)GET_PORT(&sa));
(*env)->SetIntField(env, socket, psi_portID, (int)port); (*env)->SetIntField(env, socket, psi_portID, (int)port);
port = (*env)->GetIntField(env, this, psi_localportID); port = (*env)->GetIntField(env, this, psi_localportID);
@ -795,10 +594,9 @@ Java_java_net_TwoStacksPlainSocketImpl_socketClose0(JNIEnv *env, jobject this,
jboolean useDeferredClose) { jboolean useDeferredClose) {
jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); jint fd=-1;
jint fd=-1, fd1=-1;
if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { if (IS_NULL(fdObj)) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"socket already closed"); "socket already closed");
return; return;
@ -806,17 +604,10 @@ Java_java_net_TwoStacksPlainSocketImpl_socketClose0(JNIEnv *env, jobject this,
if (!IS_NULL(fdObj)) { if (!IS_NULL(fdObj)) {
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
} }
if (!IS_NULL(fd1Obj)) {
fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
}
if (fd != -1) { if (fd != -1) {
(*env)->SetIntField(env, fdObj, IO_fd_fdID, -1); (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1);
NET_SocketClose(fd); NET_SocketClose(fd);
} }
if (fd1 != -1) {
(*env)->SetIntField(env, fd1Obj, IO_fd_fdID, -1);
NET_SocketClose(fd1);
}
} }
/* /*
@ -831,7 +622,7 @@ JNIEXPORT void JNICALL
Java_java_net_TwoStacksPlainSocketImpl_socketNativeSetOption Java_java_net_TwoStacksPlainSocketImpl_socketNativeSetOption
(JNIEnv *env, jobject this, jint cmd, jboolean on, jobject value) (JNIEnv *env, jobject this, jint cmd, jboolean on, jobject value)
{ {
int fd, fd1; int fd;
int level = 0, optname = 0, optlen = 0; int level = 0, optname = 0, optlen = 0;
union { union {
int i; int i;
@ -843,8 +634,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketNativeSetOption
* Get SOCKET and check that it hasn't been closed * Get SOCKET and check that it hasn't been closed
*/ */
fd = getFD(env, this); fd = getFD(env, this);
fd1 = getFD1(env, this); if (fd < 0) {
if (fd < 0 && fd1 < 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
return; return;
} }
@ -901,12 +691,6 @@ Java_java_net_TwoStacksPlainSocketImpl_socketNativeSetOption
return; return;
} }
} }
if (fd1 != -1) {
if (setsockopt(fd1, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
sizeof(timeout)) < 0) {
NET_ThrowCurrent(env, "setsockopt SO_RCVTIMEO");
}
}
} }
return; return;
} }
@ -980,12 +764,6 @@ Java_java_net_TwoStacksPlainSocketImpl_socketNativeSetOption
NET_ThrowCurrent(env, "setsockopt"); NET_ThrowCurrent(env, "setsockopt");
} }
} }
if (fd1 != -1) {
if (NET_SetSockOpt(fd1, level, optname, (void *)&optval, optlen) < 0) {
NET_ThrowCurrent(env, "setsockopt");
}
}
} }
@ -998,7 +776,7 @@ JNIEXPORT jint JNICALL
Java_java_net_TwoStacksPlainSocketImpl_socketGetOption Java_java_net_TwoStacksPlainSocketImpl_socketGetOption
(JNIEnv *env, jobject this, jint opt, jobject iaContainerObj) (JNIEnv *env, jobject this, jint opt, jobject iaContainerObj)
{ {
int fd, fd1; int fd;
int level = 0, optname = 0, optlen = 0; int level = 0, optname = 0, optlen = 0;
union { union {
int i; int i;
@ -1009,18 +787,12 @@ Java_java_net_TwoStacksPlainSocketImpl_socketGetOption
* Get SOCKET and check it hasn't been closed * Get SOCKET and check it hasn't been closed
*/ */
fd = getFD(env, this); fd = getFD(env, this);
fd1 = getFD1(env, this);
memset((char *)&optval, 0, sizeof(optval)); memset((char *)&optval, 0, sizeof(optval));
if (fd < 0 && fd1 < 0) { if (fd < 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
return -1; return -1;
} }
if (fd < 0) {
fd = fd1;
}
/* For IPv6, we assume both sockets have the same setting always */
/* /*
* SO_BINDADDR isn't a socket option * SO_BINDADDR isn't a socket option
@ -1035,13 +807,6 @@ Java_java_net_TwoStacksPlainSocketImpl_socketGetOption
memset((char *)&sa, 0, len); memset((char *)&sa, 0, len);
if (fd == -1) {
/* must be an IPV6 only socket. Case where both sockets are != -1
* is handled in java
*/
fd = getFD1 (env, this);
}
if (getsockname(fd, &sa.sa, &len) < 0) { if (getsockname(fd, &sa.sa, &len) < 0) {
JNU_ThrowByNameWithMessageAndLastError JNU_ThrowByNameWithMessageAndLastError
(env, JNU_JAVANETPKG "SocketException", "Error getting socket name"); (env, JNU_JAVANETPKG "SocketException", "Error getting socket name");

View File

@ -43,11 +43,10 @@ import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.JCDiagnostic.Error; import com.sun.tools.javac.util.JCDiagnostic.Error;
import com.sun.tools.javac.util.JCDiagnostic.Warning; import com.sun.tools.javac.util.JCDiagnostic.Warning;
import com.sun.tools.javac.util.JCDiagnostic.Fragment;
import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.JCDiagnostic.Fragment;
import static com.sun.tools.javac.parser.Tokens.TokenKind.*; import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT; import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
@ -290,9 +289,31 @@ public class JavacParser implements Parser {
/** Skip forward until a suitable stop token is found. /** Skip forward until a suitable stop token is found.
*/ */
protected void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) { protected void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement, boolean stopAtLambdaBody) {
while (true) { while (true) {
switch (token.kind) { switch (token.kind) {
case ARROW:
if (stopAtLambdaBody) {
//find end of lambda expression; this could be either a comma or an rparen (if in method context),
//or a semi colon (if in assignment context).
int depth = 0;
while (true) {
switch (token.kind) {
case EOF:
case LBRACE: depth++; break;
case RBRACE: depth--; break;
case COMMA:
case RPAREN:
case SEMI:
if (depth == 0) {
return;
}
break;
}
nextToken();
}
}
break;
case SEMI: case SEMI:
nextToken(); nextToken();
return; return;
@ -1076,7 +1097,8 @@ public class JavacParser implements Parser {
break; break;
case LPAREN: case LPAREN:
if (typeArgs == null && (mode & EXPR) != 0) { if (typeArgs == null && (mode & EXPR) != 0) {
ParensResult pres = analyzeParens(); LambdaClassfier lambdaClassifier = new LambdaClassfier();
ParensResult pres = analyzeParens(lambdaClassifier);
switch (pres) { switch (pres) {
case CAST: case CAST:
accept(LPAREN); accept(LPAREN);
@ -1095,9 +1117,15 @@ public class JavacParser implements Parser {
mode = EXPR; mode = EXPR;
JCExpression t1 = term3(); JCExpression t1 = term3();
return F.at(pos).TypeCast(t, t1); return F.at(pos).TypeCast(t, t1);
case BAD_LAMBDA:
Assert.checkNonNull(lambdaClassifier.diagFragment);
t = syntaxError(pos, List.nil(), Errors.InvalidLambdaParameterDeclaration(lambdaClassifier.diagFragment));
skip(false, false, false, false, true);
break;
case IMPLICIT_LAMBDA: case IMPLICIT_LAMBDA:
case EXPLICIT_LAMBDA: case EXPLICIT_LAMBDA:
t = lambdaExpressionOrStatement(true, pres == ParensResult.EXPLICIT_LAMBDA, pos); case IMPLICIT_LAMBDA_ALL_VAR:
t = lambdaExpressionOrStatement(true, pres != ParensResult.IMPLICIT_LAMBDA, pos);
break; break;
default: //PARENS default: //PARENS
accept(LPAREN); accept(LPAREN);
@ -1509,15 +1537,17 @@ public class JavacParser implements Parser {
* matching '&gt;' and see if the subsequent terminal is either '.' or '::'. * matching '&gt;' and see if the subsequent terminal is either '.' or '::'.
*/ */
@SuppressWarnings("fallthrough") @SuppressWarnings("fallthrough")
ParensResult analyzeParens() { ParensResult analyzeParens(LambdaClassfier lambdaClassifier) {
int depth = 0; int depth = 0;
boolean type = false; boolean type = false;
outer: for (int lookahead = 0 ; ; lookahead++) { outer: for (int lookahead = 0 ; ; lookahead++) {
TokenKind tk = S.token(lookahead).kind; Token lookaheadToken = S.token(lookahead);
TokenKind tk = lookaheadToken.kind;
switch (tk) { switch (tk) {
case COMMA: case COMMA:
type = true; type = true;
case EXTENDS: case SUPER: case DOT: case AMP: break;
case FINAL: case EXTENDS: case SUPER: case DOT: case AMP:
//skip //skip
break; break;
case QUES: case QUES:
@ -1534,7 +1564,8 @@ public class JavacParser implements Parser {
return ParensResult.CAST; return ParensResult.CAST;
} else if (peekToken(lookahead, LAX_IDENTIFIER)) { } else if (peekToken(lookahead, LAX_IDENTIFIER)) {
//Type, Identifier/'_'/'assert'/'enum' -> explicit lambda //Type, Identifier/'_'/'assert'/'enum' -> explicit lambda
return ParensResult.EXPLICIT_LAMBDA; lambdaClassifier.addExplicitParameter();
lookahead++; //skip Identifier
} }
break; break;
case LPAREN: case LPAREN:
@ -1547,6 +1578,10 @@ public class JavacParser implements Parser {
} }
break; break;
case RPAREN: case RPAREN:
if (peekToken(lookahead, ARROW)) {
//this is a lambda
return lambdaClassifier.result();
} else {
// if we have seen something that looks like a type, // if we have seen something that looks like a type,
// then it's a cast expression // then it's a cast expression
if (type) return ParensResult.CAST; if (type) return ParensResult.CAST;
@ -1566,23 +1601,30 @@ public class JavacParser implements Parser {
default: default:
return ParensResult.PARENS; return ParensResult.PARENS;
} }
}
case UNDERSCORE: case UNDERSCORE:
case ASSERT: case ASSERT:
case ENUM: case ENUM:
case IDENTIFIER: case IDENTIFIER:
if (peekToken(lookahead, LAX_IDENTIFIER)) { if (peekToken(lookahead, LAX_IDENTIFIER)) {
// Identifier, Identifier/'_'/'assert'/'enum' -> explicit lambda // Identifier, Identifier/'_'/'assert'/'enum' -> explicit lambda
return ParensResult.EXPLICIT_LAMBDA; if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source) &&
} else if (peekToken(lookahead, RPAREN, ARROW)) { lookaheadToken.name() == names.var) {
// Identifier, ')' '->' -> implicit lambda lambdaClassifier.addImplicitVarParameter();
return ParensResult.IMPLICIT_LAMBDA; } else {
lambdaClassifier.addExplicitParameter();
}
lookahead++; //skip Identifier
} else if ((!type && peekToken(lookahead, COMMA)) || peekToken(lookahead, RPAREN)) {
lambdaClassifier.addImplicitParameter();
} }
type = false; type = false;
break; break;
case FINAL:
case ELLIPSIS: case ELLIPSIS:
//those can only appear in explicit lambdas //those can only appear in explicit, non-var, lambdas
return ParensResult.EXPLICIT_LAMBDA; lambdaClassifier.addExplicitParameter();
lookahead++; //skip Identifier
break;
case MONKEYS_AT: case MONKEYS_AT:
type = true; type = true;
lookahead += 1; //skip '@' lookahead += 1; //skip '@'
@ -1614,7 +1656,9 @@ public class JavacParser implements Parser {
case LBRACKET: case LBRACKET:
if (peekToken(lookahead, RBRACKET, LAX_IDENTIFIER)) { if (peekToken(lookahead, RBRACKET, LAX_IDENTIFIER)) {
// '[', ']', Identifier/'_'/'assert'/'enum' -> explicit lambda // '[', ']', Identifier/'_'/'assert'/'enum' -> explicit lambda
return ParensResult.EXPLICIT_LAMBDA; lambdaClassifier.addExplicitParameter();
lookahead += 2; //skip ']' Identifier
break;
} else if (peekToken(lookahead, RBRACKET, RPAREN) || } else if (peekToken(lookahead, RBRACKET, RPAREN) ||
peekToken(lookahead, RBRACKET, AMP)) { peekToken(lookahead, RBRACKET, AMP)) {
// '[', ']', ')' -> cast // '[', ']', ')' -> cast
@ -1643,12 +1687,15 @@ public class JavacParser implements Parser {
// '>', '&' -> cast // '>', '&' -> cast
return ParensResult.CAST; return ParensResult.CAST;
} else if (peekToken(lookahead, LAX_IDENTIFIER, COMMA) || } else if (peekToken(lookahead, LAX_IDENTIFIER, COMMA) ||
peekToken(lookahead, LAX_IDENTIFIER, RPAREN, ARROW) || peekToken(lookahead, LAX_IDENTIFIER, RPAREN, ARROW)) {
peekToken(lookahead, ELLIPSIS)) {
// '>', Identifier/'_'/'assert'/'enum', ',' -> explicit lambda // '>', Identifier/'_'/'assert'/'enum', ',' -> explicit lambda
// '>', Identifier/'_'/'assert'/'enum', ')', '->' -> explicit lambda // '>', Identifier/'_'/'assert'/'enum', ')', '->' -> explicit lambda
lambdaClassifier.addExplicitParameter();
lookahead++; //skip Identifier
break;
} else if (peekToken(lookahead, ELLIPSIS)) {
// '>', '...' -> explicit lambda // '>', '...' -> explicit lambda
return ParensResult.EXPLICIT_LAMBDA; break; //this is handled in the outer switch
} }
//it looks a type, but could still be (i) a cast to generic type, //it looks a type, but could still be (i) a cast to generic type,
//(ii) an unbound method reference or (iii) an explicit lambda //(ii) an unbound method reference or (iii) an explicit lambda
@ -1666,6 +1713,61 @@ public class JavacParser implements Parser {
} }
} }
class LambdaClassfier {
ParensResult kind;
Fragment diagFragment;
void addExplicitParameter() {
reduce(ParensResult.EXPLICIT_LAMBDA);
}
void addImplicitVarParameter() {
reduce(ParensResult.IMPLICIT_LAMBDA_ALL_VAR);
}
void addImplicitParameter() {
reduce(ParensResult.IMPLICIT_LAMBDA);
}
private void reduce(ParensResult newKind) {
if (kind == null) {
kind = newKind;
} else if (kind != newKind && kind != ParensResult.BAD_LAMBDA) {
ParensResult currentKind = kind;
kind = ParensResult.BAD_LAMBDA;
switch (currentKind) {
case EXPLICIT_LAMBDA:
if (newKind == ParensResult.IMPLICIT_LAMBDA) {
diagFragment = Fragments.ImplicitAndExplicitNotAllowed;
} else if (newKind == ParensResult.IMPLICIT_LAMBDA_ALL_VAR) {
diagFragment = Fragments.VarAndExplicitNotAllowed;
}
break;
case IMPLICIT_LAMBDA:
if (newKind == ParensResult.EXPLICIT_LAMBDA) {
diagFragment = Fragments.ImplicitAndExplicitNotAllowed;
} else if (newKind == ParensResult.IMPLICIT_LAMBDA_ALL_VAR) {
diagFragment = Fragments.VarAndImplicitNotAllowed;
}
break;
case IMPLICIT_LAMBDA_ALL_VAR:
if (newKind == ParensResult.EXPLICIT_LAMBDA) {
diagFragment = Fragments.VarAndExplicitNotAllowed;
} else if (newKind == ParensResult.IMPLICIT_LAMBDA) {
diagFragment = Fragments.VarAndImplicitNotAllowed;
}
break;
default:
throw new AssertionError("unexpected option for field kind");
}
}
}
ParensResult result() {
return kind;
}
}
/** Accepts all identifier-like tokens */ /** Accepts all identifier-like tokens */
protected Filter<TokenKind> LAX_IDENTIFIER = t -> t == IDENTIFIER || t == UNDERSCORE || t == ASSERT || t == ENUM; protected Filter<TokenKind> LAX_IDENTIFIER = t -> t == IDENTIFIER || t == UNDERSCORE || t == ASSERT || t == ENUM;
@ -1673,7 +1775,15 @@ public class JavacParser implements Parser {
CAST, CAST,
EXPLICIT_LAMBDA, EXPLICIT_LAMBDA,
IMPLICIT_LAMBDA, IMPLICIT_LAMBDA,
PARENS IMPLICIT_LAMBDA_ALL_VAR,
BAD_LAMBDA,
PARENS;
}
enum BAD_LAMBDA_KIND {
EXPLICIT_AND_VAR,
IMPLICIT_AND_VAR,
EXPLICIT_AND_IMPLICIT,
} }
JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) { JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) {
@ -1896,6 +2006,9 @@ public class JavacParser implements Parser {
List<JCAnnotation> nextLevelAnnotations = typeAnnotationsOpt(); List<JCAnnotation> nextLevelAnnotations = typeAnnotationsOpt();
if (token.kind == LBRACKET) { if (token.kind == LBRACKET) {
if (t == null) {
log.error(token.pos, Errors.VarNotAllowedArray);
}
int pos = token.pos; int pos = token.pos;
nextToken(); nextToken();
t = bracketsOptCont(t, pos, nextLevelAnnotations); t = bracketsOptCont(t, pos, nextLevelAnnotations);
@ -2294,7 +2407,7 @@ public class JavacParser implements Parser {
if (token.pos == lastErrPos) if (token.pos == lastErrPos)
return stats.toList(); return stats.toList();
if (token.pos <= endPosTable.errorEndPos) { if (token.pos <= endPosTable.errorEndPos) {
skip(false, true, true, true); skip(false, true, true, true, false);
lastErrPos = token.pos; lastErrPos = token.pos;
} }
stats.addAll(stat); stats.addAll(stat);
@ -3133,7 +3246,7 @@ public class JavacParser implements Parser {
while (token.kind != EOF) { while (token.kind != EOF) {
if (token.pos <= endPosTable.errorEndPos) { if (token.pos <= endPosTable.errorEndPos) {
// error recovery // error recovery
skip(checkForImports, false, false, false); skip(checkForImports, false, false, false, false);
if (token.kind == EOF) if (token.kind == EOF)
break; break;
} }
@ -3270,7 +3383,7 @@ public class JavacParser implements Parser {
defs.append(toP(F.at(pos).Provides(serviceName, implNames))); defs.append(toP(F.at(pos).Provides(serviceName, implNames)));
} else { } else {
log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.ExpectedStr("'" + names.with + "'")); log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.ExpectedStr("'" + names.with + "'"));
skip(false, false, false, false); skip(false, false, false, false, false);
} }
} else if (token.name() == names.uses) { } else if (token.name() == names.uses) {
nextToken(); nextToken();
@ -3475,7 +3588,7 @@ public class JavacParser implements Parser {
false)); false));
if (token.pos <= endPosTable.errorEndPos) { if (token.pos <= endPosTable.errorEndPos) {
// error recovery // error recovery
skip(false, true, true, false); skip(false, true, true, false, false);
} }
} }
} }
@ -3537,7 +3650,7 @@ public class JavacParser implements Parser {
accept(LBRACE); accept(LBRACE);
if (token.pos <= endPosTable.errorEndPos) { if (token.pos <= endPosTable.errorEndPos) {
// error recovery // error recovery
skip(false, true, false, false); skip(false, true, false, false, false);
if (token.kind == LBRACE) if (token.kind == LBRACE)
nextToken(); nextToken();
} }
@ -3546,7 +3659,7 @@ public class JavacParser implements Parser {
defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface)); defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
if (token.pos <= endPosTable.errorEndPos) { if (token.pos <= endPosTable.errorEndPos) {
// error recovery // error recovery
skip(false, true, true, false); skip(false, true, true, false, false);
} }
} }
accept(RBRACE); accept(RBRACE);
@ -3713,7 +3826,7 @@ public class JavacParser implements Parser {
accept(SEMI); accept(SEMI);
if (token.pos <= endPosTable.errorEndPos) { if (token.pos <= endPosTable.errorEndPos) {
// error recovery // error recovery
skip(false, true, false, false); skip(false, true, false, false, false);
if (token.kind == LBRACE) { if (token.kind == LBRACE) {
body = block(); body = block();
} }
@ -3947,7 +4060,7 @@ public class JavacParser implements Parser {
// need to distinguish between vararg annos and array annos // need to distinguish between vararg annos and array annos
// look at typeAnnotationsPushedBack comment // look at typeAnnotationsPushedBack comment
this.permitTypeAnnotationsPushBack = true; this.permitTypeAnnotationsPushBack = true;
JCExpression type = parseType(); JCExpression type = parseType(lambdaParameter);
this.permitTypeAnnotationsPushBack = false; this.permitTypeAnnotationsPushBack = false;
if (token.kind == ELLIPSIS) { if (token.kind == ELLIPSIS) {
@ -3964,6 +4077,10 @@ public class JavacParser implements Parser {
} }
typeAnnotationsPushedBack = List.nil(); typeAnnotationsPushedBack = List.nil();
} }
if (lambdaParameter && isRestrictedLocalVarTypeName(type)) {
//implicit lambda parameter type (with 'var')
type = null;
}
return variableDeclaratorId(mods, type, lambdaParameter); return variableDeclaratorId(mods, type, lambdaParameter);
} }

View File

@ -1229,6 +1229,20 @@ compiler.err.var.not.allowed.array=\
compiler.err.var.not.allowed.compound=\ compiler.err.var.not.allowed.compound=\
''var'' is not allowed in a compound declaration ''var'' is not allowed in a compound declaration
# 0: fragment
compiler.err.invalid.lambda.parameter.declaration=\
invalid lambda parameter declaration\n\
({0})
compiler.misc.implicit.and.explicit.not.allowed=\
cannot mix implicitly-typed and explicitly-typed parameters
compiler.misc.var.and.explicit.not.allowed=\
cannot mix ''var'' and explicitly-typed parameters
compiler.misc.var.and.implicit.not.allowed=\
cannot mix ''var'' and implicitly-typed parameters
compiler.misc.local.cant.infer.null=\ compiler.misc.local.cant.infer.null=\
variable initializer is ''null'' variable initializer is ''null''

View File

@ -386,7 +386,7 @@ class JImageTask {
for (File file : options.jimages) { for (File file : options.jimages) {
if (!file.exists() || !file.isFile()) { if (!file.exists() || !file.isFile()) {
throw TASK_HELPER.newBadArgs("err.not.a.jimage", file.getName()); throw TASK_HELPER.newBadArgs("err.not.a.jimage", file);
} }
try (BasicImageReader reader = BasicImageReader.open(file.toPath())) { try (BasicImageReader reader = BasicImageReader.open(file.toPath())) {
@ -431,6 +431,8 @@ class JImageTask {
} }
} }
} }
} catch (IOException ioe) {
throw TASK_HELPER.newBadArgs("err.invalid.jimage", file, ioe.getMessage());
} }
} }
} }

View File

@ -95,6 +95,7 @@ err.not.a.task=task must be one of <extract | info | list | verify>: {0}
err.missing.arg=no value given for {0} err.missing.arg=no value given for {0}
err.not.a.dir=not a directory: {0} err.not.a.dir=not a directory: {0}
err.not.a.jimage=not a jimage file: {0} err.not.a.jimage=not a jimage file: {0}
err.invalid.jimage=Unable to open {0}: {1}
err.no.jimage=no jimage provided err.no.jimage=no jimage provided
err.option.unsupported={0} not supported: {1} err.option.unsupported={0} not supported: {1}
err.unknown.option=unknown option: {0} err.unknown.option=unknown option: {0}

View File

@ -27,6 +27,7 @@ package jdk.tools.jlink.internal.plugins;
import java.util.Map; import java.util.Map;
import java.util.function.Predicate; import java.util.function.Predicate;
import jdk.tools.jlink.plugin.Plugin; import jdk.tools.jlink.plugin.Plugin;
import jdk.tools.jlink.plugin.PluginException;
import jdk.tools.jlink.plugin.ResourcePool; import jdk.tools.jlink.plugin.ResourcePool;
import jdk.tools.jlink.plugin.ResourcePoolBuilder; import jdk.tools.jlink.plugin.ResourcePoolBuilder;
import jdk.tools.jlink.plugin.ResourcePoolEntry; import jdk.tools.jlink.plugin.ResourcePoolEntry;
@ -49,7 +50,13 @@ public final class ExcludePlugin implements Plugin {
public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) { public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
in.transformAndCopy((resource) -> { in.transformAndCopy((resource) -> {
if (resource.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)) { if (resource.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)) {
resource = predicate.test(resource.path()) ? resource : null; boolean shouldExclude = !predicate.test(resource.path());
// do not allow filtering module-info.class to avoid mutating module graph.
if (shouldExclude &&
resource.path().equals("/" + resource.moduleName() + "/module-info.class")) {
throw new PluginException("Cannot exclude " + resource.path());
}
return shouldExclude? null : resource;
} }
return resource; return resource;
}, out); }, out);

View File

@ -104,7 +104,7 @@ class ReplParser extends JavacParser {
while (token.kind != EOF) { while (token.kind != EOF) {
if (token.pos > 0 && token.pos <= endPosTable.errorEndPos) { if (token.pos > 0 && token.pos <= endPosTable.errorEndPos) {
// error recovery // error recovery
skip(true, false, false, false); skip(true, false, false, false, false);
if (token.kind == EOF) { if (token.kind == EOF) {
break; break;
} }

View File

@ -464,9 +464,8 @@ tools/pack200/CommandLineTests.java 8059906 generic-
tools/launcher/FXLauncherTest.java 8068049 linux-all,macosx-all tools/launcher/FXLauncherTest.java 8068049 linux-all,macosx-all
tools/jimage/JImageExtractTest.java 8170120 generic-all tools/jimage/JImageExtractTest.java 8198405 windows-all
tools/jimage/JImageListTest.java 8170120 generic-all tools/jimage/JImageListTest.java 8198405 windows-all
tools/jimage/JImageVerifyTest.java 8170120 generic-all
############################################################################ ############################################################################

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2018, 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
@ -154,8 +154,10 @@ public class JImageExtractTest extends JImageCliTest {
Path tmp = Files.createTempDirectory(Paths.get("."), getClass().getName()); Path tmp = Files.createTempDirectory(Paths.get("."), getClass().getName());
Files.createFile(Paths.get(tmp.toString(), ".not_empty")); Files.createFile(Paths.get(tmp.toString(), ".not_empty"));
jimage("extract", "--dir", tmp.toString(), getImagePath()) jimage("extract", "--dir", tmp.toString(), getImagePath())
.assertFailure() .assertSuccess()
.assertShowsError(); .resultChecker(r -> {
assertTrue(r.output.isEmpty(), "Output is not expected");
});
} }
public void testExtractToFile() throws IOException { public void testExtractToFile() throws IOException {

View File

@ -57,7 +57,7 @@ public class JImageListTest extends JImageCliTest {
.map(s -> s.substring(s.indexOf(':') + 1).trim()) .map(s -> s.substring(s.indexOf(':') + 1).trim())
.collect(Collectors.toList()); .collect(Collectors.toList());
assertTrue(modules.size() > 0, "Image contains at least one module."); assertTrue(modules.size() > 0, "Image contains at least one module.");
assertTrue(modules.indexOf("java.base") > 0, "Module java.base found."); assertTrue(modules.contains("java.base"), "Module java.base found.");
}); });
} }
@ -88,7 +88,7 @@ public class JImageListTest extends JImageCliTest {
.map(s -> s.substring(s.indexOf(':') + 1).trim()) .map(s -> s.substring(s.indexOf(':') + 1).trim())
.collect(Collectors.toList()); .collect(Collectors.toList());
assertTrue(modules.size() > 0, "Image contains at least one module."); assertTrue(modules.size() > 0, "Image contains at least one module.");
assertTrue(modules.indexOf("java.base") > 0, "Module java.base found."); assertTrue(modules.contains("java.base"), "Module java.base found.");
Set<String> entries = Stream.of(lines) Set<String> entries = Stream.of(lines)
.filter(s -> { return !s.startsWith("Module: ") && !s.startsWith("Offset"); }) .filter(s -> { return !s.startsWith("Module: ") && !s.startsWith("Offset"); })

View File

@ -43,6 +43,7 @@ import tests.JImageGenerator;
* @test * @test
* @summary Test image creation * @summary Test image creation
* @bug 8189777 * @bug 8189777
* @bug 8194922
* @author Jean-Francois Denise * @author Jean-Francois Denise
* @requires (vm.compMode != "Xcomp" & os.maxMemory >= 2g) * @requires (vm.compMode != "Xcomp" & os.maxMemory >= 2g)
* @library ../lib * @library ../lib
@ -276,6 +277,15 @@ public class JLinkTest {
helper.checkImage(imageDir, moduleName, res, null); helper.checkImage(imageDir, moduleName, res, null);
} }
// module-info.class should not be excluded
{
String[] userOptions = { "--exclude-resources", "/jdk_8194922/module-info.class" };
String moduleName = "jdk_8194922";
helper.generateDefaultJModule(moduleName);
helper.generateDefaultImage(userOptions, moduleName).
assertFailure("Cannot exclude /jdk_8194922/module-info.class");
}
// default compress // default compress
{ {
testCompress(helper, "compresscmdcomposite2", "--compress", "2"); testCompress(helper, "compresscmdcomposite2", "--compress", "2");

View File

@ -0,0 +1,75 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8194922
* @summary jlink --exclude-resources should never exclude module-info.class
* @modules jdk.jlink/jdk.tools.jlink.internal
* jdk.jlink/jdk.tools.jlink.internal.plugins
* jdk.jlink/jdk.tools.jlink.plugin
* @run main ExcludeModuleInfoTest
*/
import java.io.File;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;
import jdk.tools.jlink.internal.ResourcePoolManager;
import jdk.tools.jlink.internal.plugins.ExcludePlugin;
import jdk.tools.jlink.plugin.PluginException;
import jdk.tools.jlink.plugin.ResourcePool;
import jdk.tools.jlink.plugin.ResourcePoolBuilder;
import jdk.tools.jlink.plugin.ResourcePoolEntry;
public class ExcludeModuleInfoTest {
public static void main(String[] args) throws Exception {
new ExcludeModuleInfoTest().test();
}
public void test() throws Exception {
check("**.class", "/mymodule/module-info.class");
check("/java.base/module-info.class", "/java.base/module-info.class");
}
public void check(String s, String sample) throws Exception {
Map<String, String> prop = new HashMap<>();
prop.put(ExcludePlugin.NAME, s);
ExcludePlugin excludePlugin = new ExcludePlugin();
excludePlugin.configure(prop);
ResourcePoolManager resourcesMgr = new ResourcePoolManager();
ResourcePoolEntry resource = ResourcePoolEntry.create(sample, new byte[0]);
resourcesMgr.add(resource);
ResourcePoolManager resultMgr = new ResourcePoolManager();
try {
excludePlugin.transform(resourcesMgr.resourcePool(),
resultMgr.resourcePoolBuilder());
throw new AssertionError(sample + " exclusion should have resulted in exception");
} catch (PluginException pe) {
System.err.println("Got exception as expected: " + pe);
pe.printStackTrace();
}
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// key: compiler.err.var.not.allowed.array
import java.util.function.*;
class BracketsNotAllowedImplicitLambda {
BiFunction<String[], String, String> f = (var s1[], var s2) -> s2;
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// key: compiler.err.invalid.lambda.parameter.declaration
// key: compiler.misc.implicit.and.explicit.not.allowed
import java.util.function.*;
class ExplicitImplicitLambda {
IntBinaryOperator f = (int x, y) -> x + y;
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// key: compiler.err.invalid.lambda.parameter.declaration
// key: compiler.misc.var.and.implicit.not.allowed
import java.util.function.*;
class VarAllOrNothing {
IntBinaryOperator f = (x, var y) -> x + y;
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// key: compiler.err.invalid.lambda.parameter.declaration
// key: compiler.misc.var.and.explicit.not.allowed
import java.util.function.*;
class VarExplicitLambda {
IntBinaryOperator f = (int x, var y) -> x + y;
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute 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.
*/
// key: compiler.err.invalid.lambda.parameter.declaration
// key: compiler.misc.var.and.explicit.not.allowed
class VarNotAllowedExplicitLambda {
F f = (String s, var v)->{};
}

View File

@ -1,4 +1,4 @@
T8131742.java:8:38: compiler.err.expected3: ',', ')', '[' T8131742.java:8:31: compiler.err.expected: ')'
T8131742.java:8:39: compiler.err.this.as.identifier T8131742.java:8:39: compiler.err.this.as.identifier
T8131742.java:8:43: compiler.err.expected: ';' T8131742.java:8:43: compiler.err.expected: token.identifier
3 errors 3 errors

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2018, 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
@ -40,6 +40,7 @@
*/ */
import java.io.IOException; import java.io.IOException;
import java.util.Arrays;
import combo.ComboInstance; import combo.ComboInstance;
import combo.ComboParameter; import combo.ComboParameter;
@ -105,26 +106,44 @@ public class LambdaParserTest extends ComboInstance<LambdaParserTest> {
} }
} }
enum LambdaParameterKind implements ComboParameter { enum SourceKind {
IMPLICIT(""), SOURCE_9("9"),
EXPLIICT_SIMPLE("A"), SOURCE_10("10");
EXPLIICT_SIMPLE_ARR1("A[]"),
EXPLIICT_SIMPLE_ARR2("A[][]"),
EXPLICIT_VARARGS("A..."),
EXPLICIT_GENERIC1("A<X>"),
EXPLICIT_GENERIC2("A<? extends X, ? super Y>"),
EXPLICIT_GENERIC2_VARARGS("A<? extends X, ? super Y>..."),
EXPLICIT_GENERIC2_ARR1("A<? extends X, ? super Y>[]"),
EXPLICIT_GENERIC2_ARR2("A<? extends X, ? super Y>[][]");
String parameterType; String sourceNumber;
LambdaParameterKind(String parameterType) { SourceKind(String sourceNumber) {
this.parameterType = parameterType; this.sourceNumber = sourceNumber;
}
} }
boolean explicit() { enum LambdaParameterKind implements ComboParameter {
return this != IMPLICIT;
IMPLICIT_1("", ExplicitKind.IMPLICIT),
IMPLICIT_2("var", ExplicitKind.IMPLICIT_VAR),
EXPLIICT_SIMPLE("A", ExplicitKind.EXPLICIT),
EXPLIICT_SIMPLE_ARR1("A[]", ExplicitKind.EXPLICIT),
EXPLIICT_SIMPLE_ARR2("A[][]", ExplicitKind.EXPLICIT),
EXPLICIT_VARARGS("A...", ExplicitKind.EXPLICIT),
EXPLICIT_GENERIC1("A<X>", ExplicitKind.EXPLICIT),
EXPLICIT_GENERIC2("A<? extends X, ? super Y>", ExplicitKind.EXPLICIT),
EXPLICIT_GENERIC2_VARARGS("A<? extends X, ? super Y>...", ExplicitKind.EXPLICIT),
EXPLICIT_GENERIC2_ARR1("A<? extends X, ? super Y>[]", ExplicitKind.EXPLICIT),
EXPLICIT_GENERIC2_ARR2("A<? extends X, ? super Y>[][]", ExplicitKind.EXPLICIT);
enum ExplicitKind {
IMPLICIT,
IMPLICIT_VAR,
EXPLICIT;
}
String parameterType;
ExplicitKind explicitKind;
LambdaParameterKind(String parameterType, ExplicitKind ekind) {
this.parameterType = parameterType;
this.explicitKind = ekind;
} }
boolean isVarargs() { boolean isVarargs() {
@ -136,12 +155,23 @@ public class LambdaParserTest extends ComboInstance<LambdaParserTest> {
public String expand(String optParameter) { public String expand(String optParameter) {
return parameterType; return parameterType;
} }
ExplicitKind explicitKind(SourceKind sk) {
switch (explicitKind) {
case IMPLICIT_VAR:
return (sk == SourceKind.SOURCE_9) ?
ExplicitKind.EXPLICIT : ExplicitKind.IMPLICIT_VAR;
default:
return explicitKind;
}
}
} }
enum ModifierKind implements ComboParameter { enum ModifierKind implements ComboParameter {
NONE(""), NONE(""),
FINAL("final"), FINAL("final"),
PUBLIC("public"); PUBLIC("public"),
ANNO("@A");
String modifier; String modifier;
@ -152,7 +182,8 @@ public class LambdaParserTest extends ComboInstance<LambdaParserTest> {
boolean compatibleWith(LambdaParameterKind pk) { boolean compatibleWith(LambdaParameterKind pk) {
switch (this) { switch (this) {
case PUBLIC: return false; case PUBLIC: return false;
case FINAL: return pk != LambdaParameterKind.IMPLICIT; case ANNO:
case FINAL: return pk != LambdaParameterKind.IMPLICIT_1;
case NONE: return true; case NONE: return true;
default: throw new AssertionError("Invalid modifier kind " + this); default: throw new AssertionError("Invalid modifier kind " + this);
} }
@ -208,6 +239,7 @@ public class LambdaParserTest extends ComboInstance<LambdaParserTest> {
new ComboTestHelper<LambdaParserTest>() new ComboTestHelper<LambdaParserTest>()
.withFilter(LambdaParserTest::redundantTestFilter) .withFilter(LambdaParserTest::redundantTestFilter)
.withFilter(LambdaParserTest::badImplicitFilter) .withFilter(LambdaParserTest::badImplicitFilter)
.withDimension("SOURCE", (x, sk) -> x.sk = sk, SourceKind.values())
.withDimension("LAMBDA", (x, lk) -> x.lk = lk, LambdaKind.values()) .withDimension("LAMBDA", (x, lk) -> x.lk = lk, LambdaKind.values())
.withDimension("NAME", (x, name) -> x.pn = name, LambdaParameterName.values()) .withDimension("NAME", (x, name) -> x.pn = name, LambdaParameterName.values())
.withArrayDimension("TYPE", (x, type, idx) -> x.pks[idx] = type, 2, LambdaParameterKind.values()) .withArrayDimension("TYPE", (x, type, idx) -> x.pks[idx] = type, 2, LambdaParameterKind.values())
@ -221,6 +253,7 @@ public class LambdaParserTest extends ComboInstance<LambdaParserTest> {
ModifierKind[] mks = new ModifierKind[2]; ModifierKind[] mks = new ModifierKind[2];
LambdaKind lk; LambdaKind lk;
LambdaParameterName pn; LambdaParameterName pn;
SourceKind sk;
boolean badImplicitFilter() { boolean badImplicitFilter() {
return !(mks[0] != ModifierKind.NONE && lk.isShort()); return !(mks[0] != ModifierKind.NONE && lk.isShort());
@ -240,13 +273,15 @@ public class LambdaParserTest extends ComboInstance<LambdaParserTest> {
return true; return true;
} }
String template = "class Test {\n" + String template = "@interface A { }\n" +
"class Test {\n" +
" SAM s = #{EXPR};\n" + " SAM s = #{EXPR};\n" +
"}"; "}";
@Override @Override
public void doWork() throws IOException { public void doWork() throws IOException {
newCompilationTask() newCompilationTask()
.withOptions(Arrays.asList("-source", sk.sourceNumber))
.withSourceFromTemplate(template) .withSourceFromTemplate(template)
.parse(this::check); .parse(this::check);
} }
@ -256,7 +291,7 @@ public class LambdaParserTest extends ComboInstance<LambdaParserTest> {
(lk.arity() > 1 && !mks[1].compatibleWith(pks[1])); (lk.arity() > 1 && !mks[1].compatibleWith(pks[1]));
if (lk.arity() == 2 && if (lk.arity() == 2 &&
(pks[0].explicit() != pks[1].explicit() || (pks[0].explicitKind(sk) != pks[1].explicitKind(sk) ||
pks[0].isVarargs())) { pks[0].isVarargs())) {
errorExpected = true; errorExpected = true;
} }

View File

@ -60,7 +60,7 @@ class ParserTest<var extends AutoCloseable> {
List<? extends var> l2; //error List<? extends var> l2; //error
List<? super var> l3; //error List<? super var> l3; //error
try { try {
Function<var, String> f = (var x2) -> ""; //error Function<var, String> f = (var x2) -> ""; //ok
} catch (var ex) { } //error } catch (var ex) { } //error
} }

View File

@ -18,8 +18,7 @@ ParserTest.java:59:14: compiler.err.var.not.allowed.here
ParserTest.java:60:24: compiler.err.var.not.allowed.here ParserTest.java:60:24: compiler.err.var.not.allowed.here
ParserTest.java:61:22: compiler.err.var.not.allowed.here ParserTest.java:61:22: compiler.err.var.not.allowed.here
ParserTest.java:63:22: compiler.err.var.not.allowed.here ParserTest.java:63:22: compiler.err.var.not.allowed.here
ParserTest.java:63:40: compiler.err.var.not.allowed.here
ParserTest.java:64:18: compiler.err.var.not.allowed.here ParserTest.java:64:18: compiler.err.var.not.allowed.here
ParserTest.java:68:35: compiler.err.var.not.allowed.here ParserTest.java:68:35: compiler.err.var.not.allowed.here
ParserTest.java:69:22: compiler.err.var.not.allowed.here ParserTest.java:69:22: compiler.err.var.not.allowed.here
24 errors 23 errors

View File

@ -104,7 +104,7 @@ class TrialParser extends JavacParser {
while (token.kind != EOF) { while (token.kind != EOF) {
if (token.pos > 0 && token.pos <= endPosTable.errorEndPos) { if (token.pos > 0 && token.pos <= endPosTable.errorEndPos) {
// error recovery // error recovery
skip(true, false, false, false); skip(true, false, false, false, false);
if (token.kind == EOF) { if (token.kind == EOF) {
break; break;
} }

View File

@ -0,0 +1,17 @@
/*
* @test /nodynamiccopyright/
* @bug 8194892
* @summary add compiler support for local-variable syntax for lambda parameters
* @compile/fail/ref=VarInImplicitLambdaNegTest01.out -XDrawDiagnostics VarInImplicitLambdaNegTest01.java
*/
import java.util.function.*;
class VarInImplicitLambdaNegTest01 {
IntBinaryOperator f1 = (x, var y) -> x + y;
IntBinaryOperator f2 = (var x, y) -> x + y;
IntBinaryOperator f3 = (int x, var y) -> x + y;
IntBinaryOperator f4 = (int x, y) -> x + y;
BiFunction<String[], String, String> f5 = (var s1[], var s2) -> s2;
}

View File

@ -0,0 +1,6 @@
VarInImplicitLambdaNegTest01.java:11:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.var.and.implicit.not.allowed)
VarInImplicitLambdaNegTest01.java:12:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.var.and.implicit.not.allowed)
VarInImplicitLambdaNegTest01.java:13:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.var.and.explicit.not.allowed)
VarInImplicitLambdaNegTest01.java:14:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.implicit.and.explicit.not.allowed)
VarInImplicitLambdaNegTest01.java:16:54: compiler.err.var.not.allowed.array
5 errors