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)
$(ECHO) Creating jdk jimage
$(RM) -r $(JDK_IMAGE_DIR)
$(JLINK_TOOL) --add-modules $(JDK_MODULES_LIST) \
$(JLINK_JDK_EXTRA_OPTS) \
--output $(JDK_IMAGE_DIR)
$(call ExecuteWithLog, $(SUPPORT_OUTPUTDIR)/images/jdk, \
$(JLINK_TOOL) --add-modules $(JDK_MODULES_LIST) \
$(JLINK_JDK_EXTRA_OPTS) \
--output $(JDK_IMAGE_DIR) \
)
$(TOUCH) $@
$(JRE_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \
$(call DependOnVariable, JRE_MODULES_LIST) $(BASE_RELEASE_FILE)
$(ECHO) Creating jre jimage
$(RM) -r $(JRE_IMAGE_DIR)
$(JLINK_TOOL) --add-modules $(JRE_MODULES_LIST) \
$(JLINK_JRE_EXTRA_OPTS) \
--output $(JRE_IMAGE_DIR)
$(call ExecuteWithLog, $(SUPPORT_OUTPUTDIR)/images/jre, \
$(JLINK_TOOL) --add-modules $(JRE_MODULES_LIST) \
$(JLINK_JRE_EXTRA_OPTS) \
--output $(JRE_IMAGE_DIR) \
)
$(TOUCH) $@
@ -153,27 +157,33 @@ $(JRE_COMPACT1_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \
$(call DependOnVariable, JRE_COMPACT1_MODULES_LIST) $(BASE_RELEASE_FILE)
$(ECHO) Creating jre compact1 jimage
$(RM) -r $(JRE_COMPACT1_IMAGE_DIR)
$(JLINK_TOOL) --add-modules $(JRE_COMPACT1_MODULES_LIST) \
$(JLINK_JRE_EXTRA_OPTS) \
--output $(JRE_COMPACT1_IMAGE_DIR)
$(call ExecuteWithLog, $(SUPPORT_OUTPUTDIR)/images/jre_compact1, \
$(JLINK_TOOL) --add-modules $(JRE_COMPACT1_MODULES_LIST) \
$(JLINK_JRE_EXTRA_OPTS) \
--output $(JRE_COMPACT1_IMAGE_DIR) \
)
$(TOUCH) $@
$(JRE_COMPACT2_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \
$(call DependOnVariable, JRE_COMPACT2_MODULES_LIST) $(BASE_RELEASE_FILE)
$(ECHO) Creating jre compact2 jimage
$(RM) -r $(JRE_COMPACT2_IMAGE_DIR)
$(JLINK_TOOL) --add-modules $(JRE_COMPACT2_MODULES_LIST) \
$(JLINK_JRE_EXTRA_OPTS) \
--output $(JRE_COMPACT2_IMAGE_DIR)
$(call ExecuteWithLog, $(SUPPORT_OUTPUTDIR)/images/jre_compact2, \
$(JLINK_TOOL) --add-modules $(JRE_COMPACT2_MODULES_LIST) \
$(JLINK_JRE_EXTRA_OPTS) \
--output $(JRE_COMPACT2_IMAGE_DIR) \
)
$(TOUCH) $@
$(JRE_COMPACT3_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \
$(call DependOnVariable, JRE_COMPACT3_MODULES_LIST) $(BASE_RELEASE_FILE)
$(ECHO) Creating jre compact3 jimage
$(RM) -r $(JRE_COMPACT3_IMAGE_DIR)
$(JLINK_TOOL) --add-modules $(JRE_COMPACT3_MODULES_LIST) \
$(JLINK_JRE_EXTRA_OPTS) \
--output $(JRE_COMPACT3_IMAGE_DIR)
$(call ExecuteWithLog, $(SUPPORT_OUTPUTDIR)/images/jre_compact3, \
$(JLINK_TOOL) --add-modules $(JRE_COMPACT3_MODULES_LIST) \
$(JLINK_JRE_EXTRA_OPTS) \
--output $(JRE_COMPACT3_IMAGE_DIR) \
)
$(TOUCH) $@
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
# 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
$(LIBS_TARGETS): hotspot-$(JVM_VARIANT_MAIN)-libs
$(LIBS_TARGETS): $(JVM_MAIN_LIB_TARGETS)
$(LAUNCHER_TARGETS): java.base-libs
@ -719,8 +722,11 @@ else
java.base-jmod: jrtfs-jar $(filter-out java.base-jmod, $(JMOD_TARGETS))
endif
# Building java.base-jmod requires all of hotspot to be built.
java.base-jmod: hotspot
# If not already set, set the JVM target so that the JVM will be built.
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
# 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
# appropriate location otherwise jimage, jlink and jmod won't start. This
# 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
# When cross compiling and buildjdk is to be created, depend on creating the
# buildjdk instead of the default dependencies.
@ -822,8 +828,11 @@ else
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.
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: exploded-image buildtools-modules
@ -890,8 +899,10 @@ endif
################################################################################
# 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-jdk buildtools-hotspot
buildtools-jdk $(JVM_TOOLS_TARGETS)
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))
# Building java.base includes building all of hotspot.
java.base: hotspot
java.base: $(JVM_MAIN_TARGETS)
demos: demos-jdk
@ -1001,10 +1012,15 @@ endif
# This target builds the documentation image
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
test-image: prepare-test-image test-image-hotspot-jtreg-native \
test-image-jdk-jtreg-native test-image-failure-handler test-image-hotspot-gtest \
test-image-demos-jdk
test-image: prepare-test-image \
test-image-jdk-jtreg-native test-image-failure-handler \
test-image-demos-jdk $(JVM_TEST_IMAGE_TARGETS)
################################################################################
# all-images builds all our deliverables as images.
all-images: product-images test-image docs-image
@ -1143,6 +1159,8 @@ create-main-targets-include:
$(MAKESUPPORT_OUTPUTDIR)/main-targets.gmk
################################################################################
# Hook to include the corresponding custom file, if present.
$(eval $(call IncludeCustomExtension, Main-post.gmk))
.PHONY: $(ALL_TARGETS)

View File

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

View File

@ -685,6 +685,7 @@ NICE:=@NICE@
PANDOC:=@FIXPATH@ @PANDOC@
PATCH:=@PATCH@
PRINTF:=@PRINTF@
READLINK:=@READLINK@
RM:=@RM@
RMDIR:=@RMDIR@
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.
#
# 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
$(call MakeTargetDir)
$(RM) '$(call DecodeSpace, $@)'
$(CP) -fRP '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)'
if [ -n "`$(XATTR) -ls '$(call DecodeSpace, $@)'`" ]; then $(XATTR) -cs '$(call DecodeSpace, $@)'; fi
# Work around a weirdness with cp on Macosx. When copying a symlink, if
# 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
else
define install-file
@ -1000,6 +1010,7 @@ endif
# Param 2 - The command to run
ExecuteWithLog = \
$(call LogCmdlines, Exececuting: [$(strip $2)]) \
$(call MakeDir, $(dir $(strip $1))) \
$(call WriteFile, $2, $(strip $1).cmdline) \
( $(strip $2) > >($(TEE) $(strip $1).log) 2> >($(TEE) $(strip $1).log >&2) || \
( 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
($(CD) $(GENSRC_DIR)/META-INF/providers && \
p=""; \
for i in $$($(LS)); do \
for i in $$($(LS) | $(SORT)); do \
c=$$($(CAT) $$i | $(TR) -d '\n\r'); \
if test x$$p != x$$c; then \
if test x$$p != x; then \
@ -137,7 +137,7 @@ $(GENSRC_DIR)/module-info.java.extra: $(GENSRC_DIR)/_gensrc_proc_done
$(ECHO) " ;" >> $@; \
$(ECHO) "uses org.graalvm.compiler.options.OptionDescriptors;" >> $@; \
$(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) '/' '.'); \
$(ECHO) " $$c," >> $@; \
done; \

View File

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

View File

@ -1,6 +1,6 @@
#!/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.
#
# This code is free software; you can redistribute it and/or modify it
@ -94,7 +94,7 @@ diff_text() {
$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]\{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 '/\/\/ This file was generated AUTOMATICALLY from a template file.*/d' \
-e '/\/\/ java GenerateCharacter.*/d')
@ -102,9 +102,12 @@ diff_text() {
# Ignore date strings in class files.
# Anonymous lambda classes get randomly assigned counters in their names.
if test "x$SUFFIX" = "xclass"; then
if [ "$NAME" = "SystemModules.class" ]; then
# The SystemModules.class is not comparable. The way it is generated is
# too random. It can even be of different size for no apparent reason.
if [ "$NAME" = "SystemModules\$all.class" ] \
|| [ "$NAME" = "SystemModules\$default.class" ]; then
# 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=""
elif [ "$NAME" = "module-info.class" ]; then
# The module-info.class have several issues with random ordering of
@ -654,7 +657,6 @@ compare_bin_file() {
# pdb files.
PDB_DIRS="$(ls -d \
{$OTHER,$THIS}/support/modules_{cmds,libs}/{*,*/*} \
{$OTHER,$THIS}/support/demos/image/jvmti/*/lib \
{$OTHER,$THIS}/support/native/java.base/java_objs \
)"
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 '*.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
echo Libraries...
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 '*.sym' -o -name '*.idl' -o -name '*.h' -o -name '*.access' \
-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)
fi
@ -1219,7 +1227,7 @@ if [ "$STRIP_ALL" = "true" ] && [ -z "$STRIP" ]; then
STRIP_ALL=false
fi
COMPARE_ROOT=/tmp/cimages.$USER
COMPARE_ROOT=$OUTPUTDIR/compare-support
if [ "$CLEAN_OUTPUT" = "true" ]; then
echo Cleaning old output in $COMPARE_ROOT.
$RM -rf $COMPARE_ROOT

View File

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

View File

@ -35,6 +35,8 @@ import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.StringTokenizer;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
@ -702,9 +704,6 @@ public class Runtime {
*/
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.
* Calling this method suggests that the Java virtual machine expend
@ -724,7 +723,7 @@ public class Runtime {
* @see java.lang.Object#finalize()
*/
public void runFinalization() {
runFinalization0();
SharedSecrets.getJavaLangRefAccess().runFinalization();
}
/**

View File

@ -116,8 +116,24 @@ final class BootstrapMethodInvoker {
argv[0], argv[1]);
break;
case 3:
result = bootstrapMethod.invoke(caller, name, type,
argv[0], argv[1], argv[2]);
// 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,
argv[0], argv[1], argv[2]);
}
break;
case 4:
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
* CONSTANT_Integer boxes but does not intern them.
* 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 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
* 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.
*
* 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();
}
@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.
*
* 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>
* country (extension)*<br>
* </blockquote>
* depending on which fields are specified in the locale. If the
* language, script, country, and variant fields are all empty,
* this function returns the empty string.
* depending on which fields are specified in the locale. The field
* separator in the above parentheses, denoted as a comma character, may
* 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.
*/
@ -1971,9 +1972,10 @@ public final class Locale implements Cloneable, Serializable {
* script (country(, extension)*)<br>
* country (extension)*<br>
* </blockquote>
* depending on which fields are specified in the locale. If the
* language, script, country, and variant fields are all empty,
* this function returns the empty string.
* depending on which fields are specified in the locale. The field
* separator in the above parentheses, denoted as a comma character, may
* 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.
* @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.
*
* 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.
*/
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.
*
* 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();
}
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
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.
*
* 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;
/*
* This class defines the plain SocketImpl that is used for all
* Windows version lower than Vista. It adds support for IPv6 on
* 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.
* This class defines the plain SocketImpl that is used when
* the System property java.net.preferIPv4Stack is set to true.
*
* @author Chris Hegarty
*/
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;
class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl {
// true if this socket is exclusively bound
private final boolean exclusiveBind;
@ -85,43 +56,11 @@ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl
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 {
if (isClosedOrPending()) {
throw new SocketException("Socket Closed");
}
if (opt == SO_BINDADDR) {
if (fd != null && fd1 != null ) {
/* must be unbound or else bound to anyLocal */
return anyLocalBoundAddr;
}
InetAddressContainer in = new InetAddressContainer();
socketGetOption(opt, in);
return in.addr;
@ -161,7 +100,7 @@ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl
@Override
protected void close() throws IOException {
synchronized(fdLock) {
if (fd != null || fd1 != null) {
if (fd != null) {
if (!stream) {
ResourceManager.afterUdpClose();
}
@ -172,7 +111,6 @@ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl
closePending = true;
socketClose();
fd = null;
fd1 = null;
return;
} 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 */
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)
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.
*
* This code is free software; you can redistribute it and/or modify it
@ -37,14 +37,12 @@
static jfieldID IO_fd_fdID;
jfieldID psi_fdID;
jfieldID psi_fd1ID;
jfieldID psi_addressID;
jfieldID psi_portID;
jfieldID psi_localportID;
jfieldID psi_timeoutID;
jfieldID psi_trafficClassID;
jfieldID psi_serverSocketID;
jfieldID psi_lastfdID;
/*
* 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);
}
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
@ -90,15 +79,11 @@ Java_java_net_TwoStacksPlainSocketImpl_initProto(JNIEnv *env, jclass cls) {
psi_fdID = (*env)->GetFieldID(env, cls , "fd", "Ljava/io/FileDescriptor;");
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",
"Ljava/net/InetAddress;");
CHECK_NULL(psi_addressID);
psi_portID = (*env)->GetFieldID(env, cls, "port", "I");
CHECK_NULL(psi_portID);
psi_lastfdID = (*env)->GetFieldID(env, cls, "lastfd", "I");
CHECK_NULL(psi_lastfdID);
psi_localportID = (*env)->GetFieldID(env, cls, "localport", "I");
CHECK_NULL(psi_localportID);
psi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I");
@ -120,8 +105,8 @@ Java_java_net_TwoStacksPlainSocketImpl_initProto(JNIEnv *env, jclass cls) {
JNIEXPORT void JNICALL
Java_java_net_TwoStacksPlainSocketImpl_socketCreate(JNIEnv *env, jobject this,
jboolean stream) {
jobject fdObj, fd1Obj;
int fd, fd1;
jobject fdObj;
int fd;
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);
(*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 */
int family;
jint fd = -1, fd1 = -1;
jint fd = -1;
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 fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
SOCKETADDRESS sa;
@ -203,10 +158,6 @@ Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
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)) {
JNU_ThrowNullPointerException(env, "inet address argument is null.");
return;
@ -218,35 +169,15 @@ Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
}
family = sa.sa.sa_family;
if (family == AF_INET6) {
if (!ipv6_supported) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"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) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Destination unreachable");
return;
}
if (family != AF_INET) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Protocol family not supported");
}
if (fd == -1) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Destination unreachable");
return;
}
(*env)->SetObjectField(env, this, psi_fd1ID, NULL);
if (timeout <= 0) {
connect_res = connect(fd, &sa.sa, sizeof(SOCKETADDRESS));
@ -388,10 +319,9 @@ Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this,
jboolean exclBind) {
/* fdObj is the FileDescriptor field on this */
jobject fdObj, fd1Obj;
jobject fdObj;
/* fd is an int field on fdObj */
int fd, fd1 = -1, len = 0;
int ipv6_supported = ipv6_available();
int fd, len = 0;
/* family is an int field of iaObj */
int family;
@ -400,25 +330,21 @@ Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this,
SOCKETADDRESS sa;
fdObj = (*env)->GetObjectField(env, this, psi_fdID);
fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
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",
"Protocol family not supported");
return;
}
if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) {
if (IS_NULL(fdObj)) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Socket closed");
return;
} else {
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
if (ipv6_supported) {
fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
}
}
if (IS_NULL(iaObj)) {
JNU_ThrowNullPointerException(env, "inet address argument");
@ -429,42 +355,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this,
JNI_FALSE) != 0) {
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) {
NET_ThrowCurrent(env, "NET_Bind");
@ -482,7 +373,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this,
int len = sizeof(SOCKETADDRESS);
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");
return;
}
@ -505,14 +396,13 @@ Java_java_net_TwoStacksPlainSocketImpl_socketListen
{
/* this FileDescriptor fd field */
jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
jobject address;
/* fdObj's int fd field */
int fd = INVALID_SOCKET, fd1 = INVALID_SOCKET;
int fd = INVALID_SOCKET;
SOCKETADDRESS addr;
int addrlen;
if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) {
if (IS_NULL(fdObj)) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"socket closed");
return;
@ -521,10 +411,6 @@ Java_java_net_TwoStacksPlainSocketImpl_socketListen
if (!IS_NULL(fdObj)) {
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);
if (IS_NULL(address)) {
JNU_ThrowNullPointerException(env, "socket address");
@ -535,27 +421,15 @@ Java_java_net_TwoStacksPlainSocketImpl_socketListen
return;
}
if (addr.sa.sa_family == AF_INET || IN6ADDR_ISANY(&addr.sa6)) {
if (addr.sa.sa_family == AF_INET) {
/* listen on v4 */
if (listen(fd, count) == -1) {
NET_ThrowCurrent(env, "listen failed");
}
} else {
NET_SocketClose (fd);
NET_SocketClose(fd);
(*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 timeout = (*env)->GetIntField(env, this, psi_timeoutID);
jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
/* the FileDescriptor field on socket */
jobject socketFdObj;
/* cache the Inet4/6Address classes */
/* cache the Inet4 class */
static jclass inet4Cls;
static jclass inet6Cls;
/* the InetAddress field on socket */
jobject socketAddressObj;
/* the fd int field on fdObj */
jint fd=-1, fd1=-1;
jint fd=-1;
SOCKETADDRESS sa;
jint len;
int ret;
if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) {
if (IS_NULL(fdObj)) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Socket closed");
return;
}
if (!IS_NULL(fdObj)) {
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
}
if (!IS_NULL(fd1Obj)) {
fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
}
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
if (IS_NULL(socket)) {
JNU_ThrowNullPointerException(env, "socket is null");
return;
@ -611,72 +481,26 @@ Java_java_net_TwoStacksPlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
JNU_ThrowNullPointerException(env, "socket address or fd obj");
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) {
len = sizeof(struct sockaddr_in);
if (timeout) {
ret = NET_Timeout(fd, timeout);
if (ret == 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");
} else if (ret == -1) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
/* REMIND: SOCKET CLOSED PROBLEM */
/* NET_ThrowCurrent(env, "Accept failed"); */
return;
} else if (ret == -2) {
JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
"operation interrupted");
return;
}
if (fd2 == fd) { /* v4 */
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) {
ret = NET_Timeout(fd, timeout);
if (ret == 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
"Accept timed out");
return;
} else if (ret == -1) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
/* REMIND: SOCKET CLOSED PROBLEM */
/* NET_ThrowCurrent(env, "Accept failed"); */
return;
} else if (ret == -2) {
JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
"operation interrupted");
return;
}
}
}
fd = accept(fd, &sa.sa, &len);
if (fd < 0) {
/* REMIND: SOCKET CLOSED PROBLEM */
@ -692,65 +516,40 @@ Java_java_net_TwoStacksPlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, 0);
(*env)->SetIntField(env, socketFdObj, IO_fd_fdID, fd);
if (sa.sa.sa_family == AF_INET) {
if (inet4Cls == NULL) {
jclass c = (*env)->FindClass(env, "java/net/Inet4Address");
if (c != NULL) {
inet4Cls = (*env)->NewGlobalRef(env, c);
(*env)->DeleteLocalRef(env, c);
}
}
/*
* fill up the remote peer port and address in the new socket structure
*/
if (inet4Cls != NULL) {
socketAddressObj = (*env)->NewObject(env, inet4Cls, ia4_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;
}
setInetAddress_addr(env, socketAddressObj, ntohl(sa.sa4.sin_addr.s_addr));
setInetAddress_family(env, socketAddressObj, java_net_InetAddress_IPv4);
(*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);
if (sa.sa.sa_family != AF_INET) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Protocol family not supported");
return;
}
/* fields common to AF_INET and AF_INET6 */
if (inet4Cls == NULL) {
jclass c = (*env)->FindClass(env, "java/net/Inet4Address");
if (c != NULL) {
inet4Cls = (*env)->NewGlobalRef(env, c);
(*env)->DeleteLocalRef(env, c);
}
}
/*
* fill up the remote peer port and address in the new socket structure
*/
if (inet4Cls != NULL) {
socketAddressObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID);
} else {
socketAddressObj = NULL;
}
if (socketAddressObj == NULL) {
/*
* FindClass or NewObject failed so close connection and
* exit (there will be a pending exception).
*/
NET_SocketClose(fd);
return;
}
setInetAddress_addr(env, socketAddressObj, ntohl(sa.sa4.sin_addr.s_addr));
setInetAddress_family(env, socketAddressObj, java_net_InetAddress_IPv4);
(*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj);
port = ntohs ((u_short)GET_PORT(&sa));
(*env)->SetIntField(env, socket, psi_portID, (int)port);
port = (*env)->GetIntField(env, this, psi_localportID);
@ -795,10 +594,9 @@ Java_java_net_TwoStacksPlainSocketImpl_socketClose0(JNIEnv *env, jobject this,
jboolean useDeferredClose) {
jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID);
jint fd=-1, fd1=-1;
jint fd=-1;
if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) {
if (IS_NULL(fdObj)) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"socket already closed");
return;
@ -806,17 +604,10 @@ Java_java_net_TwoStacksPlainSocketImpl_socketClose0(JNIEnv *env, jobject this,
if (!IS_NULL(fdObj)) {
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
}
if (!IS_NULL(fd1Obj)) {
fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
}
if (fd != -1) {
(*env)->SetIntField(env, fdObj, IO_fd_fdID, -1);
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
(JNIEnv *env, jobject this, jint cmd, jboolean on, jobject value)
{
int fd, fd1;
int fd;
int level = 0, optname = 0, optlen = 0;
union {
int i;
@ -843,8 +634,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketNativeSetOption
* Get SOCKET and check that it hasn't been closed
*/
fd = getFD(env, this);
fd1 = getFD1(env, this);
if (fd < 0 && fd1 < 0) {
if (fd < 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
return;
}
@ -901,12 +691,6 @@ Java_java_net_TwoStacksPlainSocketImpl_socketNativeSetOption
return;
}
}
if (fd1 != -1) {
if (setsockopt(fd1, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
sizeof(timeout)) < 0) {
NET_ThrowCurrent(env, "setsockopt SO_RCVTIMEO");
}
}
}
return;
}
@ -980,12 +764,6 @@ Java_java_net_TwoStacksPlainSocketImpl_socketNativeSetOption
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
(JNIEnv *env, jobject this, jint opt, jobject iaContainerObj)
{
int fd, fd1;
int fd;
int level = 0, optname = 0, optlen = 0;
union {
int i;
@ -1009,18 +787,12 @@ Java_java_net_TwoStacksPlainSocketImpl_socketGetOption
* Get SOCKET and check it hasn't been closed
*/
fd = getFD(env, this);
fd1 = getFD1(env, this);
memset((char *)&optval, 0, sizeof(optval));
if (fd < 0 && fd1 < 0) {
if (fd < 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
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
@ -1035,13 +807,6 @@ Java_java_net_TwoStacksPlainSocketImpl_socketGetOption
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) {
JNU_ThrowByNameWithMessageAndLastError
(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.util.*;
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.Warning;
import com.sun.tools.javac.util.JCDiagnostic.Fragment;
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.ASSERT;
@ -290,9 +289,31 @@ public class JavacParser implements Parser {
/** 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) {
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:
nextToken();
return;
@ -1076,7 +1097,8 @@ public class JavacParser implements Parser {
break;
case LPAREN:
if (typeArgs == null && (mode & EXPR) != 0) {
ParensResult pres = analyzeParens();
LambdaClassfier lambdaClassifier = new LambdaClassfier();
ParensResult pres = analyzeParens(lambdaClassifier);
switch (pres) {
case CAST:
accept(LPAREN);
@ -1095,9 +1117,15 @@ public class JavacParser implements Parser {
mode = EXPR;
JCExpression t1 = term3();
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 EXPLICIT_LAMBDA:
t = lambdaExpressionOrStatement(true, pres == ParensResult.EXPLICIT_LAMBDA, pos);
case IMPLICIT_LAMBDA_ALL_VAR:
t = lambdaExpressionOrStatement(true, pres != ParensResult.IMPLICIT_LAMBDA, pos);
break;
default: //PARENS
accept(LPAREN);
@ -1509,15 +1537,17 @@ public class JavacParser implements Parser {
* matching '&gt;' and see if the subsequent terminal is either '.' or '::'.
*/
@SuppressWarnings("fallthrough")
ParensResult analyzeParens() {
ParensResult analyzeParens(LambdaClassfier lambdaClassifier) {
int depth = 0;
boolean type = false;
outer: for (int lookahead = 0 ; ; lookahead++) {
TokenKind tk = S.token(lookahead).kind;
Token lookaheadToken = S.token(lookahead);
TokenKind tk = lookaheadToken.kind;
switch (tk) {
case COMMA:
type = true;
case EXTENDS: case SUPER: case DOT: case AMP:
break;
case FINAL: case EXTENDS: case SUPER: case DOT: case AMP:
//skip
break;
case QUES:
@ -1534,7 +1564,8 @@ public class JavacParser implements Parser {
return ParensResult.CAST;
} else if (peekToken(lookahead, LAX_IDENTIFIER)) {
//Type, Identifier/'_'/'assert'/'enum' -> explicit lambda
return ParensResult.EXPLICIT_LAMBDA;
lambdaClassifier.addExplicitParameter();
lookahead++; //skip Identifier
}
break;
case LPAREN:
@ -1547,24 +1578,29 @@ public class JavacParser implements Parser {
}
break;
case RPAREN:
// if we have seen something that looks like a type,
// then it's a cast expression
if (type) return ParensResult.CAST;
// otherwise, disambiguate cast vs. parenthesized expression
// based on subsequent token.
switch (S.token(lookahead + 1).kind) {
/*case PLUSPLUS: case SUBSUB: */
case BANG: case TILDE:
case LPAREN: case THIS: case SUPER:
case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
case TRUE: case FALSE: case NULL:
case NEW: case IDENTIFIER: case ASSERT: case ENUM: case UNDERSCORE:
case BYTE: case SHORT: case CHAR: case INT:
case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
return ParensResult.CAST;
default:
return ParensResult.PARENS;
if (peekToken(lookahead, ARROW)) {
//this is a lambda
return lambdaClassifier.result();
} else {
// if we have seen something that looks like a type,
// then it's a cast expression
if (type) return ParensResult.CAST;
// otherwise, disambiguate cast vs. parenthesized expression
// based on subsequent token.
switch (S.token(lookahead + 1).kind) {
/*case PLUSPLUS: case SUBSUB: */
case BANG: case TILDE:
case LPAREN: case THIS: case SUPER:
case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
case TRUE: case FALSE: case NULL:
case NEW: case IDENTIFIER: case ASSERT: case ENUM: case UNDERSCORE:
case BYTE: case SHORT: case CHAR: case INT:
case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
return ParensResult.CAST;
default:
return ParensResult.PARENS;
}
}
case UNDERSCORE:
case ASSERT:
@ -1572,17 +1608,23 @@ public class JavacParser implements Parser {
case IDENTIFIER:
if (peekToken(lookahead, LAX_IDENTIFIER)) {
// Identifier, Identifier/'_'/'assert'/'enum' -> explicit lambda
return ParensResult.EXPLICIT_LAMBDA;
} else if (peekToken(lookahead, RPAREN, ARROW)) {
// Identifier, ')' '->' -> implicit lambda
return ParensResult.IMPLICIT_LAMBDA;
if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source) &&
lookaheadToken.name() == names.var) {
lambdaClassifier.addImplicitVarParameter();
} else {
lambdaClassifier.addExplicitParameter();
}
lookahead++; //skip Identifier
} else if ((!type && peekToken(lookahead, COMMA)) || peekToken(lookahead, RPAREN)) {
lambdaClassifier.addImplicitParameter();
}
type = false;
break;
case FINAL:
case ELLIPSIS:
//those can only appear in explicit lambdas
return ParensResult.EXPLICIT_LAMBDA;
//those can only appear in explicit, non-var, lambdas
lambdaClassifier.addExplicitParameter();
lookahead++; //skip Identifier
break;
case MONKEYS_AT:
type = true;
lookahead += 1; //skip '@'
@ -1614,7 +1656,9 @@ public class JavacParser implements Parser {
case LBRACKET:
if (peekToken(lookahead, RBRACKET, LAX_IDENTIFIER)) {
// '[', ']', Identifier/'_'/'assert'/'enum' -> explicit lambda
return ParensResult.EXPLICIT_LAMBDA;
lambdaClassifier.addExplicitParameter();
lookahead += 2; //skip ']' Identifier
break;
} else if (peekToken(lookahead, RBRACKET, RPAREN) ||
peekToken(lookahead, RBRACKET, AMP)) {
// '[', ']', ')' -> cast
@ -1643,12 +1687,15 @@ public class JavacParser implements Parser {
// '>', '&' -> cast
return ParensResult.CAST;
} else if (peekToken(lookahead, LAX_IDENTIFIER, COMMA) ||
peekToken(lookahead, LAX_IDENTIFIER, RPAREN, ARROW) ||
peekToken(lookahead, ELLIPSIS)) {
peekToken(lookahead, LAX_IDENTIFIER, RPAREN, ARROW)) {
// '>', Identifier/'_'/'assert'/'enum', ',' -> explicit lambda
// '>', Identifier/'_'/'assert'/'enum', ')', '->' -> explicit lambda
lambdaClassifier.addExplicitParameter();
lookahead++; //skip Identifier
break;
} else if (peekToken(lookahead, ELLIPSIS)) {
// '>', '...' -> 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,
//(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 */
protected Filter<TokenKind> LAX_IDENTIFIER = t -> t == IDENTIFIER || t == UNDERSCORE || t == ASSERT || t == ENUM;
@ -1673,7 +1775,15 @@ public class JavacParser implements Parser {
CAST,
EXPLICIT_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) {
@ -1896,6 +2006,9 @@ public class JavacParser implements Parser {
List<JCAnnotation> nextLevelAnnotations = typeAnnotationsOpt();
if (token.kind == LBRACKET) {
if (t == null) {
log.error(token.pos, Errors.VarNotAllowedArray);
}
int pos = token.pos;
nextToken();
t = bracketsOptCont(t, pos, nextLevelAnnotations);
@ -2294,7 +2407,7 @@ public class JavacParser implements Parser {
if (token.pos == lastErrPos)
return stats.toList();
if (token.pos <= endPosTable.errorEndPos) {
skip(false, true, true, true);
skip(false, true, true, true, false);
lastErrPos = token.pos;
}
stats.addAll(stat);
@ -3133,7 +3246,7 @@ public class JavacParser implements Parser {
while (token.kind != EOF) {
if (token.pos <= endPosTable.errorEndPos) {
// error recovery
skip(checkForImports, false, false, false);
skip(checkForImports, false, false, false, false);
if (token.kind == EOF)
break;
}
@ -3270,7 +3383,7 @@ public class JavacParser implements Parser {
defs.append(toP(F.at(pos).Provides(serviceName, implNames)));
} else {
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) {
nextToken();
@ -3475,7 +3588,7 @@ public class JavacParser implements Parser {
false));
if (token.pos <= endPosTable.errorEndPos) {
// error recovery
skip(false, true, true, false);
skip(false, true, true, false, false);
}
}
}
@ -3537,7 +3650,7 @@ public class JavacParser implements Parser {
accept(LBRACE);
if (token.pos <= endPosTable.errorEndPos) {
// error recovery
skip(false, true, false, false);
skip(false, true, false, false, false);
if (token.kind == LBRACE)
nextToken();
}
@ -3546,7 +3659,7 @@ public class JavacParser implements Parser {
defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
if (token.pos <= endPosTable.errorEndPos) {
// error recovery
skip(false, true, true, false);
skip(false, true, true, false, false);
}
}
accept(RBRACE);
@ -3713,7 +3826,7 @@ public class JavacParser implements Parser {
accept(SEMI);
if (token.pos <= endPosTable.errorEndPos) {
// error recovery
skip(false, true, false, false);
skip(false, true, false, false, false);
if (token.kind == LBRACE) {
body = block();
}
@ -3947,7 +4060,7 @@ public class JavacParser implements Parser {
// need to distinguish between vararg annos and array annos
// look at typeAnnotationsPushedBack comment
this.permitTypeAnnotationsPushBack = true;
JCExpression type = parseType();
JCExpression type = parseType(lambdaParameter);
this.permitTypeAnnotationsPushBack = false;
if (token.kind == ELLIPSIS) {
@ -3964,6 +4077,10 @@ public class JavacParser implements Parser {
}
typeAnnotationsPushedBack = List.nil();
}
if (lambdaParameter && isRestrictedLocalVarTypeName(type)) {
//implicit lambda parameter type (with 'var')
type = null;
}
return variableDeclaratorId(mods, type, lambdaParameter);
}

View File

@ -1229,6 +1229,20 @@ compiler.err.var.not.allowed.array=\
compiler.err.var.not.allowed.compound=\
''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=\
variable initializer is ''null''

View File

@ -386,7 +386,7 @@ class JImageTask {
for (File file : options.jimages) {
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())) {
@ -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.not.a.dir=not a directory: {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.option.unsupported={0} not supported: {1}
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.function.Predicate;
import jdk.tools.jlink.plugin.Plugin;
import jdk.tools.jlink.plugin.PluginException;
import jdk.tools.jlink.plugin.ResourcePool;
import jdk.tools.jlink.plugin.ResourcePoolBuilder;
import jdk.tools.jlink.plugin.ResourcePoolEntry;
@ -49,7 +50,13 @@ public final class ExcludePlugin implements Plugin {
public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
in.transformAndCopy((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;
}, out);

View File

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

View File

@ -464,9 +464,8 @@ tools/pack200/CommandLineTests.java 8059906 generic-
tools/launcher/FXLauncherTest.java 8068049 linux-all,macosx-all
tools/jimage/JImageExtractTest.java 8170120 generic-all
tools/jimage/JImageListTest.java 8170120 generic-all
tools/jimage/JImageVerifyTest.java 8170120 generic-all
tools/jimage/JImageExtractTest.java 8198405 windows-all
tools/jimage/JImageListTest.java 8198405 windows-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.
*
* 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());
Files.createFile(Paths.get(tmp.toString(), ".not_empty"));
jimage("extract", "--dir", tmp.toString(), getImagePath())
.assertFailure()
.assertShowsError();
.assertSuccess()
.resultChecker(r -> {
assertTrue(r.output.isEmpty(), "Output is not expected");
});
}
public void testExtractToFile() throws IOException {

View File

@ -57,7 +57,7 @@ public class JImageListTest extends JImageCliTest {
.map(s -> s.substring(s.indexOf(':') + 1).trim())
.collect(Collectors.toList());
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())
.collect(Collectors.toList());
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)
.filter(s -> { return !s.startsWith("Module: ") && !s.startsWith("Offset"); })

View File

@ -43,6 +43,7 @@ import tests.JImageGenerator;
* @test
* @summary Test image creation
* @bug 8189777
* @bug 8194922
* @author Jean-Francois Denise
* @requires (vm.compMode != "Xcomp" & os.maxMemory >= 2g)
* @library ../lib
@ -276,6 +277,15 @@ public class JLinkTest {
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
{
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:43: compiler.err.expected: ';'
T8131742.java:8:43: compiler.err.expected: token.identifier
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.
*
* This code is free software; you can redistribute it and/or modify it
@ -40,6 +40,7 @@
*/
import java.io.IOException;
import java.util.Arrays;
import combo.ComboInstance;
import combo.ComboParameter;
@ -105,26 +106,44 @@ public class LambdaParserTest extends ComboInstance<LambdaParserTest> {
}
}
enum SourceKind {
SOURCE_9("9"),
SOURCE_10("10");
String sourceNumber;
SourceKind(String sourceNumber) {
this.sourceNumber = sourceNumber;
}
}
enum LambdaParameterKind implements ComboParameter {
IMPLICIT(""),
EXPLIICT_SIMPLE("A"),
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;
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);
LambdaParameterKind(String parameterType) {
this.parameterType = parameterType;
enum ExplicitKind {
IMPLICIT,
IMPLICIT_VAR,
EXPLICIT;
}
boolean explicit() {
return this != IMPLICIT;
String parameterType;
ExplicitKind explicitKind;
LambdaParameterKind(String parameterType, ExplicitKind ekind) {
this.parameterType = parameterType;
this.explicitKind = ekind;
}
boolean isVarargs() {
@ -136,12 +155,23 @@ public class LambdaParserTest extends ComboInstance<LambdaParserTest> {
public String expand(String optParameter) {
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 {
NONE(""),
FINAL("final"),
PUBLIC("public");
PUBLIC("public"),
ANNO("@A");
String modifier;
@ -152,7 +182,8 @@ public class LambdaParserTest extends ComboInstance<LambdaParserTest> {
boolean compatibleWith(LambdaParameterKind pk) {
switch (this) {
case PUBLIC: return false;
case FINAL: return pk != LambdaParameterKind.IMPLICIT;
case ANNO:
case FINAL: return pk != LambdaParameterKind.IMPLICIT_1;
case NONE: return true;
default: throw new AssertionError("Invalid modifier kind " + this);
}
@ -208,6 +239,7 @@ public class LambdaParserTest extends ComboInstance<LambdaParserTest> {
new ComboTestHelper<LambdaParserTest>()
.withFilter(LambdaParserTest::redundantTestFilter)
.withFilter(LambdaParserTest::badImplicitFilter)
.withDimension("SOURCE", (x, sk) -> x.sk = sk, SourceKind.values())
.withDimension("LAMBDA", (x, lk) -> x.lk = lk, LambdaKind.values())
.withDimension("NAME", (x, name) -> x.pn = name, LambdaParameterName.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];
LambdaKind lk;
LambdaParameterName pn;
SourceKind sk;
boolean badImplicitFilter() {
return !(mks[0] != ModifierKind.NONE && lk.isShort());
@ -240,13 +273,15 @@ public class LambdaParserTest extends ComboInstance<LambdaParserTest> {
return true;
}
String template = "class Test {\n" +
" SAM s = #{EXPR};\n" +
"}";
String template = "@interface A { }\n" +
"class Test {\n" +
" SAM s = #{EXPR};\n" +
"}";
@Override
public void doWork() throws IOException {
newCompilationTask()
.withOptions(Arrays.asList("-source", sk.sourceNumber))
.withSourceFromTemplate(template)
.parse(this::check);
}
@ -256,7 +291,7 @@ public class LambdaParserTest extends ComboInstance<LambdaParserTest> {
(lk.arity() > 1 && !mks[1].compatibleWith(pks[1]));
if (lk.arity() == 2 &&
(pks[0].explicit() != pks[1].explicit() ||
(pks[0].explicitKind(sk) != pks[1].explicitKind(sk) ||
pks[0].isVarargs())) {
errorExpected = true;
}

View File

@ -60,7 +60,7 @@ class ParserTest<var extends AutoCloseable> {
List<? extends var> l2; //error
List<? super var> l3; //error
try {
Function<var, String> f = (var x2) -> ""; //error
Function<var, String> f = (var x2) -> ""; //ok
} 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:61: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:68:35: 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) {
if (token.pos > 0 && token.pos <= endPosTable.errorEndPos) {
// error recovery
skip(true, false, false, false);
skip(true, false, false, false, false);
if (token.kind == EOF) {
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