--- a/doc/testing.html Sat Mar 23 15:11:51 2019 +0000
+++ b/doc/testing.html Sat Mar 30 09:30:03 2019 +0000
@@ -39,7 +39,7 @@
<h2 id="using-make-test-the-run-test-framework">Using "make test" (the run-test framework)</h2>
<p>This new way of running tests is developer-centric. It assumes that you have built a JDK locally and want to test it. Running common test targets is simple, and more complex ad-hoc combination of tests is possible. The user interface is forgiving, and clearly report errors it cannot resolve.</p>
<p>The main target <code>test</code> uses the jdk-image as the tested product. There is also an alternate target <code>exploded-test</code> that uses the exploded image instead. Not all tests will run successfully on the exploded image, but using this target can greatly improve rebuild times for certain workflows.</p>
-<p>Previously, <code>make test</code> was used invoke an old system for running test, and <code>make run-test</code> was used for the new test framework. For backward compatibility with scripts and muscle memory, <code>run-test</code> (and variants like <code>exploded-run-test</code> or <code>run-test-tier1</code>) are kept as aliases. The old system can still be accessed for some time using <code>cd test && make</code>.</p>
+<p>Previously, <code>make test</code> was used to invoke an old system for running tests, and <code>make run-test</code> was used for the new test framework. For backward compatibility with scripts and muscle memory, <code>run-test</code> (and variants like <code>exploded-run-test</code> or <code>run-test-tier1</code>) are kept as aliases.</p>
<p>Some example command-lines:</p>
<pre><code>$ make test-tier1
$ make test-jdk_lang JTREG="JOBS=8"
--- a/doc/testing.md Sat Mar 23 15:11:51 2019 +0000
+++ b/doc/testing.md Sat Mar 30 09:30:03 2019 +0000
@@ -12,11 +12,10 @@
instead. Not all tests will run successfully on the exploded image, but using
this target can greatly improve rebuild times for certain workflows.
-Previously, `make test` was used invoke an old system for running test, and
+Previously, `make test` was used to invoke an old system for running tests, and
`make run-test` was used for the new test framework. For backward compatibility
with scripts and muscle memory, `run-test` (and variants like
-`exploded-run-test` or `run-test-tier1`) are kept as aliases. The old system
-can still be accessed for some time using `cd test && make`.
+`exploded-run-test` or `run-test-tier1`) are kept as aliases.
Some example command-lines:
--- a/make/autoconf/lib-x11.m4 Sat Mar 23 15:11:51 2019 +0000
+++ b/make/autoconf/lib-x11.m4 Sat Mar 30 09:30:03 2019 +0000
@@ -119,7 +119,7 @@
if test "x$X11_HEADERS_OK" = xno; then
HELP_MSG_MISSING_DEPENDENCY([x11])
- AC_MSG_ERROR([Could not find all X11 headers (shape.h Xrender.h Xrander.h XTest.h Intrinsic.h). $HELP_MSG])
+ AC_MSG_ERROR([Could not find all X11 headers (shape.h Xrender.h Xrandr.h XTest.h Intrinsic.h). $HELP_MSG])
fi
# If XLinearGradient isn't available in Xrender.h, signal that it needs to be
--- a/make/autoconf/toolchain_windows.m4 Sat Mar 23 15:11:51 2019 +0000
+++ b/make/autoconf/toolchain_windows.m4 Sat Mar 30 09:30:03 2019 +0000
@@ -87,6 +87,7 @@
VS_VS_PLATFORM_NAME_2017="v141"
VS_SDK_PLATFORM_NAME_2017=
VS_SUPPORTED_2017=true
+VS_TOOLSET_SUPPORTED_2017=true
################################################################################
@@ -177,6 +178,15 @@
# build environment and assigns it to VS_ENV_CMD
AC_DEFUN([TOOLCHAIN_FIND_VISUAL_STUDIO_BAT_FILE],
[
+ # VS2017 provides the option to install previous minor versions of the MSVC
+ # toolsets. It is not possible to directly download earlier minor versions of
+ # VS2017 and in order to build with a previous minor compiler toolset version,
+ # it is now possible to compile with earlier minor versions by passing
+ # -vcvars_ver=<toolset_version> argument to vcvarsall.bat.
+ AC_ARG_WITH(msvc-toolset-version, [AS_HELP_STRING([--with-msvc-toolset-version],
+ [specific MSVC toolset version to use, passed as -vcvars_ver argument to
+ pass to vcvarsall.bat (Windows only)])])
+
VS_VERSION="$1"
eval VS_COMNTOOLS_VAR="\${VS_ENVVAR_${VS_VERSION}}"
eval VS_COMNTOOLS="\$${VS_COMNTOOLS_VAR}"
@@ -184,6 +194,7 @@
eval VS_EDITIONS="\${VS_EDITIONS_${VS_VERSION}}"
eval SDK_INSTALL_DIR="\${VS_SDK_INSTALLDIR_${VS_VERSION}}"
eval VS_ENV_ARGS="\${VS_ENV_ARGS_${VS_VERSION}}"
+ eval VS_TOOLSET_SUPPORTED="\${VS_TOOLSET_SUPPORTED_${VS_VERSION}}"
# When using --with-tools-dir, assume it points to the correct and default
# version of Visual Studio or that --with-toolchain-version was also set.
@@ -240,6 +251,12 @@
TOOLCHAIN_CHECK_POSSIBLE_WIN_SDK_ROOT([${VS_VERSION}],
[C:/Program Files (x86)/$SDK_INSTALL_DIR], [well-known name])
fi
+
+ if test "x$VS_TOOLSET_SUPPORTED" != x; then
+ if test "x$with_msvc_toolset_version" != x; then
+ VS_ENV_ARGS="$VS_ENV_ARGS -vcvars_ver=$with_msvc_toolset_version"
+ fi
+ fi
])
################################################################################
@@ -423,6 +440,8 @@
>> $EXTRACT_VC_ENV_BAT_FILE
$ECHO 'echo VCINSTALLDIR="%VCINSTALLDIR% " >> set-vs-env.sh' \
>> $EXTRACT_VC_ENV_BAT_FILE
+ $ECHO 'echo VCToolsRedistDir="%VCToolsRedistDir% " >> set-vs-env.sh' \
+ >> $EXTRACT_VC_ENV_BAT_FILE
$ECHO 'echo WindowsSdkDir="%WindowsSdkDir% " >> set-vs-env.sh' \
>> $EXTRACT_VC_ENV_BAT_FILE
$ECHO 'echo WINDOWSSDKDIR="%WINDOWSSDKDIR% " >> set-vs-env.sh' \
@@ -440,6 +459,8 @@
>> $EXTRACT_VC_ENV_BAT_FILE
$ECHO "$WINPATH_BASH -c 'echo VCINSTALLDIR="'\"$VCINSTALLDIR \" >> set-vs-env.sh' \
>> $EXTRACT_VC_ENV_BAT_FILE
+ $ECHO "$WINPATH_BASH -c 'echo VCToolsRedistDir="'\"$VCToolsRedistDir \" >> set-vs-env.sh' \
+ >> $EXTRACT_VC_ENV_BAT_FILE
$ECHO "$WINPATH_BASH -c 'echo WindowsSdkDir="'\"$WindowsSdkDir \" >> set-vs-env.sh' \
>> $EXTRACT_VC_ENV_BAT_FILE
$ECHO "$WINPATH_BASH -c 'echo WINDOWSSDKDIR="'\"$WINDOWSSDKDIR \" >> set-vs-env.sh' \
@@ -517,6 +538,7 @@
VS_INCLUDE=`$ECHO "$VS_INCLUDE" | $SED -e 's/\\\\*;* *$//'`
VS_LIB=`$ECHO "$VS_LIB" | $SED 's/\\\\*;* *$//'`
VCINSTALLDIR=`$ECHO "$VCINSTALLDIR" | $SED 's/\\\\* *$//'`
+ VCToolsRedistDir=`$ECHO "$VCToolsRedistDir" | $SED 's/\\\\* *$//'`
WindowsSdkDir=`$ECHO "$WindowsSdkDir" | $SED 's/\\\\* *$//'`
WINDOWSSDKDIR=`$ECHO "$WINDOWSSDKDIR" | $SED 's/\\\\* *$//'`
if test -z "$WINDOWSSDKDIR"; then
@@ -638,11 +660,13 @@
POSSIBLE_MSVC_DLL="$CYGWIN_VC_INSTALL_DIR/redist/x86/Microsoft.VC${VS_VERSION_INTERNAL}.CRT/$DLL_NAME"
fi
else
+ CYGWIN_VC_TOOLS_REDIST_DIR="$VCToolsRedistDir"
+ BASIC_FIXUP_PATH(CYGWIN_VC_TOOLS_REDIST_DIR)
# Probe: Using well-known location from VS 2017
if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
- POSSIBLE_MSVC_DLL="`ls $CYGWIN_VC_INSTALL_DIR/Redist/MSVC/*/x64/Microsoft.VC${VS_VERSION_INTERNAL}.CRT/$DLL_NAME`"
+ POSSIBLE_MSVC_DLL="`ls $CYGWIN_VC_TOOLS_REDIST_DIR/x64/Microsoft.VC${VS_VERSION_INTERNAL}.CRT/$DLL_NAME`"
else
- POSSIBLE_MSVC_DLL="`ls $CYGWIN_VC_INSTALL_DIR/Redist/MSVC/*/x86/Microsoft.VC${VS_VERSION_INTERNAL}.CRT/$DLL_NAME`"
+ POSSIBLE_MSVC_DLL="`ls $CYGWIN_VC_TOOLS_REDIST_DIR/x86/Microsoft.VC${VS_VERSION_INTERNAL}.CRT/$DLL_NAME`"
fi
fi
# In case any of the above finds more than one file, loop over them.
--- a/make/autoconf/version-numbers Sat Mar 23 15:11:51 2019 +0000
+++ b/make/autoconf/version-numbers Sat Mar 30 09:30:03 2019 +0000
@@ -35,7 +35,7 @@
DEFAULT_VERSION_DATE=2019-09-17
DEFAULT_VERSION_CLASSFILE_MAJOR=57 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`"
DEFAULT_VERSION_CLASSFILE_MINOR=0
-DEFAULT_ACCEPTABLE_BOOT_VERSIONS="11 12 13"
+DEFAULT_ACCEPTABLE_BOOT_VERSIONS="12 13"
LAUNCHER_NAME=openjdk
PRODUCT_NAME=OpenJDK
--- a/make/conf/jib-profiles.js Sat Mar 23 15:11:51 2019 +0000
+++ b/make/conf/jib-profiles.js Sat Mar 30 09:30:03 2019 +0000
@@ -365,7 +365,8 @@
};
};
- common.boot_jdk_version = "11";
+ common.boot_jdk_version = "12";
+ common.boot_jdk_build_number = "33";
common.boot_jdk_home = input.get("boot_jdk", "install_path") + "/jdk-"
+ common.boot_jdk_version
+ (input.build_os == "macosx" ? ".jdk/Contents/Home" : "");
@@ -980,7 +981,7 @@
server: "jpg",
product: "jdk",
version: common.boot_jdk_version,
- build_number: "28",
+ build_number: common.boot_jdk_build_number,
file: "bundles/" + boot_jdk_platform + "/jdk-" + common.boot_jdk_version + "_"
+ boot_jdk_platform + "_bin" + boot_jdk_ext,
configure_args: "--with-boot-jdk=" + common.boot_jdk_home,
--- a/make/data/publicsuffixlist/VERSION Sat Mar 23 15:11:51 2019 +0000
+++ b/make/data/publicsuffixlist/VERSION Sat Mar 30 09:30:03 2019 +0000
@@ -1,2 +1,2 @@
-Github: https://raw.githubusercontent.com/publicsuffix/list/2225db8d9f4a2a27ec697c883360632fa0c16261/public_suffix_list.dat
-Date: 2018-05-24
+Github: https://raw.githubusercontent.com/publicsuffix/list/ce0d1a5fba657e55adea3abde4b7f1e50636ff10/public_suffix_list.dat
+Date: 2019-01-28
--- a/make/data/publicsuffixlist/public_suffix_list.dat Sat Mar 23 15:11:51 2019 +0000
+++ b/make/data/publicsuffixlist/public_suffix_list.dat Sat Mar 30 09:30:03 2019 +0000
@@ -381,8 +381,13 @@
net.bm
org.bm
-// bn : https://en.wikipedia.org/wiki/.bn
-*.bn
+// bn : http://www.bnnic.bn/faqs
+bn
+com.bn
+edu.bn
+gov.bn
+net.bn
+org.bn
// bo : https://nic.bo/delegacion2015.php#h-1.10
bo
@@ -546,6 +551,7 @@
not.br
ntr.br
odo.br
+ong.br
org.br
osasco.br
palmas.br
@@ -1239,7 +1245,7 @@
utazas.hu
video.hu
-// id : https://register.pandi.or.id/
+// id : https://pandi.id/en/domain/registration-requirements/
id
ac.id
biz.id
@@ -1250,6 +1256,7 @@
my.id
net.id
or.id
+ponpes.id
sch.id
web.id
@@ -1407,9 +1414,9 @@
tos.it
toscana.it
trentin-sud-tirol.it
-trentin-süd-tirol.it
+trentin-süd-tirol.it
trentin-sudtirol.it
-trentin-südtirol.it
+trentin-südtirol.it
trentin-sued-tirol.it
trentin-suedtirol.it
trentino-a-adige.it
@@ -1419,9 +1426,9 @@
trentino-s-tirol.it
trentino-stirol.it
trentino-sud-tirol.it
-trentino-süd-tirol.it
+trentino-süd-tirol.it
trentino-sudtirol.it
-trentino-südtirol.it
+trentino-südtirol.it
trentino-sued-tirol.it
trentino-suedtirol.it
trentino.it
@@ -1432,15 +1439,15 @@
trentinos-tirol.it
trentinostirol.it
trentinosud-tirol.it
-trentinosüd-tirol.it
+trentinosüd-tirol.it
trentinosudtirol.it
-trentinosüdtirol.it
+trentinosüdtirol.it
trentinosued-tirol.it
trentinosuedtirol.it
trentinsud-tirol.it
-trentinsüd-tirol.it
+trentinsüd-tirol.it
trentinsudtirol.it
-trentinsüdtirol.it
+trentinsüdtirol.it
trentinsued-tirol.it
trentinsuedtirol.it
tuscany.it
@@ -1457,13 +1464,13 @@
valled-aosta.it
valledaosta.it
vallee-aoste.it
-vallée-aoste.it
+vallée-aoste.it
vallee-d-aoste.it
-vallée-d-aoste.it
+vallée-d-aoste.it
valleeaoste.it
-valléeaoste.it
+valléeaoste.it
valleedaoste.it
-valléedaoste.it
+valléedaoste.it
vao.it
vda.it
ven.it
@@ -1497,7 +1504,7 @@
avellino.it
ba.it
balsan-sudtirol.it
-balsan-südtirol.it
+balsan-südtirol.it
balsan-suedtirol.it
balsan.it
bari.it
@@ -1516,7 +1523,7 @@
bolzano-altoadige.it
bolzano.it
bozen-sudtirol.it
-bozen-südtirol.it
+bozen-südtirol.it
bozen-suedtirol.it
bozen.it
br.it
@@ -1525,7 +1532,7 @@
bs.it
bt.it
bulsan-sudtirol.it
-bulsan-südtirol.it
+bulsan-südtirol.it
bulsan-suedtirol.it
bulsan.it
bz.it
@@ -1545,9 +1552,9 @@
cb.it
ce.it
cesena-forli.it
-cesena-forlì.it
+cesena-forlì.it
cesenaforli.it
-cesenaforlì.it
+cesenaforlì.it
ch.it
chieti.it
ci.it
@@ -1578,9 +1585,9 @@
fm.it
foggia.it
forli-cesena.it
-forlì-cesena.it
+forlì-cesena.it
forlicesena.it
-forlìcesena.it
+forlìcesena.it
fr.it
frosinone.it
ge.it
@@ -1711,7 +1718,7 @@
sr.it
ss.it
suedtirol.it
-südtirol.it
+südtirol.it
sv.it
ta.it
taranto.it
@@ -3692,8 +3699,16 @@
seoul.kr
ulsan.kr
-// kw : https://en.wikipedia.org/wiki/.kw
-*.kw
+// kw : https://www.nic.kw/policies/
+// Confirmed by registry <nic.tech@citra.gov.kw>
+kw
+com.kw
+edu.kw
+emb.kw
+gov.kw
+ind.kw
+net.kw
+org.kw
// ky : http://www.icta.ky/da_ky_reg_dom.php
// Confirmed by registry <kysupport@perimeterusa.com> 2008-06-17
@@ -3775,10 +3790,18 @@
org.lr
net.lr
-// ls : https://en.wikipedia.org/wiki/.ls
+// ls : http://www.nic.ls/
+// Confirmed by registry <lsadmin@nic.ls>
ls
+ac.ls
+biz.ls
co.ls
+edu.ls
+gov.ls
+info.ls
+net.ls
org.ls
+sc.ls
// lt : https://en.wikipedia.org/wiki/.lt
lt
@@ -4636,9 +4659,6 @@
// ccTLD for the Netherlands
nl
-// BV.nl will be a registry for dutch BV's (besloten vennootschap)
-bv.nl
-
// no : http://www.norid.no/regelverk/index.en.html
// The Norwegian registry has declined to notify us of updates. The web pages
// referenced below are the official source of the data. There is also an
@@ -8329,9 +8349,6 @@
// goo : 2014-12-18 NTT Resonant Inc.
goo
-// goodhands : 2015-07-31 Allstate Fire and Casualty Insurance Company
-goodhands
-
// goodyear : 2015-07-02 The Goodyear Tire & Rubber Company
goodyear
@@ -8608,9 +8625,6 @@
// iveco : 2015-09-03 CNH Industrial N.V.
iveco
-// iwc : 2014-06-23 Richemont DNS Inc.
-iwc
-
// jaguar : 2014-11-13 Jaguar Land Rover Ltd
jaguar
@@ -8635,9 +8649,6 @@
// jio : 2015-04-02 Reliance Industries Limited
jio
-// jlc : 2014-12-04 Richemont DNS Inc.
-jlc
-
// jll : 2015-04-02 Jones Lang LaSalle Incorporated
jll
@@ -8989,9 +9000,6 @@
// menu : 2013-09-11 Wedding TLD2, LLC
menu
-// meo : 2014-11-07 MEO Servicos de Comunicacoes e Multimedia, S.A.
-meo
-
// merckmsd : 2016-07-14 MSD Registry Holdings, Inc.
merckmsd
@@ -9283,9 +9291,6 @@
// panasonic : 2015-07-30 Panasonic Corporation
panasonic
-// panerai : 2014-11-07 Richemont DNS Inc.
-panerai
-
// paris : 2014-01-30 City of Paris
paris
@@ -9634,9 +9639,6 @@
// sap : 2014-03-27 SAP AG
sap
-// sapo : 2014-11-07 MEO Servicos de Comunicacoes e Multimedia, S.A.
-sapo
-
// sarl : 2014-07-03 Binky Moon, LLC
sarl
@@ -9877,9 +9879,6 @@
// statefarm : 2015-07-30 State Farm Mutual Automobile Insurance Company
statefarm
-// statoil : 2014-12-04 Statoil ASA
-statoil
-
// stc : 2014-10-09 Saudi Telecom Company
stc
@@ -9991,9 +9990,6 @@
// technology : 2013-09-13 Binky Moon, LLC
technology
-// telecity : 2015-02-19 TelecityGroup International Limited
-telecity
-
// telefonica : 2014-10-16 Telefónica S.A.
telefonica
@@ -10201,9 +10197,6 @@
// vision : 2013-12-05 Binky Moon, LLC
vision
-// vista : 2014-09-18 Vistaprint Limited
-vista
-
// vistaprint : 2014-09-18 Vistaprint Limited
vistaprint
@@ -10642,9 +10635,6 @@
// xn--zfr164b : 2013-11-08 China Organizational Name Administration Center
政务
-// xperia : 2015-05-14 Sony Mobile Communications AB
-xperia
-
// xyz : 2013-12-05 XYZ.COM LLC
xyz
@@ -10737,6 +10727,7 @@
// Amazon Elastic Beanstalk : https://aws.amazon.com/elasticbeanstalk/
// Submitted by Luke Wells <psl-maintainers@amazon.com>
cn-north-1.eb.amazonaws.com.cn
+cn-northwest-1.eb.amazonaws.com.cn
elasticbeanstalk.com
ap-northeast-1.elasticbeanstalk.com
ap-northeast-2.elasticbeanstalk.com
@@ -10823,6 +10814,10 @@
t3l3p0rt.net
tele.amune.org
+// Apigee : https://apigee.com/
+// Submitted by Apigee Security Team <security@apigee.com>
+apigee.io
+
// Aptible : https://www.aptible.com/
// Submitted by Thomas Orozco <thomas@aptible.com>
on-aptible.com
@@ -10842,6 +10837,11 @@
// Submitted by Vincent Tseng <vincenttseng@asustor.com>
myasustor.com
+// Automattic Inc. : https://automattic.com/
+// Submitted by Alex Concha <alex.concha@automattic.com>
+go-vip.co
+wpcomstaging.com
+
// AVM : https://avm.de
// Submitted by Andreas Weise <a.weise@avm.de>
myfritz.net
@@ -10888,6 +10888,11 @@
// Submitted by Dave Tharp <browsersafetymark.io@quicinc.com>
browsersafetymark.io
+// Bytemark Hosting : https://www.bytemark.co.uk
+// Submitted by Paul Cammish <paul.cammish@bytemark.co.uk>
+dh.bytemark.co.uk
+vm.bytemark.co.uk
+
// callidomus : https://www.callidomus.com/
// Submitted by Marcus Popp <admin@callidomus.com>
mycd.eu
@@ -11080,6 +11085,11 @@
reg.dk
store.dk
+// dapps.earth : https://dapps.earth/
+// Submitted by Daniil Burdakov <icqkill@gmail.com>
+*.dapps.earth
+*.bzz.dapps.earth
+
// Debian : https://www.debian.org/
// Submitted by Peter Palfrader / Debian Sysadmin Team <dsa-publicsuffixlist@debian.org>
debian.net
@@ -11092,6 +11102,11 @@
// Submitted by Norbert Auler <mail@dnshome.de>
dnshome.de
+// DotArai : https://www.dotarai.com/
+// Submitted by Atsadawat Netcharadsang <atsadawat@dotarai.co.th>
+online.th
+shop.th
+
// DrayTek Corp. : https://www.draytek.com/
// Submitted by Paul Fang <mis@draytek.com>
drayddns.com
@@ -11648,6 +11663,10 @@
app.os.fedoraproject.org
app.os.stg.fedoraproject.org
+// Fermax : https://fermax.com/
+// submitted by Koen Van Isterdael <k.vanisterdael@fermax.be>
+mydobiss.com
+
// Filegear Inc. : https://www.filegear.com
// Submitted by Jason Zhu <jason@owtware.com>
filegear.me
@@ -11713,6 +11732,8 @@
// Google, Inc.
// Submitted by Eduardo Vela <evn@google.com>
+run.app
+a.run.app
*.0emm.com
appspot.com
blogspot.ae
@@ -11918,6 +11939,12 @@
lcube-server.de
svn-repos.de
+// Leadpages : https://www.leadpages.net
+// Submitted by Greg Dallavalle <domains@leadpages.net>
+leadpages.co
+lpages.co
+lpusercontent.com
+
// Lightmaker Property Manager, Inc. : https://app.lmpm.com/
// Submitted by Greg Holland <greg.holland@lmpm.com>
app.lmpm.com
@@ -11935,6 +11962,15 @@
// Submitted by Victor Velchev <admin@liquidnetlimited.com>
we.bs
+// LubMAN UMCS Sp. z o.o : https://lubman.pl/
+// Submitted by Ireneusz Maliszewski <ireneusz.maliszewski@lubman.pl>
+krasnik.pl
+leczna.pl
+lubartow.pl
+lublin.pl
+poniatowa.pl
+swidnik.pl
+
// Lug.org.uk : https://lug.org.uk
// Submitted by Jon Spriggs <admin@lug.org.uk>
uklugs.org
@@ -12322,6 +12358,10 @@
chirurgiens-dentistes-en-france.fr
byen.site
+// Redstar Consultants : https://www.redstarconsultants.com/
+// Submitted by Jons Slemmer <jons@redstarconsultants.com>
+instantcloud.cn
+
// Russian Academy of Sciences
// Submitted by Tech Support <support@rasnet.ru>
ras.ru
@@ -12350,6 +12390,10 @@
rackmaze.com
rackmaze.net
+// Read The Docs, Inc : https://www.readthedocs.org
+// Submitted by David Fischer <team@readthedocs.org>
+readthedocs.io
+
// Red Hat, Inc. OpenShift : https://openshift.redhat.com/
// Submitted by Tim Kramer <tkramer@rhcloud.com>
rhcloud.com
@@ -12426,6 +12470,10 @@
sinaapp.com
vipsinaapp.com
+// Siteleaf : https://www.siteleaf.com/
+// Submitted by Skylar Challand <support@siteleaf.com>
+siteleaf.net
+
// Skyhat : http://www.skyhat.io
// Submitted by Shante Adam <shante@skyhat.io>
bounty-full.com
@@ -12451,10 +12499,6 @@
// Submitted by Stefan Neufeind <info@speedpartner.de>
customer.speedpartner.de
-// Stackspace : https://www.stackspace.io/
-// Submitted by Lina He <info@stackspace.io>
-stackspace.space
-
// Storj Labs Inc. : https://storj.io/
// Submitted by Philip Hutchins <hostmaster@storj.io>
storj.farm
@@ -12495,6 +12539,12 @@
med.pl
sopot.pl
+// Telebit : https://telebit.cloud
+// Submitted by AJ ONeal <aj@telebit.cloud>
+telebit.app
+telebit.io
+*.telebit.xyz
+
// The Gwiddle Foundation : https://gwiddlefoundation.org.uk
// Submitted by Joshua Bayfield <joshua.bayfield@gwiddlefoundation.org.uk>
gwiddle.co.uk
@@ -12533,7 +12583,7 @@
webspace.rocks
lima.zone
-// TransIP : htts://www.transip.nl
+// TransIP : https://www.transip.nl
// Submitted by Rory Breuk <rbreuk@transip.nl>
*.transurl.be
*.transurl.eu
--- a/make/hotspot/lib/JvmFeatures.gmk Sat Mar 23 15:11:51 2019 +0000
+++ b/make/hotspot/lib/JvmFeatures.gmk Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 2019, 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
@@ -47,6 +47,9 @@
ifeq ($(call check-jvm-feature, zero), true)
JVM_CFLAGS_FEATURES += -DZERO -DCC_INTERP -DZERO_LIBARCH='"$(OPENJDK_TARGET_CPU_LEGACY_LIB)"' $(LIBFFI_CFLAGS)
JVM_LIBS_FEATURES += $(LIBFFI_LIBS)
+ ifeq ($(ENABLE_LIBFFI_BUNDLING), true)
+ JVM_LDFLAGS_FEATURES += $(call SET_EXECUTABLE_ORIGIN,/..)
+ endif
ifeq ($(call isTargetCpu, sparcv9), true)
BUILD_LIBJVM_EXTRA_FILES := $(TOPDIR)/src/hotspot/cpu/sparc/memset_with_concurrent_readers_sparc.cpp
endif
@@ -123,7 +126,7 @@
JVM_CFLAGS_FEATURES += -DINCLUDE_NMT=0
JVM_EXCLUDE_FILES += \
memBaseline.cpp memReporter.cpp mallocTracker.cpp virtualMemoryTracker.cpp nmtCommon.cpp \
- memTracker.cpp nmtDCmd.cpp mallocSiteTable.cpp
+ memTracker.cpp nmtDCmd.cpp mallocSiteTable.cpp threadStackTracker.cpp
endif
ifneq ($(call check-jvm-feature, aot), true)
--- a/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -72,15 +72,12 @@
}
void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
- Register start, Register end, Register scratch, RegSet saved_regs) {
+ Register start, Register count, Register scratch, RegSet saved_regs) {
__ push(saved_regs, sp);
- // must compute element count unless barrier set interface is changed (other platforms supply count)
- assert_different_registers(start, end, scratch);
- __ lea(scratch, Address(end, BytesPerHeapOop));
- __ sub(scratch, scratch, start); // subtract start to get #bytes
- __ lsr(scratch, scratch, LogBytesPerHeapOop); // convert to element count
+ assert_different_registers(start, count, scratch);
+ assert_different_registers(c_rarg0, count);
__ mov(c_rarg0, start);
- __ mov(c_rarg1, scratch);
+ __ mov(c_rarg1, count);
__ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_post_entry), 2);
__ pop(saved_regs, sp);
}
--- a/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -39,7 +39,7 @@
void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
Register addr, Register count, RegSet saved_regs);
void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
- Register start, Register end, Register tmp, RegSet saved_regs);
+ Register start, Register count, Register tmp, RegSet saved_regs);
void g1_write_barrier_pre(MacroAssembler* masm,
Register obj,
--- a/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -62,18 +62,22 @@
}
void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
- Register start, Register end, Register scratch, RegSet saved_regs) {
+ Register start, Register count, Register scratch, RegSet saved_regs) {
BarrierSet* bs = BarrierSet::barrier_set();
CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
CardTable* ct = ctbs->card_table();
- Label L_loop;
+ Label L_loop, L_done;
+ const Register end = count;
+ __ cbz(count, L_done); // zero count - nothing to do
+
+ __ lea(end, Address(start, count, Address::lsl(LogBytesPerHeapOop))); // end = start + count << LogBytesPerHeapOop
+ __ sub(end, end, BytesPerHeapOop); // last element address to make inclusive
__ lsr(start, start, CardTable::card_shift);
__ lsr(end, end, CardTable::card_shift);
- __ sub(end, end, start); // number of bytes to copy
+ __ sub(count, end, start); // number of bytes to copy
- const Register count = end; // 'end' register contains bytes count now
__ load_byte_map_base(scratch);
__ add(start, start, scratch);
if (ct->scanned_concurrently()) {
@@ -83,6 +87,7 @@
__ strb(zr, Address(start, count));
__ subs(count, count, 1);
__ br(Assembler::GE, L_loop);
+ __ bind(L_done);
}
void CardTableBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
--- a/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -33,7 +33,7 @@
void store_check(MacroAssembler* masm, Register obj, Address dst);
virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
- Register start, Register end, Register tmp, RegSet saved_regs);
+ Register start, Register count, Register tmp, RegSet saved_regs);
virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Address dst, Register val, Register tmp1, Register tmp2);
--- a/src/hotspot/cpu/aarch64/gc/shared/modRefBarrierSetAssembler_aarch64.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/cpu/aarch64/gc/shared/modRefBarrierSetAssembler_aarch64.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -37,10 +37,10 @@
}
void ModRefBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
- Register start, Register end, Register tmp,
+ Register start, Register count, Register tmp,
RegSet saved_regs) {
if (is_oop) {
- gen_write_ref_array_post_barrier(masm, decorators, start, end, tmp, saved_regs);
+ gen_write_ref_array_post_barrier(masm, decorators, start, count, tmp, saved_regs);
}
}
--- a/src/hotspot/cpu/aarch64/gc/shared/modRefBarrierSetAssembler_aarch64.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/cpu/aarch64/gc/shared/modRefBarrierSetAssembler_aarch64.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -37,7 +37,7 @@
virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
Register addr, Register count, RegSet saved_regs) {}
virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
- Register start, Register end, Register tmp, RegSet saved_regs) {}
+ Register start, Register count, Register tmp, RegSet saved_regs) {}
virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Address dst, Register val, Register tmp1, Register tmp2) = 0;
@@ -46,7 +46,7 @@
virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
Register addr, Register count, RegSet saved_regs);
virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
- Register start, Register end, Register tmp, RegSet saved_regs);
+ Register start, Register count, Register tmp, RegSet saved_regs);
virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Address dst, Register val, Register tmp1, Register tmp2);
};
--- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -73,16 +73,13 @@
}
void ShenandoahBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
- Register start, Register end, Register scratch, RegSet saved_regs) {
+ Register start, Register count, Register scratch, RegSet saved_regs) {
if (is_oop) {
__ push(saved_regs, sp);
- // must compute element count unless barrier set interface is changed (other platforms supply count)
- assert_different_registers(start, end, scratch);
- __ lea(scratch, Address(end, BytesPerHeapOop));
- __ sub(scratch, scratch, start); // subtract start to get #bytes
- __ lsr(scratch, scratch, LogBytesPerHeapOop); // convert to element count
+ assert_different_registers(start, count, scratch);
+ assert_different_registers(c_rarg0, count);
__ mov(c_rarg0, start);
- __ mov(c_rarg1, scratch);
+ __ mov(c_rarg1, count);
__ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_array_post_entry), 2);
__ pop(saved_regs, sp);
}
--- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -78,7 +78,7 @@
virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
Register addr, Register count, RegSet saved_regs);
virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
- Register start, Register end, Register tmp, RegSet saved_regs);
+ Register start, Register count, Register tmp, RegSet saved_regs);
virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Register dst, Address src, Register tmp1, Register tmp_thread);
virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
--- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -1375,8 +1375,6 @@
__ pop(RegSet::of(d, count), sp);
if (VerifyOops)
verify_oop_array(size, d, count, r16);
- __ sub(count, count, 1); // make an inclusive end pointer
- __ lea(count, Address(d, count, Address::lsl(exact_log2(size))));
}
bs->arraycopy_epilogue(_masm, decorators, is_oop, d, count, rscratch1, RegSet());
@@ -1448,8 +1446,6 @@
__ pop(RegSet::of(d, count), sp);
if (VerifyOops)
verify_oop_array(size, d, count, r16);
- __ sub(count, count, 1); // make an inclusive end pointer
- __ lea(count, Address(d, count, Address::lsl(exact_log2(size))));
}
bs->arraycopy_epilogue(_masm, decorators, is_oop, d, count, rscratch1, RegSet());
__ leave();
@@ -1842,8 +1838,7 @@
__ br(Assembler::EQ, L_done_pop);
__ BIND(L_do_card_marks);
- __ add(to, to, -heapOopSize); // make an inclusive end pointer
- bs->arraycopy_epilogue(_masm, decorators, is_oop, start_to, to, rscratch1, wb_post_saved_regs);
+ bs->arraycopy_epilogue(_masm, decorators, is_oop, start_to, count_save, rscratch1, wb_post_saved_regs);
__ bind(L_done_pop);
__ pop(RegSet::of(r18, r19, r20, r21), sp);
--- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -2885,7 +2885,7 @@
{
Label notVolatile;
__ tbz(r5, ConstantPoolCacheEntry::is_volatile_shift, notVolatile);
- __ membar(MacroAssembler::StoreLoad);
+ __ membar(MacroAssembler::StoreLoad | MacroAssembler::StoreStore);
__ bind(notVolatile);
}
}
@@ -3029,7 +3029,7 @@
{
Label notVolatile;
__ tbz(r3, ConstantPoolCacheEntry::is_volatile_shift, notVolatile);
- __ membar(MacroAssembler::StoreLoad);
+ __ membar(MacroAssembler::StoreLoad | MacroAssembler::StoreStore);
__ bind(notVolatile);
}
}
--- a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -1455,13 +1455,11 @@
break;
}
} else {
- if (opr2->is_address()) {
- DEBUG_ONLY( Unimplemented(); ) // Seems to be unused at the moment.
- LIR_Address *addr = opr2->as_address_ptr();
- BasicType type = addr->type();
- if (type == T_OBJECT) { __ ld(R0, index_or_disp(addr), addr->base()->as_register()); }
- else { __ lwa(R0, index_or_disp(addr), addr->base()->as_register()); }
- __ cmpd(BOOL_RESULT, opr1->as_register(), R0);
+ assert(opr1->type() != T_ADDRESS && opr2->type() != T_ADDRESS, "currently unsupported");
+ if (opr1->type() == T_OBJECT || opr1->type() == T_ARRAY) {
+ // There are only equal/notequal comparisons on objects.
+ assert(condition == lir_cond_equal || condition == lir_cond_notEqual, "oops");
+ __ cmpd(BOOL_RESULT, opr1->as_register(), opr2->as_register());
} else {
if (unsigned_comp) {
__ cmplw(BOOL_RESULT, opr1->as_register(), opr2->as_register());
@@ -1497,14 +1495,6 @@
} else {
ShouldNotReachHere();
}
- } else if (opr1->is_address()) {
- DEBUG_ONLY( Unimplemented(); ) // Seems to be unused at the moment.
- LIR_Address * addr = opr1->as_address_ptr();
- BasicType type = addr->type();
- assert (opr2->is_constant(), "Checking");
- if (type == T_OBJECT) { __ ld(R0, index_or_disp(addr), addr->base()->as_register()); }
- else { __ lwa(R0, index_or_disp(addr), addr->base()->as_register()); }
- __ cmpdi(BOOL_RESULT, R0, opr2->as_constant_ptr()->as_jint());
} else {
ShouldNotReachHere();
}
--- a/src/hotspot/cpu/x86/crc32c.h Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/cpu/x86/crc32c.h Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,6 +22,9 @@
*
*/
+#ifndef CPU_X86_CRC32C_H
+#define CPU_X86_CRC32C_H
+
enum {
// S. Gueron / Information Processing Letters 112 (2012) 184
// shows than anything above 6K and below 32K is a good choice
@@ -64,3 +67,5 @@
// a) constants table generation (hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp)
// b) constant fetch from that table (macroAssembler_x86.cpp)
// c) unrolled for loop (macroAssembler_x86.cpp)
+
+#endif /* !CPU_X86_CRC32C_H */
--- a/src/hotspot/cpu/x86/vm_version_x86.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/cpu/x86/vm_version_x86.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -901,11 +901,15 @@
FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
}
+#ifdef _LP64
+ // These are only supported on 64-bit
if (UseSHA && supports_avx2() && supports_bmi2()) {
if (FLAG_IS_DEFAULT(UseSHA512Intrinsics)) {
FLAG_SET_DEFAULT(UseSHA512Intrinsics, true);
}
- } else if (UseSHA512Intrinsics) {
+ } else
+#endif
+ if (UseSHA512Intrinsics) {
warning("Intrinsics for SHA-384 and SHA-512 crypto hash functions not available on this CPU.");
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
}
--- a/src/hotspot/os/aix/os_aix.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/os/aix/os_aix.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -37,6 +37,7 @@
#include "compiler/compileBroker.hpp"
#include "interpreter/interpreter.hpp"
#include "logging/log.hpp"
+#include "logging/logStream.hpp"
#include "libo4.hpp"
#include "libperfstat_aix.hpp"
#include "libodm_aix.hpp"
@@ -923,6 +924,11 @@
char buf[64];
log_warning(os, thread)("Failed to start thread - pthread_create failed (%d=%s) for attributes: %s.",
ret, os::errno_name(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr));
+ // Log some OS information which might explain why creating the thread failed.
+ log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads());
+ LogStream st(Log(os, thread)::info());
+ os::Posix::print_rlimit_info(&st);
+ os::print_memory_info(&st);
}
pthread_attr_destroy(&attr);
--- a/src/hotspot/os/bsd/os_bsd.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/os/bsd/os_bsd.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -33,6 +33,7 @@
#include "compiler/disassembler.hpp"
#include "interpreter/interpreter.hpp"
#include "logging/log.hpp"
+#include "logging/logStream.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/filemap.hpp"
#include "oops/oop.inline.hpp"
@@ -743,6 +744,11 @@
} else {
log_warning(os, thread)("Failed to start thread - pthread_create failed (%s) for attributes: %s.",
os::errno_name(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr));
+ // Log some OS information which might explain why creating the thread failed.
+ log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads());
+ LogStream st(Log(os, thread)::info());
+ os::Posix::print_rlimit_info(&st);
+ os::print_memory_info(&st);
}
pthread_attr_destroy(&attr);
--- a/src/hotspot/os/linux/os_linux.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/os/linux/os_linux.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -780,6 +780,13 @@
} else {
log_warning(os, thread)("Failed to start thread - pthread_create failed (%s) for attributes: %s.",
os::errno_name(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr));
+ // Log some OS information which might explain why creating the thread failed.
+ log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads());
+ LogStream st(Log(os, thread)::info());
+ os::Posix::print_rlimit_info(&st);
+ os::print_memory_info(&st);
+ os::Linux::print_proc_sys_info(&st);
+ os::Linux::print_container_info(&st);
}
pthread_attr_destroy(&attr);
--- a/src/hotspot/os/solaris/os_solaris.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/os/solaris/os_solaris.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -33,6 +33,7 @@
#include "compiler/disassembler.hpp"
#include "interpreter/interpreter.hpp"
#include "logging/log.hpp"
+#include "logging/logStream.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/filemap.hpp"
#include "oops/oop.inline.hpp"
@@ -992,6 +993,11 @@
} else {
log_warning(os, thread)("Failed to start thread - thr_create failed (%s) for attributes: %s.",
os::errno_name(status), describe_thr_create_attributes(buf, sizeof(buf), stack_size, flags));
+ // Log some OS information which might explain why creating the thread failed.
+ log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads());
+ LogStream st(Log(os, thread)::info());
+ os::Posix::print_rlimit_info(&st);
+ os::print_memory_info(&st);
}
if (status != 0) {
--- a/src/hotspot/os/windows/os_windows.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/os/windows/os_windows.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -36,6 +36,7 @@
#include "compiler/disassembler.hpp"
#include "interpreter/interpreter.hpp"
#include "logging/log.hpp"
+#include "logging/logStream.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/filemap.hpp"
#include "oops/oop.inline.hpp"
@@ -669,6 +670,10 @@
} else {
log_warning(os, thread)("Failed to start thread - _beginthreadex failed (%s) for attributes: %s.",
os::errno_name(errno), describe_beginthreadex_attributes(buf, sizeof(buf), stack_size, initflag));
+ // Log some OS information which might explain why creating the thread failed.
+ log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads());
+ LogStream st(Log(os, thread)::info());
+ os::print_memory_info(&st);
}
if (thread_handle == NULL) {
--- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -132,6 +132,10 @@
return NULL;
}
+static unsigned long ucontext_get_trap(const ucontext_t * uc) {
+ return uc->uc_mcontext.regs->trap;
+}
+
ExtendedPC os::fetch_frame_from_context(const void* ucVoid,
intptr_t** ret_sp, intptr_t** ret_fp) {
@@ -304,9 +308,22 @@
// Handle ALL stack overflow variations here
if (sig == SIGSEGV) {
- // Si_addr may not be valid due to a bug in the linux-ppc64 kernel (see
+ // si_addr may not be valid due to a bug in the linux-ppc64 kernel (see
// comment below). Use get_stack_bang_address instead of si_addr.
- address addr = ((NativeInstruction*)pc)->get_stack_bang_address(uc);
+ // If SIGSEGV is caused due to a branch to an invalid address an
+ // "Instruction Storage" interruption is generated and 'pc' (NIP) already
+ // contains the invalid address. Otherwise, the SIGSEGV is caused due to
+ // load/store instruction trying to load/store from/to an invalid address
+ // and causing a "Data Storage" interruption, so we inspect the intruction
+ // in order to extract the faulty data addresss.
+ address addr;
+ if ((ucontext_get_trap(uc) & 0x0F00 /* no IRQ reply bits */) == 0x0400) {
+ // Instruction interruption
+ addr = pc;
+ } else {
+ // Data interruption (0x0300): extract faulty data address
+ addr = ((NativeInstruction*)pc)->get_stack_bang_address(uc);
+ }
// Check if fault address is within thread stack.
if (thread->on_local_stack(addr)) {
--- a/src/hotspot/os_cpu/linux_s390/thread_linux_s390.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/os_cpu/linux_s390/thread_linux_s390.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016 SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019 SAP SE. 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
@@ -63,7 +63,7 @@
if (ret_frame.is_interpreted_frame()) {
frame::z_ijava_state* istate = ret_frame.ijava_state_unchecked();
- if (!((Method*)(istate->method))->is_metaspace_object()) {
+ if ((stack_base() >= (address)istate && (address)istate > stack_end()) || !((Method*)(istate->method))->is_metaspace_object()) {
return false;
}
uint64_t reg_bcp = uc->uc_mcontext.gregs[13/*Z_BCP*/];
--- a/src/hotspot/share/classfile/classFileParser.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/classfile/classFileParser.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -6113,7 +6113,7 @@
// For the boot and platform class loaders, skip classes that are not found in the
// java runtime image, such as those found in the --patch-module entries.
// These classes can't be loaded from the archive during runtime.
- if (!ClassLoader::is_modules_image(stream->source()) && strncmp(stream->source(), "jrt:", 4) != 0) {
+ if (!stream->from_boot_loader_modules_image() && strncmp(stream->source(), "jrt:", 4) != 0) {
skip = true;
}
--- a/src/hotspot/share/classfile/classFileStream.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/classfile/classFileStream.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -38,12 +38,14 @@
ClassFileStream::ClassFileStream(const u1* buffer,
int length,
const char* source,
- bool verify_stream) :
+ bool verify_stream,
+ bool from_boot_loader_modules_image) :
_buffer_start(buffer),
_buffer_end(buffer + length),
_current(buffer),
_source(source),
- _need_verify(verify_stream) {}
+ _need_verify(verify_stream),
+ _from_boot_loader_modules_image(from_boot_loader_modules_image) {}
const u1* ClassFileStream::clone_buffer() const {
u1* const new_buffer_start = NEW_RESOURCE_ARRAY(u1, length());
@@ -69,7 +71,8 @@
return new ClassFileStream(new_buffer_start,
length(),
clone_source(),
- need_verify());
+ need_verify(),
+ from_boot_loader_modules_image());
}
uint64_t ClassFileStream::compute_fingerprint() const {
--- a/src/hotspot/share/classfile/classFileStream.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/classfile/classFileStream.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -44,7 +44,7 @@
mutable const u1* _current; // Current buffer position
const char* const _source; // Source of stream (directory name, ZIP/JAR archive name)
bool _need_verify; // True if verification is on for the class file
-
+ bool _from_boot_loader_modules_image; // True if this was created by ClassPathImageEntry.
void truncated_file_error(TRAPS) const ;
protected:
@@ -57,7 +57,8 @@
ClassFileStream(const u1* buffer,
int length,
const char* source,
- bool verify_stream = verify); // to be verified by default
+ bool verify_stream = verify, // to be verified by default
+ bool from_boot_loader_modules_image = false);
virtual const ClassFileStream* clone() const;
@@ -77,6 +78,7 @@
const char* source() const { return _source; }
bool need_verify() const { return _need_verify; }
void set_verify(bool flag) { _need_verify = flag; }
+ bool from_boot_loader_modules_image() const { return _from_boot_loader_modules_image; }
void check_truncated_file(bool b, TRAPS) const {
if (b) {
--- a/src/hotspot/share/classfile/classLoader.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/classfile/classLoader.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -361,6 +361,8 @@
}
}
+DEBUG_ONLY(ClassPathImageEntry* ClassPathImageEntry::_singleton = NULL;)
+
void ClassPathImageEntry::close_jimage() {
if (_jimage != NULL) {
(*JImageClose)(_jimage);
@@ -373,12 +375,17 @@
_jimage(jimage) {
guarantee(jimage != NULL, "jimage file is null");
guarantee(name != NULL, "jimage file name is null");
+ assert(_singleton == NULL, "VM supports only one jimage");
+ DEBUG_ONLY(_singleton = this);
size_t len = strlen(name) + 1;
_name = NEW_C_HEAP_ARRAY(const char, len, mtClass);
strncpy((char *)_name, name, len);
}
ClassPathImageEntry::~ClassPathImageEntry() {
+ assert(_singleton == this, "must be");
+ DEBUG_ONLY(_singleton = NULL);
+
if (_name != NULL) {
FREE_C_HEAP_ARRAY(const char, _name);
_name = NULL;
@@ -442,10 +449,12 @@
char* data = NEW_RESOURCE_ARRAY(char, size);
(*JImageGetResource)(_jimage, location, data, size);
// Resource allocated
+ assert(this == (ClassPathImageEntry*)ClassLoader::get_jrt_entry(), "must be");
return new ClassFileStream((u1*)data,
(int)size,
_name,
- ClassFileStream::verify);
+ ClassFileStream::verify,
+ true); // from_boot_loader_modules_image
}
return NULL;
@@ -459,7 +468,9 @@
}
bool ClassPathImageEntry::is_modules_image() const {
- return ClassLoader::is_modules_image(name());
+ assert(this == _singleton, "VM supports a single jimage");
+ assert(this == (ClassPathImageEntry*)ClassLoader::get_jrt_entry(), "must be used for jrt entry");
+ return true;
}
#if INCLUDE_CDS
@@ -737,8 +748,8 @@
// Check for a jimage
if (Arguments::has_jimage()) {
assert(_jrt_entry == NULL, "should not setup bootstrap class search path twice");
+ _jrt_entry = new_entry;
assert(new_entry != NULL && new_entry->is_modules_image(), "No java runtime image present");
- _jrt_entry = new_entry;
assert(_jrt_entry->jimage() != NULL, "No java runtime image");
}
} else {
@@ -1499,7 +1510,7 @@
}
// for index 0 and the stream->source() is the modules image or has the jrt: protocol.
// The class must be from the runtime modules image.
- if (i == 0 && (is_modules_image(src) || string_starts_with(src, "jrt:"))) {
+ if (i == 0 && (stream->from_boot_loader_modules_image() || string_starts_with(src, "jrt:"))) {
classpath_index = i;
break;
}
@@ -1515,7 +1526,7 @@
// The shared path table is set up after module system initialization.
// The path table contains no entry before that. Any classes loaded prior
// to the setup of the shared path table must be from the modules image.
- assert(is_modules_image(src), "stream must be from modules image");
+ assert(stream->from_boot_loader_modules_image(), "stream must be loaded by boot loader from modules image");
assert(FileMapInfo::get_number_of_shared_paths() == 0, "shared path table must not have been setup");
classpath_index = 0;
}
--- a/src/hotspot/share/classfile/classLoader.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/classfile/classLoader.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -114,6 +114,7 @@
private:
JImageFile* _jimage;
const char* _name;
+ DEBUG_ONLY(static ClassPathImageEntry* _singleton;)
public:
bool is_modules_image() const;
bool is_jar_file() const { return false; }
@@ -439,8 +440,6 @@
// distinguish from a class_name with no package name, as both cases have a NULL return value
static const char* package_from_name(const char* const class_name, bool* bad_class_name = NULL);
- static bool is_modules_image(const char* name) { return string_ends_with(name, MODULES_IMAGE_NAME); }
-
// Debugging
static void verify() PRODUCT_RETURN;
};
--- a/src/hotspot/share/classfile/verifier.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/classfile/verifier.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -574,7 +574,7 @@
ClassVerifier::ClassVerifier(
InstanceKlass* klass, TRAPS)
: _thread(THREAD), _previous_symbol(NULL), _symbols(NULL), _exception_type(NULL),
- _message(NULL), _klass(klass) {
+ _message(NULL), _method_signatures_table(NULL), _klass(klass) {
_this_type = VerificationType::reference_type(klass->name());
}
@@ -601,6 +601,13 @@
void ClassVerifier::verify_class(TRAPS) {
log_info(verification)("Verifying class %s with new format", _klass->external_name());
+ // Either verifying both local and remote classes or just remote classes.
+ assert(BytecodeVerificationRemote, "Should not be here");
+
+ // Create hash table containing method signatures.
+ method_signatures_table_type method_signatures_table;
+ set_method_signatures_table(&method_signatures_table);
+
Array<Method*>* methods = _klass->methods();
int num_methods = methods->length();
@@ -625,6 +632,55 @@
}
}
+// Translate the signature entries into verification types and save them in
+// the growable array. Also, save the count of arguments.
+void ClassVerifier::translate_signature(Symbol* const method_sig,
+ sig_as_verification_types* sig_verif_types,
+ TRAPS) {
+ SignatureStream sig_stream(method_sig);
+ VerificationType sig_type[2];
+ int sig_i = 0;
+ GrowableArray<VerificationType>* verif_types = sig_verif_types->sig_verif_types();
+
+ // Translate the signature arguments into verification types.
+ while (!sig_stream.at_return_type()) {
+ int n = change_sig_to_verificationType(&sig_stream, sig_type, CHECK_VERIFY(this));
+ assert(n <= 2, "Unexpected signature type");
+
+ // Store verification type(s). Longs and Doubles each have two verificationTypes.
+ for (int x = 0; x < n; x++) {
+ verif_types->push(sig_type[x]);
+ }
+ sig_i += n;
+ sig_stream.next();
+ }
+
+ // Set final arg count, not including the return type. The final arg count will
+ // be compared with sig_verify_types' length to see if there is a return type.
+ sig_verif_types->set_num_args(sig_i);
+
+ // Store verification type(s) for the return type, if there is one.
+ if (sig_stream.type() != T_VOID) {
+ int n = change_sig_to_verificationType(&sig_stream, sig_type, CHECK_VERIFY(this));
+ assert(n <= 2, "Unexpected signature return type");
+ for (int y = 0; y < n; y++) {
+ verif_types->push(sig_type[y]);
+ }
+ }
+}
+
+void ClassVerifier::create_method_sig_entry(sig_as_verification_types* sig_verif_types,
+ int sig_index, TRAPS) {
+ // Translate the signature into verification types.
+ ConstantPool* cp = _klass->constants();
+ Symbol* const method_sig = cp->symbol_at(sig_index);
+ translate_signature(method_sig, sig_verif_types, CHECK_VERIFY(this));
+
+ // Add the list of this signature's verification types to the table.
+ bool is_unique = method_signatures_table()->put(sig_index, sig_verif_types);
+ assert(is_unique, "Duplicate entries in method_signature_table");
+}
+
void ClassVerifier::verify_method(const methodHandle& m, TRAPS) {
HandleMark hm(THREAD);
_method = m; // initialize _method
@@ -2734,44 +2790,28 @@
ref_class_type = cp_ref_index_to_type(index, cp, CHECK_VERIFY(this));
}
- // For a small signature length, we just allocate 128 bytes instead
- // of parsing the signature once to find its size.
- // -3 is for '(', ')' and return descriptor; multiply by 2 is for
- // longs/doubles to be consertive.
assert(sizeof(VerificationType) == sizeof(uintptr_t),
"buffer type must match VerificationType size");
- uintptr_t on_stack_sig_types_buffer[128];
- // If we make a VerificationType[128] array directly, the compiler calls
- // to the c-runtime library to do the allocation instead of just
- // stack allocating it. Plus it would run constructors. This shows up
- // in performance profiles.
+
+ // Get the UTF8 index for this signature.
+ int sig_index = cp->signature_ref_index_at(cp->name_and_type_ref_index_at(index));
- VerificationType* sig_types;
- int size = (method_sig->utf8_length() - 3) * 2;
- if (size > 128) {
- // Long and double occupies two slots here.
- ArgumentSizeComputer size_it(method_sig);
- size = size_it.size();
- sig_types = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, VerificationType, size);
- } else{
- sig_types = (VerificationType*)on_stack_sig_types_buffer;
+ // Get the signature's verification types.
+ sig_as_verification_types* mth_sig_verif_types;
+ sig_as_verification_types** mth_sig_verif_types_ptr = method_signatures_table()->get(sig_index);
+ if (mth_sig_verif_types_ptr != NULL) {
+ // Found the entry for the signature's verification types in the hash table.
+ mth_sig_verif_types = *mth_sig_verif_types_ptr;
+ assert(mth_sig_verif_types != NULL, "Unexpected NULL sig_as_verification_types value");
+ } else {
+ // Not found, add the entry to the table.
+ GrowableArray<VerificationType>* verif_types = new GrowableArray<VerificationType>(10);
+ mth_sig_verif_types = new sig_as_verification_types(verif_types);
+ create_method_sig_entry(mth_sig_verif_types, sig_index, CHECK_VERIFY(this));
}
- SignatureStream sig_stream(method_sig);
- int sig_i = 0;
- while (!sig_stream.at_return_type()) {
- sig_i += change_sig_to_verificationType(
- &sig_stream, &sig_types[sig_i], CHECK_VERIFY(this));
- sig_stream.next();
- }
- int nargs = sig_i;
-#ifdef ASSERT
- {
- ArgumentSizeComputer size_it(method_sig);
- assert(nargs == size_it.size(), "Argument sizes do not match");
- assert(nargs <= (method_sig->utf8_length() - 3) * 2, "estimate of max size isn't conservative enough");
- }
-#endif
+ // Get the number of arguments for this signature.
+ int nargs = mth_sig_verif_types->num_args();
// Check instruction operands
u2 bci = bcs->bci();
@@ -2844,10 +2884,16 @@
}
}
+
+ // Get the verification types for the method's arguments.
+ GrowableArray<VerificationType>* sig_verif_types = mth_sig_verif_types->sig_verif_types();
+ assert(sig_verif_types != NULL, "Missing signature's array of verification types");
// Match method descriptor with operand stack
- for (int i = nargs - 1; i >= 0; i--) { // Run backwards
- current_frame->pop_stack(sig_types[i], CHECK_VERIFY(this));
+ // The arguments are on the stack in descending order.
+ for (int i = nargs - 1; i >= 0; i--) { // Run backwards
+ current_frame->pop_stack(sig_verif_types->at(i), CHECK_VERIFY(this));
}
+
// Check objectref on operand stack
if (opcode != Bytecodes::_invokestatic &&
opcode != Bytecodes::_invokedynamic) {
@@ -2919,7 +2965,8 @@
}
}
// Push the result type.
- if (sig_stream.type() != T_VOID) {
+ int sig_verif_types_len = sig_verif_types->length();
+ if (sig_verif_types_len > nargs) { // There's a return type
if (method_name == vmSymbols::object_initializer_name()) {
// <init> method must have a void return type
/* Unreachable? Class file parser verifies that methods with '<' have
@@ -2928,11 +2975,13 @@
"Return type must be void in <init> method");
return;
}
- VerificationType return_type[2];
- int n = change_sig_to_verificationType(
- &sig_stream, return_type, CHECK_VERIFY(this));
- for (int i = 0; i < n; i++) {
- current_frame->push_stack(return_type[i], CHECK_VERIFY(this)); // push types backwards
+
+ assert(sig_verif_types_len <= nargs + 2,
+ "Signature verification types array return type is bogus");
+ for (int i = nargs; i < sig_verif_types_len; i++) {
+ assert(i == nargs || sig_verif_types->at(i).is_long2() ||
+ sig_verif_types->at(i).is_double2(), "Unexpected return verificationType");
+ current_frame->push_stack(sig_verif_types->at(i), CHECK_VERIFY(this));
}
}
}
--- a/src/hotspot/share/classfile/verifier.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/classfile/verifier.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -31,6 +31,7 @@
#include "runtime/handles.hpp"
#include "utilities/exceptions.hpp"
#include "utilities/growableArray.hpp"
+#include "utilities/resourceHash.hpp"
// The verifier class
class Verifier : AllStatic {
@@ -246,6 +247,33 @@
void stackmap_details(outputStream* ss, const Method* method) const;
};
+class sig_as_verification_types : public ResourceObj {
+ private:
+ int _num_args; // Number of arguments, not including return type.
+ GrowableArray<VerificationType>* _sig_verif_types;
+
+ public:
+
+ sig_as_verification_types(GrowableArray<VerificationType>* sig_verif_types) :
+ _num_args(0), _sig_verif_types(sig_verif_types) {
+ }
+
+ int num_args() const { return _num_args; }
+ void set_num_args(int num_args) { _num_args = num_args; }
+
+ GrowableArray<VerificationType>* sig_verif_types() { return _sig_verif_types; }
+ void set_sig_verif_types(GrowableArray<VerificationType>* sig_verif_types) {
+ _sig_verif_types = sig_verif_types;
+ }
+
+};
+
+// This hashtable is indexed by the Utf8 constant pool indexes pointed to
+// by constant pool (Interface)Method_refs' NameAndType signature entries.
+typedef ResourceHashtable<int, sig_as_verification_types*,
+ primitive_hash<int>, primitive_equals<int>, 1007>
+ method_signatures_table_type;
+
// A new instance of this class is created for each class being verified
class ClassVerifier : public StackObj {
private:
@@ -257,6 +285,8 @@
Symbol* _exception_type;
char* _message;
+ method_signatures_table_type* _method_signatures_table;
+
ErrorContext _error_context; // contains information about an error
void verify_method(const methodHandle& method, TRAPS);
@@ -383,6 +413,13 @@
// the message_buffer will be filled in with the exception message.
void verify_class(TRAPS);
+ // Translates method signature entries into verificationTypes and saves them
+ // in the growable array.
+ void translate_signature(Symbol* const method_sig, sig_as_verification_types* sig_verif_types, TRAPS);
+
+ // Initializes a sig_as_verification_types entry and puts it in the hash table.
+ void create_method_sig_entry(sig_as_verification_types* sig_verif_types, int sig_index, TRAPS);
+
// Return status modes
Symbol* result() const { return _exception_type; }
bool has_error() const { return result() != NULL; }
@@ -400,6 +437,14 @@
Klass* load_class(Symbol* name, TRAPS);
+ method_signatures_table_type* method_signatures_table() const {
+ return _method_signatures_table;
+ }
+
+ void set_method_signatures_table(method_signatures_table_type* method_signatures_table) {
+ _method_signatures_table = method_signatures_table;
+ }
+
int change_sig_to_verificationType(
SignatureStream* sig_type, VerificationType* inference_type, TRAPS);
--- a/src/hotspot/share/code/nmethod.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/code/nmethod.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -1089,7 +1089,6 @@
if (_method->code() == this) {
_method->clear_code(); // Break a cycle
}
- _method = NULL; // Clear the method of this dead nmethod
}
// Make the class unloaded - i.e., change state and notify sweeper
@@ -1109,6 +1108,9 @@
Universe::heap()->unregister_nmethod(this);
}
+ // Clear the method of this dead nmethod
+ set_method(NULL);
+
// Log the unloading.
log_state_change();
--- a/src/hotspot/share/gc/g1/g1BarrierSet.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1BarrierSet.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -58,7 +58,8 @@
_satb_mark_queue_buffer_allocator("SATB Buffer Allocator", G1SATBBufferSize),
_dirty_card_queue_buffer_allocator("DC Buffer Allocator", G1UpdateBufferSize),
_satb_mark_queue_set(),
- _dirty_card_queue_set()
+ _dirty_card_queue_set(),
+ _shared_dirty_card_queue(&_dirty_card_queue_set)
{}
void G1BarrierSet::enqueue(oop pre_val) {
--- a/src/hotspot/share/gc/g1/g1BarrierSet.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1BarrierSet.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -27,6 +27,7 @@
#include "gc/g1/g1DirtyCardQueue.hpp"
#include "gc/g1/g1SATBMarkQueueSet.hpp"
+#include "gc/g1/g1SharedDirtyCardQueue.hpp"
#include "gc/shared/cardTable.hpp"
#include "gc/shared/cardTableBarrierSet.hpp"
@@ -42,6 +43,7 @@
BufferNode::Allocator _dirty_card_queue_buffer_allocator;
G1SATBMarkQueueSet _satb_mark_queue_set;
G1DirtyCardQueueSet _dirty_card_queue_set;
+ G1SharedDirtyCardQueue _shared_dirty_card_queue;
static G1BarrierSet* g1_barrier_set() {
return barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set());
@@ -91,6 +93,10 @@
return g1_barrier_set()->_dirty_card_queue_set;
}
+ static G1SharedDirtyCardQueue& shared_dirty_card_queue() {
+ return g1_barrier_set()->_shared_dirty_card_queue;
+ }
+
// Callbacks for runtime accesses.
template <DecoratorSet decorators, typename BarrierSetT = G1BarrierSet>
class AccessBarrier: public ModRefBarrierSet::AccessBarrier<decorators, BarrierSetT> {
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -1682,12 +1682,10 @@
// later, based on the concurrent refinement object.
G1BarrierSet::dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon,
&bs->dirty_card_queue_buffer_allocator(),
- Shared_DirtyCardQ_lock,
true); // init_free_ids
dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon,
- &bs->dirty_card_queue_buffer_allocator(),
- Shared_DirtyCardQ_lock);
+ &bs->dirty_card_queue_buffer_allocator());
// Create the hot card cache.
_hot_card_cache = new G1HotCardCache(this);
@@ -2537,7 +2535,7 @@
// Update common counters.
increment_total_collections(full /* full gc */);
- if (full) {
+ if (full || collector_state()->in_initial_mark_gc()) {
increment_old_marking_cycles_started();
}
@@ -2863,16 +2861,92 @@
};
void G1CollectedHeap::start_new_collection_set() {
+ double start = os::elapsedTime();
+
collection_set()->start_incremental_building();
clear_cset_fast_test();
guarantee(_eden.length() == 0, "eden should have been cleared");
policy()->transfer_survivors_to_cset(survivor());
+
+ // We redo the verification but now wrt to the new CSet which
+ // has just got initialized after the previous CSet was freed.
+ _cm->verify_no_collection_set_oops();
+
+ phase_times()->record_start_new_cset_time_ms((os::elapsedTime() - start) * 1000.0);
}
-bool
-G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
+void G1CollectedHeap::calculate_collection_set(G1EvacuationInfo& evacuation_info, double target_pause_time_ms){
+ policy()->finalize_collection_set(target_pause_time_ms, &_survivor);
+ evacuation_info.set_collectionset_regions(collection_set()->region_length());
+
+ _cm->verify_no_collection_set_oops();
+
+ if (_hr_printer.is_active()) {
+ G1PrintCollectionSetClosure cl(&_hr_printer);
+ _collection_set.iterate(&cl);
+ }
+}
+
+G1HeapVerifier::G1VerifyType G1CollectedHeap::young_collection_verify_type() const {
+ if (collector_state()->in_initial_mark_gc()) {
+ return G1HeapVerifier::G1VerifyConcurrentStart;
+ } else if (collector_state()->in_young_only_phase()) {
+ return G1HeapVerifier::G1VerifyYoungNormal;
+ } else {
+ return G1HeapVerifier::G1VerifyMixed;
+ }
+}
+
+void G1CollectedHeap::verify_before_young_collection(G1HeapVerifier::G1VerifyType type) {
+ if (VerifyRememberedSets) {
+ log_info(gc, verify)("[Verifying RemSets before GC]");
+ VerifyRegionRemSetClosure v_cl;
+ heap_region_iterate(&v_cl);
+ }
+ _verifier->verify_before_gc(type);
+ _verifier->check_bitmaps("GC Start");
+}
+
+void G1CollectedHeap::verify_after_young_collection(G1HeapVerifier::G1VerifyType type) {
+ if (VerifyRememberedSets) {
+ log_info(gc, verify)("[Verifying RemSets after GC]");
+ VerifyRegionRemSetClosure v_cl;
+ heap_region_iterate(&v_cl);
+ }
+ _verifier->verify_after_gc(type);
+ _verifier->check_bitmaps("GC End");
+}
+
+void G1CollectedHeap::expand_heap_after_young_collection(){
+ size_t expand_bytes = _heap_sizing_policy->expansion_amount();
+ if (expand_bytes > 0) {
+ // No need for an ergo logging here,
+ // expansion_amount() does this when it returns a value > 0.
+ double expand_ms;
+ if (!expand(expand_bytes, _workers, &expand_ms)) {
+ // We failed to expand the heap. Cannot do anything about it.
+ }
+ phase_times()->record_expand_heap_time(expand_ms);
+ }
+}
+
+const char* G1CollectedHeap::young_gc_name() const {
+ if (collector_state()->in_initial_mark_gc()) {
+ return "Pause Young (Concurrent Start)";
+ } else if (collector_state()->in_young_only_phase()) {
+ if (collector_state()->in_young_gc_before_mixed()) {
+ return "Pause Young (Prepare Mixed)";
+ } else {
+ return "Pause Young (Normal)";
+ }
+ } else {
+ return "Pause Young (Mixed)";
+ }
+}
+
+bool G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
assert_at_safepoint_on_vm_thread();
guarantee(!is_gc_active(), "collection is not reentrant");
@@ -2880,16 +2954,16 @@
return false;
}
- _gc_timer_stw->register_gc_start();
-
GCIdMark gc_id_mark;
- _gc_tracer_stw->report_gc_start(gc_cause(), _gc_timer_stw->gc_start());
SvcGCMarker sgcm(SvcGCMarker::MINOR);
ResourceMark rm;
policy()->note_gc_start();
+ _gc_timer_stw->register_gc_start();
+ _gc_tracer_stw->report_gc_start(gc_cause(), _gc_timer_stw->gc_start());
+
wait_for_root_region_scanning();
print_heap_before_gc();
@@ -2909,8 +2983,7 @@
// We do not allow initial-mark to be piggy-backed on a mixed GC.
assert(!collector_state()->in_initial_mark_gc() ||
- collector_state()->in_young_only_phase(), "sanity");
-
+ collector_state()->in_young_only_phase(), "sanity");
// We also do not allow mixed GCs during marking.
assert(!collector_state()->mark_or_rebuild_in_progress() || collector_state()->in_young_only_phase(), "sanity");
@@ -2918,39 +2991,19 @@
// thread has completed its logging output and it's safe to signal
// the CM thread, the flag's value in the policy has been reset.
bool should_start_conc_mark = collector_state()->in_initial_mark_gc();
+ if (should_start_conc_mark) {
+ _cm->gc_tracer_cm()->set_gc_cause(gc_cause());
+ }
// Inner scope for scope based logging, timers, and stats collection
{
G1EvacuationInfo evacuation_info;
- if (collector_state()->in_initial_mark_gc()) {
- // We are about to start a marking cycle, so we increment the
- // full collection counter.
- increment_old_marking_cycles_started();
- _cm->gc_tracer_cm()->set_gc_cause(gc_cause());
- }
-
_gc_tracer_stw->report_yc_type(collector_state()->yc_type());
GCTraceCPUTime tcpu;
- G1HeapVerifier::G1VerifyType verify_type;
- FormatBuffer<> gc_string("Pause Young ");
- if (collector_state()->in_initial_mark_gc()) {
- gc_string.append("(Concurrent Start)");
- verify_type = G1HeapVerifier::G1VerifyConcurrentStart;
- } else if (collector_state()->in_young_only_phase()) {
- if (collector_state()->in_young_gc_before_mixed()) {
- gc_string.append("(Prepare Mixed)");
- } else {
- gc_string.append("(Normal)");
- }
- verify_type = G1HeapVerifier::G1VerifyYoungNormal;
- } else {
- gc_string.append("(Mixed)");
- verify_type = G1HeapVerifier::G1VerifyMixed;
- }
- GCTraceTime(Info, gc) tm(gc_string, NULL, gc_cause(), true);
+ GCTraceTime(Info, gc) tm(young_gc_name(), NULL, gc_cause(), true);
uint active_workers = WorkerPolicy::calc_active_workers(workers()->total_workers(),
workers()->active_workers(),
@@ -2965,88 +3018,43 @@
G1HeapTransition heap_transition(this);
size_t heap_used_bytes_before_gc = used();
- // Don't dynamically change the number of GC threads this early. A value of
- // 0 is used to indicate serial work. When parallel work is done,
- // it will be set.
-
- { // Call to jvmpi::post_class_unload_events must occur outside of active GC
+ {
IsGCActiveMark x;
gc_prologue(false);
- if (VerifyRememberedSets) {
- log_info(gc, verify)("[Verifying RemSets before GC]");
- VerifyRegionRemSetClosure v_cl;
- heap_region_iterate(&v_cl);
- }
-
- _verifier->verify_before_gc(verify_type);
-
- _verifier->check_bitmaps("GC Start");
-
-#if COMPILER2_OR_JVMCI
- DerivedPointerTable::clear();
-#endif
-
- // Please see comment in g1CollectedHeap.hpp and
- // G1CollectedHeap::ref_processing_init() to see how
- // reference processing currently works in G1.
-
- // Enable discovery in the STW reference processor
- _ref_processor_stw->enable_discovery();
+ G1HeapVerifier::G1VerifyType verify_type = young_collection_verify_type();
+ verify_before_young_collection(verify_type);
{
+ // The elapsed time induced by the start time below deliberately elides
+ // the possible verification above.
+ double sample_start_time_sec = os::elapsedTime();
+
+ // Please see comment in g1CollectedHeap.hpp and
+ // G1CollectedHeap::ref_processing_init() to see how
+ // reference processing currently works in G1.
+ _ref_processor_stw->enable_discovery();
+
// We want to temporarily turn off discovery by the
// CM ref processor, if necessary, and turn it back on
// on again later if we do. Using a scoped
// NoRefDiscovery object will do this.
NoRefDiscovery no_cm_discovery(_ref_processor_cm);
- // Forget the current alloc region (we might even choose it to be part
+ policy()->record_collection_pause_start(sample_start_time_sec);
+
+ // Forget the current allocation region (we might even choose it to be part
// of the collection set!).
_allocator->release_mutator_alloc_region();
- // This timing is only used by the ergonomics to handle our pause target.
- // It is unclear why this should not include the full pause. We will
- // investigate this in CR 7178365.
- //
- // Preserving the old comment here if that helps the investigation:
- //
- // The elapsed time induced by the start time below deliberately elides
- // the possible verification above.
- double sample_start_time_sec = os::elapsedTime();
-
- policy()->record_collection_pause_start(sample_start_time_sec);
-
- if (collector_state()->in_initial_mark_gc()) {
- concurrent_mark()->pre_initial_mark();
- }
-
- policy()->finalize_collection_set(target_pause_time_ms, &_survivor);
-
- evacuation_info.set_collectionset_regions(collection_set()->region_length());
-
- register_humongous_regions_with_cset();
-
- assert(_verifier->check_cset_fast_test(), "Inconsistency in the InCSetState table.");
-
- // We call this after finalize_cset() to
- // ensure that the CSet has been finalized.
- _cm->verify_no_cset_oops();
-
- if (_hr_printer.is_active()) {
- G1PrintCollectionSetClosure cl(&_hr_printer);
- _collection_set.iterate(&cl);
- }
-
- // Initialize the GC alloc regions.
- _allocator->init_gc_alloc_regions(evacuation_info);
+ calculate_collection_set(evacuation_info, target_pause_time_ms);
G1ParScanThreadStateSet per_thread_states(this,
workers()->active_workers(),
collection_set()->young_region_length(),
collection_set()->optional_region_length());
- pre_evacuate_collection_set();
+ pre_evacuate_collection_set(evacuation_info);
// Actually do the work...
evacuate_collection_set(&per_thread_states);
@@ -3054,39 +3062,12 @@
post_evacuate_collection_set(evacuation_info, &per_thread_states);
- const size_t* surviving_young_words = per_thread_states.surviving_young_words();
- free_collection_set(&_collection_set, evacuation_info, surviving_young_words);
-
- eagerly_reclaim_humongous_regions();
-
- record_obj_copy_mem_stats();
+ start_new_collection_set();
+
_survivor_evac_stats.adjust_desired_plab_sz();
_old_evac_stats.adjust_desired_plab_sz();
- double start = os::elapsedTime();
- start_new_collection_set();
- phase_times()->record_start_new_cset_time_ms((os::elapsedTime() - start) * 1000.0);
-
- if (evacuation_failed()) {
- double recalculate_used_start = os::elapsedTime();
- set_used(recalculate_used());
- phase_times()->record_evac_fail_recalc_used_time((os::elapsedTime() - recalculate_used_start) * 1000.0);
-
- if (_archive_allocator != NULL) {
- _archive_allocator->clear_used();
- }
- for (uint i = 0; i < ParallelGCThreads; i++) {
- if (_evacuation_failed_info_array[i].has_failed()) {
- _gc_tracer_stw->report_evacuation_failed(_evacuation_failed_info_array[i]);
- }
- }
- } else {
- // The "used" of the the collection set have already been subtracted
- // when they were freed. Add in the bytes evacuated.
- increase_used(policy()->bytes_copied_during_gc());
- }
-
- if (collector_state()->in_initial_mark_gc()) {
+ if (should_start_conc_mark) {
// We have to do this before we notify the CM threads that
// they can start working to make sure that all the
// appropriate initialization is done on the CM object.
@@ -3100,50 +3081,16 @@
_allocator->init_mutator_alloc_region();
- {
- size_t expand_bytes = _heap_sizing_policy->expansion_amount();
- if (expand_bytes > 0) {
- size_t bytes_before = capacity();
- // No need for an ergo logging here,
- // expansion_amount() does this when it returns a value > 0.
- double expand_ms;
- if (!expand(expand_bytes, _workers, &expand_ms)) {
- // We failed to expand the heap. Cannot do anything about it.
- }
- phase_times()->record_expand_heap_time(expand_ms);
- }
- }
-
- // We redo the verification but now wrt to the new CSet which
- // has just got initialized after the previous CSet was freed.
- _cm->verify_no_cset_oops();
-
- // This timing is only used by the ergonomics to handle our pause target.
- // It is unclear why this should not include the full pause. We will
- // investigate this in CR 7178365.
+ expand_heap_after_young_collection();
+
double sample_end_time_sec = os::elapsedTime();
double pause_time_ms = (sample_end_time_sec - sample_start_time_sec) * MILLIUNITS;
size_t total_cards_scanned = phase_times()->sum_thread_work_items(G1GCPhaseTimes::ScanRS, G1GCPhaseTimes::ScanRSScannedCards);
policy()->record_collection_pause_end(pause_time_ms, total_cards_scanned, heap_used_bytes_before_gc);
-
- evacuation_info.set_collectionset_used_before(collection_set()->bytes_used_before());
- evacuation_info.set_bytes_copied(policy()->bytes_copied_during_gc());
-
- if (VerifyRememberedSets) {
- log_info(gc, verify)("[Verifying RemSets after GC]");
- VerifyRegionRemSetClosure v_cl;
- heap_region_iterate(&v_cl);
- }
-
- _verifier->verify_after_gc(verify_type);
- _verifier->check_bitmaps("GC End");
-
- assert(!_ref_processor_stw->discovery_enabled(), "Postcondition");
- _ref_processor_stw->verify_no_references_recorded();
-
- // CM reference discovery will be re-enabled if necessary.
}
+ verify_after_young_collection(verify_type);
+
#ifdef TRACESPINNING
ParallelTaskTerminator::print_termination_counts();
#endif
@@ -3159,11 +3106,6 @@
policy()->print_phases();
heap_transition.print();
- // It is not yet to safe to tell the concurrent mark to
- // start as we have some optional output below. We don't want the
- // output from the concurrent mark thread interfering with this
- // logging output either.
-
_hrm->verify_optional();
_verifier->verify_region_sets_optional();
@@ -3190,13 +3132,11 @@
// that came from the pause.
if (should_start_conc_mark) {
- // CAUTION: after the doConcurrentMark() call below,
- // the concurrent marking thread(s) could be running
- // concurrently with us. Make sure that anything after
- // this point does not assume that we are the only GC thread
- // running. Note: of course, the actual marking work will
- // not start until the safepoint itself is released in
- // SuspendibleThreadSet::desynchronize().
+ // CAUTION: after the doConcurrentMark() call below, the concurrent marking
+ // thread(s) could be running concurrently with us. Make sure that anything
+ // after this point does not assume that we are the only GC thread running.
+ // Note: of course, the actual marking work will not start until the safepoint
+ // itself is released in SuspendibleThreadSet::desynchronize().
do_concurrent_mark();
}
@@ -3677,6 +3617,7 @@
make_pending_list_reachable();
+ assert(!rp->discovery_enabled(), "Postcondition");
rp->verify_no_references_recorded();
double ref_proc_time = os::elapsedTime() - ref_proc_start;
@@ -3699,7 +3640,7 @@
phase_times()->record_merge_pss_time_ms((os::elapsedTime() - merge_pss_time_start) * 1000.0);
}
-void G1CollectedHeap::pre_evacuate_collection_set() {
+void G1CollectedHeap::pre_evacuate_collection_set(G1EvacuationInfo& evacuation_info) {
_expand_heap_after_alloc_failure = true;
_evacuation_failed = false;
@@ -3707,11 +3648,23 @@
_hot_card_cache->reset_hot_cache_claimed_index();
_hot_card_cache->set_use_cache(false);
+ // Initialize the GC alloc regions.
+ _allocator->init_gc_alloc_regions(evacuation_info);
+
+ register_humongous_regions_with_cset();
+ assert(_verifier->check_cset_fast_test(), "Inconsistency in the InCSetState table.");
+
rem_set()->prepare_for_oops_into_collection_set_do();
_preserved_marks_set.assert_empty();
+#if COMPILER2_OR_JVMCI
+ DerivedPointerTable::clear();
+#endif
+
// InitialMark needs claim bits to keep track of the marked-through CLDs.
if (collector_state()->in_initial_mark_gc()) {
+ concurrent_mark()->pre_initial_mark();
+
double start_clear_claimed_marks = os::elapsedTime();
ClassLoaderDataGraph::clear_claimed_marks();
@@ -3918,19 +3871,34 @@
phase_times()->record_string_deduplication_time(string_cleanup_time_ms);
}
+ _allocator->release_gc_alloc_regions(evacuation_info);
+
if (evacuation_failed()) {
restore_after_evac_failure();
// Reset the G1EvacuationFailureALot counters and flags
- // Note: the values are reset only when an actual
- // evacuation failure occurs.
NOT_PRODUCT(reset_evacuation_should_fail();)
+
+ double recalculate_used_start = os::elapsedTime();
+ set_used(recalculate_used());
+ phase_times()->record_evac_fail_recalc_used_time((os::elapsedTime() - recalculate_used_start) * 1000.0);
+
+ if (_archive_allocator != NULL) {
+ _archive_allocator->clear_used();
+ }
+ for (uint i = 0; i < ParallelGCThreads; i++) {
+ if (_evacuation_failed_info_array[i].has_failed()) {
+ _gc_tracer_stw->report_evacuation_failed(_evacuation_failed_info_array[i]);
+ }
+ }
+ } else {
+ // The "used" of the the collection set have already been subtracted
+ // when they were freed. Add in the bytes evacuated.
+ increase_used(policy()->bytes_copied_during_gc());
}
_preserved_marks_set.assert_empty();
- _allocator->release_gc_alloc_regions(evacuation_info);
-
merge_per_thread_state_info(per_thread_states);
// Reset and re-enable the hot card cache.
@@ -3942,6 +3910,16 @@
purge_code_root_memory();
redirty_logged_cards();
+
+ free_collection_set(&_collection_set, evacuation_info, per_thread_states->surviving_young_words());
+
+ eagerly_reclaim_humongous_regions();
+
+ record_obj_copy_mem_stats();
+
+ evacuation_info.set_collectionset_used_before(collection_set()->bytes_used_before());
+ evacuation_info.set_bytes_copied(policy()->bytes_copied_during_gc());
+
#if COMPILER2_OR_JVMCI
double start = os::elapsedTime();
DerivedPointerTable::update_pointers();
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -357,6 +357,8 @@
assert(Thread::current()->is_VM_thread(), "current thread is not VM thread"); \
} while (0)
+ const char* young_gc_name() const;
+
// The young region list.
G1EdenRegions _eden;
G1SurvivorRegions _survivor;
@@ -730,14 +732,21 @@
// to the GC locker being active, true otherwise
bool do_collection_pause_at_safepoint(double target_pause_time_ms);
+ G1HeapVerifier::G1VerifyType young_collection_verify_type() const;
+ void verify_before_young_collection(G1HeapVerifier::G1VerifyType type);
+ void verify_after_young_collection(G1HeapVerifier::G1VerifyType type);
+
+ void calculate_collection_set(G1EvacuationInfo& evacuation_info, double target_pause_time_ms);
+
// Actually do the work of evacuating the collection set.
void evacuate_collection_set(G1ParScanThreadStateSet* per_thread_states);
void evacuate_optional_collection_set(G1ParScanThreadStateSet* per_thread_states);
void evacuate_optional_regions(G1ParScanThreadStateSet* per_thread_states, G1OptionalCSet* ocset);
- void pre_evacuate_collection_set();
+ void pre_evacuate_collection_set(G1EvacuationInfo& evacuation_info);
void post_evacuate_collection_set(G1EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* pss);
+ void expand_heap_after_young_collection();
// Update object copying statistics.
void record_obj_copy_mem_stats();
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -734,7 +734,9 @@
};
void G1ConcurrentMark::pre_initial_mark() {
- // Initialize marking structures. This has to be done in a STW phase.
+ assert_at_safepoint_on_vm_thread();
+
+ // Reset marking state.
reset();
// For each region note start of marking.
@@ -1944,7 +1946,7 @@
}
};
-void G1ConcurrentMark::verify_no_cset_oops() {
+void G1ConcurrentMark::verify_no_collection_set_oops() {
assert(SafepointSynchronize::is_at_safepoint(), "should be at a safepoint");
if (!_g1h->collector_state()->mark_or_rebuild_in_progress()) {
return;
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -579,7 +579,7 @@
// Verify that there are no collection set oops on the stacks (taskqueues /
// global mark stack) and fingers (global / per-task).
// If marking is not in progress, it's a no-op.
- void verify_no_cset_oops() PRODUCT_RETURN;
+ void verify_no_collection_set_oops() PRODUCT_RETURN;
inline bool do_yield_check();
--- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -56,21 +56,18 @@
}
};
-G1DirtyCardQueue::G1DirtyCardQueue(G1DirtyCardQueueSet* qset, bool permanent) :
+G1DirtyCardQueue::G1DirtyCardQueue(G1DirtyCardQueueSet* qset) :
// Dirty card queues are always active, so we create them with their
// active field set to true.
- PtrQueue(qset, permanent, true /* active */)
+ PtrQueue(qset, true /* active */)
{ }
G1DirtyCardQueue::~G1DirtyCardQueue() {
- if (!is_permanent()) {
- flush();
- }
+ flush();
}
G1DirtyCardQueueSet::G1DirtyCardQueueSet(bool notify_when_complete) :
PtrQueueSet(notify_when_complete),
- _shared_dirty_card_queue(this, true /* permanent */),
_free_ids(NULL),
_processed_buffers_mut(0),
_processed_buffers_rs_thread(0),
@@ -90,10 +87,8 @@
void G1DirtyCardQueueSet::initialize(Monitor* cbl_mon,
BufferNode::Allocator* allocator,
- Mutex* lock,
bool init_free_ids) {
PtrQueueSet::initialize(cbl_mon, allocator);
- _shared_dirty_card_queue.set_lock(lock);
if (init_free_ids) {
_free_ids = new G1FreeIdSet(0, num_par_ids());
}
@@ -217,13 +212,7 @@
} closure;
Threads::threads_do(&closure);
- shared_dirty_card_queue()->reset();
-}
-
-void G1DirtyCardQueueSet::concatenate_log(G1DirtyCardQueue& dcq) {
- if (!dcq.is_empty()) {
- dcq.flush();
- }
+ G1BarrierSet::shared_dirty_card_queue().reset();
}
void G1DirtyCardQueueSet::concatenate_logs() {
@@ -234,16 +223,16 @@
size_t old_limit = max_completed_buffers();
set_max_completed_buffers(MaxCompletedBuffersUnlimited);
- class ConcatenateThreadLogClosure : public ThreadClosure {
- G1DirtyCardQueueSet* _qset;
- public:
- ConcatenateThreadLogClosure(G1DirtyCardQueueSet* qset) : _qset(qset) {}
+ struct ConcatenateThreadLogClosure : public ThreadClosure {
virtual void do_thread(Thread* t) {
- _qset->concatenate_log(G1ThreadLocalData::dirty_card_queue(t));
+ G1DirtyCardQueue& dcq = G1ThreadLocalData::dirty_card_queue(t);
+ if (!dcq.is_empty()) {
+ dcq.flush();
+ }
}
- } closure(this);
+ } closure;
Threads::threads_do(&closure);
- concatenate_log(_shared_dirty_card_queue);
+ G1BarrierSet::shared_dirty_card_queue().flush();
set_max_completed_buffers(old_limit);
}
--- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -48,7 +48,7 @@
// A ptrQueue whose elements are "oops", pointers to object heads.
class G1DirtyCardQueue: public PtrQueue {
public:
- G1DirtyCardQueue(G1DirtyCardQueueSet* qset, bool permanent = false);
+ G1DirtyCardQueue(G1DirtyCardQueueSet* qset);
// Flush before destroying; queue may be used to capture pending work while
// doing something else, with auto-flush on completion.
@@ -70,11 +70,7 @@
};
-
-
class G1DirtyCardQueueSet: public PtrQueueSet {
- G1DirtyCardQueue _shared_dirty_card_queue;
-
// Apply the closure to the elements of "node" from it's index to
// buffer_size. If all closure applications return true, then
// returns true. Stops processing after the first closure
@@ -116,15 +112,12 @@
// Current buffer node used for parallel iteration.
BufferNode* volatile _cur_par_buffer_node;
- void concatenate_log(G1DirtyCardQueue& dcq);
-
public:
G1DirtyCardQueueSet(bool notify_when_complete = true);
~G1DirtyCardQueueSet();
void initialize(Monitor* cbl_mon,
BufferNode::Allocator* allocator,
- Mutex* lock,
bool init_free_ids = false);
// The number of parallel ids that can be claimed to allow collector or
@@ -147,10 +140,6 @@
// by reset_for_par_iteration.
void par_apply_closure_to_all_completed_buffers(G1CardTableEntryClosure* cl);
- G1DirtyCardQueue* shared_dirty_card_queue() {
- return &_shared_dirty_card_queue;
- }
-
// If a full collection is happening, reset partial logs, and ignore
// completed ones: the full collection will make them all irrelevant.
void abandon_logs();
--- a/src/hotspot/share/gc/g1/g1Policy.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1Policy.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -1188,9 +1188,11 @@
return (uint) result;
}
-void G1Policy::finalize_collection_set(double target_pause_time_ms, G1SurvivorRegions* survivor) {
+uint G1Policy::finalize_collection_set(double target_pause_time_ms, G1SurvivorRegions* survivor) {
double time_remaining_ms = _collection_set->finalize_young_part(target_pause_time_ms, survivor);
_collection_set->finalize_old_part(time_remaining_ms);
+
+ return _collection_set->region_length();
}
void G1Policy::transfer_survivors_to_cset(const G1SurvivorRegions* survivors) {
--- a/src/hotspot/share/gc/g1/g1Policy.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1Policy.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -344,7 +344,7 @@
bool next_gc_should_be_mixed(const char* true_action_str,
const char* false_action_str) const;
- void finalize_collection_set(double target_pause_time_ms, G1SurvivorRegions* survivor);
+ uint finalize_collection_set(double target_pause_time_ms, G1SurvivorRegions* survivor);
private:
// Set the state to start a concurrent marking cycle and clear
// _initiate_conc_mark_if_possible because it has now been
--- a/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, 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
@@ -205,8 +205,10 @@
MemoryType type) :
G1RegionToSpaceMapper(rs, actual_size, page_size, alloc_granularity, commit_factor, type),
_rs(rs),
+ _dram_mapper(NULL),
_num_committed_dram(0),
_num_committed_nvdimm(0),
+ _start_index_of_dram(0),
_page_size(page_size),
_commit_factor(commit_factor),
_type(type) {
@@ -248,7 +250,6 @@
_dram_mapper = new G1RegionsSmallerThanCommitSizeMapper(rs_dram, rs_dram.size(), _page_size, _region_granularity, _commit_factor, _type);
}
- _start_index_of_nvdimm = 0;
_start_index_of_dram = (uint)(rs_nvdimm.size() / _region_granularity);
return true;
}
--- a/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -101,12 +101,10 @@
// part of space is mapped to dram and part to nv-dimm
class G1RegionToHeteroSpaceMapper : public G1RegionToSpaceMapper {
private:
- size_t _pages_per_region;
ReservedSpace _rs;
G1RegionToSpaceMapper* _dram_mapper;
uint _num_committed_dram;
uint _num_committed_nvdimm;
- uint _start_index_of_nvdimm;
uint _start_index_of_dram;
size_t _page_size;
size_t _commit_factor;
--- a/src/hotspot/share/gc/g1/g1RemSet.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/g1/g1RemSet.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -35,6 +35,7 @@
#include "gc/g1/g1OopClosures.inline.hpp"
#include "gc/g1/g1RootClosures.hpp"
#include "gc/g1/g1RemSet.hpp"
+#include "gc/g1/g1SharedDirtyCardQueue.hpp"
#include "gc/g1/heapRegion.inline.hpp"
#include "gc/g1/heapRegionManager.inline.hpp"
#include "gc/g1/heapRegionRemSet.hpp"
@@ -519,9 +520,7 @@
}
void G1RemSet::prepare_for_oops_into_collection_set_do() {
- G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
- dcqs.concatenate_logs();
-
+ G1BarrierSet::dirty_card_queue_set().concatenate_logs();
_scan_state->reset();
}
@@ -660,29 +659,30 @@
assert(!dirty_region.is_empty(), "sanity");
G1ConcurrentRefineOopClosure conc_refine_cl(_g1h, worker_i);
-
- bool card_processed =
- r->oops_on_card_seq_iterate_careful<false>(dirty_region, &conc_refine_cl);
+ if (r->oops_on_card_seq_iterate_careful<false>(dirty_region, &conc_refine_cl)) {
+ _num_conc_refined_cards++; // Unsynchronized update, only used for logging.
+ return;
+ }
// If unable to process the card then we encountered an unparsable
- // part of the heap (e.g. a partially allocated object) while
- // processing a stale card. Despite the card being stale, redirty
- // and re-enqueue, because we've already cleaned the card. Without
- // this we could incorrectly discard a non-stale card.
- if (!card_processed) {
- // The card might have gotten re-dirtied and re-enqueued while we
- // worked. (In fact, it's pretty likely.)
- if (*card_ptr != G1CardTable::dirty_card_val()) {
- *card_ptr = G1CardTable::dirty_card_val();
- MutexLockerEx x(Shared_DirtyCardQ_lock,
- Mutex::_no_safepoint_check_flag);
- G1DirtyCardQueue* sdcq =
- G1BarrierSet::dirty_card_queue_set().shared_dirty_card_queue();
- sdcq->enqueue(card_ptr);
- }
- } else {
- _num_conc_refined_cards++; // Unsynchronized update, only used for logging.
+ // part of the heap (e.g. a partially allocated object, so only
+ // temporarily a problem) while processing a stale card. Despite
+ // the card being stale, we can't simply ignore it, because we've
+ // already marked the card cleaned, so taken responsibility for
+ // ensuring the card gets scanned.
+ //
+ // However, the card might have gotten re-dirtied and re-enqueued
+ // while we worked. (In fact, it's pretty likely.)
+ if (*card_ptr == G1CardTable::dirty_card_val()) {
+ return;
}
+
+ // Re-dirty the card and enqueue in the *shared* queue. Can't use
+ // the thread-local queue, because that might be the queue that is
+ // being processed by us; we could be a Java thread conscripted to
+ // perform refinement on our queue's current buffer.
+ *card_ptr = G1CardTable::dirty_card_val();
+ G1BarrierSet::shared_dirty_card_queue().enqueue(card_ptr);
}
bool G1RemSet::refine_card_during_gc(CardValue* card_ptr,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/g1/g1SharedDirtyCardQueue.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/g1/g1DirtyCardQueue.hpp"
+#include "gc/g1/g1SharedDirtyCardQueue.hpp"
+#include "gc/shared/ptrQueue.hpp"
+#include "runtime/mutex.hpp"
+#include "runtime/mutexLocker.hpp"
+
+G1SharedDirtyCardQueue::G1SharedDirtyCardQueue(G1DirtyCardQueueSet* qset) :
+ _qset(qset),
+ _buffer(NULL),
+ _index(0)
+{}
+
+G1SharedDirtyCardQueue::~G1SharedDirtyCardQueue() {
+ flush();
+}
+
+void G1SharedDirtyCardQueue::enqueue(void* card_ptr) {
+ MutexLockerEx ml(Shared_DirtyCardQ_lock, Mutex::_no_safepoint_check_flag);
+ if (_index == 0) {
+ flush();
+ _buffer = _qset->allocate_buffer();
+ _index = _qset->buffer_size();
+ assert(_index != 0, "invariant");
+ }
+ _buffer[--_index] = card_ptr;
+}
+
+void G1SharedDirtyCardQueue::flush() {
+ if (_buffer != NULL) {
+ BufferNode* node = BufferNode::make_node_from_buffer(_buffer, _index);
+ _buffer = NULL;
+ _index = 0;
+ if (node->index() == _qset->buffer_size()) {
+ _qset->deallocate_buffer(node);
+ } else {
+ _qset->enqueue_completed_buffer(node);
+ }
+ }
+ assert(_index == 0, "invariant");
+}
+
+void G1SharedDirtyCardQueue::reset() {
+ if (_buffer == NULL) {
+ _index = 0;
+ } else {
+ _index = _qset->buffer_size();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/g1/g1SharedDirtyCardQueue.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_GC_G1_G1SHAREDDIRTYCARDQUEUE_HPP
+#define SHARE_GC_G1_G1SHAREDDIRTYCARDQUEUE_HPP
+
+#include "utilities/globalDefinitions.hpp"
+
+class G1DirtyCardQueueSet;
+
+// A dirty card queue providing thread-safe enqueue. A shared global
+// instance can be used for cases where a thread-local dirty card can't
+// be used.
+class G1SharedDirtyCardQueue {
+ G1DirtyCardQueueSet* const _qset;
+ void** _buffer;
+ size_t _index;
+
+ // Noncopyable
+ G1SharedDirtyCardQueue(const G1SharedDirtyCardQueue&);
+ G1SharedDirtyCardQueue& operator=(const G1SharedDirtyCardQueue&);
+
+public:
+ G1SharedDirtyCardQueue(G1DirtyCardQueueSet* qset);
+ ~G1SharedDirtyCardQueue(); // flushes the queue.
+
+ // Thread-safe addition to shared logging buffer.
+ void enqueue(void* card_ptr);
+
+ // Flush any pending entries to the qset and remove the buffer.
+ // Not thread-safe.
+ void flush();
+
+ // Discard any pending entries.
+ // Not thread-safe.
+ void reset();
+};
+
+#endif // SHARE_GC_G1_G1SHAREDDIRTYCARDQUEUE_HPP
--- a/src/hotspot/share/gc/parallel/adjoiningGenerations.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/parallel/adjoiningGenerations.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -119,7 +119,7 @@
}
}
-AdjoiningGenerations::AdjoiningGenerations() { }
+AdjoiningGenerations::AdjoiningGenerations(): _young_gen(NULL), _old_gen(NULL), _virtual_spaces(NULL) { }
size_t AdjoiningGenerations::reserved_byte_size() {
return virtual_spaces()->reserved_space().size();
--- a/src/hotspot/share/gc/parallel/adjoiningGenerations.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/parallel/adjoiningGenerations.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -50,6 +50,7 @@
bool request_young_gen_expansion(size_t desired_change_in_bytes);
protected:
+ AdjoiningGenerations();
// The young generation and old generation, respectively
PSYoungGen* _young_gen;
PSOldGen* _old_gen;
@@ -59,7 +60,6 @@
public:
AdjoiningGenerations(ReservedSpace rs, GenerationSizer* policy, size_t alignment);
- AdjoiningGenerations();
// Accessors
PSYoungGen* young_gen() { return _young_gen; }
--- a/src/hotspot/share/gc/parallel/gcTaskThread.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/parallel/gcTaskThread.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, 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
@@ -167,7 +167,6 @@
// so that a task can complete without waiting for idle tasks.
// They have to be terminated separately.
IdleGCTask::destroy((IdleGCTask*)task);
- set_is_working(true);
}
// Check if we should release our inner resources.
--- a/src/hotspot/share/gc/parallel/gcTaskThread.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/parallel/gcTaskThread.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -47,8 +47,6 @@
GCTaskTimeStamp* time_stamp_at(uint index);
void add_task_timestamp(const char* name, jlong t_entry, jlong t_exit);
- bool _is_working; // True if participating in GC tasks
-
// Factory create and destroy methods.
static GCTaskThread* create(GCTaskManager* manager,
uint which,
@@ -85,7 +83,6 @@
uint processor_id() const {
return _processor_id;
}
- void set_is_working(bool v) { _is_working = v; }
};
class GCTaskTimeStamp : public CHeapObj<mtGC>
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -93,7 +93,15 @@
public:
ParallelScavengeHeap(GenerationSizer* policy) :
- CollectedHeap(), _collector_policy(policy), _death_march_count(0) { }
+ CollectedHeap(),
+ _collector_policy(policy),
+ _gens(NULL),
+ _death_march_count(0),
+ _young_manager(NULL),
+ _old_manager(NULL),
+ _eden_pool(NULL),
+ _survivor_pool(NULL),
+ _old_pool(NULL) { }
// For use by VM operations
enum CollectionType {
--- a/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -49,34 +49,25 @@
init_survivor_size,
gc_pause_goal_sec,
gc_cost_ratio),
+ _avg_major_pause(new AdaptivePaddedAverage(AdaptiveTimeWeight, PausePadding)),
+ _avg_base_footprint(new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight)),
+ _gc_stats(),
_collection_cost_margin_fraction(AdaptiveSizePolicyCollectionCostMargin / 100.0),
+ _major_pause_old_estimator(new LinearLeastSquareFit(AdaptiveSizePolicyWeight)),
+ _major_pause_young_estimator(new LinearLeastSquareFit(AdaptiveSizePolicyWeight)),
_latest_major_mutator_interval_seconds(0),
_space_alignment(space_alignment),
_gc_minor_pause_goal_sec(gc_minor_pause_goal_sec),
_live_at_last_full_gc(init_promo_size),
- _young_gen_change_for_major_pause_count(0)
+ _change_old_gen_for_min_pauses(0),
+ _change_young_gen_for_maj_pauses(0),
+ _old_gen_policy_is_ready(false),
+ _young_gen_size_increment_supplement(YoungGenerationSizeSupplement),
+ _old_gen_size_increment_supplement(TenuredGenerationSizeSupplement),
+ _bytes_absorbed_from_eden(0)
{
- // Sizing policy statistics
- _avg_major_pause =
- new AdaptivePaddedAverage(AdaptiveTimeWeight, PausePadding);
- _avg_minor_interval = new AdaptiveWeightedAverage(AdaptiveTimeWeight);
- _avg_major_interval = new AdaptiveWeightedAverage(AdaptiveTimeWeight);
-
- _avg_base_footprint = new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight);
- _major_pause_old_estimator =
- new LinearLeastSquareFit(AdaptiveSizePolicyWeight);
- _major_pause_young_estimator =
- new LinearLeastSquareFit(AdaptiveSizePolicyWeight);
- _major_collection_estimator =
- new LinearLeastSquareFit(AdaptiveSizePolicyWeight);
-
- _young_gen_size_increment_supplement = YoungGenerationSizeSupplement;
- _old_gen_size_increment_supplement = TenuredGenerationSizeSupplement;
-
// Start the timers
_major_timer.start();
-
- _old_gen_policy_is_ready = false;
}
size_t PSAdaptiveSizePolicy::calculate_free_based_on_live(size_t live, uintx ratio_as_percentage) {
--- a/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -75,7 +75,6 @@
// Statistical data gathered for GC
GCStats _gc_stats;
- size_t _survivor_size_limit; // Limit in bytes of survivor size
const double _collection_cost_margin_fraction;
// Variable for estimating the major and minor pause times.
@@ -111,13 +110,6 @@
// Flag indicating that the adaptive policy is ready to use
bool _old_gen_policy_is_ready;
- // Changing the generation sizing depends on the data that is
- // gathered about the effects of changes on the pause times and
- // throughput. These variable count the number of data points
- // gathered. The policy may use these counters as a threshold
- // for reliable data.
- julong _young_gen_change_for_major_pause_count;
-
// To facilitate faster growth at start up, supplement the normal
// growth percentage for the young gen eden and the
// old gen space for promotion with these value which decay
--- a/src/hotspot/share/gc/parallel/psFileBackedVirtualspace.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/parallel/psFileBackedVirtualspace.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -51,10 +51,6 @@
return true;
}
-PSFileBackedVirtualSpace::PSFileBackedVirtualSpace(ReservedSpace rs, const char* path) {
- PSFileBackedVirtualSpace(rs, os::vm_page_size(), path);
-}
-
bool PSFileBackedVirtualSpace::expand_by(size_t bytes) {
assert(special(), "Since entire space is committed at initialization, _special should always be true for PSFileBackedVirtualSpace");
--- a/src/hotspot/share/gc/parallel/psFileBackedVirtualspace.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/parallel/psFileBackedVirtualspace.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -34,7 +34,6 @@
bool _mapping_succeeded;
public:
PSFileBackedVirtualSpace(ReservedSpace rs, size_t alignment, const char* file_path);
- PSFileBackedVirtualSpace(ReservedSpace rs, const char* file_path);
bool initialize();
bool expand_by(size_t bytes);
--- a/src/hotspot/share/gc/parallel/psMarkSweepDecorator.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/parallel/psMarkSweepDecorator.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -52,7 +52,11 @@
public:
PSMarkSweepDecorator(MutableSpace* space, ObjectStartArray* start_array,
size_t allowed_dead_ratio) :
- _space(space), _start_array(start_array),
+ _space(space),
+ _start_array(start_array),
+ _first_dead(NULL),
+ _end_of_live(NULL),
+ _compaction_top(NULL),
_allowed_dead_ratio(allowed_dead_ratio) { }
// During a compacting collection, we need to collapse objects into
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -406,19 +406,16 @@
size_t mark_bitmap_size;
#endif // #ifdef ASSERT
-ParallelCompactData::ParallelCompactData()
-{
- _region_start = 0;
-
- _region_vspace = 0;
- _reserved_byte_size = 0;
- _region_data = 0;
- _region_count = 0;
-
- _block_vspace = 0;
- _block_data = 0;
- _block_count = 0;
-}
+ParallelCompactData::ParallelCompactData() :
+ _region_start(NULL),
+ DEBUG_ONLY(_region_end(NULL) COMMA)
+ _region_vspace(NULL),
+ _reserved_byte_size(0),
+ _region_data(NULL),
+ _region_count(0),
+ _block_vspace(NULL),
+ _block_data(NULL),
+ _block_count(0) {}
bool ParallelCompactData::initialize(MemRegion covered_region)
{
--- a/src/hotspot/share/gc/parallel/psVirtualspace.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/parallel/psVirtualspace.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -46,7 +46,13 @@
}
// Deprecated.
-PSVirtualSpace::PSVirtualSpace(): _alignment(os::vm_page_size()) {
+PSVirtualSpace::PSVirtualSpace():
+ _alignment(os::vm_page_size()),
+ _reserved_low_addr(NULL),
+ _reserved_high_addr(NULL),
+ _committed_low_addr(NULL),
+ _committed_high_addr(NULL),
+ _special(false) {
}
// Deprecated.
--- a/src/hotspot/share/gc/parallel/psVirtualspace.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/parallel/psVirtualspace.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -64,7 +64,14 @@
// Eventually all instances should be created with the above 1- or 2-arg
// constructors. Then the 1st constructor below should become protected and
// the 2nd ctor and initialize() removed.
- PSVirtualSpace(size_t alignment): _alignment(alignment) { }
+ PSVirtualSpace(size_t alignment):
+ _alignment(alignment),
+ _reserved_low_addr(NULL),
+ _reserved_high_addr(NULL),
+ _committed_low_addr(NULL),
+ _committed_high_addr(NULL),
+ _special(false) {
+ }
PSVirtualSpace();
bool initialize(ReservedSpace rs, size_t commit_size);
--- a/src/hotspot/share/gc/parallel/psYoungGen.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/parallel/psYoungGen.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, 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
@@ -35,12 +35,22 @@
#include "runtime/java.hpp"
#include "utilities/align.hpp"
-PSYoungGen::PSYoungGen(size_t initial_size,
- size_t min_size,
- size_t max_size) :
+PSYoungGen::PSYoungGen(size_t initial_size, size_t min_size, size_t max_size) :
+ _reserved(),
+ _virtual_space(NULL),
+ _eden_space(NULL),
+ _from_space(NULL),
+ _to_space(NULL),
+ _eden_mark_sweep(NULL),
+ _from_mark_sweep(NULL),
+ _to_mark_sweep(NULL),
_init_gen_size(initial_size),
_min_gen_size(min_size),
- _max_gen_size(max_size)
+ _max_gen_size(max_size),
+ _gen_counters(NULL),
+ _eden_counters(NULL),
+ _from_counters(NULL),
+ _to_counters(NULL)
{}
void PSYoungGen::initialize_virtual_space(ReservedSpace rs, size_t alignment) {
--- a/src/hotspot/share/gc/shared/adaptiveSizePolicy.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/shared/adaptiveSizePolicy.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -48,40 +48,38 @@
_eden_size(init_eden_size),
_promo_size(init_promo_size),
_survivor_size(init_survivor_size),
+ _avg_minor_pause(new AdaptivePaddedAverage(AdaptiveTimeWeight, PausePadding)),
+ _avg_minor_interval(new AdaptiveWeightedAverage(AdaptiveTimeWeight)),
+ _avg_minor_gc_cost(new AdaptiveWeightedAverage(AdaptiveTimeWeight)),
+ _avg_major_interval(new AdaptiveWeightedAverage(AdaptiveTimeWeight)),
+ _avg_major_gc_cost(new AdaptiveWeightedAverage(AdaptiveTimeWeight)),
+ _avg_young_live(new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight)),
+ _avg_eden_live(new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight)),
+ _avg_old_live(new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight)),
+ _avg_survived(new AdaptivePaddedAverage(AdaptiveSizePolicyWeight, SurvivorPadding)),
+ _avg_pretenured(new AdaptivePaddedNoZeroDevAverage(AdaptiveSizePolicyWeight, SurvivorPadding)),
+ _minor_pause_old_estimator(new LinearLeastSquareFit(AdaptiveSizePolicyWeight)),
+ _minor_pause_young_estimator(new LinearLeastSquareFit(AdaptiveSizePolicyWeight)),
+ _minor_collection_estimator(new LinearLeastSquareFit(AdaptiveSizePolicyWeight)),
+ _major_collection_estimator(new LinearLeastSquareFit(AdaptiveSizePolicyWeight)),
_latest_minor_mutator_interval_seconds(0),
_threshold_tolerance_percent(1.0 + ThresholdTolerance/100.0),
_gc_pause_goal_sec(gc_pause_goal_sec),
+ _young_gen_policy_is_ready(false),
+ _change_young_gen_for_min_pauses(0),
+ _change_old_gen_for_maj_pauses(0),
+ _change_old_gen_for_throughput(0),
+ _change_young_gen_for_throughput(0),
+ _increment_tenuring_threshold_for_gc_cost(false),
+ _decrement_tenuring_threshold_for_gc_cost(false),
+ _decrement_tenuring_threshold_for_survivor_limit(false),
+ _decrease_for_footprint(0),
+ _decide_at_full_gc(0),
_young_gen_change_for_minor_throughput(0),
_old_gen_change_for_major_throughput(0) {
- _avg_minor_pause =
- new AdaptivePaddedAverage(AdaptiveTimeWeight, PausePadding);
- _avg_minor_interval = new AdaptiveWeightedAverage(AdaptiveTimeWeight);
- _avg_minor_gc_cost = new AdaptiveWeightedAverage(AdaptiveTimeWeight);
- _avg_major_gc_cost = new AdaptiveWeightedAverage(AdaptiveTimeWeight);
-
- _avg_young_live = new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight);
- _avg_old_live = new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight);
- _avg_eden_live = new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight);
-
- _avg_survived = new AdaptivePaddedAverage(AdaptiveSizePolicyWeight,
- SurvivorPadding);
- _avg_pretenured = new AdaptivePaddedNoZeroDevAverage(
- AdaptiveSizePolicyWeight,
- SurvivorPadding);
-
- _minor_pause_old_estimator =
- new LinearLeastSquareFit(AdaptiveSizePolicyWeight);
- _minor_pause_young_estimator =
- new LinearLeastSquareFit(AdaptiveSizePolicyWeight);
- _minor_collection_estimator =
- new LinearLeastSquareFit(AdaptiveSizePolicyWeight);
- _major_collection_estimator =
- new LinearLeastSquareFit(AdaptiveSizePolicyWeight);
// Start the timers
_minor_timer.start();
-
- _young_gen_policy_is_ready = false;
}
bool AdaptiveSizePolicy::tenuring_threshold_change() const {
--- a/src/hotspot/share/gc/shared/concurrentGCThread.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/shared/concurrentGCThread.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, 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
@@ -54,13 +54,6 @@
assert(this == Thread::current(), "just checking");
}
-void ConcurrentGCThread::wait_for_universe_init() {
- MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
- while (!is_init_completed() && !_should_terminate) {
- CGC_lock->wait(Mutex::_no_safepoint_check_flag, 1);
- }
-}
-
void ConcurrentGCThread::terminate() {
assert(_should_terminate, "Should only be called on terminate request.");
// Signal that it is terminated
@@ -74,7 +67,7 @@
void ConcurrentGCThread::run() {
initialize_in_thread();
- wait_for_universe_init();
+ wait_init_completed();
run_service();
--- a/src/hotspot/share/gc/shared/gcStats.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/shared/gcStats.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -26,8 +26,4 @@
#include "gc/shared/gcStats.hpp"
#include "gc/shared/gcUtil.inline.hpp"
-GCStats::GCStats() {
- _avg_promoted = new AdaptivePaddedNoZeroDevAverage(
- AdaptiveSizePolicyWeight,
- PromotedPadding);
-}
+GCStats::GCStats() : _avg_promoted(new AdaptivePaddedNoZeroDevAverage(AdaptiveSizePolicyWeight, PromotedPadding)) {}
--- a/src/hotspot/share/gc/shared/ptrQueue.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/shared/ptrQueue.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -36,18 +36,16 @@
#include <new>
-PtrQueue::PtrQueue(PtrQueueSet* qset, bool permanent, bool active) :
+PtrQueue::PtrQueue(PtrQueueSet* qset, bool active) :
_qset(qset),
_active(active),
- _permanent(permanent),
_index(0),
_capacity_in_bytes(0),
- _buf(NULL),
- _lock(NULL)
+ _buf(NULL)
{}
PtrQueue::~PtrQueue() {
- assert(_permanent || (_buf == NULL), "queue must be flushed before delete");
+ assert(_buf == NULL, "queue must be flushed before delete");
}
void PtrQueue::flush_impl() {
@@ -271,23 +269,13 @@
return;
}
- if (_lock) {
- assert(_lock->owned_by_self(), "Required.");
-
- BufferNode* node = BufferNode::make_node_from_buffer(_buf, index());
- _buf = NULL; // clear shared _buf field
-
- qset()->enqueue_completed_buffer(node);
- assert(_buf == NULL, "multiple enqueuers appear to be racing");
- } else {
- BufferNode* node = BufferNode::make_node_from_buffer(_buf, index());
- if (qset()->process_or_enqueue_completed_buffer(node)) {
- // Recycle the buffer. No allocation.
- assert(_buf == BufferNode::make_buffer_from_node(node), "invariant");
- assert(capacity() == qset()->buffer_size(), "invariant");
- reset();
- return;
- }
+ BufferNode* node = BufferNode::make_node_from_buffer(_buf, index());
+ if (qset()->process_or_enqueue_completed_buffer(node)) {
+ // Recycle the buffer. No allocation.
+ assert(_buf == BufferNode::make_buffer_from_node(node), "invariant");
+ assert(capacity() == qset()->buffer_size(), "invariant");
+ reset();
+ return;
}
}
// Set capacity in case this is the first allocation.
--- a/src/hotspot/share/gc/shared/ptrQueue.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/shared/ptrQueue.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -54,11 +54,6 @@
// Whether updates should be logged.
bool _active;
- // If true, the queue is permanent, and doesn't need to deallocate
- // its buffer in the destructor (since that obtains a lock which may not
- // be legally locked by then.
- const bool _permanent;
-
// The (byte) index at which an object was last enqueued. Starts at
// capacity_in_bytes (indicating an empty buffer) and goes towards zero.
// Value is always pointer-size aligned.
@@ -111,27 +106,20 @@
return byte_index_to_index(capacity_in_bytes());
}
- // If there is a lock associated with this buffer, this is that lock.
- Mutex* _lock;
-
PtrQueueSet* qset() { return _qset; }
- bool is_permanent() const { return _permanent; }
// Process queue entries and release resources.
void flush_impl();
// Initialize this queue to contain a null buffer, and be part of the
// given PtrQueueSet.
- PtrQueue(PtrQueueSet* qset, bool permanent = false, bool active = false);
+ PtrQueue(PtrQueueSet* qset, bool active = false);
- // Requires queue flushed or permanent.
+ // Requires queue flushed.
~PtrQueue();
public:
- // Associate a lock with a ptr queue.
- void set_lock(Mutex* lock) { _lock = lock; }
-
// Forcibly set empty.
void reset() {
if (_buf != NULL) {
--- a/src/hotspot/share/gc/shared/satbMarkQueue.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/shared/satbMarkQueue.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -35,14 +35,14 @@
#include "runtime/threadSMR.hpp"
#include "runtime/vmThread.hpp"
-SATBMarkQueue::SATBMarkQueue(SATBMarkQueueSet* qset, bool permanent) :
+SATBMarkQueue::SATBMarkQueue(SATBMarkQueueSet* qset) :
// SATB queues are only active during marking cycles. We create
// them with their active field set to false. If a thread is
// created during a cycle and its SATB queue needs to be activated
// before the thread starts running, we'll need to set its active
// field to true. This must be done in the collector-specific
// BarrierSet thread attachment protocol.
- PtrQueue(qset, permanent, false /* active */)
+ PtrQueue(qset, false /* active */)
{ }
void SATBMarkQueue::flush() {
--- a/src/hotspot/share/gc/shared/satbMarkQueue.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/shared/satbMarkQueue.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -55,7 +55,7 @@
inline void apply_filter(Filter filter_out);
public:
- SATBMarkQueue(SATBMarkQueueSet* qset, bool permanent = false);
+ SATBMarkQueue(SATBMarkQueueSet* qset);
// Process queue entries and free resources.
void flush();
--- a/src/hotspot/share/gc/shenandoah/shenandoahSATBMarkQueueSet.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahSATBMarkQueueSet.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -31,7 +31,7 @@
class ShenandoahSATBMarkQueue: public SATBMarkQueue {
public:
- ShenandoahSATBMarkQueue(SATBMarkQueueSet* qset) : SATBMarkQueue(qset, /* permanent = */ false) {}
+ ShenandoahSATBMarkQueue(SATBMarkQueueSet* qset) : SATBMarkQueue(qset) {}
virtual bool should_enqueue_buffer();
};
--- a/src/hotspot/share/gc/z/zNMethodTableEntry.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/z/zNMethodTableEntry.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -37,13 +37,11 @@
// |11111111 11111111 11111111 11111111 11111111 11111111 11111111 111111|1|1|
// +---------------------------------------------------------------------+-+-+
// | | |
-// | | |
-// | | |
// | 1-1 Unregistered Flag (1-bits) * |
// | |
// | 0-0 Registered Flag (1-bits) *
// |
-// * 63-3 NMethod Address (61-bits)
+// * 63-2 NMethod Address (62-bits)
//
class nmethod;
--- a/src/hotspot/share/gc/z/zObjectAllocator.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/z/zObjectAllocator.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -186,10 +186,6 @@
ZAllocationFlags flags;
flags.set_no_reserve();
- if (!ZStallOnOutOfMemory) {
- flags.set_non_blocking();
- }
-
return alloc_object(size, flags);
}
--- a/src/hotspot/share/gc/z/z_globals.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/gc/z/z_globals.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -39,28 +39,24 @@
constraint, \
writeable) \
\
- product(ccstr, ZPath, NULL, \
+ experimental(ccstr, ZPath, NULL, \
"Filesystem path for Java heap backing storage " \
"(must be a tmpfs or a hugetlbfs filesystem)") \
\
- product(double, ZAllocationSpikeTolerance, 2.0, \
+ experimental(double, ZAllocationSpikeTolerance, 2.0, \
"Allocation spike tolerance factor") \
\
- product(double, ZFragmentationLimit, 25.0, \
+ experimental(double, ZFragmentationLimit, 25.0, \
"Maximum allowed heap fragmentation") \
\
- product(bool, ZStallOnOutOfMemory, true, \
- "Allow Java threads to stall and wait for GC to complete " \
- "instead of immediately throwing an OutOfMemoryError") \
- \
- product(size_t, ZMarkStackSpaceLimit, 8*G, \
+ experimental(size_t, ZMarkStackSpaceLimit, 8*G, \
"Maximum number of bytes allocated for mark stacks") \
range(32*M, 1024*G) \
\
- product(uint, ZCollectionInterval, 0, \
+ experimental(uint, ZCollectionInterval, 0, \
"Force GC at a fixed time interval (in seconds)") \
\
- product(uint, ZStatisticsInterval, 10, \
+ diagnostic(uint, ZStatisticsInterval, 10, \
"Time between statistics print outs (in seconds)") \
range(1, (uint)-1) \
\
--- a/src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -46,13 +46,9 @@
return _chunkstate != NULL;
}
-static fio_fd open_existing(const char* path) {
- return os::open(path, O_RDWR, S_IREAD | S_IWRITE);
-}
-
static fio_fd open_chunk(const char* path) {
assert(JfrStream_lock->owned_by_self(), "invariant");
- return path != NULL ? open_existing(path) : invalid_fd;
+ return path != NULL ? os::open(path, O_CREAT | O_RDWR, S_IREAD | S_IWRITE) : invalid_fd;
}
bool JfrChunkWriter::open() {
--- a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -24,17 +24,315 @@
#include "precompiled.hpp"
#include "jfr/jfrEvents.hpp"
+#include "jfr/jni/jfrJavaSupport.hpp"
#include "jfr/leakprofiler/leakProfiler.hpp"
#include "jfr/recorder/repository/jfrEmergencyDump.hpp"
#include "jfr/recorder/service/jfrPostBox.hpp"
#include "jfr/recorder/service/jfrRecorderService.hpp"
#include "jfr/utilities/jfrTypes.hpp"
+#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/atomic.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/globals.hpp"
#include "runtime/mutexLocker.hpp"
-#include "runtime/thread.hpp"
+#include "runtime/os.hpp"
+#include "runtime/thread.inline.hpp"
+#include "utilities/growableArray.hpp"
+
+static const char vm_error_filename_fmt[] = "hs_err_pid%p.jfr";
+static const char vm_oom_filename_fmt[] = "hs_oom_pid%p.jfr";
+static const char vm_soe_filename_fmt[] = "hs_soe_pid%p.jfr";
+static const char chunk_file_jfr_ext[] = ".jfr";
+static const size_t iso8601_len = 19; // "YYYY-MM-DDTHH:MM:SS"
+
+static fio_fd open_exclusivly(const char* path) {
+ return os::open(path, O_CREAT | O_RDWR, S_IREAD | S_IWRITE);
+}
+
+static int file_sort(const char** const file1, const char** file2) {
+ assert(NULL != *file1 && NULL != *file2, "invariant");
+ int cmp = strncmp(*file1, *file2, iso8601_len);
+ if (0 == cmp) {
+ const char* const dot1 = strchr(*file1, '.');
+ assert(NULL != dot1, "invariant");
+ const char* const dot2 = strchr(*file2, '.');
+ assert(NULL != dot2, "invariant");
+ ptrdiff_t file1_len = dot1 - *file1;
+ ptrdiff_t file2_len = dot2 - *file2;
+ if (file1_len < file2_len) {
+ return -1;
+ }
+ if (file1_len > file2_len) {
+ return 1;
+ }
+ assert(file1_len == file2_len, "invariant");
+ cmp = strncmp(*file1, *file2, file1_len);
+ }
+ assert(cmp != 0, "invariant");
+ return cmp;
+}
+
+static void iso8601_to_date_time(char* iso8601_str) {
+ assert(iso8601_str != NULL, "invariant");
+ assert(strlen(iso8601_str) == iso8601_len, "invariant");
+ // "YYYY-MM-DDTHH:MM:SS"
+ for (size_t i = 0; i < iso8601_len; ++i) {
+ switch (iso8601_str[i]) {
+ case 'T':
+ case '-':
+ case ':':
+ iso8601_str[i] = '_';
+ break;
+ }
+ }
+ // "YYYY_MM_DD_HH_MM_SS"
+}
+
+static void date_time(char* buffer, size_t buffer_len) {
+ assert(buffer != NULL, "invariant");
+ assert(buffer_len >= iso8601_len, "buffer too small");
+ os::iso8601_time(buffer, buffer_len);
+ assert(strlen(buffer) >= iso8601_len + 1, "invariant");
+ // "YYYY-MM-DDTHH:MM:SS"
+ buffer[iso8601_len] = '\0';
+ iso8601_to_date_time(buffer);
+}
+
+static int64_t file_size(fio_fd fd) {
+ assert(fd != invalid_fd, "invariant");
+ const int64_t current_offset = os::current_file_offset(fd);
+ const int64_t size = os::lseek(fd, 0, SEEK_END);
+ os::seek_to_file_offset(fd, current_offset);
+ return size;
+}
+
+class RepositoryIterator : public StackObj {
+ private:
+ const char* const _repo;
+ const size_t _repository_len;
+ GrowableArray<const char*>* _files;
+ const char* const fully_qualified(const char* entry) const;
+ mutable int _iterator;
+
+ public:
+ RepositoryIterator(const char* repository, size_t repository_len);
+ ~RepositoryIterator() {}
+ const char* const filter(const char* entry) const;
+ bool has_next() const;
+ const char* const next() const;
+};
+
+const char* const RepositoryIterator::fully_qualified(const char* entry) const {
+ assert(NULL != entry, "invariant");
+ char* file_path_entry = NULL;
+ // only use files that have content, not placeholders
+ const char* const file_separator = os::file_separator();
+ if (NULL != file_separator) {
+ const size_t entry_len = strlen(entry);
+ const size_t file_separator_length = strlen(file_separator);
+ const size_t file_path_entry_length = _repository_len + file_separator_length + entry_len;
+ file_path_entry = NEW_RESOURCE_ARRAY_RETURN_NULL(char, file_path_entry_length + 1);
+ if (NULL == file_path_entry) {
+ return NULL;
+ }
+ int position = 0;
+ position += jio_snprintf(&file_path_entry[position], _repository_len + 1, "%s", _repo);
+ position += jio_snprintf(&file_path_entry[position], file_separator_length + 1, "%s", os::file_separator());
+ position += jio_snprintf(&file_path_entry[position], entry_len + 1, "%s", entry);
+ file_path_entry[position] = '\0';
+ assert((size_t)position == file_path_entry_length, "invariant");
+ assert(strlen(file_path_entry) == (size_t)position, "invariant");
+ }
+ return file_path_entry;
+}
+
+const char* const RepositoryIterator::filter(const char* entry) const {
+ if (entry == NULL) {
+ return NULL;
+ }
+ const size_t entry_len = strlen(entry);
+ if (entry_len <= 2) {
+ // for "." and ".."
+ return NULL;
+ }
+ char* entry_name = NEW_RESOURCE_ARRAY_RETURN_NULL(char, entry_len + 1);
+ if (entry_name == NULL) {
+ return NULL;
+ }
+ strncpy(entry_name, entry, entry_len + 1);
+ const char* const fully_qualified_path_entry = fully_qualified(entry_name);
+ if (NULL == fully_qualified_path_entry) {
+ return NULL;
+ }
+ const fio_fd entry_fd = open_exclusivly(fully_qualified_path_entry);
+ if (invalid_fd == entry_fd) {
+ return NULL;
+ }
+ const int64_t entry_size = file_size(entry_fd);
+ os::close(entry_fd);
+ if (0 == entry_size) {
+ return NULL;
+ }
+ return entry_name;
+}
+
+RepositoryIterator::RepositoryIterator(const char* repository, size_t repository_len) :
+ _repo(repository),
+ _repository_len(repository_len),
+ _files(NULL),
+ _iterator(0) {
+ if (NULL != _repo) {
+ assert(strlen(_repo) == _repository_len, "invariant");
+ _files = new GrowableArray<const char*>(10);
+ DIR* dirp = os::opendir(_repo);
+ if (dirp == NULL) {
+ log_error(jfr, system)("Unable to open repository %s", _repo);
+ return;
+ }
+ struct dirent* dentry;
+ while ((dentry = os::readdir(dirp)) != NULL) {
+ const char* const entry_path = filter(dentry->d_name);
+ if (NULL != entry_path) {
+ _files->append(entry_path);
+ }
+ }
+ os::closedir(dirp);
+ if (_files->length() > 1) {
+ _files->sort(file_sort);
+ }
+ }
+}
+
+bool RepositoryIterator::has_next() const {
+ return (_files != NULL && _iterator < _files->length());
+}
+
+const char* const RepositoryIterator::next() const {
+ return _iterator >= _files->length() ? NULL : fully_qualified(_files->at(_iterator++));
+}
+
+static void write_emergency_file(fio_fd emergency_fd, const RepositoryIterator& iterator) {
+ assert(emergency_fd != invalid_fd, "invariant");
+ const size_t size_of_file_copy_block = 1 * M; // 1 mb
+ jbyte* const file_copy_block = NEW_RESOURCE_ARRAY_RETURN_NULL(jbyte, size_of_file_copy_block);
+ if (file_copy_block == NULL) {
+ return;
+ }
+ while (iterator.has_next()) {
+ fio_fd current_fd = invalid_fd;
+ const char* const fqn = iterator.next();
+ if (fqn != NULL) {
+ current_fd = open_exclusivly(fqn);
+ if (current_fd != invalid_fd) {
+ const int64_t current_filesize = file_size(current_fd);
+ assert(current_filesize > 0, "invariant");
+ int64_t bytes_read = 0;
+ int64_t bytes_written = 0;
+ while (bytes_read < current_filesize) {
+ const ssize_t read_result = os::read_at(current_fd, file_copy_block, size_of_file_copy_block, bytes_read);
+ if (-1 == read_result) {
+ log_info(jfr)( // For user, should not be "jfr, system"
+ "Unable to recover JFR data");
+ break;
+ }
+ bytes_read += (int64_t)read_result;
+ assert(bytes_read - bytes_written <= (int64_t)size_of_file_copy_block, "invariant");
+ bytes_written += (int64_t)os::write(emergency_fd, file_copy_block, bytes_read - bytes_written);
+ assert(bytes_read == bytes_written, "invariant");
+ }
+ os::close(current_fd);
+ }
+ }
+ }
+}
+
+static const char* create_emergency_dump_path() {
+ assert(JfrStream_lock->owned_by_self(), "invariant");
+ char* buffer = NEW_RESOURCE_ARRAY_RETURN_NULL(char, JVM_MAXPATHLEN);
+ if (NULL == buffer) {
+ return NULL;
+ }
+ const char* const cwd = os::get_current_directory(buffer, JVM_MAXPATHLEN);
+ if (NULL == cwd) {
+ return NULL;
+ }
+ size_t pos = strlen(cwd);
+ const int fsep_len = jio_snprintf(&buffer[pos], JVM_MAXPATHLEN - pos, "%s", os::file_separator());
+ const char* filename_fmt = NULL;
+ // fetch specific error cause
+ switch (JfrJavaSupport::cause()) {
+ case JfrJavaSupport::OUT_OF_MEMORY:
+ filename_fmt = vm_oom_filename_fmt;
+ break;
+ case JfrJavaSupport::STACK_OVERFLOW:
+ filename_fmt = vm_soe_filename_fmt;
+ break;
+ default:
+ filename_fmt = vm_error_filename_fmt;
+ }
+ char* emergency_dump_path = NULL;
+ pos += fsep_len;
+ if (Arguments::copy_expand_pid(filename_fmt, strlen(filename_fmt), &buffer[pos], JVM_MAXPATHLEN - pos)) {
+ const size_t emergency_filename_length = strlen(buffer);
+ emergency_dump_path = NEW_RESOURCE_ARRAY_RETURN_NULL(char, emergency_filename_length + 1);
+ if (NULL == emergency_dump_path) {
+ return NULL;
+ }
+ strncpy(emergency_dump_path, buffer, emergency_filename_length + 1);
+ }
+ if (emergency_dump_path != NULL) {
+ log_info(jfr)( // For user, should not be "jfr, system"
+ "Attempting to recover JFR data, emergency jfr file: %s", emergency_dump_path);
+ }
+ return emergency_dump_path;
+}
+
+// Caller needs ResourceMark
+static const char* create_emergency_chunk_path(const char* repository_path) {
+ assert(repository_path != NULL, "invariant");
+ assert(JfrStream_lock->owned_by_self(), "invariant");
+ const size_t repository_path_len = strlen(repository_path);
+ // date time
+ char date_time_buffer[32] = { 0 };
+ date_time(date_time_buffer, sizeof(date_time_buffer));
+ size_t date_time_len = strlen(date_time_buffer);
+ size_t chunkname_max_len = repository_path_len // repository_base_path
+ + 1 // "/"
+ + date_time_len // date_time
+ + strlen(chunk_file_jfr_ext) // .jfr
+ + 1;
+ char* chunk_path = NEW_RESOURCE_ARRAY_RETURN_NULL(char, chunkname_max_len);
+ if (chunk_path == NULL) {
+ return NULL;
+ }
+ // append the individual substrings
+ jio_snprintf(chunk_path, chunkname_max_len, "%s%s%s%s", repository_path_len, os::file_separator(), date_time_buffer, chunk_file_jfr_ext);
+ return chunk_path;
+}
+
+static fio_fd emergency_dump_file_descriptor() {
+ assert(JfrStream_lock->owned_by_self(), "invariant");
+ ResourceMark rm;
+ const char* const emergency_dump_path = create_emergency_dump_path();
+ return emergency_dump_path != NULL ? open_exclusivly(emergency_dump_path) : invalid_fd;
+}
+
+const char* JfrEmergencyDump::build_dump_path(const char* repository_path) {
+ return repository_path == NULL ? create_emergency_dump_path() : create_emergency_chunk_path(repository_path);
+}
+
+void JfrEmergencyDump::on_vm_error(const char* repository_path) {
+ assert(repository_path != NULL, "invariant");
+ ResourceMark rm;
+ MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
+ const fio_fd emergency_fd = emergency_dump_file_descriptor();
+ if (emergency_fd != invalid_fd) {
+ RepositoryIterator iterator(repository_path, strlen(repository_path));
+ write_emergency_file(emergency_fd, iterator);
+ os::close(emergency_fd);
+ }
+}
/*
* We are just about to exit the VM, so we will be very aggressive
--- a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -33,6 +33,8 @@
class JfrEmergencyDump : AllStatic {
public:
static void on_vm_shutdown(bool exception_handler);
+ static void on_vm_error(const char* repository_path);
+ static const char* build_dump_path(const char* repository_path);
};
#endif // SHARE_JFR_RECORDER_REPOSITORY_JFREMERGENCYDUMP_HPP
--- a/src/hotspot/share/jfr/recorder/repository/jfrRepository.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/jfr/recorder/repository/jfrRepository.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -28,12 +28,11 @@
#include "jfr/recorder/jfrRecorder.hpp"
#include "jfr/recorder/repository/jfrChunkState.hpp"
#include "jfr/recorder/repository/jfrChunkWriter.hpp"
+#include "jfr/recorder/repository/jfrEmergencyDump.hpp"
#include "jfr/recorder/repository/jfrRepository.hpp"
#include "jfr/recorder/service/jfrPostBox.hpp"
-#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/mutex.hpp"
-#include "runtime/os.hpp"
#include "runtime/thread.inline.hpp"
static JfrRepository* _instance = NULL;
@@ -84,321 +83,13 @@
_instance = NULL;
}
-static const char vm_error_filename_fmt[] = "hs_err_pid%p.jfr";
-static const char vm_oom_filename_fmt[] = "hs_oom_pid%p.jfr";
-static const char vm_soe_filename_fmt[] = "hs_soe_pid%p.jfr";
-static const char chunk_file_jfr_ext[] = ".jfr";
-static const size_t iso8601_len = 19; // "YYYY-MM-DDTHH:MM:SS"
-
-static fio_fd open_exclusivly(const char* path) {
- return os::open(path, O_CREAT | O_WRONLY, S_IREAD | S_IWRITE);
-}
-
-static fio_fd open_existing(const char* path) {
- return os::open(path, O_RDWR, S_IREAD | S_IWRITE);
-}
-
-static int file_sort(const char** const file1, const char** file2) {
- assert(NULL != *file1 && NULL != *file2, "invariant");
- int cmp = strncmp(*file1, *file2, iso8601_len);
- if (0 == cmp) {
- const char* const dot1 = strchr(*file1, '.');
- assert(NULL != dot1, "invariant");
- const char* const dot2 = strchr(*file2, '.');
- assert(NULL != dot2, "invariant");
- ptrdiff_t file1_len = dot1 - *file1;
- ptrdiff_t file2_len = dot2 - *file2;
- if (file1_len < file2_len) {
- return -1;
- }
- if (file1_len > file2_len) {
- return 1;
- }
- assert(file1_len == file2_len, "invariant");
- cmp = strncmp(*file1, *file2, file1_len);
- }
- assert(cmp != 0, "invariant");
- return cmp;
-}
-
-static void iso8601_to_date_time(char* iso8601_str) {
- assert(iso8601_str != NULL, "invariant");
- assert(strlen(iso8601_str) == iso8601_len, "invariant");
- // "YYYY-MM-DDTHH:MM:SS"
- for (size_t i = 0; i < iso8601_len; ++i) {
- switch(iso8601_str[i]) {
- case 'T' :
- case '-' :
- case ':' :
- iso8601_str[i] = '_';
- break;
- }
- }
- // "YYYY_MM_DD_HH_MM_SS"
-}
-
-static void date_time(char* buffer, size_t buffer_len) {
- assert(buffer != NULL, "invariant");
- assert(buffer_len >= iso8601_len, "buffer too small");
- os::iso8601_time(buffer, buffer_len);
- assert(strlen(buffer) >= iso8601_len + 1, "invariant");
- // "YYYY-MM-DDTHH:MM:SS"
- buffer[iso8601_len] = '\0';
- iso8601_to_date_time(buffer);
-}
-
-static int64_t file_size(fio_fd fd) {
- assert(fd != invalid_fd, "invariant");
- const int64_t current_offset = os::current_file_offset(fd);
- const int64_t size = os::lseek(fd, 0, SEEK_END);
- os::seek_to_file_offset(fd, current_offset);
- return size;
-}
-
-class RepositoryIterator : public StackObj {
- private:
- const char* const _repo;
- const size_t _repository_len;
- GrowableArray<const char*>* _files;
- const char* const fully_qualified(const char* entry) const;
- mutable int _iterator;
-
- public:
- RepositoryIterator(const char* repository, size_t repository_len);
- ~RepositoryIterator() {}
- debug_only(void print_repository_files() const;)
- const char* const filter(const char* entry) const;
- bool has_next() const;
- const char* const next() const;
-};
-
-const char* const RepositoryIterator::fully_qualified(const char* entry) const {
- assert(NULL != entry, "invariant");
- char* file_path_entry = NULL;
- // only use files that have content, not placeholders
- const char* const file_separator = os::file_separator();
- if (NULL != file_separator) {
- const size_t entry_len = strlen(entry);
- const size_t file_separator_length = strlen(file_separator);
- const size_t file_path_entry_length = _repository_len + file_separator_length + entry_len;
- file_path_entry = NEW_RESOURCE_ARRAY_RETURN_NULL(char, file_path_entry_length + 1);
- if (NULL == file_path_entry) {
- return NULL;
- }
- int position = 0;
- position += jio_snprintf(&file_path_entry[position], _repository_len + 1, "%s", _repo);
- position += jio_snprintf(&file_path_entry[position], file_separator_length + 1, "%s", os::file_separator());
- position += jio_snprintf(&file_path_entry[position], entry_len + 1, "%s", entry);
- file_path_entry[position] = '\0';
- assert((size_t)position == file_path_entry_length, "invariant");
- assert(strlen(file_path_entry) == (size_t)position, "invariant");
- }
- return file_path_entry;
-}
-
-const char* const RepositoryIterator::filter(const char* entry) const {
- if (entry == NULL) {
- return NULL;
- }
- const size_t entry_len = strlen(entry);
- if (entry_len <= 2) {
- // for "." and ".."
- return NULL;
- }
- char* entry_name = NEW_RESOURCE_ARRAY_RETURN_NULL(char, entry_len + 1);
- if (entry_name == NULL) {
- return NULL;
- }
- strncpy(entry_name, entry, entry_len + 1);
- const char* const fully_qualified_path_entry = fully_qualified(entry_name);
- if (NULL == fully_qualified_path_entry) {
- return NULL;
- }
- const fio_fd entry_fd = open_existing(fully_qualified_path_entry);
- if (invalid_fd == entry_fd) {
- return NULL;
- }
- const int64_t entry_size = file_size(entry_fd);
- os::close(entry_fd);
- if (0 == entry_size) {
- return NULL;
- }
- return entry_name;
-}
-
-RepositoryIterator::RepositoryIterator(const char* repository, size_t repository_len) :
- _repo(repository),
- _repository_len(repository_len),
- _files(NULL),
- _iterator(0) {
- if (NULL != _repo) {
- assert(strlen(_repo) == _repository_len, "invariant");
- _files = new GrowableArray<const char*>(10);
- DIR* dirp = os::opendir(_repo);
- if (dirp == NULL) {
- log_error(jfr, system)("Unable to open repository %s", _repo);
- return;
- }
- struct dirent* dentry;
- while ((dentry = os::readdir(dirp)) != NULL) {
- const char* const entry_path = filter(dentry->d_name);
- if (NULL != entry_path) {
- _files->append(entry_path);
- }
- }
- os::closedir(dirp);
- if (_files->length() > 1) {
- _files->sort(file_sort);
- }
- }
-}
-
-#ifdef ASSERT
-void RepositoryIterator::print_repository_files() const {
- while (has_next()) {
- log_error(jfr, system)( "%s", next());
- }
-}
-#endif
-
-bool RepositoryIterator::has_next() const {
- return (_files != NULL && _iterator < _files->length());
-}
-
-const char* const RepositoryIterator::next() const {
- return _iterator >= _files->length() ? NULL : fully_qualified(_files->at(_iterator++));
-}
-
-static void write_emergency_file(fio_fd emergency_fd, const RepositoryIterator& iterator) {
- assert(emergency_fd != invalid_fd, "invariant");
- const size_t size_of_file_copy_block = 1 * M; // 1 mb
- jbyte* const file_copy_block = NEW_RESOURCE_ARRAY_RETURN_NULL(jbyte, size_of_file_copy_block);
- if (file_copy_block == NULL) {
- return;
- }
- int64_t bytes_written_total = 0;
- while (iterator.has_next()) {
- fio_fd current_fd = invalid_fd;
- const char* const fqn = iterator.next();
- if (fqn != NULL) {
- current_fd = open_existing(fqn);
- if (current_fd != invalid_fd) {
- const int64_t current_filesize = file_size(current_fd);
- assert(current_filesize > 0, "invariant");
- int64_t bytes_read = 0;
- int64_t bytes_written = 0;
- while (bytes_read < current_filesize) {
- const ssize_t read_result = os::read_at(current_fd, file_copy_block, size_of_file_copy_block, bytes_read);
- if (-1 == read_result) {
- log_info(jfr) ( // For user, should not be "jfr, system"
- "Unable to recover JFR data");
- break;
- }
- bytes_read += (int64_t)read_result;
- assert(bytes_read - bytes_written <= (int64_t)size_of_file_copy_block, "invariant");
- bytes_written += (int64_t)os::write(emergency_fd, file_copy_block, bytes_read - bytes_written);
- assert(bytes_read == bytes_written, "invariant");
- }
- os::close(current_fd);
- bytes_written_total += bytes_written;
- }
- }
- }
-}
-
-static const char* create_emergency_dump_path() {
- assert(JfrStream_lock->owned_by_self(), "invariant");
- char* buffer = NEW_RESOURCE_ARRAY_RETURN_NULL(char, O_BUFLEN);
- if (NULL == buffer) {
- return NULL;
- }
- const char* const cwd = os::get_current_directory(buffer, O_BUFLEN);
- if (NULL == cwd) {
- return NULL;
- }
- size_t pos = strlen(cwd);
- const int fsep_len = jio_snprintf(&buffer[pos], O_BUFLEN - pos, "%s", os::file_separator());
- const char* filename_fmt = NULL;
- // fetch specific error cause
- switch (JfrJavaSupport::cause()) {
- case JfrJavaSupport::OUT_OF_MEMORY:
- filename_fmt = vm_oom_filename_fmt;
- break;
- case JfrJavaSupport::STACK_OVERFLOW:
- filename_fmt = vm_soe_filename_fmt;
- break;
- default:
- filename_fmt = vm_error_filename_fmt;
- }
- char* emergency_dump_path = NULL;
- pos += fsep_len;
- if (Arguments::copy_expand_pid(filename_fmt, strlen(filename_fmt), &buffer[pos], O_BUFLEN - pos)) {
- const size_t emergency_filename_length = strlen(buffer);
- emergency_dump_path = NEW_RESOURCE_ARRAY_RETURN_NULL(char, emergency_filename_length + 1);
- if (NULL == emergency_dump_path) {
- return NULL;
- }
- strncpy(emergency_dump_path, buffer, emergency_filename_length + 1);
- }
- return emergency_dump_path;
-}
-
-// Caller needs ResourceMark
-static const char* create_emergency_chunk_path(const char* repository_base, size_t repository_len) {
- assert(repository_base != NULL, "invariant");
- assert(JfrStream_lock->owned_by_self(), "invariant");
- // date time
- char date_time_buffer[32] = {0};
- date_time(date_time_buffer, sizeof(date_time_buffer));
- size_t date_time_len = strlen(date_time_buffer);
- size_t chunkname_max_len = repository_len // repository_base
- + 1 // "/"
- + date_time_len // date_time
- + strlen(chunk_file_jfr_ext) // .jfr
- + 1;
- char* chunk_path = NEW_RESOURCE_ARRAY_RETURN_NULL(char, chunkname_max_len);
- if (chunk_path == NULL) {
- return NULL;
- }
- // append the individual substrings
- jio_snprintf(chunk_path, chunkname_max_len, "%s%s%s%s", repository_base, os::file_separator(), date_time_buffer, chunk_file_jfr_ext);
- return chunk_path;
-}
-
-static fio_fd emergency_dump_file() {
- assert(JfrStream_lock->owned_by_self(), "invariant");
- ResourceMark rm;
- const char* const emergency_dump_path = create_emergency_dump_path();
- if (emergency_dump_path == NULL) {
- return invalid_fd;
- }
- const fio_fd fd = open_exclusivly(emergency_dump_path);
- if (fd != invalid_fd) {
- log_info(jfr)( // For user, should not be "jfr, system"
- "Attempting to recover JFR data, emergency jfr file: %s", emergency_dump_path);
- }
- return fd;
-}
-
-static const char* emergency_path(const char* repository, size_t repository_len) {
- return repository == NULL ? create_emergency_dump_path() : create_emergency_chunk_path(repository, repository_len);
-}
-
void JfrRepository::on_vm_error() {
assert(!JfrStream_lock->owned_by_self(), "invariant");
- const char* path = _path;
- if (path == NULL) {
+ if (_path == NULL) {
// completed already
return;
}
- ResourceMark rm;
- MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
- const fio_fd emergency_fd = emergency_dump_file();
- if (emergency_fd != invalid_fd) {
- RepositoryIterator iterator(path, strlen(path));
- write_emergency_file(emergency_fd, iterator);
- os::close(emergency_fd);
- }
+ JfrEmergencyDump::on_vm_error(_path);
}
bool JfrRepository::set_path(const char* path) {
@@ -467,10 +158,7 @@
assert(JfrStream_lock->owned_by_self(), "invariant");
if (vm_error) {
ResourceMark rm;
- const char* repository_path = _path;
- const size_t repository_path_len = repository_path != NULL ? strlen(repository_path) : 0;
- const char* const path = emergency_path(repository_path, repository_path_len);
- _chunkwriter->set_chunk_path(path);
+ _chunkwriter->set_chunk_path(JfrEmergencyDump::build_dump_path(_path));
}
return _chunkwriter->open();
}
--- a/src/hotspot/share/memory/heapInspection.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/memory/heapInspection.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -121,6 +121,11 @@
}
KlassInfoEntry* KlassInfoBucket::lookup(Klass* const k) {
+ // Can happen if k is an archived class that we haven't loaded yet.
+ if (k->java_mirror() == NULL) {
+ return NULL;
+ }
+
KlassInfoEntry* elt = _list;
while (elt != NULL) {
if (elt->is_equal(k)) {
@@ -202,7 +207,8 @@
assert(_buckets != NULL, "Allocation failure should have been caught");
KlassInfoEntry* e = _buckets[idx].lookup(k);
// Lookup may fail if this is a new klass for which we
- // could not allocate space for an new entry.
+ // could not allocate space for an new entry, or if it's
+ // an archived class that we haven't loaded yet.
assert(e == NULL || k == e->klass(), "must be equal");
return e;
}
--- a/src/hotspot/share/memory/heapShared.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/memory/heapShared.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -68,6 +68,7 @@
{"java/lang/Byte$ByteCache", "archivedCache"},
{"java/lang/Short$ShortCache", "archivedCache"},
{"java/lang/Character$CharacterCache", "archivedCache"},
+ {"java/util/jar/Attributes$Name", "KNOWN_NAMES"},
};
// Entry fields for subgraphs archived in the open archive heap region.
static ArchivableStaticFieldInfo open_archive_subgraph_entry_fields[] = {
--- a/src/hotspot/share/oops/instanceKlass.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/oops/instanceKlass.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -3367,7 +3367,9 @@
if (cfs != NULL) {
if (cfs->source() != NULL) {
if (module_name != NULL) {
- if (ClassLoader::is_modules_image(cfs->source())) {
+ // When the boot loader created the stream, it didn't know the module name
+ // yet. Let's format it now.
+ if (cfs->from_boot_loader_modules_image()) {
info_stream.print(" source: jrt:/%s", module_name);
} else {
info_stream.print(" source: %s", cfs->source());
--- a/src/hotspot/share/opto/graphKit.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/opto/graphKit.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -2450,6 +2450,8 @@
Node* parm2, Node* parm3,
Node* parm4, Node* parm5,
Node* parm6, Node* parm7) {
+ assert(call_addr != NULL, "must not call NULL targets");
+
// Slow-path call
bool is_leaf = !(flags & RC_NO_LEAF);
bool has_io = (!is_leaf && !(flags & RC_NO_IO));
--- a/src/hotspot/share/opto/library_call.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/opto/library_call.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -6353,6 +6353,9 @@
}
if (state == NULL) return false;
+ assert(stubAddr != NULL, "Stub is generated");
+ if (stubAddr == NULL) return false;
+
// Call the stub.
Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, OptoRuntime::sha_implCompress_Type(),
stubAddr, stubName, TypePtr::BOTTOM,
@@ -6425,6 +6428,9 @@
fatal("unknown SHA intrinsic predicate: %d", predicate);
}
if (klass_SHA_name != NULL) {
+ assert(stub_addr != NULL, "Stub is generated");
+ if (stub_addr == NULL) return false;
+
// get DigestBase klass to lookup for SHA klass
const TypeInstPtr* tinst = _gvn.type(digestBase_obj)->isa_instptr();
assert(tinst != NULL, "digestBase_obj is not instance???");
--- a/src/hotspot/share/opto/matcher.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/opto/matcher.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -416,14 +416,20 @@
return rms;
}
-//---------------------------init_first_stack_mask-----------------------------
+#define NOF_STACK_MASKS (3*6+5)
+
// Create the initial stack mask used by values spilling to the stack.
// Disallow any debug info in outgoing argument areas by setting the
// initial mask accordingly.
void Matcher::init_first_stack_mask() {
// Allocate storage for spill masks as masks for the appropriate load type.
- RegMask *rms = (RegMask*)C->comp_arena()->Amalloc_D(sizeof(RegMask) * (3*6+5));
+ RegMask *rms = (RegMask*)C->comp_arena()->Amalloc_D(sizeof(RegMask) * NOF_STACK_MASKS);
+
+ // Initialize empty placeholder masks into the newly allocated arena
+ for (int i = 0; i < NOF_STACK_MASKS; i++) {
+ new (rms + i) RegMask();
+ }
idealreg2spillmask [Op_RegN] = &rms[0];
idealreg2spillmask [Op_RegI] = &rms[1];
--- a/src/hotspot/share/runtime/globals.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/runtime/globals.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -371,6 +371,10 @@
"Generate a lot of safepoints. This works with " \
"GuaranteedSafepointInterval") \
\
+ diagnostic(bool, HandshakeALot, false, \
+ "Generate a lot of handshakes. This works with " \
+ "GuaranteedSafepointInterval") \
+ \
product_pd(bool, BackgroundCompilation, \
"A thread requesting compilation is not blocked during " \
"compilation") \
--- a/src/hotspot/share/runtime/init.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/runtime/init.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -36,6 +36,7 @@
#include "runtime/handles.inline.hpp"
#include "runtime/icache.hpp"
#include "runtime/init.hpp"
+#include "runtime/orderAccess.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/sharedRuntime.hpp"
#include "services/memTracker.hpp"
@@ -186,11 +187,19 @@
static volatile bool _init_completed = false;
bool is_init_completed() {
- return _init_completed;
+ return OrderAccess::load_acquire(&_init_completed);
}
+void wait_init_completed() {
+ MonitorLockerEx ml(InitCompleted_lock, Monitor::_no_safepoint_check_flag);
+ while (!_init_completed) {
+ ml.wait(Monitor::_no_safepoint_check_flag);
+ }
+}
void set_init_completed() {
assert(Universe::is_fully_initialized(), "Should have completed initialization");
- _init_completed = true;
+ MonitorLockerEx ml(InitCompleted_lock, Monitor::_no_safepoint_check_flag);
+ OrderAccess::release_store(&_init_completed, true);
+ ml.notify_all();
}
--- a/src/hotspot/share/runtime/init.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/runtime/init.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -40,6 +40,7 @@
void exit_globals(); // call destructors before exit
bool is_init_completed(); // returns true when bootstrapping has completed
+void wait_init_completed(); // wait until set_init_completed() has been called
void set_init_completed(); // set basic init to completed
#endif // SHARE_RUNTIME_INIT_HPP
--- a/src/hotspot/share/runtime/mutexLocker.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/runtime/mutexLocker.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -97,6 +97,7 @@
Mutex* DirectivesStack_lock = NULL;
Mutex* MultiArray_lock = NULL;
Monitor* Terminator_lock = NULL;
+Monitor* InitCompleted_lock = NULL;
Monitor* BeforeExit_lock = NULL;
Monitor* Notify_lock = NULL;
Mutex* ProfilePrint_lock = NULL;
@@ -283,6 +284,7 @@
def(VMOperationRequest_lock , PaddedMonitor, nonleaf, true, Monitor::_safepoint_check_sometimes);
def(RetData_lock , PaddedMutex , nonleaf, false, Monitor::_safepoint_check_always);
def(Terminator_lock , PaddedMonitor, nonleaf, true, Monitor::_safepoint_check_sometimes);
+ def(InitCompleted_lock , PaddedMonitor, leaf, true, Monitor::_safepoint_check_never);
def(VtableStubs_lock , PaddedMutex , nonleaf, true, Monitor::_safepoint_check_never);
def(Notify_lock , PaddedMonitor, nonleaf, true, Monitor::_safepoint_check_always);
def(JNIGlobalAlloc_lock , PaddedMutex , nonleaf, true, Monitor::_safepoint_check_never);
--- a/src/hotspot/share/runtime/mutexLocker.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/runtime/mutexLocker.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -96,6 +96,7 @@
extern Mutex* DirectivesStack_lock; // a lock held when mutating the dirstack and ref counting directives
extern Mutex* MultiArray_lock; // a lock used to guard allocation of multi-dim arrays
extern Monitor* Terminator_lock; // a lock used to guard termination of the vm
+extern Monitor* InitCompleted_lock; // a lock used to signal threads waiting on init completed
extern Monitor* BeforeExit_lock; // a lock used to guard cleanups and shutdown hooks
extern Monitor* Notify_lock; // a lock used to synchronize the start-up of the vm
extern Mutex* ProfilePrint_lock; // a lock used to serialize the printing of profiles
--- a/src/hotspot/share/runtime/synchronizer.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/runtime/synchronizer.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -1270,6 +1270,21 @@
}
Thread::muxRelease(&gListLock);
+
+ LogStreamHandle(Debug, monitorinflation) lsh_debug;
+ LogStreamHandle(Info, monitorinflation) lsh_info;
+ LogStream * ls = NULL;
+ if (log_is_enabled(Debug, monitorinflation)) {
+ ls = &lsh_debug;
+ } else if ((tally != 0 || inUseTally != 0) &&
+ log_is_enabled(Info, monitorinflation)) {
+ ls = &lsh_info;
+ }
+ if (ls != NULL) {
+ ls->print_cr("omFlush: jt=" INTPTR_FORMAT ", free_monitor_tally=%d"
+ ", in_use_monitor_tally=%d" ", omFreeProvision=%d",
+ p2i(Self), tally, inUseTally, Self->omFreeProvision);
+ }
}
static void post_monitor_inflate_event(EventJavaMonitorInflate* event,
@@ -1665,24 +1680,18 @@
// than a beginning to end measurement of the phase.
log_info(safepoint, cleanup)("deflating per-thread idle monitors, %3.7f secs, monitors=%d", counters->perThreadTimes, counters->perThreadScavenged);
- LogStreamHandle(Debug, monitorinflation) lsh_debug;
- LogStreamHandle(Info, monitorinflation) lsh_info;
- LogStream * ls = NULL;
- if (log_is_enabled(Debug, monitorinflation)) {
- ls = &lsh_debug;
- } else if (counters->perThreadScavenged != 0 && log_is_enabled(Info, monitorinflation)) {
- ls = &lsh_info;
- }
- if (ls != NULL) {
- ls->print_cr("deflating per-thread idle monitors, %3.7f secs, %d monitors", counters->perThreadTimes, counters->perThreadScavenged);
- }
-
gMonitorFreeCount += counters->nScavenged;
if (log_is_enabled(Debug, monitorinflation)) {
// exit_globals()'s call to audit_and_print_stats() is done
// at the Info level.
ObjectSynchronizer::audit_and_print_stats(false /* on_exit */);
+ } else if (log_is_enabled(Info, monitorinflation)) {
+ Thread::muxAcquire(&gListLock, "finish_deflate_idle_monitors");
+ log_info(monitorinflation)("gMonitorPopulation=%d, gOmInUseCount=%d, "
+ "gMonitorFreeCount=%d", gMonitorPopulation,
+ gOmInUseCount, gMonitorFreeCount);
+ Thread::muxRelease(&gListLock);
}
ForceMonitorScavenge = 0; // Reset
@@ -1708,8 +1717,6 @@
int deflated_count = deflate_monitor_list(thread->omInUseList_addr(), &freeHeadp, &freeTailp);
- timer.stop();
-
Thread::muxAcquire(&gListLock, "deflate_thread_local_monitors");
// Adjust counters
@@ -1718,8 +1725,6 @@
counters->nScavenged += deflated_count;
counters->nInuse += thread->omInUseCount;
counters->perThreadScavenged += deflated_count;
- // For now, we only care about cumulative per-thread deflation time.
- counters->perThreadTimes += timer.seconds();
// Move the scavenged monitors back to the global free list.
if (freeHeadp != NULL) {
@@ -1730,7 +1735,26 @@
freeTailp->FreeNext = gFreeList;
gFreeList = freeHeadp;
}
+
+ timer.stop();
+ // Safepoint logging cares about cumulative perThreadTimes and
+ // we'll capture most of the cost, but not the muxRelease() which
+ // should be cheap.
+ counters->perThreadTimes += timer.seconds();
+
Thread::muxRelease(&gListLock);
+
+ LogStreamHandle(Debug, monitorinflation) lsh_debug;
+ LogStreamHandle(Info, monitorinflation) lsh_info;
+ LogStream * ls = NULL;
+ if (log_is_enabled(Debug, monitorinflation)) {
+ ls = &lsh_debug;
+ } else if (deflated_count != 0 && log_is_enabled(Info, monitorinflation)) {
+ ls = &lsh_info;
+ }
+ if (ls != NULL) {
+ ls->print_cr("jt=" INTPTR_FORMAT ": deflating per-thread idle monitors, %3.7f secs, %d monitors", p2i(thread), timer.seconds(), deflated_count);
+ }
}
// Monitor cleanup on JavaThread::exit
@@ -1839,13 +1863,13 @@
// Check gMonitorPopulation:
if (gMonitorPopulation == chkMonitorPopulation) {
- ls->print_cr("gMonitorPopulation=%d equals chkMonitorPopulation=%d",
- gMonitorPopulation, chkMonitorPopulation);
+ ls->print_cr("gMonitorPopulation=%d equals chkMonitorPopulation=%d",
+ gMonitorPopulation, chkMonitorPopulation);
} else {
- ls->print_cr("ERROR: gMonitorPopulation=%d is not equal to "
- "chkMonitorPopulation=%d", gMonitorPopulation,
- chkMonitorPopulation);
- error_cnt++;
+ ls->print_cr("ERROR: gMonitorPopulation=%d is not equal to "
+ "chkMonitorPopulation=%d", gMonitorPopulation,
+ chkMonitorPopulation);
+ error_cnt++;
}
// Check gOmInUseList and gOmInUseCount:
--- a/src/hotspot/share/runtime/synchronizer.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/runtime/synchronizer.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -199,11 +199,11 @@
static u_char* get_gvars_stwRandom_addr();
};
-// ObjectLocker enforced balanced locking and can never thrown an
+// ObjectLocker enforces balanced locking and can never throw an
// IllegalMonitorStateException. However, a pending exception may
// have to pass through, and we must also be able to deal with
// asynchronous exceptions. The caller is responsible for checking
-// the threads pending exception if needed.
+// the thread's pending exception if needed.
class ObjectLocker : public StackObj {
private:
Thread* _thread;
--- a/src/hotspot/share/runtime/thread.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/runtime/thread.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -2264,48 +2264,19 @@
void JavaThread::handle_special_runtime_exit_condition(bool check_asyncs) {
//
- // Check for pending external suspend. Internal suspend requests do
- // not use handle_special_runtime_exit_condition().
+ // Check for pending external suspend.
// If JNIEnv proxies are allowed, don't self-suspend if the target
// thread is not the current thread. In older versions of jdbx, jdbx
// threads could call into the VM with another thread's JNIEnv so we
// can be here operating on behalf of a suspended thread (4432884).
bool do_self_suspend = is_external_suspend_with_lock();
if (do_self_suspend && (!AllowJNIEnvProxy || this == JavaThread::current())) {
- //
- // Because thread is external suspended the safepoint code will count
- // thread as at a safepoint. This can be odd because we can be here
- // as _thread_in_Java which would normally transition to _thread_blocked
- // at a safepoint. We would like to mark the thread as _thread_blocked
- // before calling java_suspend_self like all other callers of it but
- // we must then observe proper safepoint protocol. (We can't leave
- // _thread_blocked with a safepoint in progress). However we can be
- // here as _thread_in_native_trans so we can't use a normal transition
- // constructor/destructor pair because they assert on that type of
- // transition. We could do something like:
- //
- // JavaThreadState state = thread_state();
- // set_thread_state(_thread_in_vm);
- // {
- // ThreadBlockInVM tbivm(this);
- // java_suspend_self()
- // }
- // set_thread_state(_thread_in_vm_trans);
- // if (safepoint) block;
- // set_thread_state(state);
- //
- // but that is pretty messy. Instead we just go with the way the
- // code has worked before and note that this is the only path to
- // java_suspend_self that doesn't put the thread in _thread_blocked
- // mode.
-
frame_anchor()->make_walkable(this);
- java_suspend_self();
-
- // We might be here for reasons in addition to the self-suspend request
- // so check for other async requests.
- }
-
+ java_suspend_self_with_safepoint_check();
+ }
+
+ // We might be here for reasons in addition to the self-suspend request
+ // so check for other async requests.
if (check_asyncs) {
check_and_handle_async_exceptions();
}
@@ -2424,6 +2395,7 @@
// to complete an external suspend request.
//
int JavaThread::java_suspend_self() {
+ assert(thread_state() == _thread_blocked, "wrong state for java_suspend_self()");
int ret = 0;
// we are in the process of exiting so don't suspend
@@ -2471,6 +2443,36 @@
return ret;
}
+// Helper routine to set up the correct thread state before calling java_suspend_self.
+// This is called when regular thread-state transition helpers can't be used because
+// we can be in various states, in particular _thread_in_native_trans.
+// Because this thread is external suspended the safepoint code will count it as at
+// a safepoint, regardless of what its actual current thread-state is. But
+// is_ext_suspend_completed() may be waiting to see a thread transition from
+// _thread_in_native_trans to _thread_blocked. So we set the thread state directly
+// to _thread_blocked. The problem with setting thread state directly is that a
+// safepoint could happen just after java_suspend_self() returns after being resumed,
+// and the VM thread will see the _thread_blocked state. So we must check for a safepoint
+// after restoring the state to make sure we won't leave while a safepoint is in progress.
+// However, not all initial-states are allowed when performing a safepoint check, as we
+// should never be blocking at a safepoint whilst in those states. Of these 'bad' states
+// only _thread_in_native is possible when executing this code (based on our two callers).
+// A thread that is _thread_in_native is already safepoint-safe and so it doesn't matter
+// whether the VMThread sees the _thread_blocked state, or the _thread_in_native state,
+// and so we don't need the explicit safepoint check.
+
+void JavaThread::java_suspend_self_with_safepoint_check() {
+ assert(this == Thread::current(), "invariant");
+ JavaThreadState state = thread_state();
+ set_thread_state(_thread_blocked);
+ java_suspend_self();
+ set_thread_state(state);
+ InterfaceSupport::serialize_thread_state_with_handler(this);
+ if (state != _thread_in_native) {
+ SafepointMechanism::block_if_requested(this);
+ }
+}
+
#ifdef ASSERT
// Verify the JavaThread has not yet been published in the Threads::list, and
// hence doesn't need protection from concurrent access at this stage.
@@ -2502,32 +2504,10 @@
// threads could call into the VM with another thread's JNIEnv so we
// can be here operating on behalf of a suspended thread (4432884).
if (do_self_suspend && (!AllowJNIEnvProxy || curJT == thread)) {
- JavaThreadState state = thread->thread_state();
-
- // We mark this thread_blocked state as a suspend-equivalent so
- // that a caller to is_ext_suspend_completed() won't be confused.
- // The suspend-equivalent state is cleared by java_suspend_self().
- thread->set_suspend_equivalent();
-
- // If the safepoint code sees the _thread_in_native_trans state, it will
- // wait until the thread changes to other thread state. There is no
- // guarantee on how soon we can obtain the SR_lock and complete the
- // self-suspend request. It would be a bad idea to let safepoint wait for
- // too long. Temporarily change the state to _thread_blocked to
- // let the VM thread know that this thread is ready for GC. The problem
- // of changing thread state is that safepoint could happen just after
- // java_suspend_self() returns after being resumed, and VM thread will
- // see the _thread_blocked state. We must check for safepoint
- // after restoring the state and make sure we won't leave while a safepoint
- // is in progress.
- thread->set_thread_state(_thread_blocked);
- thread->java_suspend_self();
- thread->set_thread_state(state);
-
- InterfaceSupport::serialize_thread_state_with_handler(thread);
- }
-
- SafepointMechanism::block_if_requested(curJT);
+ thread->java_suspend_self_with_safepoint_check();
+ } else {
+ SafepointMechanism::block_if_requested(curJT);
+ }
if (thread->is_deopt_suspend()) {
thread->clear_deopt_suspend();
@@ -2948,9 +2928,21 @@
}
}
+#ifdef ASSERT
+void JavaThread::verify_states_for_handshake() {
+ // This checks that the thread has a correct frame state during a handshake.
+ assert((!has_last_Java_frame() && java_call_counter() == 0) ||
+ (has_last_Java_frame() && java_call_counter() > 0),
+ "unexpected frame info: has_last_frame=%d, java_call_counter=%d",
+ has_last_Java_frame(), java_call_counter());
+}
+#endif
+
void JavaThread::nmethods_do(CodeBlobClosure* cf) {
assert((!has_last_Java_frame() && java_call_counter() == 0) ||
- (has_last_Java_frame() && java_call_counter() > 0), "wrong java_sp info!");
+ (has_last_Java_frame() && java_call_counter() > 0),
+ "unexpected frame info: has_last_frame=%d, java_call_counter=%d",
+ has_last_Java_frame(), java_call_counter());
if (has_last_Java_frame()) {
// Traverse the execution stack
@@ -4457,7 +4449,7 @@
void Threads::remove(JavaThread* p) {
- // Reclaim the objectmonitors from the omInUseList and omFreeList of the moribund thread.
+ // Reclaim the ObjectMonitors from the omInUseList and omFreeList of the moribund thread.
ObjectSynchronizer::omFlush(p);
// Extra scope needed for Thread_lock, so we can check
--- a/src/hotspot/share/runtime/thread.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/runtime/thread.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -1348,10 +1348,16 @@
inline void clear_ext_suspended();
public:
- void java_suspend();
- void java_resume();
- int java_suspend_self();
+ void java_suspend(); // higher-level suspension logic called by the public APIs
+ void java_resume(); // higher-level resume logic called by the public APIs
+ int java_suspend_self(); // low-level self-suspension mechanics
+ private:
+ // mid-level wrapper around java_suspend_self to set up correct state and
+ // check for a pending safepoint at the end
+ void java_suspend_self_with_safepoint_check();
+
+ public:
void check_and_wait_while_suspended() {
assert(JavaThread::current() == this, "sanity check");
@@ -1868,6 +1874,9 @@
// RedefineClasses Support
void metadata_do(MetadataClosure* f);
+ // Debug method asserting thread states are correct during a handshake operation.
+ DEBUG_ONLY(void verify_states_for_handshake();)
+
// Misc. operations
char* name() const { return (char*)get_thread_name(); }
void print_on(outputStream* st, bool print_extended_info) const;
--- a/src/hotspot/share/runtime/vmThread.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/runtime/vmThread.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -434,22 +434,35 @@
static VM_None safepointALot_op("SafepointALot");
static VM_Cleanup cleanup_op;
-VM_Operation* VMThread::no_op_safepoint(bool check_time) {
+class HandshakeALotTC : public ThreadClosure {
+ public:
+ virtual void do_thread(Thread* thread) {
+#ifdef ASSERT
+ assert(thread->is_Java_thread(), "must be");
+ JavaThread* jt = (JavaThread*)thread;
+ jt->verify_states_for_handshake();
+#endif
+ }
+};
+
+VM_Operation* VMThread::no_op_safepoint() {
+ // Check for handshakes first since we may need to return a VMop.
+ if (HandshakeALot) {
+ HandshakeALotTC haltc;
+ Handshake::execute(&haltc);
+ }
+ // Check for a cleanup before SafepointALot to keep stats correct.
+ long interval_ms = SafepointTracing::time_since_last_safepoint_ms();
+ bool max_time_exceeded = GuaranteedSafepointInterval != 0 &&
+ (interval_ms >= GuaranteedSafepointInterval);
+ if (max_time_exceeded && SafepointSynchronize::is_cleanup_needed()) {
+ return &cleanup_op;
+ }
if (SafepointALot) {
return &safepointALot_op;
}
- if (!SafepointSynchronize::is_cleanup_needed()) {
- return NULL;
- }
- if (check_time) {
- long interval_ms = SafepointTracing::time_since_last_safepoint_ms();
- bool max_time_exceeded = GuaranteedSafepointInterval != 0 &&
- (interval_ms > GuaranteedSafepointInterval);
- if (!max_time_exceeded) {
- return NULL;
- }
- }
- return &cleanup_op;
+ // Nothing to be done.
+ return NULL;
}
void VMThread::loop() {
@@ -491,19 +504,22 @@
exit(-1);
}
- if (timedout && (_cur_vm_operation = VMThread::no_op_safepoint(false)) != NULL) {
- MutexUnlockerEx mul(VMOperationQueue_lock,
- Mutex::_no_safepoint_check_flag);
- // Force a safepoint since we have not had one for at least
- // 'GuaranteedSafepointInterval' milliseconds. This will run all
- // the clean-up processing that needs to be done regularly at a
- // safepoint
- SafepointSynchronize::begin();
- #ifdef ASSERT
+ if (timedout) {
+ // Have to unlock VMOperationQueue_lock just in case no_op_safepoint()
+ // has to do a handshake.
+ MutexUnlockerEx mul(VMOperationQueue_lock, Mutex::_no_safepoint_check_flag);
+ if ((_cur_vm_operation = VMThread::no_op_safepoint()) != NULL) {
+ // Force a safepoint since we have not had one for at least
+ // 'GuaranteedSafepointInterval' milliseconds and we need to clean
+ // something. This will run all the clean-up processing that needs
+ // to be done at a safepoint.
+ SafepointSynchronize::begin();
+ #ifdef ASSERT
if (GCALotAtAllSafepoints) InterfaceSupport::check_gc_alot();
- #endif
- SafepointSynchronize::end();
- _cur_vm_operation = NULL;
+ #endif
+ SafepointSynchronize::end();
+ _cur_vm_operation = NULL;
+ }
}
_cur_vm_operation = _vm_queue->remove_next();
@@ -615,10 +631,9 @@
VMOperationRequest_lock->notify_all();
}
- //
- // We want to make sure that we get to a safepoint regularly.
- //
- if ((_cur_vm_operation = VMThread::no_op_safepoint(false)) != NULL) {
+ // We want to make sure that we get to a safepoint regularly
+ // even when executing VMops that don't require safepoints.
+ if ((_cur_vm_operation = VMThread::no_op_safepoint()) != NULL) {
HandleMark hm(VMThread::vm_thread());
SafepointSynchronize::begin();
SafepointSynchronize::end();
--- a/src/hotspot/share/runtime/vmThread.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/runtime/vmThread.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -123,7 +123,7 @@
static VMOperationTimeoutTask* _timeout_task;
- static VM_Operation* no_op_safepoint(bool check_time);
+ static VM_Operation* no_op_safepoint();
void evaluate_operation(VM_Operation* op);
--- a/src/hotspot/share/services/heapDumper.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/services/heapDumper.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -958,6 +958,11 @@
// creates HPROF_GC_INSTANCE_DUMP record for the given object
void DumperSupport::dump_instance(DumpWriter* writer, oop o) {
Klass* k = o->klass();
+ if (k->java_mirror() == NULL) {
+ // Ignoring this object since the corresponding java mirror is not loaded.
+ // Might be a dormant archive object.
+ return;
+ }
writer->write_u1(HPROF_GC_INSTANCE_DUMP);
writer->write_objectID(o);
--- a/src/hotspot/share/services/memBaseline.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/services/memBaseline.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -156,6 +156,11 @@
return false;
}
+ // Walk simple thread stacks
+ if (!ThreadStackTracker::walk_simple_thread_stack_site(&malloc_walker)) {
+ return false;
+ }
+
_malloc_sites.move(malloc_walker.malloc_sites());
// The malloc sites are collected in size order
_malloc_sites_order = by_size;
--- a/src/hotspot/share/services/memReporter.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/services/memReporter.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -26,6 +26,7 @@
#include "memory/allocation.hpp"
#include "services/mallocTracker.hpp"
#include "services/memReporter.hpp"
+#include "services/threadStackTracker.hpp"
#include "services/virtualMemoryTracker.hpp"
#include "utilities/globalDefinitions.hpp"
@@ -46,11 +47,13 @@
void MemReporterBase::print_malloc(size_t amount, size_t count, MEMFLAGS flag) const {
const char* scale = current_scale();
outputStream* out = output();
+ const char* alloc_type = (flag == mtThreadStack) ? "" : "malloc=";
+
if (flag != mtNone) {
- out->print("(malloc=" SIZE_FORMAT "%s type=%s",
+ out->print("(%s" SIZE_FORMAT "%s type=%s", alloc_type,
amount_in_current_scale(amount), scale, NMTUtil::flag_to_name(flag));
} else {
- out->print("(malloc=" SIZE_FORMAT "%s",
+ out->print("(%s" SIZE_FORMAT "%s", alloc_type,
amount_in_current_scale(amount), scale);
}
@@ -126,10 +129,17 @@
// Count thread's native stack in "Thread" category
if (flag == mtThread) {
- const VirtualMemory* thread_stack_usage =
- (const VirtualMemory*)_vm_snapshot->by_type(mtThreadStack);
- reserved_amount += thread_stack_usage->reserved();
- committed_amount += thread_stack_usage->committed();
+ if (ThreadStackTracker::track_as_vm()) {
+ const VirtualMemory* thread_stack_usage =
+ (const VirtualMemory*)_vm_snapshot->by_type(mtThreadStack);
+ reserved_amount += thread_stack_usage->reserved();
+ committed_amount += thread_stack_usage->committed();
+ } else {
+ const MallocMemory* thread_stack_usage =
+ (const MallocMemory*)_malloc_snapshot->by_type(mtThreadStack);
+ reserved_amount += thread_stack_usage->malloc_size();
+ committed_amount += thread_stack_usage->malloc_size();
+ }
} else if (flag == mtNMT) {
// Count malloc headers in "NMT" category
reserved_amount += _malloc_snapshot->malloc_overhead()->size();
@@ -150,12 +160,22 @@
out->print_cr("%27s ( instance classes #" SIZE_FORMAT ", array classes #" SIZE_FORMAT ")",
" ", _instance_class_count, _array_class_count);
} else if (flag == mtThread) {
- // report thread count
- out->print_cr("%27s (thread #" SIZE_FORMAT ")", " ", _malloc_snapshot->thread_count());
- const VirtualMemory* thread_stack_usage =
- _vm_snapshot->by_type(mtThreadStack);
- out->print("%27s (stack: ", " ");
- print_total(thread_stack_usage->reserved(), thread_stack_usage->committed());
+ if (ThreadStackTracker::track_as_vm()) {
+ const VirtualMemory* thread_stack_usage =
+ _vm_snapshot->by_type(mtThreadStack);
+ // report thread count
+ out->print_cr("%27s (thread #" SIZE_FORMAT ")", " ", ThreadStackTracker::thread_count());
+ out->print("%27s (stack: ", " ");
+ print_total(thread_stack_usage->reserved(), thread_stack_usage->committed());
+ } else {
+ MallocMemory* thread_stack_memory = _malloc_snapshot->by_type(mtThreadStack);
+ const char* scale = current_scale();
+ // report thread count
+ assert(ThreadStackTracker::thread_count() == 0, "Not used");
+ out->print_cr("%27s (thread #" SIZE_FORMAT ")", " ", thread_stack_memory->malloc_count());
+ out->print("%27s (Stack: " SIZE_FORMAT "%s", " ",
+ amount_in_current_scale(thread_stack_memory->malloc_size()), scale);
+ }
out->print_cr(")");
}
@@ -368,10 +388,11 @@
size_t early_amount, size_t early_count, MEMFLAGS flags) const {
const char* scale = current_scale();
outputStream* out = output();
+ const char* alloc_type = (flags == mtThread) ? "" : "malloc=";
- out->print("malloc=" SIZE_FORMAT "%s", amount_in_current_scale(current_amount), scale);
- // Report type only if it is valid
- if (flags != mtNone) {
+ out->print("%s" SIZE_FORMAT "%s", alloc_type, amount_in_current_scale(current_amount), scale);
+ // Report type only if it is valid and not under "thread" category
+ if (flags != mtNone && flags != mtThread) {
out->print(" type=%s", NMTUtil::flag_to_name(flags));
}
@@ -497,15 +518,25 @@
}
out->print_cr(")");
- // report thread stack
- const VirtualMemory* current_thread_stack =
+ out->print("%27s (stack: ", " ");
+ if (ThreadStackTracker::track_as_vm()) {
+ // report thread stack
+ const VirtualMemory* current_thread_stack =
_current_baseline.virtual_memory(mtThreadStack);
- const VirtualMemory* early_thread_stack =
- _early_baseline.virtual_memory(mtThreadStack);
+ const VirtualMemory* early_thread_stack =
+ _early_baseline.virtual_memory(mtThreadStack);
- out->print("%27s (stack: ", " ");
- print_virtual_memory_diff(current_thread_stack->reserved(), current_thread_stack->committed(),
- early_thread_stack->reserved(), early_thread_stack->committed());
+ print_virtual_memory_diff(current_thread_stack->reserved(), current_thread_stack->committed(),
+ early_thread_stack->reserved(), early_thread_stack->committed());
+ } else {
+ const MallocMemory* current_thread_stack =
+ _current_baseline.malloc_memory(mtThreadStack);
+ const MallocMemory* early_thread_stack =
+ _early_baseline.malloc_memory(mtThreadStack);
+
+ print_malloc_diff(current_thread_stack->malloc_size(), current_thread_stack->malloc_count(),
+ early_thread_stack->malloc_size(), early_thread_stack->malloc_count(), flag);
+ }
out->print_cr(")");
}
--- a/src/hotspot/share/services/memTracker.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/services/memTracker.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -31,6 +31,7 @@
#include "services/memReporter.hpp"
#include "services/mallocTracker.inline.hpp"
#include "services/memTracker.hpp"
+#include "services/threadStackTracker.hpp"
#include "utilities/debug.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/vmError.hpp"
@@ -92,7 +93,8 @@
void MemTracker::init() {
NMT_TrackingLevel level = tracking_level();
if (level >= NMT_summary) {
- if (!VirtualMemoryTracker::late_initialize(level)) {
+ if (!VirtualMemoryTracker::late_initialize(level) ||
+ !ThreadStackTracker::late_initialize(level)) {
shutdown();
return;
}
@@ -164,6 +166,7 @@
OrderAccess::fence();
VirtualMemoryTracker::transition(current_level, level);
MallocTracker::transition(current_level, level);
+ ThreadStackTracker::transition(current_level, level);
} else {
// Upgrading tracking level is not supported and has never been supported.
// Allocating and deallocating malloc tracking structures is not thread safe and
--- a/src/hotspot/share/services/memTracker.hpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/services/memTracker.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -82,6 +82,7 @@
#include "runtime/mutexLocker.hpp"
#include "runtime/threadCritical.hpp"
#include "services/mallocTracker.hpp"
+#include "services/threadStackTracker.hpp"
#include "services/virtualMemoryTracker.hpp"
extern volatile bool NMT_stack_walkable;
@@ -241,31 +242,19 @@
}
}
-#ifdef _AIX
- // See JDK-8202772 - temporarily disable thread stack tracking on AIX.
- static inline void record_thread_stack(void* addr, size_t size) {}
- static inline void release_thread_stack(void* addr, size_t size) {}
-#else
- static inline void record_thread_stack(void* addr, size_t size) {
+ static void record_thread_stack(void* addr, size_t size) {
if (tracking_level() < NMT_summary) return;
if (addr != NULL) {
- // uses thread stack malloc slot for book keeping number of threads
- MallocMemorySummary::record_malloc(0, mtThreadStack);
- record_virtual_memory_reserve(addr, size, CALLER_PC, mtThreadStack);
+ ThreadStackTracker::new_thread_stack((address)addr, size, CALLER_PC);
}
}
static inline void release_thread_stack(void* addr, size_t size) {
if (tracking_level() < NMT_summary) return;
if (addr != NULL) {
- // uses thread stack malloc slot for book keeping number of threads
- MallocMemorySummary::record_free(0, mtThreadStack);
- ThreadCritical tc;
- if (tracking_level() < NMT_summary) return;
- VirtualMemoryTracker::remove_released_region((address)addr, size);
+ ThreadStackTracker::delete_thread_stack((address)addr, size);
}
}
-#endif
// Query lock is used to synchronize the access to tracking data.
// So far, it is only used by JCmd query, but it may be used by
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/services/threadStackTracker.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2019, Red Hat, Inc. All rights reserved.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+
+#include "runtime/atomic.hpp"
+#include "runtime/threadCritical.hpp"
+#include "services/mallocTracker.hpp"
+#include "services/memTracker.hpp"
+#include "services/virtualMemoryTracker.hpp"
+#include "services/threadStackTracker.hpp"
+
+volatile size_t ThreadStackTracker::_thread_count = 0;
+SortedLinkedList<SimpleThreadStackSite, ThreadStackTracker::compare_thread_stack_base>* ThreadStackTracker::_simple_thread_stacks = NULL;
+
+bool ThreadStackTracker::late_initialize(NMT_TrackingLevel level) {
+ if (level == NMT_detail && !track_as_vm()) {
+ _simple_thread_stacks = new (std::nothrow, ResourceObj::C_HEAP, mtNMT)
+ SortedLinkedList<SimpleThreadStackSite, ThreadStackTracker::compare_thread_stack_base>();
+ return (_simple_thread_stacks != NULL);
+ }
+ return true;
+}
+
+bool ThreadStackTracker::transition(NMT_TrackingLevel from, NMT_TrackingLevel to) {
+ assert (from != NMT_minimal, "cannot convert from the lowest tracking level to anything");
+ if (to == NMT_minimal) {
+ assert(from == NMT_summary || from == NMT_detail, "Just check");
+ ThreadCritical tc;
+ if (_simple_thread_stacks != NULL) {
+ delete _simple_thread_stacks;
+ _simple_thread_stacks = NULL;
+ }
+ }
+ return true;
+}
+
+int ThreadStackTracker::compare_thread_stack_base(const SimpleThreadStackSite& s1, const SimpleThreadStackSite& s2) {
+ return s1.base() - s2.base();
+}
+
+void ThreadStackTracker::new_thread_stack(void* base, size_t size, const NativeCallStack& stack) {
+ assert(MemTracker::tracking_level() >= NMT_summary, "Must be");
+ assert(base != NULL, "Should have been filtered");
+ if (track_as_vm()) {
+ ThreadCritical tc;
+ VirtualMemoryTracker::add_reserved_region((address)base, size, stack, mtThreadStack);
+ _thread_count ++;
+ } else {
+ // Use a slot in mallocMemorySummary for thread stack bookkeeping
+ MallocMemorySummary::record_malloc(size, mtThreadStack);
+ if (MemTracker::tracking_level() == NMT_detail) {
+ ThreadCritical tc;
+ assert(_simple_thread_stacks != NULL, "Must be initialized");
+ SimpleThreadStackSite site((address)base, size, stack);
+ _simple_thread_stacks->add(site);
+ }
+ }
+}
+
+void ThreadStackTracker::delete_thread_stack(void* base, size_t size) {
+ assert(MemTracker::tracking_level() >= NMT_summary, "Must be");
+ assert(base != NULL, "Should have been filtered");
+ if(track_as_vm()) {
+ ThreadCritical tc;
+ VirtualMemoryTracker::remove_released_region((address)base, size);
+ _thread_count--;
+ } else {
+ // Use a slot in mallocMemorySummary for thread stack bookkeeping
+ MallocMemorySummary::record_free(size, mtThreadStack);
+ if (MemTracker::tracking_level() == NMT_detail) {
+ ThreadCritical tc;
+ assert(_simple_thread_stacks != NULL, "Must be initialized");
+ SimpleThreadStackSite site((address)base, size);
+ bool removed = _simple_thread_stacks->remove(site);
+ assert(removed, "Must exist");
+ }
+ }
+}
+
+bool ThreadStackTracker::walk_simple_thread_stack_site(MallocSiteWalker* walker) {
+ if (!track_as_vm()) {
+ LinkedListImpl<MallocSite> _sites;
+ {
+ ThreadCritical tc;
+ assert(_simple_thread_stacks != NULL, "Must be initialized");
+ LinkedListIterator<SimpleThreadStackSite> itr(_simple_thread_stacks->head());
+ const SimpleThreadStackSite* ts = itr.next();
+ // Consolidate sites and convert to MallocSites, so we can piggyback into
+ // malloc snapshot
+ while (ts != NULL) {
+ MallocSite site(*ts->call_stack(), mtThreadStack);
+ MallocSite* exist = _sites.find(site);
+ if (exist != NULL) {
+ exist->allocate(ts->size());
+ } else {
+ site.allocate(ts->size());
+ _sites.add(site);
+ }
+ ts = itr.next();
+ }
+ }
+
+ // Piggyback to malloc snapshot
+ LinkedListIterator<MallocSite> site_itr(_sites.head());
+ const MallocSite* s = site_itr.next();
+ while (s != NULL) {
+ walker->do_malloc_site(s);
+ s = site_itr.next();
+ }
+ }
+ return true;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/services/threadStackTracker.hpp Sat Mar 30 09:30:03 2019 +0000
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2019, Red Hat, Inc. All rights reserved.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_SERVICES_THREADSTACKTRACKER_HPP
+#define SHARE_SERVICES_THREADSTACKTRACKER_HPP
+
+#if INCLUDE_NMT
+
+#include "services/allocationSite.hpp"
+#include "services/mallocSiteTable.hpp"
+#include "services/nmtCommon.hpp"
+#include "utilities/nativeCallStack.hpp"
+#include "utilities/linkedlist.hpp"
+
+class SimpleThreadStackSite;
+
+class SimpleThreadStack {
+ friend class SimpleThreadStackSite;
+private:
+ address _base;
+ size_t _size;
+public:
+ SimpleThreadStack() : _base(NULL), _size(0) { }
+ bool equals(const SimpleThreadStack& s) const {
+ return base() == s.base();
+ }
+
+ size_t size() const { return _size; }
+ address base() const { return _base; }
+private:
+ void set_size(size_t size) { _size = size; }
+ void set_base(address base) { _base = base; }
+};
+
+class SimpleThreadStackSite : public AllocationSite<SimpleThreadStack> {
+public:
+ SimpleThreadStackSite(address base, size_t size, const NativeCallStack& stack) :
+ AllocationSite<SimpleThreadStack>(stack, mtThreadStack) {
+ data()->set_size(size);
+ data()->set_base(base);
+ }
+
+ SimpleThreadStackSite(address base, size_t size) :
+ AllocationSite<SimpleThreadStack>(NativeCallStack::empty_stack(), mtThreadStack) {
+ data()->set_base(base);
+ data()->set_size(size);
+ }
+
+ bool equals(const SimpleThreadStackSite& mts) const {
+ bool eq = base() == mts.base();
+ assert(!eq || size() == mts.size(), "Must match");
+ return eq;
+ }
+
+ size_t size() const { return peek()->size(); }
+ address base() const { return peek()->base(); }
+};
+
+ /*
+ * Most of platforms, that hotspot support, have their thread stacks backed by
+ * virtual memory by default. For these cases, thread stack tracker simply
+ * delegates tracking to virtual memory tracker.
+ * However, there are exceptions, (e.g. AIX), that platforms can provide stacks
+ * that are not page aligned. A hypothetical VM implementation, it can provide
+ * it own stacks. In these case, track_as_vm() should return false and manage
+ * stack tracking by this tracker internally.
+ * During memory snapshot, tracked thread stacks memory data is walked and stored
+ * along with malloc'd data inside baseline. The regions are not scanned and assumed
+ * all committed for now. Can add scanning phase when there is a need.
+ */
+class ThreadStackTracker : AllStatic {
+private:
+ static volatile size_t _thread_count;
+
+ static int compare_thread_stack_base(const SimpleThreadStackSite& s1, const SimpleThreadStackSite& s2);
+ static SortedLinkedList<SimpleThreadStackSite, compare_thread_stack_base>* _simple_thread_stacks;
+public:
+ // Late phase initialization
+ static bool late_initialize(NMT_TrackingLevel level);
+ static bool transition(NMT_TrackingLevel from, NMT_TrackingLevel to);
+
+ static void new_thread_stack(void* base, size_t size, const NativeCallStack& stack);
+ static void delete_thread_stack(void* base, size_t size);
+
+ static bool track_as_vm() { return AIX_ONLY(false) NOT_AIX(true); }
+ static size_t thread_count() { return _thread_count; }
+
+ // Snapshot support. Piggyback thread stack data in malloc slot, NMT always handles
+ // thread stack slot specially since beginning.
+ static bool walk_simple_thread_stack_site(MallocSiteWalker* walker);
+};
+
+#endif // INCLUDE_NMT
+#endif // SHARE_SERVICES_THREADSTACKTRACKER_HPP
--- a/src/hotspot/share/services/virtualMemoryTracker.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/services/virtualMemoryTracker.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, 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,6 +29,7 @@
#include "runtime/os.hpp"
#include "runtime/threadCritical.hpp"
#include "services/memTracker.hpp"
+#include "services/threadStackTracker.hpp"
#include "services/virtualMemoryTracker.hpp"
size_t VirtualMemorySummary::_snapshot[CALC_OBJ_SIZE_IN_TYPE(VirtualMemorySnapshot, size_t)];
@@ -40,9 +41,12 @@
}
void VirtualMemorySummary::snapshot(VirtualMemorySnapshot* s) {
- // Snapshot current thread stacks
- VirtualMemoryTracker::snapshot_thread_stacks();
- as_snapshot()->copy_to(s);
+ // Only if thread stack is backed by virtual memory
+ if (ThreadStackTracker::track_as_vm()) {
+ // Snapshot current thread stacks
+ VirtualMemoryTracker::snapshot_thread_stacks();
+ as_snapshot()->copy_to(s);
+ }
}
SortedLinkedList<ReservedMemoryRegion, compare_reserved_region_base>* VirtualMemoryTracker::_reserved_regions;
--- a/src/hotspot/share/utilities/vmError.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/hotspot/share/utilities/vmError.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -1725,7 +1725,16 @@
const char* const eol = os::line_separator();
const char* const msg = "this message should be truncated during formatting";
char * const dataPtr = NULL; // bad data pointer
- const void (*funcPtr)(void) = (const void(*)()) 0xF; // bad function pointer
+ const void (*funcPtr)(void); // bad function pointer
+
+#if defined(PPC64) && !defined(ABI_ELFv2)
+ struct FunctionDescriptor functionDescriptor;
+
+ functionDescriptor.set_entry((address) 0xF);
+ funcPtr = (const void(*)()) &functionDescriptor;
+#else
+ funcPtr = (const void(*)()) 0xF;
+#endif
// Keep this in sync with test/hotspot/jtreg/runtime/ErrorHandling/ErrorHandler.java
// which tests cases 1 thru 13.
--- a/src/java.base/share/classes/java/io/DataOutputStream.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.base/share/classes/java/io/DataOutputStream.java Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2019, 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
@@ -317,7 +317,10 @@
* thrice the length of <code>str</code>.
*
* @param str a string to be written.
- * @exception IOException if an I/O error occurs.
+ * @throws UTFDataFormatException if the modified UTF-8 encoding of
+ * {@code str} would exceed 65535 bytes in length
+ * @throws IOException if some other I/O error occurs.
+ * @see #writeChars(String)
*/
public final void writeUTF(String str) throws IOException {
writeUTF(str, this);
@@ -341,55 +344,49 @@
* @param str a string to be written.
* @param out destination to write to
* @return The number of bytes written out.
- * @exception IOException if an I/O error occurs.
+ * @throws UTFDataFormatException if the modified UTF-8 encoding of
+ * {@code str} would exceed 65535 bytes in length
+ * @throws IOException if some other I/O error occurs.
*/
static int writeUTF(String str, DataOutput out) throws IOException {
- int strlen = str.length();
- int utflen = 0;
- int c, count = 0;
+ final int strlen = str.length();
+ int utflen = strlen; // optimized for ASCII
- /* use charAt instead of copying String to char array */
for (int i = 0; i < strlen; i++) {
- c = str.charAt(i);
- if ((c >= 0x0001) && (c <= 0x007F)) {
- utflen++;
- } else if (c > 0x07FF) {
- utflen += 3;
- } else {
- utflen += 2;
- }
+ int c = str.charAt(i);
+ if (c >= 0x80 || c == 0)
+ utflen += (c >= 0x800) ? 2 : 1;
}
- if (utflen > 65535)
- throw new UTFDataFormatException(
- "encoded string too long: " + utflen + " bytes");
+ if (utflen > 65535 || /* overflow */ utflen < strlen)
+ throw new UTFDataFormatException(tooLongMsg(str, utflen));
- byte[] bytearr = null;
+ final byte[] bytearr;
if (out instanceof DataOutputStream) {
DataOutputStream dos = (DataOutputStream)out;
- if(dos.bytearr == null || (dos.bytearr.length < (utflen+2)))
+ if (dos.bytearr == null || (dos.bytearr.length < (utflen + 2)))
dos.bytearr = new byte[(utflen*2) + 2];
bytearr = dos.bytearr;
} else {
- bytearr = new byte[utflen+2];
+ bytearr = new byte[utflen + 2];
}
+ int count = 0;
bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF);
- int i=0;
- for (i=0; i<strlen; i++) {
- c = str.charAt(i);
- if (!((c >= 0x0001) && (c <= 0x007F))) break;
- bytearr[count++] = (byte) c;
+ int i = 0;
+ for (i = 0; i < strlen; i++) { // optimized for initial run of ASCII
+ int c = str.charAt(i);
+ if (c >= 0x80 || c == 0) break;
+ bytearr[count++] = (byte) c;
}
- for (;i < strlen; i++){
- c = str.charAt(i);
- if ((c >= 0x0001) && (c <= 0x007F)) {
+ for (; i < strlen; i++) {
+ int c = str.charAt(i);
+ if (c < 0x80 && c != 0) {
bytearr[count++] = (byte) c;
-
- } else if (c > 0x07FF) {
+ } else if (c >= 0x800) {
bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
bytearr[count++] = (byte) (0x80 | ((c >> 6) & 0x3F));
bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
@@ -398,10 +395,20 @@
bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
}
}
- out.write(bytearr, 0, utflen+2);
+ out.write(bytearr, 0, utflen + 2);
return utflen + 2;
}
+ private static String tooLongMsg(String s, int bits32) {
+ int slen = s.length();
+ String head = s.substring(0, 8);
+ String tail = s.substring(slen - 8, slen);
+ // handle int overflow with max 3x expansion
+ long actualLength = (long)slen + Integer.toUnsignedLong(bits32 - slen);
+ return "encoded string (" + head + "..." + tail + ") too long: "
+ + actualLength + " bytes";
+ }
+
/**
* Returns the current value of the counter <code>written</code>,
* the number of bytes written to this data output stream so far.
--- a/src/java.base/share/classes/java/io/InputStream.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.base/share/classes/java/io/InputStream.java Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2019, 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
@@ -237,7 +237,7 @@
* <code>b[off+len-1]</code> unaffected.
*
* <p> In every case, elements <code>b[0]</code> through
- * <code>b[off]</code> and elements <code>b[off+len]</code> through
+ * <code>b[off-1]</code> and elements <code>b[off+len]</code> through
* <code>b[b.length-1]</code> are unaffected.
*
* <p> The <code>read(b,</code> <code>off,</code> <code>len)</code> method
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Sat Mar 30 09:30:03 2019 +0000
@@ -422,6 +422,10 @@
* because the desired class member is missing, or because the
* desired class member is not accessible to the lookup class, or
* because the lookup object is not trusted enough to access the member.
+ * In the case of a field setter function on a {@code final} field,
+ * finality enforcement is treated as a kind of access control,
+ * and the lookup will fail, except in special cases of
+ * {@link Lookup#unreflectSetter Lookup.unreflectSetter}.
* In any of these cases, a {@code ReflectiveOperationException} will be
* thrown from the attempted lookup. The exact class will be one of
* the following:
@@ -1438,6 +1442,7 @@
* @return a method handle which can store values into the field
* @throws NoSuchFieldException if the field does not exist
* @throws IllegalAccessException if access checking fails, or if the field is {@code static}
+ * or {@code final}
* @exception SecurityException if a security manager is present and it
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null
@@ -1561,6 +1566,7 @@
* @return a method handle which can store values into the field
* @throws NoSuchFieldException if the field does not exist
* @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
+ * or is {@code final}
* @exception SecurityException if a security manager is present and it
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null
@@ -1840,10 +1846,10 @@
* Produces a method handle giving read access to a reflected field.
* The type of the method handle will have a return type of the field's
* value type.
- * If the field is static, the method handle will take no arguments.
+ * If the field is {@code static}, the method handle will take no arguments.
* Otherwise, its single argument will be the instance containing
* the field.
- * If the field's {@code accessible} flag is not set,
+ * If the {@code Field} object's {@code accessible} flag is not set,
* access checking is performed immediately on behalf of the lookup class.
* <p>
* If the field is static, and
@@ -1857,8 +1863,43 @@
public MethodHandle unreflectGetter(Field f) throws IllegalAccessException {
return unreflectField(f, false);
}
+
+ /**
+ * Produces a method handle giving write access to a reflected field.
+ * The type of the method handle will have a void return type.
+ * If the field is {@code static}, the method handle will take a single
+ * argument, of the field's value type, the value to be stored.
+ * Otherwise, the two arguments will be the instance containing
+ * the field, and the value to be stored.
+ * If the {@code Field} object's {@code accessible} flag is not set,
+ * access checking is performed immediately on behalf of the lookup class.
+ * <p>
+ * If the field is {@code final}, write access will not be
+ * allowed and access checking will fail, except under certain
+ * narrow circumstances documented for {@link Field#set Field.set}.
+ * A method handle is returned only if a corresponding call to
+ * the {@code Field} object's {@code set} method could return
+ * normally. In particular, fields which are both {@code static}
+ * and {@code final} may never be set.
+ * <p>
+ * If the field is {@code static}, and
+ * if the returned method handle is invoked, the field's class will
+ * be initialized, if it has not already been initialized.
+ * @param f the reflected field
+ * @return a method handle which can store values into the reflected field
+ * @throws IllegalAccessException if access checking fails,
+ * or if the field is {@code final} and write access
+ * is not enabled on the {@code Field} object
+ * @throws NullPointerException if the argument is null
+ */
+ public MethodHandle unreflectSetter(Field f) throws IllegalAccessException {
+ return unreflectField(f, true);
+ }
+
private MethodHandle unreflectField(Field f, boolean isSetter) throws IllegalAccessException {
MemberName field = new MemberName(f, isSetter);
+ if (isSetter && field.isStatic() && field.isFinal())
+ throw field.makeAccessException("static final field has no write access", this);
assert(isSetter
? MethodHandleNatives.refKindIsSetter(field.getReferenceKind())
: MethodHandleNatives.refKindIsGetter(field.getReferenceKind()));
@@ -1868,28 +1909,6 @@
}
/**
- * Produces a method handle giving write access to a reflected field.
- * The type of the method handle will have a void return type.
- * If the field is static, the method handle will take a single
- * argument, of the field's value type, the value to be stored.
- * Otherwise, the two arguments will be the instance containing
- * the field, and the value to be stored.
- * If the field's {@code accessible} flag is not set,
- * access checking is performed immediately on behalf of the lookup class.
- * <p>
- * If the field is static, and
- * if the returned method handle is invoked, the field's class will
- * be initialized, if it has not already been initialized.
- * @param f the reflected field
- * @return a method handle which can store values into the reflected field
- * @throws IllegalAccessException if access checking fails
- * @throws NullPointerException if the argument is null
- */
- public MethodHandle unreflectSetter(Field f) throws IllegalAccessException {
- return unreflectField(f, true);
- }
-
- /**
* Produces a VarHandle giving access to a reflected field {@code f}
* of type {@code T} declared in a class of type {@code R}.
* The VarHandle's variable type is {@code T}.
--- a/src/java.base/share/classes/java/lang/module/Configuration.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.base/share/classes/java/lang/module/Configuration.java Sat Mar 30 09:30:03 2019 +0000
@@ -575,7 +575,8 @@
}
Set<ResolvedModule> reads(ResolvedModule m) {
- return Collections.unmodifiableSet(graph.get(m));
+ // The sets stored in the graph are already immutable sets
+ return Set.copyOf(graph.get(m));
}
/**
--- a/src/java.base/share/classes/java/net/ServerSocket.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.base/share/classes/java/net/ServerSocket.java Sat Mar 30 09:30:03 2019 +0000
@@ -749,8 +749,9 @@
* timeout must be {@code > 0}.
* A timeout of zero is interpreted as an infinite timeout.
* @param timeout the specified timeout, in milliseconds
- * @exception SocketException if there is an error in
- * the underlying protocol, such as a TCP error.
+ * @throws SocketException if there is an error in the underlying protocol,
+ * such as a TCP error
+ * @throws IllegalArgumentException if {@code timeout} is negative
* @since 1.1
* @see #getSoTimeout()
*/
--- a/src/java.base/share/classes/java/net/Socket.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.base/share/classes/java/net/Socket.java Sat Mar 30 09:30:03 2019 +0000
@@ -581,7 +581,8 @@
* if this socket has an associated channel,
* and the channel is in non-blocking mode
* @throws IllegalArgumentException if endpoint is null or is a
- * SocketAddress subclass not supported by this socket
+ * SocketAddress subclass not supported by this socket, or
+ * if {@code timeout} is negative
* @since 1.4
* @spec JSR-51
*/
@@ -1212,8 +1213,9 @@
* A timeout of zero is interpreted as an infinite timeout.
*
* @param timeout the specified timeout, in milliseconds.
- * @exception SocketException if there is an error
- * in the underlying protocol, such as a TCP error.
+ * @throws SocketException if there is an error in the underlying protocol,
+ * such as a TCP error
+ * @throws IllegalArgumentException if {@code timeout} is negative
* @since 1.1
* @see #getSoTimeout()
*/
@@ -1221,7 +1223,7 @@
if (isClosed())
throw new SocketException("Socket is closed");
if (timeout < 0)
- throw new IllegalArgumentException("timeout < 0");
+ throw new IllegalArgumentException("timeout can't be negative");
getImpl().setOption(SocketOptions.SO_TIMEOUT, timeout);
}
--- a/src/java.base/share/classes/java/text/CompactNumberFormat.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.base/share/classes/java/text/CompactNumberFormat.java Sat Mar 30 09:30:03 2019 +0000
@@ -836,7 +836,8 @@
if (ch == QUOTE) {
ch = pattern.charAt(index++);
if (ch == MINUS_SIGN) {
- ch = symbols.getMinusSign();
+ sb.append(symbols.getMinusSignText());
+ continue;
}
}
sb.append(ch);
@@ -859,11 +860,14 @@
if (ch == QUOTE) {
ch = pattern.charAt(index++);
if (ch == MINUS_SIGN) {
- ch = symbols.getMinusSign();
+ String minusText = symbols.getMinusSignText();
FieldPosition fp = new FieldPosition(NumberFormat.Field.SIGN);
fp.setBeginIndex(stringIndex);
- fp.setEndIndex(stringIndex + 1);
+ fp.setEndIndex(stringIndex + minusText.length());
positions.add(fp);
+ stringIndex += minusText.length();
+ affix.append(minusText);
+ continue;
}
}
stringIndex++;
--- a/src/java.base/share/classes/java/text/DecimalFormat.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.base/share/classes/java/text/DecimalFormat.java Sat Mar 30 09:30:03 2019 +0000
@@ -54,20 +54,20 @@
import sun.util.locale.provider.ResourceBundleBasedAdapter;
/**
- * <code>DecimalFormat</code> is a concrete subclass of
- * <code>NumberFormat</code> that formats decimal numbers. It has a variety of
+ * {@code DecimalFormat} is a concrete subclass of
+ * {@code NumberFormat} that formats decimal numbers. It has a variety of
* features designed to make it possible to parse and format numbers in any
* locale, including support for Western, Arabic, and Indic digits. It also
* supports different kinds of numbers, including integers (123), fixed-point
* numbers (123.4), scientific notation (1.23E4), percentages (12%), and
* currency amounts ($123). All of these can be localized.
*
- * <p>To obtain a <code>NumberFormat</code> for a specific locale, including the
- * default locale, call one of <code>NumberFormat</code>'s factory methods, such
- * as <code>getInstance()</code>. In general, do not call the
- * <code>DecimalFormat</code> constructors directly, since the
- * <code>NumberFormat</code> factory methods may return subclasses other than
- * <code>DecimalFormat</code>. If you need to customize the format object, do
+ * <p>To obtain a {@code NumberFormat} for a specific locale, including the
+ * default locale, call one of {@code NumberFormat}'s factory methods, such
+ * as {@code getInstance()}. In general, do not call the
+ * {@code DecimalFormat} constructors directly, since the
+ * {@code NumberFormat} factory methods may return subclasses other than
+ * {@code DecimalFormat}. If you need to customize the format object, do
* something like this:
*
* <blockquote><pre>
@@ -77,16 +77,16 @@
* }
* </pre></blockquote>
*
- * <p>A <code>DecimalFormat</code> comprises a <em>pattern</em> and a set of
+ * <p>A {@code DecimalFormat} comprises a <em>pattern</em> and a set of
* <em>symbols</em>. The pattern may be set directly using
- * <code>applyPattern()</code>, or indirectly using the API methods. The
- * symbols are stored in a <code>DecimalFormatSymbols</code> object. When using
- * the <code>NumberFormat</code> factory methods, the pattern and symbols are
- * read from localized <code>ResourceBundle</code>s.
+ * {@code applyPattern()}, or indirectly using the API methods. The
+ * symbols are stored in a {@code DecimalFormatSymbols} object. When using
+ * the {@code NumberFormat} factory methods, the pattern and symbols are
+ * read from localized {@code ResourceBundle}s.
*
* <h2>Patterns</h2>
*
- * <code>DecimalFormat</code> patterns have the following syntax:
+ * {@code DecimalFormat} patterns have the following syntax:
* <blockquote><pre>
* <i>Pattern:</i>
* <i>PositivePattern</i>
@@ -123,26 +123,26 @@
* 0 <i>MinimumExponent<sub>opt</sub></i>
* </pre></blockquote>
*
- * <p>A <code>DecimalFormat</code> pattern contains a positive and negative
- * subpattern, for example, <code>"#,##0.00;(#,##0.00)"</code>. Each
+ * <p>A {@code DecimalFormat} pattern contains a positive and negative
+ * subpattern, for example, {@code "#,##0.00;(#,##0.00)"}. Each
* subpattern has a prefix, numeric part, and suffix. The negative subpattern
* is optional; if absent, then the positive subpattern prefixed with the
- * localized minus sign (<code>'-'</code> in most locales) is used as the
- * negative subpattern. That is, <code>"0.00"</code> alone is equivalent to
- * <code>"0.00;-0.00"</code>. If there is an explicit negative subpattern, it
+ * localized minus sign ({@code '-'} in most locales) is used as the
+ * negative subpattern. That is, {@code "0.00"} alone is equivalent to
+ * {@code "0.00;-0.00"}. If there is an explicit negative subpattern, it
* serves only to specify the negative prefix and suffix; the number of digits,
* minimal digits, and other characteristics are all the same as the positive
- * pattern. That means that <code>"#,##0.0#;(#)"</code> produces precisely
- * the same behavior as <code>"#,##0.0#;(#,##0.0#)"</code>.
+ * pattern. That means that {@code "#,##0.0#;(#)"} produces precisely
+ * the same behavior as {@code "#,##0.0#;(#,##0.0#)"}.
*
* <p>The prefixes, suffixes, and various symbols used for infinity, digits,
* thousands separators, decimal separators, etc. may be set to arbitrary
* values, and they will appear properly during formatting. However, care must
* be taken that the symbols and strings do not conflict, or parsing will be
* unreliable. For example, either the positive and negative prefixes or the
- * suffixes must be distinct for <code>DecimalFormat.parse()</code> to be able
+ * suffixes must be distinct for {@code DecimalFormat.parse()} to be able
* to distinguish positive from negative values. (If they are identical, then
- * <code>DecimalFormat</code> will behave as if no negative subpattern was
+ * {@code DecimalFormat} will behave as if no negative subpattern was
* specified.) Another example is that the decimal separator and thousands
* separator should be distinct characters, or parsing will be impossible.
*
@@ -151,8 +151,8 @@
* of digits between the grouping characters, such as 3 for 100,000,000 or 4 for
* 1,0000,0000. If you supply a pattern with multiple grouping characters, the
* interval between the last one and the end of the integer is the one that is
- * used. So <code>"#,##,###,####"</code> == <code>"######,####"</code> ==
- * <code>"##,####,####"</code>.
+ * used. So {@code "#,##,###,####"} == {@code "######,####"} ==
+ * {@code "##,####,####"}.
*
* <h3><a id="special_pattern_character">Special Pattern Characters</a></h3>
*
@@ -164,7 +164,7 @@
*
* <p>The characters listed here are used in non-localized patterns. Localized
* patterns use the corresponding characters taken from this formatter's
- * <code>DecimalFormatSymbols</code> object instead, and these characters lose
+ * {@code DecimalFormatSymbols} object instead, and these characters lose
* their special status. Two exceptions are the currency sign and quote, which
* are not localized.
*
@@ -180,53 +180,53 @@
* </thead>
* <tbody>
* <tr style="vertical-align:top">
- * <th scope="row"><code>0</code>
+ * <th scope="row">{@code 0}
* <td>Number
* <td>Yes
* <td>Digit
* <tr style="vertical-align: top">
- * <th scope="row"><code>#</code>
+ * <th scope="row">{@code #}
* <td>Number
* <td>Yes
* <td>Digit, zero shows as absent
* <tr style="vertical-align:top">
- * <th scope="row"><code>.</code>
+ * <th scope="row">{@code .}
* <td>Number
* <td>Yes
* <td>Decimal separator or monetary decimal separator
* <tr style="vertical-align: top">
- * <th scope="row"><code>-</code>
+ * <th scope="row">{@code -}
* <td>Number
* <td>Yes
* <td>Minus sign
* <tr style="vertical-align:top">
- * <th scope="row"><code>,</code>
+ * <th scope="row">{@code ,}
* <td>Number
* <td>Yes
* <td>Grouping separator
* <tr style="vertical-align: top">
- * <th scope="row"><code>E</code>
+ * <th scope="row">{@code E}
* <td>Number
* <td>Yes
* <td>Separates mantissa and exponent in scientific notation.
* <em>Need not be quoted in prefix or suffix.</em>
* <tr style="vertical-align:top">
- * <th scope="row"><code>;</code>
+ * <th scope="row">{@code ;}
* <td>Subpattern boundary
* <td>Yes
* <td>Separates positive and negative subpatterns
* <tr style="vertical-align: top">
- * <th scope="row"><code>%</code>
+ * <th scope="row">{@code %}
* <td>Prefix or suffix
* <td>Yes
* <td>Multiply by 100 and show as percentage
* <tr style="vertical-align:top">
- * <th scope="row"><code>\u2030</code>
+ * <th scope="row">{@code \u2030}
* <td>Prefix or suffix
* <td>Yes
* <td>Multiply by 1000 and show as per mille value
* <tr style="vertical-align: top">
- * <th scope="row"><code>¤</code> (<code>\u00A4</code>)
+ * <th scope="row">{@code ¤} ({@code \u00A4})
* <td>Prefix or suffix
* <td>No
* <td>Currency sign, replaced by currency symbol. If
@@ -234,13 +234,13 @@
* If present in a pattern, the monetary decimal separator
* is used instead of the decimal separator.
* <tr style="vertical-align:top">
- * <th scope="row"><code>'</code>
+ * <th scope="row">{@code '}
* <td>Prefix or suffix
* <td>No
* <td>Used to quote special characters in a prefix or suffix,
- * for example, <code>"'#'#"</code> formats 123 to
- * <code>"#123"</code>. To create a single quote
- * itself, use two in a row: <code>"# o''clock"</code>.
+ * for example, {@code "'#'#"} formats 123 to
+ * {@code "#123"}. To create a single quote
+ * itself, use two in a row: {@code "# o''clock"}.
* </tbody>
* </table>
* </blockquote>
@@ -251,18 +251,18 @@
* and a power of ten, for example, 1234 can be expressed as 1.234 x 10^3. The
* mantissa is often in the range 1.0 ≤ x {@literal <} 10.0, but it need not
* be.
- * <code>DecimalFormat</code> can be instructed to format and parse scientific
+ * {@code DecimalFormat} can be instructed to format and parse scientific
* notation <em>only via a pattern</em>; there is currently no factory method
* that creates a scientific notation format. In a pattern, the exponent
* character immediately followed by one or more digit characters indicates
- * scientific notation. Example: <code>"0.###E0"</code> formats the number
- * 1234 as <code>"1.234E3"</code>.
+ * scientific notation. Example: {@code "0.###E0"} formats the number
+ * 1234 as {@code "1.234E3"}.
*
* <ul>
* <li>The number of digit characters after the exponent character gives the
* minimum exponent digit count. There is no maximum. Negative exponents are
* formatted using the localized minus sign, <em>not</em> the prefix and suffix
- * from the pattern. This allows patterns such as <code>"0.###E0 m/s"</code>.
+ * from the pattern. This allows patterns such as {@code "0.###E0 m/s"}.
*
* <li>The minimum and maximum number of integer digits are interpreted
* together:
@@ -273,19 +273,19 @@
* number of integer digits, and the minimum number of integer digits to be
* interpreted as 1. The most common use of this is to generate
* <em>engineering notation</em>, in which the exponent is a multiple of three,
- * e.g., <code>"##0.#####E0"</code>. Using this pattern, the number 12345
- * formats to <code>"12.345E3"</code>, and 123456 formats to
- * <code>"123.456E3"</code>.
+ * e.g., {@code "##0.#####E0"}. Using this pattern, the number 12345
+ * formats to {@code "12.345E3"}, and 123456 formats to
+ * {@code "123.456E3"}.
*
* <li>Otherwise, the minimum number of integer digits is achieved by adjusting the
- * exponent. Example: 0.00123 formatted with <code>"00.###E0"</code> yields
- * <code>"12.3E-4"</code>.
+ * exponent. Example: 0.00123 formatted with {@code "00.###E0"} yields
+ * {@code "12.3E-4"}.
* </ul>
*
* <li>The number of significant digits in the mantissa is the sum of the
* <em>minimum integer</em> and <em>maximum fraction</em> digits, and is
* unaffected by the maximum integer digits. For example, 12345 formatted with
- * <code>"##0.##E0"</code> is <code>"12.3E3"</code>. To show all digits, set
+ * {@code "##0.##E0"} is {@code "12.3E3"}. To show all digits, set
* the significant digits count to zero. The number of significant digits
* does not affect parsing.
*
@@ -294,38 +294,38 @@
*
* <h3>Rounding</h3>
*
- * <code>DecimalFormat</code> provides rounding modes defined in
+ * {@code DecimalFormat} provides rounding modes defined in
* {@link java.math.RoundingMode} for formatting. By default, it uses
* {@link java.math.RoundingMode#HALF_EVEN RoundingMode.HALF_EVEN}.
*
* <h3>Digits</h3>
*
- * For formatting, <code>DecimalFormat</code> uses the ten consecutive
+ * For formatting, {@code DecimalFormat} uses the ten consecutive
* characters starting with the localized zero digit defined in the
- * <code>DecimalFormatSymbols</code> object as digits. For parsing, these
+ * {@code DecimalFormatSymbols} object as digits. For parsing, these
* digits as well as all Unicode decimal digits, as defined by
* {@link Character#digit Character.digit}, are recognized.
*
* <h4>Special Values</h4>
*
- * <p><code>NaN</code> is formatted as a string, which typically has a single character
- * <code>\uFFFD</code>. This string is determined by the
- * <code>DecimalFormatSymbols</code> object. This is the only value for which
+ * <p>{@code NaN} is formatted as a string, which typically has a single character
+ * {@code \uFFFD}. This string is determined by the
+ * {@code DecimalFormatSymbols} object. This is the only value for which
* the prefixes and suffixes are not used.
*
* <p>Infinity is formatted as a string, which typically has a single character
- * <code>\u221E</code>, with the positive or negative prefixes and suffixes
+ * {@code \u221E}, with the positive or negative prefixes and suffixes
* applied. The infinity string is determined by the
- * <code>DecimalFormatSymbols</code> object.
+ * {@code DecimalFormatSymbols} object.
*
- * <p>Negative zero (<code>"-0"</code>) parses to
+ * <p>Negative zero ({@code "-0"}) parses to
* <ul>
- * <li><code>BigDecimal(0)</code> if <code>isParseBigDecimal()</code> is
+ * <li>{@code BigDecimal(0)} if {@code isParseBigDecimal()} is
* true,
- * <li><code>Long(0)</code> if <code>isParseBigDecimal()</code> is false
- * and <code>isParseIntegerOnly()</code> is true,
- * <li><code>Double(-0.0)</code> if both <code>isParseBigDecimal()</code>
- * and <code>isParseIntegerOnly()</code> are false.
+ * <li>{@code Long(0)} if {@code isParseBigDecimal()} is false
+ * and {@code isParseIntegerOnly()} is true,
+ * <li>{@code Double(-0.0)} if both {@code isParseBigDecimal()}
+ * and {@code isParseIntegerOnly()} are false.
* </ul>
*
* <h3><a id="synchronization">Synchronization</a></h3>
@@ -425,7 +425,7 @@
* locale.
*
* @param pattern a non-localized pattern string.
- * @exception NullPointerException if <code>pattern</code> is null
+ * @exception NullPointerException if {@code pattern} is null
* @exception IllegalArgumentException if the given pattern is invalid.
* @see java.text.NumberFormat#getInstance
* @see java.text.NumberFormat#getNumberInstance
@@ -475,7 +475,7 @@
* <p>
* This implementation uses the maximum precision permitted.
* @param number the number to format
- * @param toAppendTo the <code>StringBuffer</code> to which the formatted
+ * @param toAppendTo the {@code StringBuffer} to which the formatted
* text is to be appended
* @param pos keeps track on the position of the field within the
* returned string. For example, for formatting a number
@@ -485,11 +485,11 @@
* and end index of {@code fieldPosition} will be set
* to 0 and 9, respectively for the output string
* {@code 1,234,567.89}.
- * @return the value passed in as <code>toAppendTo</code>
- * @exception IllegalArgumentException if <code>number</code> is
- * null or not an instance of <code>Number</code>.
- * @exception NullPointerException if <code>toAppendTo</code> or
- * <code>pos</code> is null
+ * @return the value passed in as {@code toAppendTo}
+ * @exception IllegalArgumentException if {@code number} is
+ * null or not an instance of {@code Number}.
+ * @exception NullPointerException if {@code toAppendTo} or
+ * {@code pos} is null
* @exception ArithmeticException if rounding is needed with rounding
* mode being set to RoundingMode.UNNECESSARY
* @see java.text.FieldPosition
@@ -914,13 +914,13 @@
}
/**
- * Formats an Object producing an <code>AttributedCharacterIterator</code>.
- * You can use the returned <code>AttributedCharacterIterator</code>
+ * Formats an Object producing an {@code AttributedCharacterIterator}.
+ * You can use the returned {@code AttributedCharacterIterator}
* to build the resulting String, as well as to determine information
* about the resulting String.
* <p>
* Each attribute key of the AttributedCharacterIterator will be of type
- * <code>NumberFormat.Field</code>, with the attribute value being the
+ * {@code NumberFormat.Field}, with the attribute value being the
* same as the attribute key.
*
* @exception NullPointerException if obj is null.
@@ -1916,7 +1916,7 @@
if (negativeExponent) {
exponent = -exponent;
fieldStart = result.length();
- result.append(symbols.getMinusSign());
+ result.append(symbols.getMinusSignText());
delegate.formatted(Field.EXPONENT_SIGN, Field.EXPONENT_SIGN,
fieldStart, result.length(), result);
}
@@ -2042,17 +2042,17 @@
}
/**
- * Appends the String <code>string</code> to <code>result</code>.
- * <code>delegate</code> is notified of all the
- * <code>FieldPosition</code>s in <code>positions</code>.
+ * Appends the String {@code string} to {@code result}.
+ * {@code delegate} is notified of all the
+ * {@code FieldPosition}s in {@code positions}.
* <p>
- * If one of the <code>FieldPosition</code>s in <code>positions</code>
- * identifies a <code>SIGN</code> attribute, it is mapped to
- * <code>signAttribute</code>. This is used
- * to map the <code>SIGN</code> attribute to the <code>EXPONENT</code>
+ * If one of the {@code FieldPosition}s in {@code positions}
+ * identifies a {@code SIGN} attribute, it is mapped to
+ * {@code signAttribute}. This is used
+ * to map the {@code SIGN} attribute to the {@code EXPONENT}
* attribute as necessary.
* <p>
- * This is used by <code>subformat</code> to add the prefix/suffix.
+ * This is used by {@code subformat} to add the prefix/suffix.
*/
private void append(StringBuffer result, String string,
FieldDelegate delegate,
@@ -2078,60 +2078,60 @@
}
/**
- * Parses text from a string to produce a <code>Number</code>.
+ * Parses text from a string to produce a {@code Number}.
* <p>
* The method attempts to parse text starting at the index given by
- * <code>pos</code>.
- * If parsing succeeds, then the index of <code>pos</code> is updated
+ * {@code pos}.
+ * If parsing succeeds, then the index of {@code pos} is updated
* to the index after the last character used (parsing does not necessarily
* use all characters up to the end of the string), and the parsed
- * number is returned. The updated <code>pos</code> can be used to
+ * number is returned. The updated {@code pos} can be used to
* indicate the starting point for the next call to this method.
- * If an error occurs, then the index of <code>pos</code> is not
- * changed, the error index of <code>pos</code> is set to the index of
+ * If an error occurs, then the index of {@code pos} is not
+ * changed, the error index of {@code pos} is set to the index of
* the character where the error occurred, and null is returned.
* <p>
* The subclass returned depends on the value of {@link #isParseBigDecimal}
* as well as on the string being parsed.
* <ul>
- * <li>If <code>isParseBigDecimal()</code> is false (the default),
- * most integer values are returned as <code>Long</code>
- * objects, no matter how they are written: <code>"17"</code> and
- * <code>"17.000"</code> both parse to <code>Long(17)</code>.
- * Values that cannot fit into a <code>Long</code> are returned as
- * <code>Double</code>s. This includes values with a fractional part,
- * infinite values, <code>NaN</code>, and the value -0.0.
- * <code>DecimalFormat</code> does <em>not</em> decide whether to
- * return a <code>Double</code> or a <code>Long</code> based on the
+ * <li>If {@code isParseBigDecimal()} is false (the default),
+ * most integer values are returned as {@code Long}
+ * objects, no matter how they are written: {@code "17"} and
+ * {@code "17.000"} both parse to {@code Long(17)}.
+ * Values that cannot fit into a {@code Long} are returned as
+ * {@code Double}s. This includes values with a fractional part,
+ * infinite values, {@code NaN}, and the value -0.0.
+ * {@code DecimalFormat} does <em>not</em> decide whether to
+ * return a {@code Double} or a {@code Long} based on the
* presence of a decimal separator in the source string. Doing so
* would prevent integers that overflow the mantissa of a double,
- * such as <code>"-9,223,372,036,854,775,808.00"</code>, from being
+ * such as {@code "-9,223,372,036,854,775,808.00"}, from being
* parsed accurately.
* <p>
- * Callers may use the <code>Number</code> methods
- * <code>doubleValue</code>, <code>longValue</code>, etc., to obtain
+ * Callers may use the {@code Number} methods
+ * {@code doubleValue}, {@code longValue}, etc., to obtain
* the type they want.
- * <li>If <code>isParseBigDecimal()</code> is true, values are returned
- * as <code>BigDecimal</code> objects. The values are the ones
+ * <li>If {@code isParseBigDecimal()} is true, values are returned
+ * as {@code BigDecimal} objects. The values are the ones
* constructed by {@link java.math.BigDecimal#BigDecimal(String)}
* for corresponding strings in locale-independent format. The
* special cases negative and positive infinity and NaN are returned
- * as <code>Double</code> instances holding the values of the
- * corresponding <code>Double</code> constants.
+ * as {@code Double} instances holding the values of the
+ * corresponding {@code Double} constants.
* </ul>
* <p>
- * <code>DecimalFormat</code> parses all Unicode characters that represent
- * decimal digits, as defined by <code>Character.digit()</code>. In
- * addition, <code>DecimalFormat</code> also recognizes as digits the ten
+ * {@code DecimalFormat} parses all Unicode characters that represent
+ * decimal digits, as defined by {@code Character.digit()}. In
+ * addition, {@code DecimalFormat} also recognizes as digits the ten
* consecutive characters starting with the localized zero digit defined in
- * the <code>DecimalFormatSymbols</code> object.
+ * the {@code DecimalFormatSymbols} object.
*
* @param text the string to be parsed
- * @param pos A <code>ParsePosition</code> object with index and error
+ * @param pos A {@code ParsePosition} object with index and error
* index information as described above.
- * @return the parsed value, or <code>null</code> if the parse fails
- * @exception NullPointerException if <code>text</code> or
- * <code>pos</code> is null.
+ * @return the parsed value, or {@code null} if the parse fails
+ * @exception NullPointerException if {@code text} or
+ * {@code pos} is null.
*/
@Override
public Number parse(String text, ParsePosition pos) {
@@ -2475,7 +2475,7 @@
boolean[] stat = new boolean[STATUS_LENGTH];
DigitList exponentDigits = new DigitList();
- if (subparse(text, pos, "", Character.toString(symbols.getMinusSign()), exponentDigits, true, stat) &&
+ if (subparse(text, pos, "", symbols.getMinusSignText(), exponentDigits, true, stat) &&
exponentDigits.fitsIntoLong(stat[STATUS_POSITIVE], true)) {
position = pos.index; // Advance past the exponent
exponent = (int)exponentDigits.getLong();
@@ -2573,7 +2573,7 @@
/**
* Returns the FieldPositions of the fields in the prefix used for
* positive numbers. This is not used if the user has explicitly set
- * a positive prefix via <code>setPositivePrefix</code>. This is
+ * a positive prefix via {@code setPositivePrefix}. This is
* lazily created.
*
* @return FieldPositions in positive prefix
@@ -2614,7 +2614,7 @@
/**
* Returns the FieldPositions of the fields in the prefix used for
* negative numbers. This is not used if the user has explicitly set
- * a negative prefix via <code>setNegativePrefix</code>. This is
+ * a negative prefix via {@code setNegativePrefix}. This is
* lazily created.
*
* @return FieldPositions in positive prefix
@@ -2655,7 +2655,7 @@
/**
* Returns the FieldPositions of the fields in the suffix used for
* positive numbers. This is not used if the user has explicitly set
- * a positive suffix via <code>setPositiveSuffix</code>. This is
+ * a positive suffix via {@code setPositiveSuffix}. This is
* lazily created.
*
* @return FieldPositions in positive prefix
@@ -2696,7 +2696,7 @@
/**
* Returns the FieldPositions of the fields in the suffix used for
* negative numbers. This is not used if the user has explicitly set
- * a negative suffix via <code>setNegativeSuffix</code>. This is
+ * a negative suffix via {@code setNegativeSuffix}. This is
* lazily created.
*
* @return FieldPositions in positive prefix
@@ -2811,7 +2811,7 @@
/**
* Returns whether the {@link #parse(java.lang.String, java.text.ParsePosition)}
- * method returns <code>BigDecimal</code>. The default value is false.
+ * method returns {@code BigDecimal}. The default value is false.
*
* @return {@code true} if the parse method returns BigDecimal;
* {@code false} otherwise
@@ -2824,7 +2824,7 @@
/**
* Sets whether the {@link #parse(java.lang.String, java.text.ParsePosition)}
- * method returns <code>BigDecimal</code>.
+ * method returns {@code BigDecimal}.
*
* @param newValue {@code true} if the parse method returns BigDecimal;
* {@code false} otherwise
@@ -2991,14 +2991,14 @@
}
continue;
case PATTERN_PERCENT:
- c = symbols.getPercent();
- break;
+ buffer.append(symbols.getPercentText());
+ continue;
case PATTERN_PER_MILLE:
- c = symbols.getPerMill();
- break;
+ buffer.append(symbols.getPerMillText());
+ continue;
case PATTERN_MINUS:
- c = symbols.getMinusSign();
- break;
+ buffer.append(symbols.getMinusSignText());
+ continue;
}
}
buffer.append(c);
@@ -3027,12 +3027,11 @@
for (int i=0; i<pattern.length(); ) {
char c = pattern.charAt(i++);
if (c == QUOTE) {
- int field = -1;
Format.Field fieldID = null;
+ String string = null;
c = pattern.charAt(i++);
switch (c) {
case CURRENCY_SIGN:
- String string;
if (i<pattern.length() &&
pattern.charAt(i) == CURRENCY_SIGN) {
++i;
@@ -3040,41 +3039,32 @@
} else {
string = symbols.getCurrencySymbol();
}
- if (!string.isEmpty()) {
- if (positions == null) {
- positions = new ArrayList<>(2);
- }
- FieldPosition fp = new FieldPosition(Field.CURRENCY);
- fp.setBeginIndex(stringIndex);
- fp.setEndIndex(stringIndex + string.length());
- positions.add(fp);
- stringIndex += string.length();
- }
- continue;
+ fieldID = Field.CURRENCY;
+ break;
case PATTERN_PERCENT:
- c = symbols.getPercent();
- field = -1;
+ string = symbols.getPercentText();
fieldID = Field.PERCENT;
break;
case PATTERN_PER_MILLE:
- c = symbols.getPerMill();
- field = -1;
+ string = symbols.getPerMillText();
fieldID = Field.PERMILLE;
break;
case PATTERN_MINUS:
- c = symbols.getMinusSign();
- field = -1;
+ string = symbols.getMinusSignText();
fieldID = Field.SIGN;
break;
}
- if (fieldID != null) {
+
+ if (fieldID != null && !string.isEmpty()) {
if (positions == null) {
positions = new ArrayList<>(2);
}
- FieldPosition fp = new FieldPosition(fieldID, field);
+ FieldPosition fp = new FieldPosition(fieldID);
fp.setBeginIndex(stringIndex);
- fp.setEndIndex(stringIndex + 1);
+ fp.setEndIndex(stringIndex + string.length());
positions.add(fp);
+ stringIndex += string.length();
+ continue;
}
}
stringIndex++;
@@ -3129,14 +3119,14 @@
} else if (localized) {
switch (c) {
case PATTERN_PERCENT:
- c = symbols.getPercent();
- break;
+ buffer.append(symbols.getPercentText());
+ continue;
case PATTERN_PER_MILLE:
- c = symbols.getPerMill();
- break;
+ buffer.append(symbols.getPerMillText());
+ continue;
case PATTERN_MINUS:
- c = symbols.getMinusSign();
- break;
+ buffer.append(symbols.getMinusSignText());
+ continue;
}
}
buffer.append(c);
@@ -3155,11 +3145,11 @@
needQuote = affix.indexOf(symbols.getZeroDigit()) >= 0
|| affix.indexOf(symbols.getGroupingSeparator()) >= 0
|| affix.indexOf(symbols.getDecimalSeparator()) >= 0
- || affix.indexOf(symbols.getPercent()) >= 0
- || affix.indexOf(symbols.getPerMill()) >= 0
+ || affix.indexOf(symbols.getPercentText()) >= 0
+ || affix.indexOf(symbols.getPerMillText()) >= 0
|| affix.indexOf(symbols.getDigit()) >= 0
|| affix.indexOf(symbols.getPatternSeparator()) >= 0
- || affix.indexOf(symbols.getMinusSign()) >= 0
+ || affix.indexOf(symbols.getMinusSignText()) >= 0
|| affix.indexOf(CURRENCY_SIGN) >= 0;
} else {
needQuote = affix.indexOf(PATTERN_ZERO_DIGIT) >= 0
@@ -3235,7 +3225,7 @@
if ((negPrefixPattern != null && posPrefixPattern != null &&
negPrefixPattern.equals("'-" + posPrefixPattern)) ||
(negPrefixPattern == posPrefixPattern && // n == p == null
- negativePrefix.equals(symbols.getMinusSign() + positivePrefix)))
+ negativePrefix.equals(symbols.getMinusSignText() + positivePrefix)))
break;
}
result.append(localized ? symbols.getPatternSeparator() :
@@ -3255,16 +3245,16 @@
* by this routine, since that is the typical end-user desire;
* use setMaximumInteger if you want to set a real value.
* For negative numbers, use a second pattern, separated by a semicolon
- * <P>Example <code>"#,#00.0#"</code> → 1,234.56
+ * <P>Example {@code "#,#00.0#"} → 1,234.56
* <P>This means a minimum of 2 integer digits, 1 fraction digit, and
* a maximum of 2 fraction digits.
- * <p>Example: <code>"#,#00.0#;(#,#00.0#)"</code> for negatives in
+ * <p>Example: {@code "#,#00.0#;(#,#00.0#)"} for negatives in
* parentheses.
* <p>In negative patterns, the minimum and maximum counts are ignored;
* these are presumed to be set in the positive pattern.
*
* @param pattern a new pattern
- * @exception NullPointerException if <code>pattern</code> is null
+ * @exception NullPointerException if {@code pattern} is null
* @exception IllegalArgumentException if the given pattern is invalid.
*/
public void applyPattern(String pattern) {
@@ -3282,16 +3272,16 @@
* by this routine, since that is the typical end-user desire;
* use setMaximumInteger if you want to set a real value.
* For negative numbers, use a second pattern, separated by a semicolon
- * <P>Example <code>"#,#00.0#"</code> → 1,234.56
+ * <P>Example {@code "#,#00.0#"} → 1,234.56
* <P>This means a minimum of 2 integer digits, 1 fraction digit, and
* a maximum of 2 fraction digits.
- * <p>Example: <code>"#,#00.0#;(#,#00.0#)"</code> for negatives in
+ * <p>Example: {@code "#,#00.0#;(#,#00.0#)"} for negatives in
* parentheses.
* <p>In negative patterns, the minimum and maximum counts are ignored;
* these are presumed to be set in the positive pattern.
*
* @param pattern a new pattern
- * @exception NullPointerException if <code>pattern</code> is null
+ * @exception NullPointerException if {@code pattern} is null
* @exception IllegalArgumentException if the given pattern is invalid.
*/
public void applyLocalizedPattern(String pattern) {
@@ -3309,7 +3299,7 @@
char perMill = PATTERN_PER_MILLE;
char digit = PATTERN_DIGIT;
char separator = PATTERN_SEPARATOR;
- String exponent = PATTERN_EXPONENT;
+ String exponent = PATTERN_EXPONENT;
char minus = PATTERN_MINUS;
if (localized) {
zeroDigit = symbols.getZeroDigit();
@@ -3635,8 +3625,8 @@
/**
* Sets the maximum number of digits allowed in the integer portion of a
* number.
- * For formatting numbers other than <code>BigInteger</code> and
- * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
+ * For formatting numbers other than {@code BigInteger} and
+ * {@code BigDecimal} objects, the lower of {@code newValue} and
* 309 is used. Negative input values are replaced with 0.
* @see NumberFormat#setMaximumIntegerDigits
*/
@@ -3656,8 +3646,8 @@
/**
* Sets the minimum number of digits allowed in the integer portion of a
* number.
- * For formatting numbers other than <code>BigInteger</code> and
- * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
+ * For formatting numbers other than {@code BigInteger} and
+ * {@code BigDecimal} objects, the lower of {@code newValue} and
* 309 is used. Negative input values are replaced with 0.
* @see NumberFormat#setMinimumIntegerDigits
*/
@@ -3677,8 +3667,8 @@
/**
* Sets the maximum number of digits allowed in the fraction portion of a
* number.
- * For formatting numbers other than <code>BigInteger</code> and
- * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
+ * For formatting numbers other than {@code BigInteger} and
+ * {@code BigDecimal} objects, the lower of {@code newValue} and
* 340 is used. Negative input values are replaced with 0.
* @see NumberFormat#setMaximumFractionDigits
*/
@@ -3698,8 +3688,8 @@
/**
* Sets the minimum number of digits allowed in the fraction portion of a
* number.
- * For formatting numbers other than <code>BigInteger</code> and
- * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
+ * For formatting numbers other than {@code BigInteger} and
+ * {@code BigDecimal} objects, the lower of {@code newValue} and
* 340 is used. Negative input values are replaced with 0.
* @see NumberFormat#setMinimumFractionDigits
*/
@@ -3719,8 +3709,8 @@
/**
* Gets the maximum number of digits allowed in the integer portion of a
* number.
- * For formatting numbers other than <code>BigInteger</code> and
- * <code>BigDecimal</code> objects, the lower of the return value and
+ * For formatting numbers other than {@code BigInteger} and
+ * {@code BigDecimal} objects, the lower of the return value and
* 309 is used.
* @see #setMaximumIntegerDigits
*/
@@ -3732,8 +3722,8 @@
/**
* Gets the minimum number of digits allowed in the integer portion of a
* number.
- * For formatting numbers other than <code>BigInteger</code> and
- * <code>BigDecimal</code> objects, the lower of the return value and
+ * For formatting numbers other than {@code BigInteger} and
+ * {@code BigDecimal} objects, the lower of the return value and
* 309 is used.
* @see #setMinimumIntegerDigits
*/
@@ -3745,8 +3735,8 @@
/**
* Gets the maximum number of digits allowed in the fraction portion of a
* number.
- * For formatting numbers other than <code>BigInteger</code> and
- * <code>BigDecimal</code> objects, the lower of the return value and
+ * For formatting numbers other than {@code BigInteger} and
+ * {@code BigDecimal} objects, the lower of the return value and
* 340 is used.
* @see #setMaximumFractionDigits
*/
@@ -3758,8 +3748,8 @@
/**
* Gets the minimum number of digits allowed in the fraction portion of a
* number.
- * For formatting numbers other than <code>BigInteger</code> and
- * <code>BigDecimal</code> objects, the lower of the return value and
+ * For formatting numbers other than {@code BigInteger} and
+ * {@code BigDecimal} objects, the lower of the return value and
* 340 is used.
* @see #setMinimumFractionDigits
*/
@@ -3775,7 +3765,7 @@
* {@link DecimalFormatSymbols#getCurrency DecimalFormatSymbols.getCurrency}
* on this number format's symbols.
*
- * @return the currency used by this decimal format, or <code>null</code>
+ * @return the currency used by this decimal format, or {@code null}
* @since 1.4
*/
@Override
@@ -3792,7 +3782,7 @@
* on this number format's symbols.
*
* @param currency the new currency to be used by this decimal format
- * @exception NullPointerException if <code>currency</code> is null
+ * @exception NullPointerException if {@code currency} is null
* @since 1.4
*/
@Override
@@ -3809,7 +3799,7 @@
/**
* Gets the {@link java.math.RoundingMode} used in this DecimalFormat.
*
- * @return The <code>RoundingMode</code> used for this DecimalFormat.
+ * @return The {@code RoundingMode} used for this DecimalFormat.
* @see #setRoundingMode(RoundingMode)
* @since 1.6
*/
@@ -3821,9 +3811,9 @@
/**
* Sets the {@link java.math.RoundingMode} used in this DecimalFormat.
*
- * @param roundingMode The <code>RoundingMode</code> to be used
+ * @param roundingMode The {@code RoundingMode} to be used
* @see #getRoundingMode()
- * @exception NullPointerException if <code>roundingMode</code> is null.
+ * @exception NullPointerException if {@code roundingMode} is null.
* @since 1.6
*/
@Override
@@ -3845,38 +3835,38 @@
* <li>
* Verify that the superclass's digit count fields correctly reflect
* the limits imposed on formatting numbers other than
- * <code>BigInteger</code> and <code>BigDecimal</code> objects. These
+ * {@code BigInteger} and {@code BigDecimal} objects. These
* limits are stored in the superclass for serialization compatibility
- * with older versions, while the limits for <code>BigInteger</code> and
- * <code>BigDecimal</code> objects are kept in this class.
+ * with older versions, while the limits for {@code BigInteger} and
+ * {@code BigDecimal} objects are kept in this class.
* If, in the superclass, the minimum or maximum integer digit count is
- * larger than <code>DOUBLE_INTEGER_DIGITS</code> or if the minimum or
+ * larger than {@code DOUBLE_INTEGER_DIGITS} or if the minimum or
* maximum fraction digit count is larger than
- * <code>DOUBLE_FRACTION_DIGITS</code>, then the stream data is invalid
- * and this method throws an <code>InvalidObjectException</code>.
+ * {@code DOUBLE_FRACTION_DIGITS}, then the stream data is invalid
+ * and this method throws an {@code InvalidObjectException}.
* <li>
- * If <code>serialVersionOnStream</code> is less than 4, initialize
- * <code>roundingMode</code> to {@link java.math.RoundingMode#HALF_EVEN
+ * If {@code serialVersionOnStream} is less than 4, initialize
+ * {@code roundingMode} to {@link java.math.RoundingMode#HALF_EVEN
* RoundingMode.HALF_EVEN}. This field is new with version 4.
* <li>
- * If <code>serialVersionOnStream</code> is less than 3, then call
+ * If {@code serialVersionOnStream} is less than 3, then call
* the setters for the minimum and maximum integer and fraction digits with
* the values of the corresponding superclass getters to initialize the
* fields in this class. The fields in this class are new with version 3.
* <li>
- * If <code>serialVersionOnStream</code> is less than 1, indicating that
+ * If {@code serialVersionOnStream} is less than 1, indicating that
* the stream was written by JDK 1.1, initialize
- * <code>useExponentialNotation</code>
+ * {@code useExponentialNotation}
* to false, since it was not present in JDK 1.1.
* <li>
- * Set <code>serialVersionOnStream</code> to the maximum allowed value so
+ * Set {@code serialVersionOnStream} to the maximum allowed value so
* that default serialization will work properly if this object is streamed
* out again.
* </ol>
*
* <p>Stream versions older than 2 will not have the affix pattern variables
- * <code>posPrefixPattern</code> etc. As a result, they will be initialized
- * to <code>null</code>, which means the affix strings will be taken as
+ * {@code posPrefixPattern} etc. As a result, they will be initialized
+ * to {@code null}, which means the affix strings will be taken as
* literal values. This is exactly what we want, since that corresponds to
* the pre-version-2 behavior.
*/
@@ -3960,14 +3950,14 @@
/**
* The prefix pattern for non-negative numbers. This variable corresponds
- * to <code>positivePrefix</code>.
+ * to {@code positivePrefix}.
*
- * <p>This pattern is expanded by the method <code>expandAffix()</code> to
- * <code>positivePrefix</code> to update the latter to reflect changes in
- * <code>symbols</code>. If this variable is <code>null</code> then
- * <code>positivePrefix</code> is taken as a literal value that does not
- * change when <code>symbols</code> changes. This variable is always
- * <code>null</code> for <code>DecimalFormat</code> objects older than
+ * <p>This pattern is expanded by the method {@code expandAffix()} to
+ * {@code positivePrefix} to update the latter to reflect changes in
+ * {@code symbols}. If this variable is {@code null} then
+ * {@code positivePrefix} is taken as a literal value that does not
+ * change when {@code symbols} changes. This variable is always
+ * {@code null} for {@code DecimalFormat} objects older than
* stream version 2 restored from stream.
*
* @serial
@@ -3977,8 +3967,8 @@
/**
* The suffix pattern for non-negative numbers. This variable corresponds
- * to <code>positiveSuffix</code>. This variable is analogous to
- * <code>posPrefixPattern</code>; see that variable for further
+ * to {@code positiveSuffix}. This variable is analogous to
+ * {@code posPrefixPattern}; see that variable for further
* documentation.
*
* @serial
@@ -3988,8 +3978,8 @@
/**
* The prefix pattern for negative numbers. This variable corresponds
- * to <code>negativePrefix</code>. This variable is analogous to
- * <code>posPrefixPattern</code>; see that variable for further
+ * to {@code negativePrefix}. This variable is analogous to
+ * {@code posPrefixPattern}; see that variable for further
* documentation.
*
* @serial
@@ -3999,8 +3989,8 @@
/**
* The suffix pattern for negative numbers. This variable corresponds
- * to <code>negativeSuffix</code>. This variable is analogous to
- * <code>posPrefixPattern</code>; see that variable for further
+ * to {@code negativeSuffix}. This variable is analogous to
+ * {@code posPrefixPattern}; see that variable for further
* documentation.
*
* @serial
@@ -4019,7 +4009,7 @@
/**
* The number of digits between grouping separators in the integer
* portion of a number. Must be greater than 0 if
- * <code>NumberFormat.groupingUsed</code> is true.
+ * {@code NumberFormat.groupingUsed} is true.
*
* @serial
* @see #getGroupingSize
@@ -4053,7 +4043,7 @@
private transient boolean isCurrencyFormat = false;
/**
- * The <code>DecimalFormatSymbols</code> object used by this format.
+ * The {@code DecimalFormatSymbols} object used by this format.
* It contains the symbols used to format numbers, e.g. the grouping separator,
* decimal separator, and so on.
*
@@ -4074,28 +4064,28 @@
/**
* FieldPositions describing the positive prefix String. This is
- * lazily created. Use <code>getPositivePrefixFieldPositions</code>
+ * lazily created. Use {@code getPositivePrefixFieldPositions}
* when needed.
*/
private transient FieldPosition[] positivePrefixFieldPositions;
/**
* FieldPositions describing the positive suffix String. This is
- * lazily created. Use <code>getPositiveSuffixFieldPositions</code>
+ * lazily created. Use {@code getPositiveSuffixFieldPositions}
* when needed.
*/
private transient FieldPosition[] positiveSuffixFieldPositions;
/**
* FieldPositions describing the negative prefix String. This is
- * lazily created. Use <code>getNegativePrefixFieldPositions</code>
+ * lazily created. Use {@code getNegativePrefixFieldPositions}
* when needed.
*/
private transient FieldPosition[] negativePrefixFieldPositions;
/**
* FieldPositions describing the negative suffix String. This is
- * lazily created. Use <code>getNegativeSuffixFieldPositions</code>
+ * lazily created. Use {@code getNegativeSuffixFieldPositions}
* when needed.
*/
private transient FieldPosition[] negativeSuffixFieldPositions;
@@ -4103,7 +4093,7 @@
/**
* The minimum number of digits used to display the exponent when a number is
* formatted in exponential notation. This field is ignored if
- * <code>useExponentialNotation</code> is not true.
+ * {@code useExponentialNotation} is not true.
*
* @serial
* @since 1.2
@@ -4112,9 +4102,9 @@
/**
* The maximum number of digits allowed in the integer portion of a
- * <code>BigInteger</code> or <code>BigDecimal</code> number.
- * <code>maximumIntegerDigits</code> must be greater than or equal to
- * <code>minimumIntegerDigits</code>.
+ * {@code BigInteger} or {@code BigDecimal} number.
+ * {@code maximumIntegerDigits} must be greater than or equal to
+ * {@code minimumIntegerDigits}.
*
* @serial
* @see #getMaximumIntegerDigits
@@ -4124,9 +4114,9 @@
/**
* The minimum number of digits allowed in the integer portion of a
- * <code>BigInteger</code> or <code>BigDecimal</code> number.
- * <code>minimumIntegerDigits</code> must be less than or equal to
- * <code>maximumIntegerDigits</code>.
+ * {@code BigInteger} or {@code BigDecimal} number.
+ * {@code minimumIntegerDigits} must be less than or equal to
+ * {@code maximumIntegerDigits}.
*
* @serial
* @see #getMinimumIntegerDigits
@@ -4136,9 +4126,9 @@
/**
* The maximum number of digits allowed in the fractional portion of a
- * <code>BigInteger</code> or <code>BigDecimal</code> number.
- * <code>maximumFractionDigits</code> must be greater than or equal to
- * <code>minimumFractionDigits</code>.
+ * {@code BigInteger} or {@code BigDecimal} number.
+ * {@code maximumFractionDigits} must be greater than or equal to
+ * {@code minimumFractionDigits}.
*
* @serial
* @see #getMaximumFractionDigits
@@ -4148,9 +4138,9 @@
/**
* The minimum number of digits allowed in the fractional portion of a
- * <code>BigInteger</code> or <code>BigDecimal</code> number.
- * <code>minimumFractionDigits</code> must be less than or equal to
- * <code>maximumFractionDigits</code>.
+ * {@code BigInteger} or {@code BigDecimal} number.
+ * {@code minimumFractionDigits} must be less than or equal to
+ * {@code maximumFractionDigits}.
*
* @serial
* @see #getMinimumFractionDigits
@@ -4247,19 +4237,19 @@
* <ul>
* <li><b>0</b> (default): versions before the Java 2 platform v1.2
* <li><b>1</b>: version for 1.2, which includes the two new fields
- * <code>useExponentialNotation</code> and
- * <code>minExponentDigits</code>.
+ * {@code useExponentialNotation} and
+ * {@code minExponentDigits}.
* <li><b>2</b>: version for 1.3 and later, which adds four new fields:
- * <code>posPrefixPattern</code>, <code>posSuffixPattern</code>,
- * <code>negPrefixPattern</code>, and <code>negSuffixPattern</code>.
+ * {@code posPrefixPattern}, {@code posSuffixPattern},
+ * {@code negPrefixPattern}, and {@code negSuffixPattern}.
* <li><b>3</b>: version for 1.5 and later, which adds five new fields:
- * <code>maximumIntegerDigits</code>,
- * <code>minimumIntegerDigits</code>,
- * <code>maximumFractionDigits</code>,
- * <code>minimumFractionDigits</code>, and
- * <code>parseBigDecimal</code>.
+ * {@code maximumIntegerDigits},
+ * {@code minimumIntegerDigits},
+ * {@code maximumFractionDigits},
+ * {@code minimumFractionDigits}, and
+ * {@code parseBigDecimal}.
* <li><b>4</b>: version for 1.6 and later, which adds one new field:
- * <code>roundingMode</code>.
+ * {@code roundingMode}.
* </ul>
* @since 1.2
* @serial
--- a/src/java.base/share/classes/java/text/DecimalFormatSymbols.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.base/share/classes/java/text/DecimalFormatSymbols.java Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, 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
@@ -38,12 +38,14 @@
package java.text;
+import java.io.InvalidObjectException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.text.spi.DecimalFormatSymbolsProvider;
import java.util.Currency;
import java.util.Locale;
+import java.util.Objects;
import sun.util.locale.provider.CalendarDataUtility;
import sun.util.locale.provider.LocaleProviderAdapter;
import sun.util.locale.provider.LocaleServiceProviderPool;
@@ -51,11 +53,11 @@
/**
* This class represents the set of symbols (such as the decimal separator,
- * the grouping separator, and so on) needed by <code>DecimalFormat</code>
- * to format numbers. <code>DecimalFormat</code> creates for itself an instance of
- * <code>DecimalFormatSymbols</code> from its locale data. If you need to change any
- * of these symbols, you can get the <code>DecimalFormatSymbols</code> object from
- * your <code>DecimalFormat</code> and modify it.
+ * the grouping separator, and so on) needed by {@code DecimalFormat}
+ * to format numbers. {@code DecimalFormat} creates for itself an instance of
+ * {@code DecimalFormatSymbols} from its locale data. If you need to change any
+ * of these symbols, you can get the {@code DecimalFormatSymbols} object from
+ * your {@code DecimalFormat} and modify it.
*
* <p>If the locale contains "rg" (region override)
* <a href="../util/Locale.html#def_locale_extension">Unicode extension</a>,
@@ -107,7 +109,7 @@
* instead of the Latin numbering system.
*
* @param locale the desired locale
- * @exception NullPointerException if <code>locale</code> is null
+ * @exception NullPointerException if {@code locale} is null
*/
public DecimalFormatSymbols( Locale locale ) {
initialize( locale );
@@ -115,16 +117,16 @@
/**
* Returns an array of all locales for which the
- * <code>getInstance</code> methods of this class can return
+ * {@code getInstance} methods of this class can return
* localized instances.
* The returned array represents the union of locales supported by the Java
* runtime and by installed
* {@link java.text.spi.DecimalFormatSymbolsProvider DecimalFormatSymbolsProvider}
- * implementations. It must contain at least a <code>Locale</code>
+ * implementations. It must contain at least a {@code Locale}
* instance equal to {@link java.util.Locale#US Locale.US}.
*
* @return an array of locales for which localized
- * <code>DecimalFormatSymbols</code> instances are available.
+ * {@code DecimalFormatSymbols} instances are available.
* @since 1.6
*/
public static Locale[] getAvailableLocales() {
@@ -134,8 +136,8 @@
}
/**
- * Gets the <code>DecimalFormatSymbols</code> instance for the default
- * locale. This method provides access to <code>DecimalFormatSymbols</code>
+ * Gets the {@code DecimalFormatSymbols} instance for the default
+ * locale. This method provides access to {@code DecimalFormatSymbols}
* instances for locales supported by the Java runtime itself as well
* as for those supported by installed
* {@link java.text.spi.DecimalFormatSymbolsProvider
@@ -145,7 +147,7 @@
* getInstance(Locale.getDefault(Locale.Category.FORMAT))}.
* @see java.util.Locale#getDefault(java.util.Locale.Category)
* @see java.util.Locale.Category#FORMAT
- * @return a <code>DecimalFormatSymbols</code> instance.
+ * @return a {@code DecimalFormatSymbols} instance.
* @since 1.6
*/
public static final DecimalFormatSymbols getInstance() {
@@ -153,8 +155,8 @@
}
/**
- * Gets the <code>DecimalFormatSymbols</code> instance for the specified
- * locale. This method provides access to <code>DecimalFormatSymbols</code>
+ * Gets the {@code DecimalFormatSymbols} instance for the specified
+ * locale. This method provides access to {@code DecimalFormatSymbols}
* instances for locales supported by the Java runtime itself as well
* as for those supported by installed
* {@link java.text.spi.DecimalFormatSymbolsProvider
@@ -169,8 +171,8 @@
* instead of the Latin numbering system.
*
* @param locale the desired locale.
- * @return a <code>DecimalFormatSymbols</code> instance.
- * @exception NullPointerException if <code>locale</code> is null
+ * @return a {@code DecimalFormatSymbols} instance.
+ * @exception NullPointerException if {@code locale} is null
* @since 1.6
*/
public static final DecimalFormatSymbols getInstance(Locale locale) {
@@ -255,6 +257,41 @@
*/
public void setPerMill(char perMill) {
this.perMill = perMill;
+ this.perMillText = Character.toString(perMill);
+ }
+
+ /**
+ * Gets the string used for per mille sign. Different for Arabic, etc.
+ *
+ * @return the string used for per mille sign
+ * @since 13
+ */
+ String getPerMillText() {
+ return perMillText;
+ }
+
+ /**
+ * Sets the string used for per mille sign. Different for Arabic, etc.
+ *
+ * Setting the {@code perMillText} affects the return value of
+ * {@link #getPerMill()}, in which the first non-format character of
+ * {@code perMillText} is returned.
+ *
+ * @param perMillText the string used for per mille sign
+ * @throws NullPointerException if {@code perMillText} is null
+ * @throws IllegalArgumentException if {@code perMillText} is an empty string
+ * @see #getPerMill()
+ * @see #getPerMillText()
+ * @since 13
+ */
+ void setPerMillText(String perMillText) {
+ Objects.requireNonNull(perMillText);
+ if (perMillText.isEmpty()) {
+ throw new IllegalArgumentException("Empty argument string");
+ }
+
+ this.perMillText = perMillText;
+ this.perMill = findNonFormatChar(perMillText, '\u2030');
}
/**
@@ -273,6 +310,41 @@
*/
public void setPercent(char percent) {
this.percent = percent;
+ this.percentText = Character.toString(percent);
+ }
+
+ /**
+ * Gets the string used for percent sign. Different for Arabic, etc.
+ *
+ * @return the string used for percent sign
+ * @since 13
+ */
+ String getPercentText() {
+ return percentText;
+ }
+
+ /**
+ * Sets the string used for percent sign. Different for Arabic, etc.
+ *
+ * Setting the {@code percentText} affects the return value of
+ * {@link #getPercent()}, in which the first non-format character of
+ * {@code percentText} is returned.
+ *
+ * @param percentText the string used for percent sign
+ * @throws NullPointerException if {@code percentText} is null
+ * @throws IllegalArgumentException if {@code percentText} is an empty string
+ * @see #getPercent()
+ * @see #getPercentText()
+ * @since 13
+ */
+ void setPercentText(String percentText) {
+ Objects.requireNonNull(percentText);
+ if (percentText.isEmpty()) {
+ throw new IllegalArgumentException("Empty argument string");
+ }
+
+ this.percentText = percentText;
+ this.percent = findNonFormatChar(percentText, '%');
}
/**
@@ -373,6 +445,46 @@
*/
public void setMinusSign(char minusSign) {
this.minusSign = minusSign;
+ this.minusSignText = Character.toString(minusSign);
+ }
+
+ /**
+ * Gets the string used to represent minus sign. If no explicit
+ * negative format is specified, one is formed by prefixing
+ * minusSignText to the positive format.
+ *
+ * @return the string representing minus sign
+ * @since 13
+ */
+ String getMinusSignText() {
+ return minusSignText;
+ }
+
+ /**
+ * Sets the string used to represent minus sign. If no explicit
+ * negative format is specified, one is formed by prefixing
+ * minusSignText to the positive format.
+ *
+ * Setting the {@code minusSignText} affects the return value of
+ * {@link #getMinusSign()}, in which the first non-format character of
+ * {@code minusSignText} is returned.
+ *
+ * @param minusSignText the character representing minus sign
+ * @throws NullPointerException if {@code minusSignText} is null
+ * @throws IllegalArgumentException if {@code minusSignText} is an
+ * empty string
+ * @see #getMinusSign()
+ * @see #getMinusSignText()
+ * @since 13
+ */
+ void setMinusSignText(String minusSignText) {
+ Objects.requireNonNull(minusSignText);
+ if (minusSignText.isEmpty()) {
+ throw new IllegalArgumentException("Empty argument string");
+ }
+
+ this.minusSignText = minusSignText;
+ this.minusSign = findNonFormatChar(minusSignText, '-');
}
/**
@@ -464,7 +576,7 @@
* symbol attribute to the currency's ISO 4217 currency code.
*
* @param currency the new currency to be used
- * @exception NullPointerException if <code>currency</code> is null
+ * @exception NullPointerException if {@code currency} is null
* @since 1.4
* @see #setCurrencySymbol
* @see #setInternationalCurrencySymbol
@@ -540,7 +652,7 @@
* Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.
*
* @param exp the exponent separator string
- * @exception NullPointerException if <code>exp</code> is null
+ * @exception NullPointerException if {@code exp} is null
* @see #getExponentSeparator()
* @since 1.6
*/
@@ -583,9 +695,12 @@
groupingSeparator == other.groupingSeparator &&
decimalSeparator == other.decimalSeparator &&
percent == other.percent &&
+ percentText.equals(other.percentText) &&
perMill == other.perMill &&
+ perMillText.equals(other.perMillText) &&
digit == other.digit &&
minusSign == other.minusSign &&
+ minusSignText.equals(other.minusSignText) &&
patternSeparator == other.patternSeparator &&
infinity.equals(other.infinity) &&
NaN.equals(other.NaN) &&
@@ -631,13 +746,16 @@
decimalSeparator = numberElements[0].charAt(0);
groupingSeparator = numberElements[1].charAt(0);
patternSeparator = numberElements[2].charAt(0);
- percent = numberElements[3].charAt(0);
+ percentText = numberElements[3];
+ percent = findNonFormatChar(percentText, '%');
zeroDigit = numberElements[4].charAt(0); //different for Arabic,etc.
digit = numberElements[5].charAt(0);
- minusSign = numberElements[6].charAt(0);
+ minusSignText = numberElements[6];
+ minusSign = findNonFormatChar(minusSignText, '-');
exponential = numberElements[7].charAt(0);
exponentialSeparator = numberElements[7]; //string representation new since 1.6
- perMill = numberElements[8].charAt(0);
+ perMillText = numberElements[8];
+ perMill = findNonFormatChar(perMillText, '\u2030');
infinity = numberElements[9];
NaN = numberElements[10];
@@ -652,6 +770,16 @@
}
/**
+ * Obtains non-format single character from String
+ */
+ private char findNonFormatChar(String src, char defChar) {
+ return (char)src.chars()
+ .filter(c -> Character.getType(c) != Character.FORMAT)
+ .findFirst()
+ .orElse(defChar);
+ }
+
+ /**
* Lazy initialization for currency related fields
*/
private void initializeCurrency(Locale locale) {
@@ -704,18 +832,24 @@
/**
* Reads the default serializable fields, provides default values for objects
* in older serial versions, and initializes non-serializable fields.
- * If <code>serialVersionOnStream</code>
- * is less than 1, initializes <code>monetarySeparator</code> to be
- * the same as <code>decimalSeparator</code> and <code>exponential</code>
+ * If {@code serialVersionOnStream}
+ * is less than 1, initializes {@code monetarySeparator} to be
+ * the same as {@code decimalSeparator} and {@code exponential}
* to be 'E'.
- * If <code>serialVersionOnStream</code> is less than 2,
- * initializes <code>locale</code>to the root locale, and initializes
- * If <code>serialVersionOnStream</code> is less than 3, it initializes
- * <code>exponentialSeparator</code> using <code>exponential</code>.
- * Sets <code>serialVersionOnStream</code> back to the maximum allowed value so that
+ * If {@code serialVersionOnStream} is less than 2,
+ * initializes {@code locale}to the root locale, and initializes
+ * If {@code serialVersionOnStream} is less than 3, it initializes
+ * {@code exponentialSeparator} using {@code exponential}.
+ * If {@code serialVersionOnStream} is less than 4, it initializes
+ * {@code perMillText}, {@code percentText}, and
+ * {@code minusSignText} using {@code perMill}, {@code percent}, and
+ * {@code minusSign} respectively.
+ * Sets {@code serialVersionOnStream} back to the maximum allowed value so that
* default serialization will work properly if this object is streamed out again.
* Initializes the currency from the intlCurrencySymbol field.
*
+ * @throws InvalidObjectException if {@code char} and {@code String}
+ * representations of either percent, per mille, and/or minus sign disagree.
* @since 1.1.6
*/
private void readObject(ObjectInputStream stream)
@@ -735,6 +869,23 @@
// didn't have exponentialSeparator. Create one using exponential
exponentialSeparator = Character.toString(exponential);
}
+ if (serialVersionOnStream < 4) {
+ // didn't have perMillText, percentText, and minusSignText.
+ // Create one using corresponding char variations.
+ perMillText = Character.toString(perMill);
+ percentText = Character.toString(percent);
+ minusSignText = Character.toString(minusSign);
+ } else {
+ // Check whether char and text fields agree
+ if (findNonFormatChar(perMillText, '\uFFFF') != perMill ||
+ findNonFormatChar(percentText, '\uFFFF') != percent ||
+ findNonFormatChar(minusSignText, '\uFFFF') != minusSign) {
+ throw new InvalidObjectException(
+ "'char' and 'String' representations of either percent, " +
+ "per mille, and/or minus sign disagree.");
+ }
+ }
+
serialVersionOnStream = currentSerialVersion;
if (intlCurrencySymbol != null) {
@@ -862,8 +1013,8 @@
* The string used to separate the mantissa from the exponent.
* Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.
* <p>
- * If both <code>exponential</code> and <code>exponentialSeparator</code>
- * exist, this <code>exponentialSeparator</code> has the precedence.
+ * If both {@code exponential} and {@code exponentialSeparator}
+ * exist, this {@code exponentialSeparator} has the precedence.
*
* @serial
* @since 1.6
@@ -878,6 +1029,39 @@
*/
private Locale locale;
+ /**
+ * String representation of per mille sign, which may include
+ * formatting characters, such as BiDi control characters.
+ * The first non-format character of this string is the same as
+ * {@code perMill}.
+ *
+ * @serial
+ * @since 13
+ */
+ private String perMillText;
+
+ /**
+ * String representation of percent sign, which may include
+ * formatting characters, such as BiDi control characters.
+ * The first non-format character of this string is the same as
+ * {@code percent}.
+ *
+ * @serial
+ * @since 13
+ */
+ private String percentText;
+
+ /**
+ * String representation of minus sign, which may include
+ * formatting characters, such as BiDi control characters.
+ * The first non-format character of this string is the same as
+ * {@code minusSign}.
+ *
+ * @serial
+ * @since 13
+ */
+ private String minusSignText;
+
// currency; only the ISO code is serialized.
private transient Currency currency;
private transient volatile boolean currencyInitialized;
@@ -891,23 +1075,28 @@
// monetarySeparator and exponential.
// - 2 for version from J2SE 1.4, which includes locale field.
// - 3 for version from J2SE 1.6, which includes exponentialSeparator field.
- private static final int currentSerialVersion = 3;
+ // - 4 for version from Java SE 13, which includes perMillText, percentText,
+ // and minusSignText field.
+ private static final int currentSerialVersion = 4;
/**
- * Describes the version of <code>DecimalFormatSymbols</code> present on the stream.
+ * Describes the version of {@code DecimalFormatSymbols} present on the stream.
* Possible values are:
* <ul>
* <li><b>0</b> (or uninitialized): versions prior to JDK 1.1.6.
*
* <li><b>1</b>: Versions written by JDK 1.1.6 or later, which include
- * two new fields: <code>monetarySeparator</code> and <code>exponential</code>.
+ * two new fields: {@code monetarySeparator} and {@code exponential}.
* <li><b>2</b>: Versions written by J2SE 1.4 or later, which include a
- * new <code>locale</code> field.
+ * new {@code locale} field.
* <li><b>3</b>: Versions written by J2SE 1.6 or later, which include a
- * new <code>exponentialSeparator</code> field.
+ * new {@code exponentialSeparator} field.
+ * <li><b>4</b>: Versions written by Java SE 13 or later, which include
+ * new {@code perMillText}, {@code percentText}, and
+ * {@code minusSignText} field.
* </ul>
- * When streaming out a <code>DecimalFormatSymbols</code>, the most recent format
- * (corresponding to the highest allowable <code>serialVersionOnStream</code>)
+ * When streaming out a {@code DecimalFormatSymbols}, the most recent format
+ * (corresponding to the highest allowable {@code serialVersionOnStream})
* is always written.
*
* @serial
--- a/src/java.base/share/classes/java/util/jar/Attributes.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.base/share/classes/java/util/jar/Attributes.java Sat Mar 30 09:30:03 2019 +0000
@@ -34,6 +34,8 @@
import java.util.Objects;
import java.util.Set;
+import jdk.internal.misc.VM;
+import jdk.internal.vm.annotation.Stable;
import sun.util.logging.PlatformLogger;
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -454,7 +456,7 @@
/**
* Avoid allocation for common Names
*/
- private static final Map<String, Name> KNOWN_NAMES;
+ private static @Stable Map<String, Name> KNOWN_NAMES;
static final Name of(String name) {
Name n = KNOWN_NAMES.get(name);
@@ -541,7 +543,7 @@
* @see <a href="{@docRoot}/../specs/jar/jar.html#jar-manifest">
* Manifest and Signature Specification</a>
*/
- public static final Name MANIFEST_VERSION = new Name("Manifest-Version");
+ public static final Name MANIFEST_VERSION;
/**
* {@code Name} object for {@code Signature-Version}
@@ -549,13 +551,13 @@
* @see <a href="{@docRoot}/../specs/jar/jar.html#jar-manifest">
* Manifest and Signature Specification</a>
*/
- public static final Name SIGNATURE_VERSION = new Name("Signature-Version");
+ public static final Name SIGNATURE_VERSION;
/**
* {@code Name} object for {@code Content-Type}
* manifest attribute.
*/
- public static final Name CONTENT_TYPE = new Name("Content-Type");
+ public static final Name CONTENT_TYPE;
/**
* {@code Name} object for {@code Class-Path}
@@ -563,7 +565,7 @@
* @see <a href="{@docRoot}/../specs/jar/jar.html#class-path-attribute">
* JAR file specification</a>
*/
- public static final Name CLASS_PATH = new Name("Class-Path");
+ public static final Name CLASS_PATH;
/**
* {@code Name} object for {@code Main-Class} manifest
@@ -572,7 +574,7 @@
* with the {@code -jar} command-line option of the
* {@code java} application launcher.
*/
- public static final Name MAIN_CLASS = new Name("Main-Class");
+ public static final Name MAIN_CLASS;
/**
* {@code Name} object for {@code Sealed} manifest attribute
@@ -580,19 +582,19 @@
* @see <a href="{@docRoot}/../specs/jar/jar.html#package-sealing">
* Package Sealing</a>
*/
- public static final Name SEALED = new Name("Sealed");
+ public static final Name SEALED;
/**
* {@code Name} object for {@code Extension-List} manifest attribute
* used for the extension mechanism that is no longer supported.
*/
- public static final Name EXTENSION_LIST = new Name("Extension-List");
+ public static final Name EXTENSION_LIST;
/**
* {@code Name} object for {@code Extension-Name} manifest attribute.
* used for the extension mechanism that is no longer supported.
*/
- public static final Name EXTENSION_NAME = new Name("Extension-Name");
+ public static final Name EXTENSION_NAME;
/**
* {@code Name} object for {@code Extension-Installation} manifest attribute.
@@ -600,25 +602,25 @@
* @deprecated Extension mechanism is no longer supported.
*/
@Deprecated
- public static final Name EXTENSION_INSTALLATION = new Name("Extension-Installation");
+ public static final Name EXTENSION_INSTALLATION;
/**
* {@code Name} object for {@code Implementation-Title}
* manifest attribute used for package versioning.
*/
- public static final Name IMPLEMENTATION_TITLE = new Name("Implementation-Title");
+ public static final Name IMPLEMENTATION_TITLE;
/**
* {@code Name} object for {@code Implementation-Version}
* manifest attribute used for package versioning.
*/
- public static final Name IMPLEMENTATION_VERSION = new Name("Implementation-Version");
+ public static final Name IMPLEMENTATION_VERSION;
/**
* {@code Name} object for {@code Implementation-Vendor}
* manifest attribute used for package versioning.
*/
- public static final Name IMPLEMENTATION_VENDOR = new Name("Implementation-Vendor");
+ public static final Name IMPLEMENTATION_VENDOR;
/**
* {@code Name} object for {@code Implementation-Vendor-Id}
@@ -627,7 +629,7 @@
* @deprecated Extension mechanism is no longer supported.
*/
@Deprecated
- public static final Name IMPLEMENTATION_VENDOR_ID = new Name("Implementation-Vendor-Id");
+ public static final Name IMPLEMENTATION_VENDOR_ID;
/**
* {@code Name} object for {@code Implementation-URL}
@@ -636,25 +638,25 @@
* @deprecated Extension mechanism is no longer supported.
*/
@Deprecated
- public static final Name IMPLEMENTATION_URL = new Name("Implementation-URL");
+ public static final Name IMPLEMENTATION_URL;
/**
* {@code Name} object for {@code Specification-Title}
* manifest attribute used for package versioning.
*/
- public static final Name SPECIFICATION_TITLE = new Name("Specification-Title");
+ public static final Name SPECIFICATION_TITLE;
/**
* {@code Name} object for {@code Specification-Version}
* manifest attribute used for package versioning.
*/
- public static final Name SPECIFICATION_VERSION = new Name("Specification-Version");
+ public static final Name SPECIFICATION_VERSION;
/**
* {@code Name} object for {@code Specification-Vendor}
* manifest attribute used for package versioning.
*/
- public static final Name SPECIFICATION_VENDOR = new Name("Specification-Vendor");
+ public static final Name SPECIFICATION_VENDOR;
/**
* {@code Name} object for {@code Multi-Release}
@@ -662,56 +664,91 @@
*
* @since 9
*/
- public static final Name MULTI_RELEASE = new Name("Multi-Release");
+ public static final Name MULTI_RELEASE;
private static void addName(Map<String, Name> names, Name name) {
names.put(name.name, name);
}
static {
- var names = new HashMap<String, Name>(64);
- addName(names, MANIFEST_VERSION);
- addName(names, SIGNATURE_VERSION);
- addName(names, CONTENT_TYPE);
- addName(names, CLASS_PATH);
- addName(names, MAIN_CLASS);
- addName(names, SEALED);
- addName(names, EXTENSION_LIST);
- addName(names, EXTENSION_NAME);
- addName(names, IMPLEMENTATION_TITLE);
- addName(names, IMPLEMENTATION_VERSION);
- addName(names, IMPLEMENTATION_VENDOR);
- addName(names, SPECIFICATION_TITLE);
- addName(names, SPECIFICATION_VERSION);
- addName(names, SPECIFICATION_VENDOR);
- addName(names, MULTI_RELEASE);
+
+ VM.initializeFromArchive(Attributes.Name.class);
+
+ if (KNOWN_NAMES == null) {
+ MANIFEST_VERSION = new Name("Manifest-Version");
+ SIGNATURE_VERSION = new Name("Signature-Version");
+ CONTENT_TYPE = new Name("Content-Type");
+ CLASS_PATH = new Name("Class-Path");
+ MAIN_CLASS = new Name("Main-Class");
+ SEALED = new Name("Sealed");
+ EXTENSION_LIST = new Name("Extension-List");
+ EXTENSION_NAME = new Name("Extension-Name");
+ EXTENSION_INSTALLATION = new Name("Extension-Installation");
+ IMPLEMENTATION_TITLE = new Name("Implementation-Title");
+ IMPLEMENTATION_VERSION = new Name("Implementation-Version");
+ IMPLEMENTATION_VENDOR = new Name("Implementation-Vendor");
+ IMPLEMENTATION_VENDOR_ID = new Name("Implementation-Vendor-Id");
+ IMPLEMENTATION_URL = new Name("Implementation-URL");
+ SPECIFICATION_TITLE = new Name("Specification-Title");
+ SPECIFICATION_VERSION = new Name("Specification-Version");
+ SPECIFICATION_VENDOR = new Name("Specification-Vendor");
+ MULTI_RELEASE = new Name("Multi-Release");
- // Common attributes used in MANIFEST.MF et.al; adding these has a
- // small footprint cost, but is likely to be quickly paid for by
- // reducing allocation when reading and parsing typical manifests
- addName(names, new Name("Add-Exports"));
- addName(names, new Name("Add-Opens"));
- addName(names, new Name("Ant-Version"));
- addName(names, new Name("Archiver-Version"));
- addName(names, new Name("Build-Jdk"));
- addName(names, new Name("Built-By"));
- addName(names, new Name("Bnd-LastModified"));
- addName(names, new Name("Bundle-Description"));
- addName(names, new Name("Bundle-DocURL"));
- addName(names, new Name("Bundle-License"));
- addName(names, new Name("Bundle-ManifestVersion"));
- addName(names, new Name("Bundle-Name"));
- addName(names, new Name("Bundle-Vendor"));
- addName(names, new Name("Bundle-Version"));
- addName(names, new Name("Bundle-SymbolicName"));
- addName(names, new Name("Created-By"));
- addName(names, new Name("Export-Package"));
- addName(names, new Name("Import-Package"));
- addName(names, new Name("Name"));
- addName(names, new Name("SHA1-Digest"));
- addName(names, new Name("X-Compile-Source-JDK"));
- addName(names, new Name("X-Compile-Target-JDK"));
- KNOWN_NAMES = names;
+ var names = new HashMap<String, Name>(64);
+ addName(names, MANIFEST_VERSION);
+ addName(names, SIGNATURE_VERSION);
+ addName(names, CONTENT_TYPE);
+ addName(names, CLASS_PATH);
+ addName(names, MAIN_CLASS);
+ addName(names, SEALED);
+ addName(names, EXTENSION_LIST);
+ addName(names, EXTENSION_NAME);
+ addName(names, IMPLEMENTATION_TITLE);
+ addName(names, IMPLEMENTATION_VERSION);
+ addName(names, IMPLEMENTATION_VENDOR);
+ addName(names, SPECIFICATION_TITLE);
+ addName(names, SPECIFICATION_VERSION);
+ addName(names, SPECIFICATION_VENDOR);
+ addName(names, MULTI_RELEASE);
+
+ // Common attributes used in MANIFEST.MF et.al; adding these has a
+ // small footprint cost, but is likely to be quickly paid for by
+ // reducing allocation when reading and parsing typical manifests
+
+ // JDK internal attributes
+ addName(names, new Name("Add-Exports"));
+ addName(names, new Name("Add-Opens"));
+ // LauncherHelper attributes
+ addName(names, new Name("Launcher-Agent-Class"));
+ addName(names, new Name("JavaFX-Application-Class"));
+ // jarsigner attributes
+ addName(names, new Name("Name"));
+ addName(names, new Name("Created-By"));
+ addName(names, new Name("SHA1-Digest"));
+ addName(names, new Name("SHA-256-Digest"));
+ KNOWN_NAMES = Map.copyOf(names);
+ } else {
+ // Even if KNOWN_NAMES was read from archive, we still need
+ // to initialize the public constants
+ MANIFEST_VERSION = KNOWN_NAMES.get("Manifest-Version");
+ SIGNATURE_VERSION = KNOWN_NAMES.get("Signature-Version");
+ CONTENT_TYPE = KNOWN_NAMES.get("Content-Type");
+ CLASS_PATH = KNOWN_NAMES.get("Class-Path");
+ MAIN_CLASS = KNOWN_NAMES.get("Main-Class");
+ SEALED = KNOWN_NAMES.get("Sealed");
+ EXTENSION_LIST = KNOWN_NAMES.get("Extension-List");
+ EXTENSION_NAME = KNOWN_NAMES.get("Extension-Name");
+ EXTENSION_INSTALLATION = KNOWN_NAMES.get("Extension-Installation");
+ IMPLEMENTATION_TITLE = KNOWN_NAMES.get("Implementation-Title");
+ IMPLEMENTATION_VERSION = KNOWN_NAMES.get("Implementation-Version");
+ IMPLEMENTATION_VENDOR = KNOWN_NAMES.get("Implementation-Vendor");
+ IMPLEMENTATION_VENDOR_ID = KNOWN_NAMES.get("Implementation-Vendor-Id");
+ IMPLEMENTATION_URL = KNOWN_NAMES.get("Implementation-URL");
+ SPECIFICATION_TITLE = KNOWN_NAMES.get("Specification-Title");
+ SPECIFICATION_VERSION = KNOWN_NAMES.get("Specification-Version");
+ SPECIFICATION_VENDOR = KNOWN_NAMES.get("Specification-Vendor");
+ MULTI_RELEASE = KNOWN_NAMES.get("Multi-Release");
+ }
}
}
}
--- a/src/java.base/share/classes/sun/security/ssl/NewSessionTicket.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/NewSessionTicket.java Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -32,7 +32,6 @@
import java.security.SecureRandom;
import java.text.MessageFormat;
import java.util.Locale;
-import java.util.Optional;
import javax.crypto.SecretKey;
import javax.net.ssl.SSLHandshakeException;
import sun.security.ssl.PskKeyExchangeModesExtension.PskKeyExchangeModesSpec;
@@ -224,9 +223,9 @@
SessionId newId = new SessionId(true,
shc.sslContext.getSecureRandom());
- Optional<SecretKey> resumptionMasterSecret =
+ SecretKey resumptionMasterSecret =
shc.handshakeSession.getResumptionMasterSecret();
- if (!resumptionMasterSecret.isPresent()) {
+ if (resumptionMasterSecret == null) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine(
"Session has no resumption secret. No ticket sent.");
@@ -239,7 +238,7 @@
byte[] nonceArr = nonce.toByteArray();
SecretKey psk = derivePreSharedKey(
shc.negotiatedCipherSuite.hashAlg,
- resumptionMasterSecret.get(), nonceArr);
+ resumptionMasterSecret, nonceArr);
int sessionTimeoutSeconds = sessionCache.getSessionTimeout();
if (sessionTimeoutSeconds > MAX_TICKET_LIFETIME) {
@@ -354,9 +353,9 @@
SSLSessionImpl sessionToSave = hc.conContext.conSession;
- Optional<SecretKey> resumptionMasterSecret =
+ SecretKey resumptionMasterSecret =
sessionToSave.getResumptionMasterSecret();
- if (!resumptionMasterSecret.isPresent()) {
+ if (resumptionMasterSecret == null) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine(
"Session has no resumption master secret. Ignoring ticket.");
@@ -366,7 +365,7 @@
// derive the PSK
SecretKey psk = derivePreSharedKey(
- sessionToSave.getSuite().hashAlg, resumptionMasterSecret.get(),
+ sessionToSave.getSuite().hashAlg, resumptionMasterSecret,
nstm.ticketNonce);
// create and cache the new session
--- a/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java Sat Mar 30 09:30:03 2019 +0000
@@ -33,7 +33,6 @@
import java.util.Locale;
import java.util.Arrays;
import java.util.Objects;
-import java.util.Optional;
import java.util.Collection;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
@@ -402,7 +401,7 @@
private static boolean canRejoin(ClientHelloMessage clientHello,
ServerHandshakeContext shc, SSLSessionImpl s) {
- boolean result = s.isRejoinable() && s.getPreSharedKey().isPresent();
+ boolean result = s.isRejoinable() && (s.getPreSharedKey() != null);
// Check protocol version
if (result && s.getProtocolVersion() != shc.negotiatedProtocol) {
@@ -530,12 +529,11 @@
private static void checkBinder(ServerHandshakeContext shc,
SSLSessionImpl session,
HandshakeHash pskBinderHash, byte[] binder) throws IOException {
- Optional<SecretKey> pskOpt = session.getPreSharedKey();
- if (!pskOpt.isPresent()) {
+ SecretKey psk = session.getPreSharedKey();
+ if (psk == null) {
throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
"Session has no PSK");
}
- SecretKey psk = pskOpt.get();
SecretKey binderKey = deriveBinderKey(shc, psk, session);
byte[] computedBinder =
@@ -647,27 +645,28 @@
}
// The session must have a pre-shared key
- Optional<SecretKey> pskOpt = chc.resumingSession.getPreSharedKey();
- if (!pskOpt.isPresent()) {
+ SecretKey psk = chc.resumingSession.getPreSharedKey();
+ if (psk == null) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine("Existing session has no PSK.");
}
return null;
}
- SecretKey psk = pskOpt.get();
+
// The PSK ID can only be used in one connections, but this method
// may be called twice in a connection if the server sends HRR.
// ID is saved in the context so it can be used in the second call.
- Optional<byte[]> pskIdOpt = Optional.ofNullable(chc.pskIdentity)
- .or(chc.resumingSession::consumePskIdentity);
- if (!pskIdOpt.isPresent()) {
+ if (chc.pskIdentity == null) {
+ chc.pskIdentity = chc.resumingSession.consumePskIdentity();
+ }
+
+ if (chc.pskIdentity == null) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine(
"PSK has no identity, or identity was already used");
}
return null;
}
- chc.pskIdentity = pskIdOpt.get();
//The session cannot be used again. Remove it from the cache.
SSLSessionContextImpl sessionCache = (SSLSessionContextImpl)
--- a/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java Sat Mar 30 09:30:03 2019 +0000
@@ -36,7 +36,6 @@
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
-import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import javax.crypto.SecretKey;
@@ -286,18 +285,20 @@
return masterSecret;
}
- Optional<SecretKey> getResumptionMasterSecret() {
- return Optional.ofNullable(resumptionMasterSecret);
+ SecretKey getResumptionMasterSecret() {
+ return resumptionMasterSecret;
}
- synchronized Optional<SecretKey> getPreSharedKey() {
- return Optional.ofNullable(preSharedKey);
+ synchronized SecretKey getPreSharedKey() {
+ return preSharedKey;
}
- synchronized Optional<SecretKey> consumePreSharedKey() {
- Optional<SecretKey> result = Optional.ofNullable(preSharedKey);
- preSharedKey = null;
- return result;
+ synchronized SecretKey consumePreSharedKey() {
+ try {
+ return preSharedKey;
+ } finally {
+ preSharedKey = null;
+ }
}
int getTicketAgeAdd() {
@@ -312,10 +313,12 @@
* be used once. This method will return the identity and then clear it
* so it cannot be used again.
*/
- synchronized Optional<byte[]> consumePskIdentity() {
- Optional<byte[]> result = Optional.ofNullable(pskIdentity);
- pskIdentity = null;
- return result;
+ synchronized byte[] consumePskIdentity() {
+ try {
+ return pskIdentity;
+ } finally {
+ pskIdentity = null;
+ }
}
void setPeerCertificates(X509Certificate[] peer) {
--- a/src/java.base/share/classes/sun/security/ssl/ServerHello.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/ServerHello.java Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -35,7 +35,6 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
-import java.util.Optional;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.net.ssl.SSLException;
@@ -544,7 +543,7 @@
shc.negotiatedProtocol, shc.negotiatedCipherSuite);
setUpPskKD(shc,
- shc.resumingSession.consumePreSharedKey().get());
+ shc.resumingSession.consumePreSharedKey());
// The session can't be resumed again---remove it from cache
SSLSessionContextImpl sessionCache = (SSLSessionContextImpl)
@@ -1223,16 +1222,16 @@
chc.sslConfig.maximumPacketSize);
} else {
// The PSK is consumed to allow it to be deleted
- Optional<SecretKey> psk =
+ SecretKey psk =
chc.resumingSession.consumePreSharedKey();
- if(!psk.isPresent()) {
+ if(psk == null) {
throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
"No PSK available. Unable to resume.");
}
chc.handshakeSession = chc.resumingSession;
- setUpPskKD(chc, psk.get());
+ setUpPskKD(chc, psk);
}
//
--- a/src/java.base/unix/classes/java/io/UnixFileSystem.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.base/unix/classes/java/io/UnixFileSystem.java Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -51,10 +51,12 @@
/* -- Normalization and construction -- */
+ @Override
public char getSeparator() {
return slash;
}
+ @Override
public char getPathSeparator() {
return colon;
}
@@ -84,6 +86,7 @@
/* Check that the given pathname is normal. If not, invoke the real
normalizer on the part of the pathname that requires normalization.
This way we iterate through the whole pathname string only once. */
+ @Override
public String normalize(String pathname) {
int n = pathname.length();
char prevChar = 0;
@@ -97,11 +100,13 @@
return pathname;
}
+ @Override
public int prefixLength(String pathname) {
if (pathname.isEmpty()) return 0;
return (pathname.charAt(0) == '/') ? 1 : 0;
}
+ @Override
public String resolve(String parent, String child) {
if (child.isEmpty()) return parent;
if (child.charAt(0) == '/') {
@@ -112,10 +117,12 @@
return parent + '/' + child;
}
+ @Override
public String getDefaultParent() {
return "/";
}
+ @Override
public String fromURIPath(String path) {
String p = path;
if (p.endsWith("/") && (p.length() > 1)) {
@@ -128,10 +135,12 @@
/* -- Path operations -- */
+ @Override
public boolean isAbsolute(File f) {
return (f.getPrefixLength() != 0);
}
+ @Override
public String resolve(File f) {
if (isAbsolute(f)) return f.getPath();
SecurityManager sm = System.getSecurityManager();
@@ -153,6 +162,7 @@
// canonicalization algorithm
private final ExpiringCache javaHomePrefixCache;
+ @Override
public String canonicalize(String path) throws IOException {
if (!useCanonCaches) {
return canonicalize0(path);
@@ -246,6 +256,7 @@
public native int getBooleanAttributes0(File f);
+ @Override
public int getBooleanAttributes(File f) {
int rv = getBooleanAttributes0(f);
String name = f.getName();
@@ -253,15 +264,25 @@
return rv | (hidden ? BA_HIDDEN : 0);
}
+ @Override
public native boolean checkAccess(File f, int access);
+
+ @Override
public native long getLastModifiedTime(File f);
+
+ @Override
public native long getLength(File f);
+
+ @Override
public native boolean setPermission(File f, int access, boolean enable, boolean owneronly);
/* -- File operations -- */
+ @Override
public native boolean createFileExclusively(String path)
throws IOException;
+
+ @Override
public boolean delete(File f) {
// Keep canonicalization caches in sync after file deletion
// and renaming operations. Could be more clever than this
@@ -277,8 +298,14 @@
return delete0(f);
}
private native boolean delete0(File f);
+
+ @Override
public native String[] list(File f);
+
+ @Override
public native boolean createDirectory(File f);
+
+ @Override
public boolean rename(File f1, File f2) {
// Keep canonicalization caches in sync after file deletion
// and renaming operations. Could be more clever than this
@@ -294,12 +321,16 @@
return rename0(f1, f2);
}
private native boolean rename0(File f1, File f2);
+
+ @Override
public native boolean setLastModifiedTime(File f, long time);
+
+ @Override
public native boolean setReadOnly(File f);
-
/* -- Filesystem interface -- */
+ @Override
public File[] listRoots() {
try {
SecurityManager security = System.getSecurityManager();
@@ -313,12 +344,15 @@
}
/* -- Disk usage -- */
+
+ @Override
public native long getSpace(File f, int t);
/* -- Basic infrastructure -- */
private native long getNameMax0(String path);
+ @Override
public int getNameMax(String path) {
long nameMax = getNameMax0(path);
if (nameMax > Integer.MAX_VALUE) {
@@ -327,10 +361,12 @@
return (int)nameMax;
}
+ @Override
public int compare(File f1, File f2) {
return f1.getPath().compareTo(f2.getPath());
}
+ @Override
public int hashCode(File f) {
return f.getPath().hashCode() ^ 1234321;
}
@@ -341,5 +377,4 @@
static {
initIDs();
}
-
}
--- a/src/java.base/unix/native/libjava/UnixFileSystem_md.c Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.base/unix/native/libjava/UnixFileSystem_md.c Sat Mar 30 09:30:03 2019 +0000
@@ -284,10 +284,10 @@
fd = handleOpen(path, O_RDWR | O_CREAT | O_EXCL, 0666);
if (fd < 0) {
if (errno != EEXIST)
- JNU_ThrowIOExceptionWithLastError(env, path);
+ JNU_ThrowIOExceptionWithLastError(env, "Could not open file");
} else {
if (close(fd) == -1)
- JNU_ThrowIOExceptionWithLastError(env, path);
+ JNU_ThrowIOExceptionWithLastError(env, "Could not close file");
rv = JNI_TRUE;
}
}
--- a/src/java.base/windows/classes/java/io/WinNTFileSystem.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.base/windows/classes/java/io/WinNTFileSystem.java Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, 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
@@ -328,7 +328,6 @@
return up + slashify(path.substring(2));
char drive = path.charAt(0);
String dir = getDriveDirectory(drive);
- String np;
if (dir != null) {
/* When resolving a directory-relative path that refers to a
drive other than the current drive, insist that the caller
@@ -641,6 +640,7 @@
// expects the path to be null or a root component ending in a backslash
private native int getNameMax0(String path);
+ @Override
public int getNameMax(String path) {
String s = null;
if (path != null) {
--- a/src/java.base/windows/native/libnet/NetworkInterface_winXP.c Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.base/windows/native/libnet/NetworkInterface_winXP.c Sat Mar 30 09:30:03 2019 +0000
@@ -41,7 +41,7 @@
#ifdef _WIN64
printf ("nif:0x%I64x name:%s\n", (UINT_PTR)nif, nif->name);
#else
- printf ("nif:0x%x name:%s\n", nif, nif->name);
+ printf ("nif:0x%x name:%s\n", (UINT_PTR)nif, nif->name);
#endif
if (nif->dNameIsUnicode) {
printf ("dName:%S index:%d ", (unsigned short *)nif->displayName,
--- a/src/java.base/windows/native/libnio/ch/FileChannelImpl.c Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.base/windows/native/libnio/ch/FileChannelImpl.c Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
--- a/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, 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
@@ -58,7 +58,7 @@
* 9: modules, small cleanups to 1.7 and 1.8 changes
* 10: local-variable type inference (var)
* 11: local-variable syntax for lambda parameters
- * 12: TBD
+ * 12: no changes (switch expressions in preview)
* 13: TBD
*/
@@ -208,38 +208,40 @@
private static final SourceVersion latestSupported = getLatestSupported();
+ /*
+ * The integer version to enum constant mapping implemented by
+ * this method assumes the JEP 322: "Time-Based Release
+ * Versioning" scheme is in effect. This scheme began in JDK
+ * 10. If the JDK versioning scheme is revised, this method may
+ * need to be updated accordingly.
+ */
private static SourceVersion getLatestSupported() {
- try {
- String specVersion = System.getProperty("java.specification.version");
-
- switch (specVersion) {
- case "13":
- return RELEASE_13;
- case "12":
- return RELEASE_12;
- case "11":
- return RELEASE_11;
- case "10":
- return RELEASE_10;
- case "9":
- return RELEASE_9;
- case "1.8":
- return RELEASE_8;
- case "1.7":
- return RELEASE_7;
- case "1.6":
- return RELEASE_6;
- }
- } catch (SecurityException se) {}
-
- return RELEASE_5;
+ int intVersion = Runtime.version().feature();
+ return (intVersion >= 11) ?
+ valueOf("RELEASE_" + Math.min(13, intVersion)):
+ RELEASE_10;
}
/**
* Returns the latest source version fully supported by the
- * current execution environment. {@code RELEASE_5} or later must
+ * current execution environment. {@code RELEASE_9} or later must
* be returned.
*
+ * @apiNote This method is included alongside {@link latest} to
+ * allow identification of situations where the language model API
+ * is running on a platform version different than the latest
+ * version modeled by the API. One way that sort of situation can
+ * occur is if an IDE or similar tool is using the API to model
+ * source version <i>N</i> while running on platform version
+ * (<i>N</i> - 1). Running in this configuration is
+ * supported by the API. Running an API on platform versions
+ * earlier than (<i>N</i> - 1) or later than <i>N</i>
+ * may or may not work as an implementation detail. If an
+ * annotation processor was generating code to run under the
+ * current execution environment, the processor should only use
+ * platform features up to the {@code latestSupported} release,
+ * which may be earlier than the {@code latest} release.
+ *
* @return the latest source version that is fully supported
*/
public static SourceVersion latestSupported() {
--- a/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java Sat Mar 30 09:30:03 2019 +0000
@@ -28,9 +28,11 @@
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
+import java.util.List;
/**
* File manager based on {@linkplain File java.io.File} and {@linkplain Path java.nio.file.Path}.
@@ -199,11 +201,40 @@
* a directory or if this file manager does not support any of the
* given paths.
*
- * @since 9
+ * @since 13
*/
default Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths(
+ Collection<? extends Path> paths) {
+ return getJavaFileObjectsFromFiles(asFiles(paths));
+ }
+
+ /**
+ * Returns file objects representing the given paths.
+ *
+ * @implSpec
+ * The default implementation converts each path to a file and calls
+ * {@link #getJavaFileObjectsFromFiles getJavaObjectsFromFiles}.
+ * IllegalArgumentException will be thrown if any of the paths
+ * cannot be converted to a file.
+ *
+ * @param paths a list of paths
+ * @return a list of file objects
+ * @throws IllegalArgumentException if the list of paths includes
+ * a directory or if this file manager does not support any of the
+ * given paths.
+ *
+ * @since 9
+ * @deprecated use {@link #getJavaFileObjectsFromPaths(Collection)} instead,
+ * to prevent the possibility of accidentally calling the method with a
+ * single {@code Path} as such an argument. Although {@code Path} implements
+ * {@code Iterable<Path>}, it would almost never be correct to pass a single
+ * {@code Path} and have it be treated as an {@code Iterable} of its
+ * components.
+ */
+ @Deprecated(since = "13")
+ default Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths(
Iterable<? extends Path> paths) {
- return getJavaFileObjectsFromFiles(asFiles(paths));
+ return getJavaFileObjectsFromPaths(asCollection(paths));
}
/**
@@ -484,4 +515,13 @@
}
};
}
+
+ private static <T> Collection<T> asCollection(Iterable<T> iterable) {
+ if (iterable instanceof Collection) {
+ return (Collection<T>) iterable;
+ }
+ List<T> result = new ArrayList<>();
+ for (T item : iterable) result.add(item);
+ return result;
+ }
}
--- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c Sat Mar 30 09:30:03 2019 +0000
@@ -122,7 +122,11 @@
*/
#define MAXFRAMEBUFFERS 16
-#if defined(__linux__) || defined(MACOSX)
+#if defined(__solaris__)
+typedef Status XineramaGetInfoFunc(Display* display, int screen_number,
+ XRectangle* framebuffer_rects, unsigned char* framebuffer_hints,
+ int* num_framebuffers);
+#else /* Linux, Mac, AIX */
typedef struct {
int screen_number;
short x_org;
@@ -132,11 +136,6 @@
} XineramaScreenInfo;
typedef XineramaScreenInfo* XineramaQueryScreensFunc(Display*, int*);
-
-#else /* SOLARIS */
-typedef Status XineramaGetInfoFunc(Display* display, int screen_number,
- XRectangle* framebuffer_rects, unsigned char* framebuffer_hints,
- int* num_framebuffers);
#endif
Bool usingXinerama = False;
@@ -425,6 +424,7 @@
if (XQueryExtension(awt_display, "RENDER",
&major_opcode, &first_event, &first_error))
{
+ DTRACE_PRINTLN("RENDER extension available");
xrenderLibHandle = dlopen("libXrender.so.1", RTLD_LAZY | RTLD_GLOBAL);
#ifdef MACOSX
@@ -438,18 +438,30 @@
RTLD_LAZY | RTLD_GLOBAL);
}
-#ifndef __linux__ /* SOLARIS */
+#if defined(__solaris__)
if (xrenderLibHandle == NULL) {
xrenderLibHandle = dlopen("/usr/lib/libXrender.so.1",
RTLD_LAZY | RTLD_GLOBAL);
}
+#elif defined(_AIX)
+ if (xrenderLibHandle == NULL) {
+ xrenderLibHandle = dlopen("libXrender.a(libXrender.so.0)",
+ RTLD_MEMBER | RTLD_LAZY | RTLD_GLOBAL);
+ }
#endif
-
if (xrenderLibHandle != NULL) {
+ DTRACE_PRINTLN("Loaded libXrender");
xrenderFindVisualFormat =
(XRenderFindVisualFormatFunc*)dlsym(xrenderLibHandle,
"XRenderFindVisualFormat");
+ if (xrenderFindVisualFormat == NULL) {
+ DTRACE_PRINTLN1("Can't find 'XRenderFindVisualFormat' in libXrender (%s)", dlerror());
+ }
+ } else {
+ DTRACE_PRINTLN1("Can't load libXrender (%s)", dlerror());
}
+ } else {
+ DTRACE_PRINTLN("RENDER extension NOT available");
}
for (i = 0; i < nTrue; i++) {
@@ -465,18 +477,23 @@
graphicsConfigs [ind]->awt_depth = pVITrue [i].depth;
memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVITrue [i],
sizeof (XVisualInfo));
- if (xrenderFindVisualFormat != NULL) {
+ if (xrenderFindVisualFormat != NULL) {
XRenderPictFormat *format = xrenderFindVisualFormat (awt_display,
- pVITrue [i].visual);
+ pVITrue [i].visual);
if (format &&
format->type == PictTypeDirect &&
format->direct.alphaMask)
{
+ DTRACE_PRINTLN1("GraphicsConfig[%d] supports Translucency", ind);
graphicsConfigs [ind]->isTranslucencySupported = 1;
memcpy(&graphicsConfigs [ind]->renderPictFormat, format,
sizeof(*format));
+ } else {
+ DTRACE_PRINTLN1(format ?
+ "GraphicsConfig[%d] has no Translucency support" :
+ "Error calling 'XRenderFindVisualFormat'", ind);
}
- }
+ }
}
if (xrenderLibHandle != NULL) {
@@ -582,7 +599,7 @@
}
#ifndef HEADLESS
-#if defined(__linux__) || defined(MACOSX)
+#if defined(__linux__) || defined(MACOSX) || defined(_AIX)
static void xinerama_init_linux()
{
void* libHandle = NULL;
@@ -595,14 +612,18 @@
libHandle = dlopen(VERSIONED_JNI_LIB_NAME("Xinerama", "1"),
RTLD_LAZY | RTLD_GLOBAL);
if (libHandle == NULL) {
+#if defined(_AIX)
+ libHandle = dlopen("libXext.a(shr_64.o)", RTLD_MEMBER | RTLD_LAZY | RTLD_GLOBAL);
+#else
libHandle = dlopen(JNI_LIB_NAME("Xinerama"), RTLD_LAZY | RTLD_GLOBAL);
+#endif
}
if (libHandle != NULL) {
XineramaQueryScreens = (XineramaQueryScreensFunc*)
dlsym(libHandle, XineramaQueryScreensName);
if (XineramaQueryScreens != NULL) {
- DTRACE_PRINTLN("calling XineramaQueryScreens func on Linux");
+ DTRACE_PRINTLN("calling XineramaQueryScreens func");
xinInfo = (*XineramaQueryScreens)(awt_display, &locNumScr);
if (xinInfo != NULL && locNumScr > XScreenCount(awt_display)) {
int32_t idx;
@@ -622,7 +643,10 @@
fbrects[idx].y = xinInfo[idx].y_org;
}
} else {
- DTRACE_PRINTLN("calling XineramaQueryScreens didn't work");
+ DTRACE_PRINTLN((xinInfo == NULL) ?
+ "calling XineramaQueryScreens didn't work" :
+ "XineramaQueryScreens <= XScreenCount"
+ );
}
} else {
DTRACE_PRINTLN("couldn't load XineramaQueryScreens symbol");
@@ -632,8 +656,7 @@
DTRACE_PRINTLN1("\ncouldn't open shared library: %s\n", dlerror());
}
}
-#endif
-#if !defined(__linux__) && !defined(MACOSX) /* Solaris */
+#elif defined(__solaris__)
static void xinerama_init_solaris()
{
void* libHandle = NULL;
@@ -689,11 +712,11 @@
}
DTRACE_PRINTLN("Xinerama extension is available");
-#if defined(__linux__) || defined(MACOSX)
+#if defined(__solaris__)
+ xinerama_init_solaris();
+#else /* Linux, Mac, AIX */
xinerama_init_linux();
-#else /* Solaris */
- xinerama_init_solaris();
-#endif /* __linux__ || MACOSX */
+#endif
}
#endif /* HEADLESS */
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/datatype/DurationDayTimeImpl.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/datatype/DurationDayTimeImpl.java Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2017 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/datatype/DurationYearMonthImpl.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/datatype/DurationYearMonthImpl.java Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2017 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
--- a/src/java.xml/share/classes/javax/xml/stream/XMLStreamException.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/java.xml/share/classes/javax/xml/stream/XMLStreamException.java Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2017 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java Sat Mar 30 09:30:03 2019 +0000
@@ -437,6 +437,18 @@
}
@Override @DefinedBy(Api.COMPILER)
+ public Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths(Collection<? extends Path> paths) {
+ try {
+ return ((StandardJavaFileManager)clientJavaFileManager).getJavaFileObjectsFromPaths(paths);
+ } catch (ClientCodeException e) {
+ throw e;
+ } catch (RuntimeException | Error e) {
+ throw new ClientCodeException(e);
+ }
+ }
+
+ @Deprecated(since = "13")
+ @Override @DefinedBy(Api.COMPILER)
public Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths(Iterable<? extends Path> paths) {
try {
return ((StandardJavaFileManager)clientJavaFileManager).getJavaFileObjectsFromPaths(paths);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/CacheFSInfo.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/CacheFSInfo.java Sat Mar 30 09:30:03 2019 +0000
@@ -26,9 +26,11 @@
package com.sun.tools.javac.file;
import java.io.IOException;
+import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
import java.util.List;
-import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import com.sun.tools.javac.util.Context;
@@ -44,6 +46,12 @@
*/
public class CacheFSInfo extends FSInfo {
+ protected final ConcurrentHashMap<Path, Path> canonicalPathCache = new ConcurrentHashMap<>();
+ protected final ConcurrentHashMap<Path, Optional<BasicFileAttributes>> attributeCache =
+ new ConcurrentHashMap<>();
+ protected final ConcurrentHashMap<Path, List<Path>> jarClassPathCache =
+ new ConcurrentHashMap<>();
+
/**
* Register a Context.Factory to create a CacheFSInfo.
*/
@@ -56,68 +64,53 @@
}
public void clearCache() {
- cache.clear();
+ canonicalPathCache.clear();
+ attributeCache.clear();
+ jarClassPathCache.clear();
}
@Override
public Path getCanonicalFile(Path file) {
- Entry e = getEntry(file);
- return e.canonicalFile;
+ return canonicalPathCache.computeIfAbsent(file, super::getCanonicalFile);
}
@Override
public boolean exists(Path file) {
- Entry e = getEntry(file);
- return e.exists;
+ return getAttributes(file).isPresent();
}
@Override
public boolean isDirectory(Path file) {
- Entry e = getEntry(file);
- return e.isDirectory;
+ return getAttributes(file).map(BasicFileAttributes::isDirectory).orElse(false);
}
@Override
public boolean isFile(Path file) {
- Entry e = getEntry(file);
- return e.isFile;
+ return getAttributes(file).map(BasicFileAttributes::isRegularFile).orElse(false);
}
@Override
public List<Path> getJarClassPath(Path file) throws IOException {
- // don't bother to lock the cache, because it is thread-safe, and
- // because the worst that can happen would be to create two identical
- // jar class paths together and have one overwrite the other.
- Entry e = getEntry(file);
- if (e.jarClassPath == null)
- e.jarClassPath = super.getJarClassPath(file);
- return e.jarClassPath;
+ synchronized (jarClassPathCache) {
+ List<Path> jarClassPath = jarClassPathCache.get(file);
+ if (jarClassPath == null) {
+ jarClassPath = super.getJarClassPath(file);
+ jarClassPathCache.put(file, jarClassPath);
+ }
+ return jarClassPath;
+ }
}
- private Entry getEntry(Path file) {
- // don't bother to lock the cache, because it is thread-safe, and
- // because the worst that can happen would be to create two identical
- // entries together and have one overwrite the other.
- Entry e = cache.get(file);
- if (e == null) {
- e = new Entry();
- e.canonicalFile = super.getCanonicalFile(file);
- e.exists = super.exists(file);
- e.isDirectory = super.isDirectory(file);
- e.isFile = super.isFile(file);
- cache.put(file, e);
- }
- return e;
+ protected Optional<BasicFileAttributes> getAttributes(Path file) {
+ return attributeCache.computeIfAbsent(file, this::maybeReadAttributes);
}
- // could also be a Map<File,SoftReference<Entry>> ?
- private final Map<Path,Entry> cache = new ConcurrentHashMap<>();
-
- private static class Entry {
- Path canonicalFile;
- boolean exists;
- boolean isFile;
- boolean isDirectory;
- List<Path> jarClassPath;
+ protected Optional<BasicFileAttributes> maybeReadAttributes(Path file) {
+ try {
+ return Optional.of(Files.readAttributes(file, BasicFileAttributes.class));
+ } catch (IOException e) {
+ // Ignore; means file not found
+ return Optional.empty();
+ }
}
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java Sat Mar 30 09:30:03 2019 +0000
@@ -897,7 +897,7 @@
@Override @DefinedBy(Api.COMPILER)
public Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths(
- Iterable<? extends Path> paths)
+ Collection<? extends Path> paths)
{
ArrayList<PathFileObject> result;
if (paths instanceof Collection<?>)
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/DelegatingJavaFileManager.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/DelegatingJavaFileManager.java Sat Mar 30 09:30:03 2019 +0000
@@ -206,6 +206,13 @@
@Override
public Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths
+ (Collection<? extends Path> paths) {
+ return baseSJFM.getJavaFileObjectsFromPaths(paths);
+ }
+
+ @Deprecated(since = "13")
+ @Override
+ public Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths
(Iterable<? extends Path> paths) {
return baseSJFM.getJavaFileObjectsFromPaths(paths);
}
--- a/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp Sat Mar 23 15:11:51 2019 +0000
+++ b/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp Sat Mar 30 09:30:03 2019 +0000
@@ -502,7 +502,7 @@
else
{
if ((dwKeySpec & CERT_NCRYPT_KEY_SPEC) == CERT_NCRYPT_KEY_SPEC) {
- PP("CNG %I64d", hCryptProv);
+ PP("CNG %I64d", (__int64)hCryptProv);
} else {
// Private key is available
BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey); //deprecated
@@ -517,7 +517,7 @@
// Set cipher mode to ECB
DWORD dwCipherMode = CRYPT_MODE_ECB;
::CryptSetKeyParam(hUserKey, KP_MODE, (BYTE*)&dwCipherMode, NULL); //deprecated
- PP("CAPI %I64d %I64d", hCryptProv, hUserKey);
+ PP("CAPI %I64d %I64d", (__int64)hCryptProv, (__int64)hUserKey);
}
// If the private key is present in smart card, we may not be able to
// determine the key length by using the private key handle. However,
@@ -863,8 +863,8 @@
SS_CHECK(::NCryptTranslateHandle(
NULL,
&hk,
- hCryptProv,
- hCryptKey,
+ (HCRYPTPROV)hCryptProv,
+ (HCRYPTKEY)hCryptKey,
NULL,
0));
}
@@ -1087,8 +1087,8 @@
SS_CHECK(::NCryptTranslateHandle(
NULL,
&hk,
- hCryptProv,
- hCryptKey,
+ (HCRYPTPROV)hCryptProv,
+ (HCRYPTKEY)hCryptKey,
NULL,
0));
}
@@ -1920,7 +1920,7 @@
// Determine the size of the blob
if (hCryptKey == 0) {
SS_CHECK(::NCryptExportKey(
- hCryptProv, NULL, BCRYPT_ECCPUBLIC_BLOB,
+ (NCRYPT_KEY_HANDLE)hCryptProv, NULL, BCRYPT_ECCPUBLIC_BLOB,
NULL, NULL, 0, &dwBlobLen, NCRYPT_SILENT_FLAG));
} else {
if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, NULL, //deprecated
@@ -1939,7 +1939,7 @@
// Generate key blob
if (hCryptKey == 0) {
SS_CHECK(::NCryptExportKey(
- hCryptProv, NULL, BCRYPT_ECCPUBLIC_BLOB,
+ (NCRYPT_KEY_HANDLE)hCryptProv, NULL, BCRYPT_ECCPUBLIC_BLOB,
NULL, pbKeyBlob, dwBlobLen, &dwBlobLen, NCRYPT_SILENT_FLAG));
} else {
if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, //deprecated
--- a/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java Sat Mar 30 09:30:03 2019 +0000
@@ -33,10 +33,11 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.TreeSet;
+import java.util.Set;
import com.sun.jdi.BooleanType;
import com.sun.jdi.BooleanValue;
@@ -110,7 +111,7 @@
// tested unsynchronized (since once true, it stays true), but must
// be set synchronously
private Map<Long, ReferenceType> typesByID;
- private TreeSet<ReferenceType> typesBySignature;
+ private Set<ReferenceType> typesBySignature;
private boolean retrievedAllTypes = false;
private Map<Long, ModuleReference> modulesByID;
@@ -843,14 +844,9 @@
throw new InternalException("Invalid reference type tag");
}
- /*
- * If a signature was specified, make sure to set it ASAP, to
- * prevent any needless JDWP command to retrieve it. (for example,
- * typesBySignature.add needs the signature, to maintain proper
- * ordering.
- */
- if (signature != null) {
- type.setSignature(signature);
+ if (signature == null && retrievedAllTypes) {
+ // do not cache if signature is not provided
+ return type;
}
typesByID.put(id, type);
@@ -920,7 +916,7 @@
private void initReferenceTypes() {
typesByID = new HashMap<>(300);
- typesBySignature = new TreeSet<>();
+ typesBySignature = new HashSet<>();
}
ReferenceTypeImpl referenceType(long ref, byte tag) {
@@ -969,6 +965,9 @@
if (retType == null) {
retType = addReferenceType(id, tag, signature);
}
+ if (signature != null) {
+ retType.setSignature(signature);
+ }
}
return retType;
}
--- a/src/jdk.jstatd/share/classes/sun/tools/jstatd/Jstatd.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/jdk.jstatd/share/classes/sun/tools/jstatd/Jstatd.java Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2019, 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
@@ -45,13 +45,14 @@
private static Registry registry;
private static int port = -1;
private static boolean startRegistry = true;
+ private static RemoteHost remoteHost;
private static void printUsage() {
System.err.println("usage: jstatd [-nr] [-p port] [-n rminame]\n" +
" jstatd -?|-h|--help");
}
- static void bind(String name, RemoteHostImpl remoteHost)
+ static void bind(String name, RemoteHost remoteHost)
throws RemoteException, MalformedURLException, Exception {
try {
@@ -138,10 +139,10 @@
try {
// use 1.5.0 dynamically generated subs.
System.setProperty("java.rmi.server.ignoreSubClasses", "true");
- RemoteHostImpl remoteHost = new RemoteHostImpl();
+ remoteHost = new RemoteHostImpl();
RemoteHost stub = (RemoteHost) UnicastRemoteObject.exportObject(
remoteHost, 0);
- bind(name.toString(), remoteHost);
+ bind(name.toString(), stub);
System.out.println("jstatd started (bound to " + name.toString() + ")");
System.out.flush();
} catch (MalformedURLException e) {
--- a/src/jdk.jstatd/share/classes/sun/tools/jstatd/RemoteHostImpl.java Sat Mar 23 15:11:51 2019 +0000
+++ b/src/jdk.jstatd/share/classes/sun/tools/jstatd/RemoteHostImpl.java Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2019, 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
@@ -50,6 +50,7 @@
private MonitoredHost monitoredHost;
private Set<Integer> activeVms;
+ private static RemoteVm rvm;
public RemoteHostImpl() throws MonitorException {
try {
@@ -76,7 +77,7 @@
try {
VmIdentifier vmid = new VmIdentifier(vmidStr);
MonitoredVm mvm = monitoredHost.getMonitoredVm(vmid);
- RemoteVmImpl rvm = new RemoteVmImpl((BufferedMonitoredVm)mvm);
+ rvm = new RemoteVmImpl((BufferedMonitoredVm)mvm);
stub = (RemoteVm) UnicastRemoteObject.exportObject(rvm, 0);
}
catch (URISyntaxException e) {
--- a/test/hotspot/jtreg/ProblemList-graal.txt Sat Mar 23 15:11:51 2019 +0000
+++ b/test/hotspot/jtreg/ProblemList-graal.txt Sat Mar 30 09:30:03 2019 +0000
@@ -206,8 +206,6 @@
serviceability/tmtools/jstat/GcCapacityTest.java 8196611 generic-all
serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorMultiArrayTest.java 8196611 generic-all
-runtime/RedefineObject/TestRedefineObject.java 8218399 generic-all
-
vmTestbase/gc/lock/jvmti/alloc/jvmtialloclock02/TestDescription.java 8218700 generic-all
vmTestbase/nsk/jdb/unmonitor/unmonitor001/unmonitor001.java 8218701 generic-all
--- a/test/hotspot/jtreg/ProblemList.txt Sat Mar 23 15:11:51 2019 +0000
+++ b/test/hotspot/jtreg/ProblemList.txt Sat Mar 30 09:30:03 2019 +0000
@@ -80,7 +80,6 @@
# :hotspot_runtime
-runtime/handshake/HandshakeWalkSuspendExitTest.java 8214174 generic-all
runtime/NMT/CheckForProperDetailStackTrace.java 8218458 generic-all
runtime/SharedArchiveFile/SASymbolTableTest.java 8193639 solaris-all
runtime/containers/docker/TestCPUSets.java 8220672 generic-all
@@ -162,6 +161,8 @@
vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/TestDescription.java 8065773 generic-all
vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023/TestDescription.java 8065773 generic-all
+vmTestbase/nsk/jdb/eval/eval001/eval001.java 8221503 generic-all
+
vmTestbase/metaspace/gc/firstGC_10m/TestDescription.java 8208250 generic-all
vmTestbase/metaspace/gc/firstGC_50m/TestDescription.java 8208250 generic-all
vmTestbase/metaspace/gc/firstGC_99m/TestDescription.java 8208250 generic-all
--- a/test/hotspot/jtreg/compiler/codecache/stress/Helper.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/hotspot/jtreg/compiler/codecache/stress/Helper.java Sat Mar 30 09:30:03 2019 +0000
@@ -40,7 +40,7 @@
public static final Random RNG = Utils.getRandomInstance();
private static final long THRESHOLD = WHITE_BOX.getIntxVMFlag("CompileThreshold");
- private static final String TEST_CASE_IMPL_CLASS_NAME = "compiler.codecache.stress.Helper$TestCaseImpl";
+ private static final String TEST_CASE_IMPL_CLASS_NAME = "compiler.codecache.stress.TestCaseImpl";
private static byte[] CLASS_DATA;
static {
try {
@@ -109,34 +109,4 @@
int method();
int expectedValue();
}
-
- public static class TestCaseImpl implements TestCase {
- private static final int RETURN_VALUE = 42;
- private static final int RECURSION_DEPTH = 10;
- private volatile int i;
-
- @Override
- public Callable<Integer> getCallable() {
- return () -> {
- i = 0;
- return method();
- };
- }
-
- @Override
- public int method() {
- ++i;
- int result = RETURN_VALUE;
- if (i < RECURSION_DEPTH) {
- return result + method();
- }
- return result;
- }
-
- @Override
- public int expectedValue() {
- return RETURN_VALUE * RECURSION_DEPTH;
- }
- }
-
}
--- a/test/hotspot/jtreg/compiler/codecache/stress/RandomAllocationTest.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/hotspot/jtreg/compiler/codecache/stress/RandomAllocationTest.java Sat Mar 30 09:30:03 2019 +0000
@@ -29,7 +29,7 @@
* @modules java.base/jdk.internal.misc
* java.management
*
- * @build sun.hotspot.WhiteBox
+ * @build sun.hotspot.WhiteBox compiler.codecache.stress.Helper compiler.codecache.stress.TestCaseImpl
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
--- a/test/hotspot/jtreg/compiler/codecache/stress/ReturnBlobToWrongHeapTest.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/hotspot/jtreg/compiler/codecache/stress/ReturnBlobToWrongHeapTest.java Sat Mar 30 09:30:03 2019 +0000
@@ -29,7 +29,7 @@
* @modules java.base/jdk.internal.misc
* java.management
*
- * @build sun.hotspot.WhiteBox
+ * @build sun.hotspot.WhiteBox compiler.codecache.stress.Helper compiler.codecache.stress.TestCaseImpl
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/codecache/stress/TestCaseImpl.java Sat Mar 30 09:30:03 2019 +0000
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+
+package compiler.codecache.stress;
+
+import java.util.concurrent.Callable;
+
+public class TestCaseImpl implements Helper.TestCase {
+ private static final int RETURN_VALUE = 42;
+ private static final int RECURSION_DEPTH = 10;
+ private volatile int i;
+
+ @Override
+ public Callable<Integer> getCallable() {
+ return () -> {
+ i = 0;
+ return method();
+ };
+ }
+
+ @Override
+ public int method() {
+ ++i;
+ int result = RETURN_VALUE;
+ if (i < RECURSION_DEPTH) {
+ return result + method();
+ }
+ return result;
+ }
+
+ @Override
+ public int expectedValue() {
+ return RETURN_VALUE * RECURSION_DEPTH;
+ }
+}
--- a/test/hotspot/jtreg/compiler/codecache/stress/UnexpectedDeoptimizationTest.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/hotspot/jtreg/compiler/codecache/stress/UnexpectedDeoptimizationTest.java Sat Mar 30 09:30:03 2019 +0000
@@ -29,7 +29,7 @@
* @modules java.base/jdk.internal.misc
* java.management
*
- * @build sun.hotspot.WhiteBox
+ * @build sun.hotspot.WhiteBox compiler.codecache.stress.Helper compiler.codecache.stress.TestCaseImpl
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/codegen/TestOopCmp.java Sat Mar 30 09:30:03 2019 +0000
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2019 SAP SE. 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 8221083
+ * @requires vm.gc.Serial
+ * @requires vm.bits == 64 & vm.opt.final.UseCompressedOops == true
+ * @summary On ppc64, C1 erroneously emits a 32-bit compare instruction for oop compares.
+ * @modules java.base/jdk.internal.misc:+open
+ * @library /test/lib /
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbatch -XX:-UseTLAB -Xmx4m -XX:+UseSerialGC -XX:HeapBaseMinAddress=0x700000000
+ * -XX:CompileCommand=compileonly,compiler.codegen.TestOopCmp::nullTest
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * compiler.codegen.TestOopCmp
+ * @author volker.simonis@gmail.com
+ */
+
+package compiler.codegen;
+
+import sun.hotspot.WhiteBox;
+
+public class TestOopCmp {
+
+ private static Object nullObj = null;
+
+ public static boolean nullTest(Object o) {
+ if (o == nullObj) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public static void main(String args[]) {
+
+ WhiteBox WB = WhiteBox.getWhiteBox();
+
+ // The test is started with -XX:HeapBaseMinAddress=0x700000000 and a
+ // small heap of only 4mb. This works pretty reliable and at least on
+ // Linux/Windows/Solaris we will get a heap starting at 0x700000000.
+ // The test also runs with -XX:+UseSerialGC which means that we'll get
+ // eden starting at 0x700000000.
+ // Calling 'System.gc()' will clean up all the objects from eden, so if
+ // eden starts at 0x700000000 the first allocation right after the
+ // system GC will be allcoated right at address 0x700000000.
+ System.gc();
+ String s = new String("I'm not null!!!");
+ if (WB.getObjectAddress(s) == 0x700000000L) {
+ System.out.println("Got object at address 0x700000000");
+ }
+
+ // We call 'nullTest()' with the newly allocated String object. If it was
+ // allocated at 0x700000000, its 32 least-significant bits will be 0 and a
+ // 32-bit comparison with 'nullObj' (which is 'null') will yield true and
+ // result in a test failure.
+ // If the code generated for 'nullTest()' correctly performs a 64-bit
+ // comparison or if we didn't manage to allcoate 's' at 0x700000000 the
+ // test will always succeed.
+ for (int i = 0; i < 30_000; i++) {
+ if (nullTest(s)) {
+ throw new RuntimeException("Comparing non-null object with null returned 'true'");
+ }
+ }
+ }
+}
--- a/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java Sat Mar 30 09:30:03 2019 +0000
@@ -174,9 +174,9 @@
private static void verifyType(CollectionInfo ci, boolean shouldExist, String pattern) {
if (shouldExist) {
- Asserts.assertTrue(ci.containsVerification(pattern), "Missing expected verification for: " + ci.getName());
+ Asserts.assertTrue(ci.containsVerification(pattern), "Missing expected verification pattern " + pattern + " for: " + ci.getName());
} else {
- Asserts.assertFalse(ci.containsVerification(pattern), "Found unexpected verification for: " + ci.getName());
+ Asserts.assertFalse(ci.containsVerification(pattern), "Found unexpected verification pattern " + pattern + " for: " + ci.getName());
}
}
--- a/test/hotspot/jtreg/runtime/Thread/SuspendAtExit.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/hotspot/jtreg/runtime/Thread/SuspendAtExit.java Sat Mar 30 09:30:03 2019 +0000
@@ -26,6 +26,7 @@
* @bug 8167108
* @summary Stress test java.lang.Thread.suspend() at thread exit.
* @run main/othervm -Xlog:thread+smr=debug SuspendAtExit
+ * @run main/othervm -Xlog:thread+smr=debug -XX:+UnlockDiagnosticVMOptions -XX:GuaranteedSafepointInterval=1 -XX:+HandshakeALot SuspendAtExit
*/
import java.util.concurrent.CountDownLatch;
--- a/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationApp.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationApp.java Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
import java.net.URL;
import java.net.URLClassLoader;
import java.io.File;
+import java.io.FileWriter;
import java.security.CodeSigner;
import java.security.CodeSource;
import java.security.ProtectionDomain;
@@ -140,8 +141,22 @@
}
static void waitAttach(String flagFile) throws Throwable {
+ // See InstrumentationTest.java for the hand-shake protocol.
if (!flagFile.equals("noattach")) {
File f = new File(flagFile);
+ try (FileWriter fw = new FileWriter(f)) {
+ long pid = ProcessHandle.current().pid();
+ System.out.println("my pid = " + pid);
+ fw.write(Long.toString(pid));
+ fw.write("\n");
+ for (int i=0; i<10; i++) {
+ // Parent process waits until we have written more than 100 bytes, so it won't
+ // read a partial pid
+ fw.write("==========");
+ }
+ fw.close();
+ }
+
long start = System.currentTimeMillis();
while (f.exists()) {
long elapsed = System.currentTimeMillis() - start;
--- a/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationTest.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationTest.java Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, 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,9 +29,6 @@
* @library /test/lib /test/hotspot/jtreg/runtime/appcds /test/hotspot/jtreg/runtime/appcds/test-classes
* @requires vm.cds
* @requires vm.flavor != "minimal"
- * @modules java.base/jdk.internal.misc
- * jdk.jartool/sun.tools.jar
- * java.management
* @build sun.hotspot.WhiteBox
* InstrumentationApp
* InstrumentationClassFileTransformer
@@ -43,10 +40,9 @@
// Note: Util is from /test/hotspot/jtreg/runtime/appcds/test-classes/TestCommon.java
import com.sun.tools.attach.VirtualMachine;
-import com.sun.tools.attach.VirtualMachineDescriptor;
import java.io.File;
-import java.io.FileOutputStream;
-import java.util.List;
+import java.io.FileInputStream;
+import java.util.Scanner;
import jdk.test.lib.Asserts;
import jdk.test.lib.cds.CDSOptions;
import jdk.test.lib.process.OutputAnalyzer;
@@ -179,24 +175,28 @@
return null;
}
- // We use the flagFile to prevent the child process to make progress, until we have
- // attached to it.
+ // Hand-shake protocol with the child process
+ // [1] Parent process (this process) launches child process (InstrumentationApp)
+ // and then waits until child process writes its pid into the flagFile.
+ // [2] Child process process starts up, writes its pid into the flagFile,
+ // and waits for the flagFile to be deleted.
+ // [3] When parent process gets the pid, it attaches to the child process
+ // (if we attempt to attach to a process too early, the SIGQUIT
+ // may cause the child to die) and deletes the flagFile.
+ // [4] Child process resumes execution.
+
File f = new File(flagFile);
- try (FileOutputStream o = new FileOutputStream(f)) {
- o.write(1);
- }
- if (!f.exists()) {
- throw new RuntimeException("Failed to create " + f);
+ f.delete();
+ if (f.exists()) {
+ throw new RuntimeException("Flag file should not exist: " + f);
}
// At this point, the child process is not yet launched. Note that
// TestCommon.exec() and OutputAnalyzer.OutputAnalyzer() both block
// until the child process has finished.
//
- // So, we will launch a AgentAttachThread which will poll the system
- // until the child process is launched, and then do the attachment.
- // The child process is uniquely identified by having flagFile in its
- // command-line -- see AgentAttachThread.getPid().
+ // So, we will launch a AgentAttachThread which will poll the flagFile
+ // until the child process is launched.
AgentAttachThread t = new AgentAttachThread(flagFile, agentJar);
t.start();
return t;
@@ -225,13 +225,17 @@
// reason the child process fails to launch, this test will be terminated
// by JTREG's time-out mechanism.
Thread.sleep(100);
- List<VirtualMachineDescriptor> vmds = VirtualMachine.list();
- for (VirtualMachineDescriptor vmd : vmds) {
- if (vmd.displayName().contains(flagFile) && vmd.displayName().contains("InstrumentationApp")) {
- // We use flagFile (which has the PID of this process) as a unique identifier
- // to ident the child process, which we want to attach to.
- System.out.println("Process found: " + vmd.id() + " " + vmd.displayName());
- return vmd.id();
+ File f = new File(flagFile);
+ if (f.exists() && f.length() > 100) {
+ try (FileInputStream in = new FileInputStream(f)) {
+ Scanner scanner = new Scanner(in);
+ return Long.toString(scanner.nextLong());
+ } catch (Throwable t) {
+ // This may happen on Windows if the child process has not
+ // fully closed the output stream to the flagFile
+ System.out.println("Ignored: " + t);
+ t.printStackTrace(System.out);
+ continue;
}
}
}
@@ -240,6 +244,7 @@
public void run() {
try {
String pid = getPid(flagFile);
+ System.out.println("child pid = " + pid);
VirtualMachine vm = VirtualMachine.attach(pid);
System.out.println(agentJar);
vm.loadAgent(agentJar);
--- a/test/hotspot/jtreg/runtime/containers/docker/DockerBasicTest.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/hotspot/jtreg/runtime/containers/docker/DockerBasicTest.java Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, 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
@@ -33,6 +33,7 @@
* @build HelloDocker
* @run driver DockerBasicTest
*/
+import jdk.test.lib.containers.docker.Common;
import jdk.test.lib.containers.docker.DockerRunOptions;
import jdk.test.lib.containers.docker.DockerTestUtils;
import jdk.test.lib.Platform;
@@ -40,7 +41,7 @@
public class DockerBasicTest {
- private static final String imageNameAndTag = "jdk10-internal:test";
+ private static final String imageNameAndTag = Common.imageName("basic");
// Diganostics: set to false to examine image after the test
private static final boolean removeImageAfterTest = true;
--- a/test/hotspot/jtreg/runtime/containers/docker/Dockerfile-BasicTest Sat Mar 23 15:11:51 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-FROM oraclelinux:7.6
-MAINTAINER mikhailo.seledtsov@oracle.com
-
-COPY /jdk /jdk
-
-ENV JAVA_HOME=/jdk
-
-CMD ["/bin/bash"]
--- a/test/hotspot/jtreg/runtime/containers/docker/Dockerfile-BasicTest-aarch64 Sat Mar 23 15:11:51 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-# Use generic ubuntu Linux on AArch64
-FROM aarch64/ubuntu
-
-COPY /jdk /jdk
-
-ENV JAVA_HOME=/jdk
-
-CMD ["/bin/bash"]
--- a/test/hotspot/jtreg/runtime/containers/docker/Dockerfile-BasicTest-ppc64le Sat Mar 23 15:11:51 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-# test on x86_64 uses Oracle Linux but we do not have this for ppc64le
-# so use some other Linux where OpenJDK works
-# FROM oraclelinux:7.2
-FROM ppc64le/ubuntu
-
-COPY /jdk /jdk
-
-ENV JAVA_HOME=/jdk
-
-CMD ["/bin/bash"]
--- a/test/hotspot/jtreg/runtime/containers/docker/Dockerfile-BasicTest-s390x Sat Mar 23 15:11:51 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-FROM s390x/ubuntu
-
-COPY /jdk /jdk
-
-ENV JAVA_HOME=/jdk
-
-CMD ["/bin/bash"]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/handshake/HandshakeSuspendExitTest.java Sat Mar 30 09:30:03 2019 +0000
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2019, 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 HandshakeSuspendExitTest
+ * @summary This test tries to stress the handshakes with new and exiting threads while suspending them.
+ * @library /testlibrary /test/lib
+ * @build HandshakeSuspendExitTest
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:GuaranteedSafepointInterval=1 -XX:+HandshakeALot HandshakeSuspendExitTest
+ */
+
+public class HandshakeSuspendExitTest implements Runnable {
+
+ static Thread[] _suspend_threads = new Thread[16];
+ static volatile boolean _exit_now = false;
+ static java.util.concurrent.Semaphore _sem = new java.util.concurrent.Semaphore(0);
+
+ @Override
+ public void run() {
+ _sem.release();
+ while (!_exit_now) {
+ // Leave last 2 threads running.
+ for (int i = 0; i < _suspend_threads.length - 2; i++) {
+ if (Thread.currentThread() != _suspend_threads[i]) {
+ _suspend_threads[i].suspend();
+ _suspend_threads[i].resume();
+ }
+ }
+ }
+ _sem.release();
+ }
+
+ public static void main(String... args) throws Exception {
+ HandshakeSuspendExitTest test = new HandshakeSuspendExitTest();
+ // Fire-up suspend threads.
+ for (int i = 0; i < _suspend_threads.length; i++) {
+ _suspend_threads[i] = new Thread(test);
+ }
+ for (int i = 0; i < _suspend_threads.length; i++) {
+ _suspend_threads[i].start();
+ }
+ // Wait for all suspend-threads to start looping.
+ for (Thread thr : _suspend_threads) {
+ _sem.acquire();
+ }
+
+ // Fire-up exiting threads.
+ Thread[] exit_threads = new Thread[128];
+ for (int i = 0; i < exit_threads.length; i++) {
+ exit_threads[i] = new Thread();
+ exit_threads[i].start();
+ }
+
+ // Try to suspend them.
+ for (Thread thr : exit_threads) {
+ thr.suspend();
+ }
+ for (Thread thr : exit_threads) {
+ thr.resume();
+ }
+
+ // Start exit and join.
+ _exit_now = true;
+ int waiting = _suspend_threads.length;
+ do {
+ // Resume any worker threads that might have suspended
+ // each other at exactly the same time so they can see
+ // _exit_now and check in via the semaphore.
+ for (Thread thr : _suspend_threads) {
+ thr.resume();
+ }
+ while (_sem.tryAcquire()) {
+ --waiting;
+ }
+ } while (waiting > 0);
+ for (Thread thr : _suspend_threads) {
+ thr.join();
+ }
+ for (Thread thr : exit_threads) {
+ thr.join();
+ }
+ }
+}
--- a/test/hotspot/jtreg/runtime/handshake/HandshakeTransitionTest.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/hotspot/jtreg/runtime/handshake/HandshakeTransitionTest.java Sat Mar 30 09:30:03 2019 +0000
@@ -62,6 +62,7 @@
true,
"-Djava.library.path=" + lib,
"-XX:+SafepointALot",
+ "-XX:+HandshakeALot",
"-XX:GuaranteedSafepointInterval=20",
"-Xlog:ergo*",
"-XX:ParallelGCThreads=1",
--- a/test/hotspot/jtreg/runtime/handshake/HandshakeWalkSuspendExitTest.java Sat Mar 23 15:11:51 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * 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 HandshakeWalkSuspendExitTest
- * @summary This test tries to stress the handshakes with new and exiting threads while suspending them.
- * @library /testlibrary /test/lib
- * @build HandshakeWalkSuspendExitTest
- * @run driver ClassFileInstaller sun.hotspot.WhiteBox
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI HandshakeWalkSuspendExitTest
- */
-
-import jdk.test.lib.Asserts;
-import sun.hotspot.WhiteBox;
-
-public class HandshakeWalkSuspendExitTest implements Runnable {
-
- static final int _test_threads = 8;
- static final int _test_exit_threads = 128;
- static Thread[] _threads = new Thread[_test_threads];
- static volatile boolean exit_now = false;
- static java.util.concurrent.Semaphore _sem = new java.util.concurrent.Semaphore(0);
-
- @Override
- public void run() {
- WhiteBox wb = WhiteBox.getWhiteBox();
- while (!exit_now) {
- _sem.release();
- // We only suspend threads on even index and not ourself.
- // Otherwise we can accidentially suspend all threads.
- for (int i = 0; i < _threads.length; i += 2) {
- wb.handshakeWalkStack(null /* ignored */, true /* stackwalk all threads */);
- if (Thread.currentThread() != _threads[i]) {
- _threads[i].suspend();
- _threads[i].resume();
- }
- }
- for (int i = 0; i < _threads.length; i += 2) {
- wb.handshakeWalkStack(_threads[i] /* thread to stackwalk */, false /* stackwalk one thread */);
- if (Thread.currentThread() != _threads[i]) {
- _threads[i].suspend();
- _threads[i].resume();
- }
- }
- }
- }
-
- public static void main(String... args) throws Exception {
- HandshakeWalkSuspendExitTest test = new HandshakeWalkSuspendExitTest();
-
- for (int i = 0; i < _threads.length; i++) {
- _threads[i] = new Thread(test);
- _threads[i].start();
- }
- for (int i = 0; i < _test_threads; i++) {
- _sem.acquire();
- }
- Thread[] exit_threads = new Thread[_test_exit_threads];
- for (int i = 0; i < _test_exit_threads; i++) {
- exit_threads[i] = new Thread(new Runnable() { public void run() {} });
- exit_threads[i].start();
- }
- exit_now = true;
- for (int i = 0; i < _threads.length; i++) {
- _threads[i].join();
- }
- for (int i = 0; i < exit_threads.length; i++) {
- exit_threads[i].join();
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/modules/ModulesSymLink.java Sat Mar 30 09:30:03 2019 +0000
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2019, Google Inc. 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.
+ */
+
+/*
+ * @test
+ * @summary Test with symbolic linked lib/modules
+ * @bug 8220095
+ * @requires (os.family == "solaris" | os.family == "linux" | os.family == "mac")
+ * @library /test/lib
+ * @modules java.management
+ * jdk.jlink
+ * @run driver ModulesSymLink
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+
+public class ModulesSymLink {
+ static String java_home;
+ static String test_jdk;
+
+ public static void main(String[] args) throws Throwable {
+ java_home = System.getProperty("java.home");
+ test_jdk = System.getProperty("user.dir") + File.separator +
+ "modulessymlink_jdk" + Long.toString(System.currentTimeMillis());
+
+ constructTestJDK();
+
+ ProcessBuilder pb = new ProcessBuilder(
+ test_jdk + File.separator + "bin" + File.separator + "java",
+ "-version");
+ OutputAnalyzer out = new OutputAnalyzer(pb.start());
+ out.shouldHaveExitValue(0);
+ }
+
+ // 1) Create a test JDK binary (jlink is used to help simplify the process,
+ // alternatively a test JDK could be copied from JAVA_HOME.)
+ // 2) Rename the test JDK's lib/modules to lib/0.
+ // 3) Then create a link to lib/0 as lib/modules.
+ static void constructTestJDK() throws Throwable {
+ Path jlink = Paths.get(java_home, "bin", "jlink");
+ System.out.println("Jlink = " + jlink);
+ OutputAnalyzer out = ProcessTools.executeProcess(jlink.toString(),
+ "--output", test_jdk,
+ "--add-modules", "java.base");
+ out.shouldHaveExitValue(0);
+
+ Path modules = Paths.get(test_jdk, "lib", "modules");
+ Path renamed_modules = Paths.get(test_jdk, "lib", "0");
+ Files.move(modules, renamed_modules);
+ Files.createSymbolicLink(modules, renamed_modules);
+ }
+}
--- a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/TestRedefineObject.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/TestRedefineObject.java Sat Mar 30 09:30:03 2019 +0000
@@ -33,8 +33,8 @@
* sure cached versions used afterward are the current version.
*
* @test
- * @bug 8005056
- * @bug 8009728
+ * @bug 8005056 8009728 8218399
+ * @requires !vm.graal.enabled
* @library /test/lib
* @modules java.base/jdk.internal.misc
* java.instrument
--- a/test/hotspot/jtreg/serviceability/sa/TestUniverse.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/hotspot/jtreg/serviceability/sa/TestUniverse.java Sat Mar 30 09:30:03 2019 +0000
@@ -29,99 +29,107 @@
import java.util.HashMap;
import jdk.test.lib.apps.LingeredApp;
import jtreg.SkippedException;
+import sun.hotspot.gc.GC;
/**
* @test
* @summary Test the 'universe' command of jhsdb clhsdb.
- * @requires vm.hasSAandCanAttach & vm.gc != "Z"
+ * @requires vm.hasSAandCanAttach
* @bug 8190307
* @library /test/lib
* @build jdk.test.lib.apps.*
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. TestUniverse withoutZ
- */
-
-/**
- * @test
- * @summary Test the 'universe' command of jhsdb clhsdb.
- * @requires vm.hasSAandCanAttach & vm.gc == "Z"
- * @bug 8190307
- * @library /test/lib
- * @build jdk.test.lib.apps.*
- * @build sun.hotspot.WhiteBox
- * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. TestUniverse withZ
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. TestUniverse
*/
public class TestUniverse {
- private static void testClhsdbForUniverse(long lingeredAppPid,
- String gc) throws Exception {
-
+ private static void testClhsdbForUniverse(long lingeredAppPid, GC gc) throws Exception {
ClhsdbLauncher launcher = new ClhsdbLauncher();
List<String> cmds = List.of("universe");
Map<String, List<String>> expStrMap = new HashMap<>();
List<String> expStrings = new ArrayList<String>();
expStrings.add("Heap Parameters");
- if (gc.contains("UseZGC")) {
- expStrings.add("ZHeap");
- }
- if (gc.contains("G1GC")) {
+ switch (gc) {
+ case Serial:
+ expStrings.add("Gen 1: old");
+ break;
+
+ case Parallel:
+ expStrings.add("ParallelScavengeHeap");
+ expStrings.add("PSYoungGen");
+ expStrings.add("eden");
+ break;
+
+ case ConcMarkSweep:
+ expStrings.add("Gen 1: concurrent mark-sweep generation");
+ break;
+
+ case G1:
expStrings.add("garbage-first heap");
expStrings.add("region size");
expStrings.add("G1 Young Generation:");
expStrings.add("regions =");
- }
- if (gc.contains("UseConcMarkSweepGC")) {
- expStrings.add("Gen 1: concurrent mark-sweep generation");
- }
- if (gc.contains("UseSerialGC")) {
- expStrings.add("Gen 1: old");
- }
- if (gc.contains("UseParallelGC")) {
- expStrings.add("ParallelScavengeHeap");
- expStrings.add("PSYoungGen");
- expStrings.add("eden");
- }
- if (gc.contains("UseEpsilonGC")) {
+ break;
+
+ case Epsilon:
expStrings.add("Epsilon heap");
expStrings.add("reserved");
expStrings.add("committed");
expStrings.add("used");
+ break;
+
+ case Z:
+ expStrings.add("ZHeap");
+ break;
+
+ case Shenandoah:
+ expStrings.add("Shenandoah Heap");
+ break;
}
+
expStrMap.put("universe", expStrings);
launcher.run(lingeredAppPid, cmds, expStrMap, null);
}
- public static void test(String gc) throws Exception {
+ private static void test(GC gc) throws Exception {
LingeredApp app = null;
try {
- List<String> vmArgs = new ArrayList<String>();
- vmArgs.add("-XX:+UnlockExperimentalVMOptions"); // unlock experimental GCs
- vmArgs.add(gc);
- app = LingeredApp.startApp(vmArgs);
- System.out.println ("Started LingeredApp with the GC option " + gc +
- " and pid " + app.getPid());
+ app = LingeredApp.startApp(List.of("-XX:+UnlockExperimentalVMOptions", "-XX:+Use" + gc + "GC"));
+ System.out.println ("Started LingeredApp with " + gc + "GC and pid " + app.getPid());
testClhsdbForUniverse(app.getPid(), gc);
} finally {
LingeredApp.stopApp(app);
}
}
+ private static boolean isSelectedAndSupported(GC gc) {
+ if (!gc.isSelected()) {
+ // Not selected
+ return false;
+ }
+
+ if (Compiler.isGraalEnabled()) {
+ if (gc == GC.ConcMarkSweep || gc == GC.Epsilon || gc == GC.Z || gc == GC.Shenandoah) {
+ // Not supported
+ System.out.println ("Skipped testing of " + gc + "GC, not supported by Graal");
+ return false;
+ }
+ }
+
+ // Selected and supported
+ return true;
+ }
+
public static void main (String... args) throws Exception {
- System.out.println("Starting TestUniverse test");
+ System.out.println("Starting TestUniverse");
try {
- test("-XX:+UseG1GC");
- test("-XX:+UseParallelGC");
- test("-XX:+UseSerialGC");
- if (!Compiler.isGraalEnabled()) { // Graal does not support all GCs
- test("-XX:+UseConcMarkSweepGC");
- if (args[0].equals("withZ")) {
- test("-XX:+UseZGC");
+ for (GC gc: GC.values()) {
+ if (isSelectedAndSupported(gc)) {
+ test(gc);
}
- test("-XX:+UseEpsilonGC");
}
} catch (SkippedException se) {
throw se;
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted002/TestDescription.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted002/TestDescription.java Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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,6 +36,7 @@
*
* @library /vmTestbase
* /test/lib
+ * @requires !vm.graal.enabled
* @run driver jdk.test.lib.FileInstaller . .
* @run main/othervm/native
* -agentlib:resexhausted=-waittime=5
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003.java Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2019, 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
@@ -26,6 +26,8 @@
import java.io.FileInputStream;
import java.io.PrintStream;
import java.security.ProtectionDomain;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
import nsk.share.Consts;
import nsk.share.test.Stresser;
@@ -77,12 +79,20 @@
public static int run(String args[], PrintStream out) {
- if ( args == null || args.length < 1 ) {
- System.err.println("TEST BUG: Classes directory should be the first argument. Check .cfg file.");
+ String testclasspath = System.getProperty("test.class.path");
+ String [] testpaths = testclasspath.split(System.getProperty("path.separator"));
+ String classesDir = "";
+
+ Pattern pattern = Pattern.compile("^(.*)classes(.*)vmTestbase(.*)$");
+ for (int i = 0 ; i < testpaths.length; i++) {
+ if (pattern.matcher(testpaths[i]).matches()) {
+ classesDir = testpaths[i];
+ }
+ }
+ if (classesDir.equals("")) {
+ System.err.println("TEST BUG: Classes directory not found in test,class.path.");
return Consts.TEST_FAILED;
}
-
- String classesDir = args[0];
Stresser stress = new Stresser(args);
String className = Helper.class.getName();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003/TEST.properties Sat Mar 30 09:30:03 2019 +0000
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 2019, 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.
+#
+
+exclusiveAccess.dirs=.
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003/TestDescription.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003/TestDescription.java Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -45,6 +45,5 @@
* -XX:MaxMetaspaceSize=9m
* -XX:-UseGCOverheadLimit
* nsk.jvmti.ResourceExhausted.resexhausted003
- * ../../classes/0/vmTestbase
*/
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted004/TestDescription.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted004/TestDescription.java Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -39,14 +39,12 @@
* @library /vmTestbase
* /test/lib
* @run driver jdk.test.lib.FileInstaller . .
- * @ignore 7013634 6606767
* @run main/othervm/native
* -agentlib:resexhausted=-waittime=5
* -Xms16m
* -Xmx16m
- * -XX:MaxMetaspaceSize=8m
+ * -XX:MaxMetaspaceSize=9m
* -XX:-UseGCOverheadLimit
* nsk.jvmti.ResourceExhausted.resexhausted004
- * ./bin/classes
*/
--- a/test/jdk/TEST.ROOT Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/TEST.ROOT Sat Mar 30 09:30:03 2019 +0000
@@ -22,8 +22,11 @@
javax/management sun/awt sun/java2d javax/xml/jaxp/testng/validation java/lang/ProcessHandle
# Tests that cannot run concurrently
-exclusiveAccess.dirs=java/rmi/Naming java/util/prefs sun/management/jmxremote sun/tools/jstatd \
-sun/security/mscapi java/util/stream java/util/Arrays/largeMemory java/util/BitSet/stream javax/rmi
+exclusiveAccess.dirs=java/rmi/Naming java/util/prefs sun/management/jmxremote \
+sun/tools/jstatd sun/tools/jcmd sun/tools/jhsdb sun/tools/jhsdb/heapconfig \
+sun/tools/jinfo sun/tools/jmap sun/tools/jps sun/tools/jstack sun/tools/jstat \
+com/sun/tools/attach sun/security/mscapi java/util/stream java/util/Arrays/largeMemory \
+java/util/BitSet/stream javax/rmi
# Group definitions
groups=TEST.groups
--- a/test/jdk/com/sun/net/httpserver/TestLogging.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/com/sun/net/httpserver/TestLogging.java Sat Mar 30 09:30:03 2019 +0000
@@ -24,6 +24,7 @@
/**
* @test
* @bug 6422914
+ * @library /test/lib
* @summary change httpserver exception printouts
*/
@@ -37,6 +38,7 @@
import java.security.*;
import java.security.cert.*;
import javax.net.ssl.*;
+import jdk.test.lib.net.URIBuilder;
public class TestLogging extends Test {
@@ -63,13 +65,25 @@
int p1 = s1.getAddress().getPort();
- URL url = new URL ("http://127.0.0.1:"+p1+"/test1/smallfile.txt");
+ URL url = URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .port(p1)
+ .path("/test1/smallfile.txt")
+ .toURLUnchecked();
+ System.out.println("URL: " + url);
HttpURLConnection urlc = (HttpURLConnection)url.openConnection();
InputStream is = urlc.getInputStream();
while (is.read() != -1) ;
is.close();
- url = new URL ("http://127.0.0.1:"+p1+"/test1/doesntexist.txt");
+ url = URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .port(p1)
+ .path("/test1/doesntexist.txt")
+ .toURLUnchecked();
+ System.out.println("URL: " + url);
urlc = (HttpURLConnection)url.openConnection();
try {
is = urlc.getInputStream();
--- a/test/jdk/com/sun/net/httpserver/bugs/6725892/Test.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/com/sun/net/httpserver/bugs/6725892/Test.java Sat Mar 30 09:30:03 2019 +0000
@@ -24,6 +24,7 @@
/**
* @test
* @bug 6725892
+ * @library /test/lib
* @run main/othervm -Dsun.net.httpserver.maxReqTime=2 Test
* @summary
*/
@@ -36,6 +37,8 @@
import java.net.*;
import javax.net.ssl.*;
+import jdk.test.lib.net.URIBuilder;
+
public class Test {
static HttpServer s1;
@@ -76,7 +79,13 @@
port = s1.getAddress().getPort();
System.out.println ("Server on port " + port);
- url = new URL ("http://127.0.0.1:"+port+"/foo");
+ url = URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .port(port)
+ .path("/foo")
+ .toURLUnchecked();
+ System.out.println("URL: " + url);
test1();
test2();
test3();
--- a/test/jdk/com/sun/net/httpserver/bugs/B6373555.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/com/sun/net/httpserver/bugs/B6373555.java Sat Mar 30 09:30:03 2019 +0000
@@ -24,6 +24,7 @@
/**
* @test
* @bug 6373555
+ * @library /test/lib
* @summary HTTP Server failing to answer client requests
*/
@@ -32,6 +33,7 @@
import java.util.*;
import com.sun.net.httpserver.*;
import java.util.concurrent.*;
+import jdk.test.lib.net.URIBuilder;
public class B6373555 {
@@ -96,7 +98,13 @@
try {
Thread.sleep(10);
byte[] buf = getBuf();
- URL url = new URL("http://127.0.0.1:"+port+"/test");
+ URL url = URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .port(port)
+ .path("/test")
+ .toURLUnchecked();
+ System.out.println("URL: " + url);
HttpURLConnection con = (HttpURLConnection)url.openConnection();
con.setDoOutput(true);
con.setDoInput(true);
--- a/test/jdk/com/sun/net/httpserver/bugs/B6401598.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/com/sun/net/httpserver/bugs/B6401598.java Sat Mar 30 09:30:03 2019 +0000
@@ -23,6 +23,7 @@
/**
* @test
+ * @library /test/lib
* @bug 6401598
* @summary new HttpServer cannot serve binary stream data
*/
@@ -31,9 +32,12 @@
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
+import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.concurrent.*;
+import jdk.test.lib.net.URIBuilder;
+
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
@@ -90,7 +94,14 @@
short counter;
for (counter = 0; counter < 1000; counter++) {
- HttpURLConnection connection = getHttpURLConnection(new URL("http://127.0.0.1:"+port+"/server/"), 10000);
+ URL url = URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .port(port)
+ .path("/server/")
+ .toURLUnchecked();
+ System.out.println("URL: " + url);
+ HttpURLConnection connection = getHttpURLConnection(url, 10000);
OutputStream os = connection.getOutputStream();
--- a/test/jdk/java/io/DataOutputStream/WriteUTF.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/java/io/DataOutputStream/WriteUTF.java Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,14 +22,21 @@
*/
/* @test
- @bug 4260284
- @summary Test if DataOutputStream will overcount written field.
-*/
+ * @bug 4260284 8219196
+ * @summary Test if DataOutputStream will overcount written field.
+ * @run testng/othervm -Xmx2g WriteUTF
+ */
-import java.io.*;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.UTFDataFormatException;
+
+import org.testng.annotations.Test;
public class WriteUTF {
- public static void main(String[] args) throws Exception {
+ @Test
+ public static void overcountWrittenField() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeUTF("Hello, World!"); // 15
@@ -37,4 +44,25 @@
if (baos.size() != dos.size())
throw new RuntimeException("Miscounted bytes in DataOutputStream.");
}
+
+ private static void writeUTF(int size) throws IOException {
+ // this character gives 3 bytes when encoded using UTF-8
+ String s = "\u0800".repeat(size);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ DataOutputStream dos = new DataOutputStream(bos);
+ dos.writeUTF(s);
+ }
+
+ @Test(expectedExceptions = UTFDataFormatException.class)
+ public void utfDataFormatException() throws IOException {
+ writeUTF(1 << 16);
+ }
+
+ // Without 8219196 fix, throws ArrayIndexOutOfBoundsException instead of
+ // expected UTFDataFormatException. Requires 2GB of heap (-Xmx2g) to run
+ // without throwing an OutOfMemoryError.
+ @Test(expectedExceptions = UTFDataFormatException.class)
+ public void arrayIndexOutOfBoundsException() throws IOException {
+ writeUTF(Integer.MAX_VALUE / 3 + 1);
+ }
}
--- a/test/jdk/java/lang/String/StringRepeat.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/java/lang/String/StringRepeat.java Sat Mar 30 09:30:03 2019 +0000
@@ -24,7 +24,7 @@
/*
* @test
* @summary This exercises String#repeat patterns and limits.
- * @run main/othervm -Xmx4G StringRepeat
+ * @run main/othervm -Xmx2g StringRepeat
*/
import java.nio.CharBuffer;
--- a/test/jdk/java/lang/invoke/MethodHandlesGeneralTest.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/java/lang/invoke/MethodHandlesGeneralTest.java Sat Mar 30 09:30:03 2019 +0000
@@ -22,6 +22,7 @@
*/
/* @test
+ * @bug 8216558
* @summary unit tests for java.lang.invoke.MethodHandles
* @library /test/lib /java/lang/invoke/common
* @compile MethodHandlesTest.java MethodHandlesGeneralTest.java remote/RemoteExample.java
@@ -664,6 +665,7 @@
boolean testNPE = ((testMode0 & TEST_NPE) != 0);
int testMode = testMode0 & ~(TEST_SETTER | TEST_BOUND | TEST_NPE);
boolean positive = positive0 && !testNPE;
+ boolean isFinal;
boolean isStatic;
Class<?> fclass;
String fname;
@@ -671,12 +673,14 @@
Field f = (fieldRef instanceof Field ? (Field)fieldRef : null);
if (f != null) {
isStatic = Modifier.isStatic(f.getModifiers());
+ isFinal = Modifier.isFinal(f.getModifiers());
fclass = f.getDeclaringClass();
fname = f.getName();
ftype = f.getType();
} else {
Object[] scnt = (Object[]) fieldRef;
isStatic = (Boolean) scnt[0];
+ isFinal = false;
fclass = (Class<?>) scnt[1];
fname = (String) scnt[2];
ftype = (Class<?>) scnt[3];
@@ -720,18 +724,21 @@
? NoSuchFieldException.class
: IllegalAccessException.class,
noAccess);
+ if (((testMode0 & TEST_SETTER) != 0) && (isFinal && isStatic)) return; // Final static field setter test failed as intended.
if (verbosity >= 5) ex.printStackTrace(System.out);
}
if (verbosity >= 3)
- System.out.println("find"+(isStatic?"Static":"")+(isGetter?"Getter":"Setter")+" "+fclass.getName()+"."+fname+"/"+ftype
- +" => "+mh
- +(noAccess == null ? "" : " !! "+noAccess));
+ System.out.println((((testMode0 & TEST_UNREFLECT) != 0)?"unreflect":"find")
+ +(((testMode0 & TEST_FIND_STATIC) != 0)?"Static":"")
+ +(isGetter?"Getter":"Setter")
+ +" "+fclass.getName()+"."+fname+"/"+ftype
+ +" => "+mh
+ +(noAccess == null ? "" : " !! "+noAccess));
if (positive && !testNPE && noAccess != null) throw new RuntimeException(noAccess);
assertEquals(positive0 ? "positive test" : "negative test erroneously passed", positive0, mh != null);
+ assertFalse("Setter methods should throw an exception if passed a final static field.", ((testMode0 & TEST_SETTER) != 0) && (isFinal && isStatic));
if (!positive && !testNPE) return; // negative access test failed as expected
assertEquals((isStatic ? 0 : 1)+(isGetter ? 0 : 1), mh.type().parameterCount());
-
-
assertSame(mh.type(), expType);
//assertNameStringContains(mh, fname); // This does not hold anymore with LFs
HasFields fields = new HasFields();
@@ -778,8 +785,7 @@
}
}
assertEquals(sawValue, expValue);
- if (f != null && f.getDeclaringClass() == HasFields.class
- && !Modifier.isFinal(f.getModifiers())) {
+ if (f != null && f.getDeclaringClass() == HasFields.class && !isFinal) {
Object random = randomArg(ftype);
f.set(fields, random);
expValue = random;
@@ -813,8 +819,8 @@
}
}
}
- if (f != null && f.getDeclaringClass() == HasFields.class) {
- f.set(fields, value); // put it back
+ if ((f != null) && (f.getDeclaringClass() == HasFields.class) && !isFinal) {
+ f.set(fields, value); // put it back if we changed it.
}
if (testNPE) {
if (caughtEx == null || !(caughtEx instanceof NullPointerException))
@@ -862,7 +868,6 @@
public void testSetter(int testMode) throws Throwable {
Lookup lookup = PRIVATE; // FIXME: test more lookups than this one
- startTest("unreflectSetter");
for (Object[] c : HasFields.CASES) {
boolean positive = (c[1] != Error.class);
testSetter(positive, lookup, c[0], c[1], testMode);
--- a/test/jdk/java/lang/invoke/MethodHandlesTest.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/java/lang/invoke/MethodHandlesTest.java Sat Mar 30 09:30:03 2019 +0000
@@ -545,14 +545,14 @@
}
public static class HasFields {
- boolean fZ = false;
- byte fB = (byte)'B';
- short fS = (short)'S';
- char fC = 'C';
- int fI = 'I';
- long fJ = 'J';
- float fF = 'F';
- double fD = 'D';
+ boolean iZ = false;
+ byte iB = (byte)'B';
+ short iS = (short)'S';
+ char iC = 'C';
+ int iI = 'I';
+ long iJ = 'J';
+ float iF = 'F';
+ double iD = 'D';
static boolean sZ = true;
static byte sB = 1+(byte)'B';
static short sS = 1+(short)'S';
@@ -561,11 +561,21 @@
static long sJ = 1+'J';
static float sF = 1+'F';
static double sD = 1+'D';
+ final static boolean fsZ = false;
+ final static byte fsB = 2+(byte)'B';
+ final static short fsS = 2+(short)'S';
+ final static char fsC = 2+'C';
+ final static int fsI = 2+'I';
+ final static long fsJ = 2+'J';
+ final static float fsF = 2+'F';
+ final static double fsD = 2+'D';
- Object fL = 'L';
- String fR = "R";
+ Object iL = 'L';
+ String iR = "R";
static Object sL = 'M';
static String sR = "S";
+ final static Object fsL = 'N';
+ final static String fsR = "T";
static final Object[][] CASES;
static {
@@ -579,14 +589,16 @@
};
HasFields fields = new HasFields();
for (Object[] t : types) {
- for (int kind = 0; kind <= 1; kind++) {
+ for (int kind = 0; kind <= 2; kind++) {
boolean isStatic = (kind != 0);
+ boolean isFinal = (kind == 2);
char btc = (Character)t[0];
- String name = (isStatic ? "s" : "f") + btc;
+ String name = (isStatic ? "s" : "i") + btc;
+ if (isFinal) name = "f" + name;
Class<?> type = (Class<?>) t[1];
Object value;
Field field;
- try {
+ try {
field = HasFields.class.getDeclaredField(name);
} catch (NoSuchFieldException | SecurityException ex) {
throw new InternalError("no field HasFields."+name);
@@ -599,11 +611,14 @@
if (type == float.class) {
float v = 'F';
if (isStatic) v++;
+ if (isFinal) v++;
assertTrue(value.equals(v));
}
+ if (isFinal && isStatic) field.setAccessible(true);
assertTrue(name.equals(field.getName()));
assertTrue(type.equals(field.getType()));
assertTrue(isStatic == (Modifier.isStatic(field.getModifiers())));
+ assertTrue(isFinal == (Modifier.isFinal(field.getModifiers())));
cases.add(new Object[]{ field, value });
}
}
--- a/test/jdk/java/lang/invoke/VarHandles/accessibility/TestFieldLookupAccessibility.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/java/lang/invoke/VarHandles/accessibility/TestFieldLookupAccessibility.java Sat Mar 30 09:30:03 2019 +0000
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 8152645
+ * @bug 8152645 8216558
* @summary test field lookup accessibility of MethodHandles and VarHandles
* @compile TestFieldLookupAccessibility.java
* pkg/A.java pkg/B_extends_A.java pkg/C.java
@@ -96,6 +96,12 @@
Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
return l.unreflectGetter(cloneAndSetAccessible(f));
}
+
+ // Setting the accessibility bit of a Field grants access under
+ // all conditions for MethodHandle getters.
+ Set<String> inaccessibleFields(Set<String> inaccessibleFields) {
+ return new HashSet<>();
+ }
},
MH_UNREFLECT_SETTER() {
Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
@@ -103,13 +109,27 @@
}
boolean isAccessible(Field f) {
- return f.isAccessible() || !Modifier.isFinal(f.getModifiers());
+ return f.isAccessible() && !Modifier.isStatic(f.getModifiers()) || !Modifier.isFinal(f.getModifiers());
}
},
MH_UNREFLECT_SETTER_ACCESSIBLE() {
Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
return l.unreflectSetter(cloneAndSetAccessible(f));
}
+
+ boolean isAccessible(Field f) {
+ return !(Modifier.isStatic(f.getModifiers()) && Modifier.isFinal(f.getModifiers()));
+ }
+
+ // Setting the accessibility bit of a Field grants access to non-static
+ // final fields for MethodHandle setters.
+ Set<String> inaccessibleFields(Set<String>inaccessibleFields) {
+ Set<String> result = new HashSet<>();
+ inaccessibleFields.stream()
+ .filter(f -> (f.contains("static") && f.contains("final")))
+ .forEach(result::add);
+ return result;
+ }
},
VH() {
Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
@@ -142,6 +162,10 @@
return true;
}
+ Set<String> inaccessibleFields(Set<String> inaccessibleFields) {
+ return new HashSet<>(inaccessibleFields);
+ }
+
static Field cloneAndSetAccessible(Field f) throws Exception {
// Clone to avoid mutating source field
f = f.getDeclaringClass().getDeclaredField(f.getName());
@@ -180,7 +204,7 @@
@Test(dataProvider = "lookupProvider")
public void test(FieldLookup fl, Class<?> src, MethodHandles.Lookup l, Set<String> inaccessibleFields) {
// Add to the expected failures all inaccessible fields due to accessibility modifiers
- Set<String> expected = new HashSet<>(inaccessibleFields);
+ Set<String> expected = fl.inaccessibleFields(inaccessibleFields);
Map<Field, Throwable> actual = new HashMap<>();
for (Field f : fields(src)) {
@@ -202,12 +226,7 @@
collect(Collectors.toSet());
if (!actualFieldNames.equals(expected)) {
if (actualFieldNames.isEmpty()) {
- // Setting the accessibility bit of a Field grants access under
- // all conditions for MethodHander getters and setters
- if (fl != FieldLookup.MH_UNREFLECT_GETTER_ACCESSIBLE &&
- fl != FieldLookup.MH_UNREFLECT_SETTER_ACCESSIBLE) {
- Assert.assertEquals(actualFieldNames, expected, "No accessibility failures:");
- }
+ Assert.assertEquals(actualFieldNames, expected, "No accessibility failures:");
}
else {
Assert.assertEquals(actualFieldNames, expected, "Accessibility failures differ:");
--- a/test/jdk/java/math/BigInteger/LargeValueExceptions.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/java/math/BigInteger/LargeValueExceptions.java Sat Mar 30 09:30:03 2019 +0000
@@ -25,7 +25,7 @@
* @test
* @bug 8200698
* @summary Tests that exceptions are thrown for ops which would overflow
- * @requires os.maxMemory >= 4g
+ * @requires (sun.arch.data.model == "64" & os.maxMemory >= 4g)
* @run testng/othervm -Xmx4g LargeValueExceptions
*/
import java.math.BigInteger;
--- a/test/jdk/java/net/HttpCookie/ExpiredCookieTest.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/java/net/HttpCookie/ExpiredCookieTest.java Sat Mar 30 09:30:03 2019 +0000
@@ -24,12 +24,14 @@
/*
* @test
* @bug 8000525
+ * @library /test/lib
*/
import java.net.*;
import java.util.*;
import java.io.*;
import java.text.*;
+import jdk.test.lib.net.URIBuilder;
public class ExpiredCookieTest {
// lifted from HttpCookie.java
@@ -81,7 +83,13 @@
"TEST4=TEST4; Path=/; Expires=" + datestring.toString());
header.put("Set-Cookie", values);
- cm.put(new URI("http://127.0.0.1/"), header);
+ URI uri = URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .path("/")
+ .buildUnchecked();
+ System.out.println("URI: " + uri);
+ cm.put(uri, header);
CookieStore cookieJar = cm.getCookieStore();
List <HttpCookie> cookies = cookieJar.getCookies();
--- a/test/jdk/java/net/HttpURLConnection/NoProxyTest.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/java/net/HttpURLConnection/NoProxyTest.java Sat Mar 30 09:30:03 2019 +0000
@@ -24,11 +24,13 @@
/*
* @test
* @bug 8144008
+ * @library /test/lib
* @summary Setting NO_PROXY on HTTP URL connections does not stop proxying
* @run main/othervm NoProxyTest
*/
import java.io.IOException;
+import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.ProxySelector;
@@ -37,6 +39,7 @@
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
+import jdk.test.lib.net.URIBuilder;
public class NoProxyTest {
@@ -52,7 +55,12 @@
public static void main(String args[]) throws MalformedURLException {
ProxySelector.setDefault(new NoProxyTestSelector());
- URL url = URI.create("http://127.0.0.1/").toURL();
+ URL url = URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .path("/")
+ .toURLUnchecked();
+ System.out.println("URL: " + url);
URLConnection connection;
try {
connection = url.openConnection(Proxy.NO_PROXY);
--- a/test/jdk/java/net/ProxySelector/NullSelector.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/java/net/ProxySelector/NullSelector.java Sat Mar 30 09:30:03 2019 +0000
@@ -23,15 +23,22 @@
/* @test
* @bug 6215885
+ * @library /test/lib
* @summary URLConnection.openConnection NPE if ProxySelector.setDefault is set to null
*/
import java.net.*;
import java.io.*;
+import jdk.test.lib.net.URIBuilder;
public class NullSelector {
public static void main(String[] args) throws Exception {
- URL url = new URL("http://127.0.0.1/");
+ URL url = URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .path("/")
+ .toURLUnchecked();
+ System.out.println("URL: " + url);
ProxySelector.setDefault(null);
URLConnection con = url.openConnection();
con.setConnectTimeout(500);
--- a/test/jdk/java/net/ResponseCache/Test2.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/java/net/ResponseCache/Test2.java Sat Mar 30 09:30:03 2019 +0000
@@ -24,6 +24,7 @@
/**
* @test
* @bug 8042622
+ * @library /test/lib
* @summary Check for CRL results in IllegalArgumentException "white space not allowed"
* @modules jdk.httpserver
* @run main/othervm Test2
@@ -38,6 +39,7 @@
import java.security.*;
import javax.security.auth.callback.*;
import javax.net.ssl.*;
+import jdk.test.lib.net.URIBuilder;
public class Test2 {
@@ -63,7 +65,7 @@
static int port;
- static String urlstring, redirstring;
+ static URL url, redir;
public static void main (String[] args) throws Exception {
Handler handler = new Handler();
@@ -78,10 +80,21 @@
server.setExecutor (executor);
server.start ();
- urlstring = "http://127.0.0.1:" + Integer.toString(port)+"/test/foo";
- redirstring = urlstring + "/redirect/bar";
+ url = URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .port(port)
+ .path("/test/foo")
+ .toURLUnchecked();
+ System.out.println("URL: " + url);
+ redir = URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .port(port)
+ .path("/test/foo/redirect/bar")
+ .toURLUnchecked();
+ System.out.println("Redir URL: " + redir);
- URL url = new URL (urlstring);
HttpURLConnection urlc = (HttpURLConnection)url.openConnection();
urlc.addRequestProperty("X-Foo", "bar");
urlc.setInstanceFollowRedirects(true);
@@ -114,7 +127,7 @@
Headers rmap = t.getResponseHeaders();
invocation ++;
if (invocation == 1) {
- rmap.add("Location", redirstring);
+ rmap.add("Location", redir.toString());
while (is.read () != -1) ;
is.close();
System.out.println ("sending response");
--- a/test/jdk/java/net/Socket/Timeouts.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/java/net/Socket/Timeouts.java Sat Mar 30 09:30:03 2019 +0000
@@ -85,8 +85,7 @@
}
/**
- * Test connect with a negative timeout. This case is not currently specified
- * but the long standing behavior is to throw IllegalArgumentException.
+ * Test connect with a negative timeout.
*/
public void testTimedConnect4() throws IOException {
try (ServerSocket ss = new ServerSocket(0)) {
@@ -303,7 +302,7 @@
s.close();
}
}
-
+
/**
* Test timed accept where the accept times out
*/
@@ -393,8 +392,7 @@
}
/**
- * Test Socket setSoTimeout with a negative timeout. This case is not currently
- * specified but the long standing behavior is to throw IllegalArgumentException.
+ * Test Socket setSoTimeout with a negative timeout.
*/
@Test(expectedExceptions = { IllegalArgumentException.class })
public void testBadTimeout1() throws IOException {
@@ -404,9 +402,7 @@
}
/**
- * Test ServerSocket setSoTimeout with a negative timeout. This case is not
- * currently specified but the long standing behavior is to throw
- * IllegalArgumentException.
+ * Test ServerSocket setSoTimeout with a negative timeout.
*/
@Test(expectedExceptions = { IllegalArgumentException.class })
public void testBadTimeout2() throws IOException {
--- a/test/jdk/java/net/URLClassLoader/closetest/CloseTest.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/java/net/URLClassLoader/closetest/CloseTest.java Sat Mar 30 09:30:03 2019 +0000
@@ -42,6 +42,7 @@
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URLClassLoader;
+import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URL;
import java.nio.file.Files;
@@ -49,6 +50,7 @@
import java.nio.file.Paths;
import jdk.test.lib.compiler.CompilerUtils;
+import jdk.test.lib.net.URIBuilder;
import jdk.test.lib.util.JarUtils;
import com.sun.net.httpserver.HttpContext;
@@ -157,8 +159,12 @@
static URL getServerURL() throws Exception {
int port = httpServer.getAddress().getPort();
- String s = "http://127.0.0.1:" + port + "/";
- return new URL(s);
+ return URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .port(port)
+ .path("/")
+ .toURL();
}
static void startHttpServer(String docroot) throws Exception {
--- a/test/jdk/java/net/URLConnection/TimeoutTest.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/java/net/URLConnection/TimeoutTest.java Sat Mar 30 09:30:03 2019 +0000
@@ -24,12 +24,14 @@
/*
* @test
* @bug 4389976
+ * @library /test/lib
* @summary can't unblock read() of InputStream from URL connection
* @run main/timeout=40/othervm -Dsun.net.client.defaultReadTimeout=2000 TimeoutTest
*/
import java.io.*;
import java.net.*;
+import jdk.test.lib.net.URIBuilder;
public class TimeoutTest {
@@ -68,7 +70,12 @@
ServerSocket ss = new ServerSocket(0);
Server s = new Server (ss);
try{
- URL url = new URL ("http://127.0.0.1:"+ss.getLocalPort());
+ URL url = URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .port(ss.getLocalPort())
+ .toURL();
+ System.out.println("URL: " + url);
URLConnection urlc = url.openConnection ();
InputStream is = urlc.getInputStream ();
throw new RuntimeException("Should have received timeout");
--- a/test/jdk/java/net/URLPermission/OpenURL.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/java/net/URLPermission/OpenURL.java Sat Mar 30 09:30:03 2019 +0000
@@ -24,11 +24,13 @@
/*
* @test
* @bug 8029354
+ * @library /test/lib
* @run main/othervm OpenURL
*/
import java.net.*;
import java.io.*;
+import jdk.test.lib.net.URIBuilder;
public class OpenURL {
@@ -37,7 +39,13 @@
System.setSecurityManager(new SecurityManager());
try {
- URL url = new URL ("http://joe@127.0.0.1/a/b");
+ URL url = URIBuilder.newBuilder()
+ .scheme("http")
+ .userInfo("joe")
+ .loopback()
+ .path("/a/b")
+ .toURL();
+ System.out.println("URL: " + url);
HttpURLConnection urlc = (HttpURLConnection)url.openConnection();
InputStream is = urlc.getInputStream();
// error will throw exception other than SecurityException
--- a/test/jdk/java/net/httpclient/AuthSchemesTest.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/java/net/httpclient/AuthSchemesTest.java Sat Mar 30 09:30:03 2019 +0000
@@ -24,6 +24,7 @@
/**
* @test
* @bug 8217237
+ * @library /test/lib
* @modules java.net.http
* @run main/othervm AuthSchemesTest
* @summary HttpClient does not deal well with multi-valued WWW-Authenticate challenge headers
@@ -37,6 +38,7 @@
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
+import jdk.test.lib.net.URIBuilder;
public class AuthSchemesTest {
static class BasicServer extends Thread {
@@ -142,7 +144,13 @@
.authenticator(authenticator)
.build();
server.start();
- URI uri = URI.create("http://127.0.0.1:" + port + "/foo");
+ URI uri = URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .port(port)
+ .path("/foo")
+ .build();
+ System.out.println("URI: " + uri);
HttpRequest request = HttpRequest.newBuilder(uri)
.GET()
.build();
--- a/test/jdk/java/net/httpclient/LargeResponseContent.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/java/net/httpclient/LargeResponseContent.java Sat Mar 30 09:30:03 2019 +0000
@@ -39,10 +39,12 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Flow;
+import jdk.test.lib.net.URIBuilder;
/**
* @test
* @bug 8212926
+ * @library /test/lib
* @summary Basic tests for response timeouts
* @run main/othervm LargeResponseContent
*/
@@ -60,7 +62,13 @@
}
void runClient() throws IOException, InterruptedException {
- URI uri = URI.create("http://127.0.0.1:" + Integer.toString(port) + "/foo");
+ URI uri = URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .port(port)
+ .path("/foo")
+ .buildUnchecked();
+ System.out.println("URI: " + uri);
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder(uri)
.GET()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/text/Format/NumberFormat/DFSMinusPerCentMill.java Sat Mar 30 09:30:03 2019 +0000
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2019, 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 8220309
+ * @library /java/text/testlib
+ * @summary Test String representation of MinusSign/Percent/PerMill symbols.
+ * This test assumes CLDR has numbering systems for "arab" and
+ * "arabext", and their minus/percent representations include
+ * BiDi formatting control characters.
+ * @run testng/othervm DFSMinusPerCentMill
+ */
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+import static org.testng.Assert.*;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+public class DFSMinusPerCentMill {
+ private enum Type {
+ NUMBER, PERCENT, CURRENCY, INTEGER, COMPACT, PERMILL
+ }
+
+ private static final Locale US_ARAB = Locale.forLanguageTag("en-US-u-nu-arab");
+ private static final Locale US_ARABEXT = Locale.forLanguageTag("en-US-u-nu-arabext");
+ private static final double SRC_NUM = -1234.56;
+
+ @DataProvider
+ Object[][] formatData() {
+ return new Object[][] {
+ // Locale, FormatStyle, expected format, expected single char symbol
+ {US_ARAB, Type.NUMBER, "\u061c-\u0661\u066c\u0662\u0663\u0664\u066b\u0665\u0666"},
+ {US_ARAB, Type.PERCENT, "\u061c-\u0661\u0662\u0663\u066c\u0664\u0665\u0666\u066a\u061c"},
+ {US_ARAB, Type.CURRENCY, "\u061c-$\u0661\u066c\u0662\u0663\u0664\u066b\u0665\u0666"},
+ {US_ARAB, Type.INTEGER, "\u061c-\u0661\u066c\u0662\u0663\u0665"},
+ {US_ARAB, Type.COMPACT, "\u061c-\u0661K"},
+ {US_ARAB, Type.PERMILL, "\u061c-\u0661\u0662\u0663\u0664\u0665\u0666\u0660\u0609"},
+
+ {US_ARABEXT, Type.NUMBER, "\u200e-\u200e\u06f1\u066c\u06f2\u06f3\u06f4\u066b\u06f5\u06f6"},
+ {US_ARABEXT, Type.PERCENT, "\u200e-\u200e\u06f1\u06f2\u06f3\u066c\u06f4\u06f5\u06f6\u066a"},
+ {US_ARABEXT, Type.CURRENCY, "\u200e-\u200e$\u06f1\u066c\u06f2\u06f3\u06f4\u066b\u06f5\u06f6"},
+ {US_ARABEXT, Type.INTEGER, "\u200e-\u200e\u06f1\u066c\u06f2\u06f3\u06f5"},
+ {US_ARABEXT, Type.COMPACT, "\u200e-\u200e\u06f1K"},
+ {US_ARABEXT, Type.PERMILL, "\u200e-\u200e\u06f1\u06f2\u06f3\u06f4\u06f5\u06f6\u06f0\u0609"},
+ };
+ }
+
+ @DataProvider
+ Object[][] charSymbols() {
+ return new Object[][]{
+ // Locale, percent, per mille, minus sign
+ {US_ARAB, '\u066a', '\u0609', '-'},
+ {US_ARABEXT, '\u066a', '\u0609', '-'},
+ };
+ }
+
+ @Test(dataProvider="formatData")
+ public void testFormatData(Locale l, Type style, String expected) {
+ NumberFormat nf = null;
+ switch (style) {
+ case NUMBER:
+ nf = NumberFormat.getNumberInstance(l);
+ break;
+ case PERCENT:
+ nf = NumberFormat.getPercentInstance(l);
+ break;
+ case CURRENCY:
+ nf = NumberFormat.getCurrencyInstance(l);
+ break;
+ case INTEGER:
+ nf = NumberFormat.getIntegerInstance(l);
+ break;
+ case COMPACT:
+ nf = NumberFormat.getCompactNumberInstance(l, NumberFormat.Style.SHORT);
+ break;
+ case PERMILL:
+ nf = new DecimalFormat("#.#\u2030", DecimalFormatSymbols.getInstance(l));
+ break;
+ }
+
+ assertEquals(nf.format(SRC_NUM), expected);
+ }
+
+ @Test(dataProvider="charSymbols")
+ public void testCharSymbols(Locale l, char percent, char permill, char minus) {
+ DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l);
+ assertEquals(dfs.getPercent(), percent);
+ assertEquals(dfs.getPerMill(), permill);
+ assertEquals(dfs.getMinusSign(), minus);
+ }
+
+ @Test
+ public void testSerialization() throws Exception {
+ DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance();
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ new ObjectOutputStream(bos).writeObject(dfs);
+ DecimalFormatSymbols dfsSerialized = (DecimalFormatSymbols)new ObjectInputStream(
+ new ByteArrayInputStream(bos.toByteArray())
+ ).readObject();
+
+ assertEquals(dfs, dfsSerialized);
+
+ // set minus/percent/permille
+ dfs.setMinusSign('a');
+ dfs.setPercent('b');
+ dfs.setPerMill('c');
+ bos = new ByteArrayOutputStream();
+ new ObjectOutputStream(bos).writeObject(dfs);
+ dfsSerialized = (DecimalFormatSymbols)new ObjectInputStream(
+ new ByteArrayInputStream(bos.toByteArray())
+ ).readObject();
+
+ assertEquals(dfs, dfsSerialized);
+ }
+}
--- a/test/jdk/java/util/Base64/TestEncodingDecodingLength.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/java/util/Base64/TestEncodingDecodingLength.java Sat Mar 30 09:30:03 2019 +0000
@@ -30,7 +30,7 @@
* @bug 8210583 8217969 8218265
* @summary Tests Base64.Encoder.encode and Base64.Decoder.decode
* with the large size of input array/buffer
- * @requires os.maxMemory >= 10g
+ * @requires (sun.arch.data.model == "64" & os.maxMemory >= 10g)
* @run main/othervm -Xms6g -Xmx8g TestEncodingDecodingLength
*
*/
--- a/test/jdk/jdk/internal/platform/docker/Dockerfile-BasicTest Sat Mar 23 15:11:51 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-FROM oraclelinux:7.6
-MAINTAINER mikhailo.seledtsov@oracle.com
-
-COPY /jdk /jdk
-
-ENV JAVA_HOME=/jdk
-
-CMD ["/bin/bash"]
--- a/test/jdk/jdk/internal/platform/docker/Dockerfile-BasicTest-aarch64 Sat Mar 23 15:11:51 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-# Use generic ubuntu Linux on AArch64
-FROM aarch64/ubuntu
-
-COPY /jdk /jdk
-
-ENV JAVA_HOME=/jdk
-
-CMD ["/bin/bash"]
--- a/test/jdk/jdk/internal/platform/docker/Dockerfile-BasicTest-ppc64le Sat Mar 23 15:11:51 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-# test on x86_64 uses Oracle Linux but we do not have this for ppc64le
-# so use some other Linux where OpenJDK works
-# FROM oraclelinux:7.2
-FROM ppc64le/ubuntu
-
-COPY /jdk /jdk
-
-ENV JAVA_HOME=/jdk
-
-CMD ["/bin/bash"]
--- a/test/jdk/jdk/internal/platform/docker/Dockerfile-BasicTest-s390x Sat Mar 23 15:11:51 2019 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-FROM s390x/ubuntu
-
-COPY /jdk /jdk
-
-ENV JAVA_HOME=/jdk
-
-CMD ["/bin/bash"]
--- a/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java Sat Mar 30 09:30:03 2019 +0000
@@ -77,22 +77,25 @@
}
public static void main(String[] args) throws Exception {
- verify(runProcess(CrasherIllegalAccess.class.getName(), ""));
- verify(runProcess(CrasherHalt.class.getName(), ""));
+ verify(runProcess(CrasherIllegalAccess.class.getName(), "", true));
+ verify(runProcess(CrasherIllegalAccess.class.getName(), "", false));
+ verify(runProcess(CrasherHalt.class.getName(), "", true));
+ verify(runProcess(CrasherHalt.class.getName(), "", false));
// Verification is excluded for the test case below until 8219680 is fixed
- long pid = runProcess(CrasherSig.class.getName(), "FPE");
+ long pid = runProcess(CrasherSig.class.getName(), "FPE", true);
// @ignore 8219680
// verify(pid);
}
- private static long runProcess(String crasher, String signal) throws Exception {
+ private static long runProcess(String crasher, String signal, boolean disk) throws Exception {
System.out.println("Test case for crasher " + crasher);
+ final String flightRecordingOptions = "dumponexit=true,disk=" + Boolean.toString(disk);
Process p = ProcessTools.createJavaProcessBuilder(true,
"-Xmx64m",
"-XX:-CreateCoredumpOnCrash",
"--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED",
- "-XX:StartFlightRecording",
+ "-XX:StartFlightRecording=" + flightRecordingOptions,
crasher,
signal)
.start();
--- a/test/jdk/sun/net/www/http/KeepAliveCache/KeepAliveTimerThread.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/sun/net/www/http/KeepAliveCache/KeepAliveTimerThread.java Sat Mar 30 09:30:03 2019 +0000
@@ -23,24 +23,26 @@
/*
* @test
+ * @library /test/lib
* @bug 4701299
* @summary Keep-Alive-Timer thread management in KeepAliveCache causes memory leak
*/
+
import java.net.*;
import java.io.*;
+import jdk.test.lib.net.URIBuilder;
public class KeepAliveTimerThread {
static class Fetcher implements Runnable {
- String url;
+ URL url;
- Fetcher(String url) {
+ Fetcher(URL url) {
this.url = url;
}
public void run() {
try {
- InputStream in =
- (new URL(url)).openConnection().getInputStream();
+ InputStream in = url.openConnection().getInputStream();
byte b[] = new byte[128];
int n;
do {
@@ -105,7 +107,12 @@
Server s = new Server (ss);
s.start();
- String url = "http://127.0.0.1:"+ss.getLocalPort();
+ URL url = URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .port(ss.getLocalPort())
+ .toURL();
+ System.out.println("URL: " + url);
// start fetch in its own thread group
ThreadGroup grp = new ThreadGroup("MyGroup");
--- a/test/jdk/sun/net/www/protocol/http/6550798/test.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/sun/net/www/protocol/http/6550798/test.java Sat Mar 30 09:30:03 2019 +0000
@@ -24,6 +24,7 @@
/**
* @test
* @bug 6550798
+ * @library /test/lib
* @summary Using InputStream.skip with ResponseCache will cause partial data to be cached
* @modules jdk.httpserver
* @run main/othervm test
@@ -33,6 +34,8 @@
import com.sun.net.httpserver.*;
import java.io.*;
+import jdk.test.lib.net.URIBuilder;
+
public class test {
final static int LEN = 16 * 1024;
@@ -58,7 +61,13 @@
s.start();
System.out.println("http request with cache hander");
- URL u = new URL("http://127.0.0.1:"+s.getAddress().getPort()+"/f");
+ URL u = URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .port(s.getAddress().getPort())
+ .path("/f")
+ .toURL();
+ System.out.println("URL: " + u);
URLConnection conn = u.openConnection();
InputStream is = null;
--- a/test/jdk/sun/net/www/protocol/http/B6890349.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/sun/net/www/protocol/http/B6890349.java Sat Mar 30 09:30:03 2019 +0000
@@ -39,7 +39,11 @@
System.out.println ("listening on " + port);
B6890349 t = new B6890349 (server);
t.start();
- URL u = new URL ("http://127.0.0.1:"+port+"/foo\nbar");
+ URL u = new URL("http",
+ InetAddress.getLoopbackAddress().getHostAddress(),
+ port,
+ "/foo\nbar");
+ System.out.println("URL: " + u);
HttpURLConnection urlc = (HttpURLConnection)u.openConnection ();
InputStream is = urlc.getInputStream();
throw new RuntimeException ("Test failed");
--- a/test/jdk/sun/net/www/protocol/http/B8012625.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/sun/net/www/protocol/http/B8012625.java Sat Mar 30 09:30:03 2019 +0000
@@ -24,6 +24,7 @@
/**
* @test
* @bug 8012625
+ * @library /test/lib
* @modules jdk.httpserver
* @run main B8012625
*/
@@ -34,6 +35,9 @@
import java.net.*;
import java.io.*;
import java.util.concurrent.*;
+
+import jdk.test.lib.net.URIBuilder;
+
import com.sun.net.httpserver.*;
public class B8012625 implements HttpHandler {
@@ -44,8 +48,13 @@
}
public void run() throws Exception {
- String u = "http://127.0.0.1:" + port + "/foo";
- URL url = new URL(u);
+ URL url = URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .port(port)
+ .path("/foo")
+ .toURL();
+ System.out.println("URL: " + url);
HttpURLConnection uc = (HttpURLConnection)url.openConnection();
uc.setDoOutput(true);
uc.setRequestMethod("POST");
--- a/test/jdk/sun/net/www/protocol/http/NoNTLM.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/sun/net/www/protocol/http/NoNTLM.java Sat Mar 30 09:30:03 2019 +0000
@@ -23,6 +23,7 @@
/* @test
* @bug 8004502
+ * @library /test/lib
* @summary Sanity check that NTLM will not be selected by the http protocol
* handler when running on a profile that does not support NTLM
* @modules java.base/sun.net.www
@@ -34,11 +35,13 @@
import java.lang.reflect.Field;
import java.net.Authenticator;
import java.net.HttpURLConnection;
+import java.net.InetAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;
+import jdk.test.lib.net.URIBuilder;
import sun.net.www.MessageHeader;
public class NoNTLM {
@@ -57,7 +60,13 @@
private volatile int respCode;
Client(int port) throws IOException {
- this.url = new URL("http://127.0.0.1:" + port + "/foo.html");
+ this.url = URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .port(port)
+ .path("/foo.html")
+ .toURLUnchecked();
+ System.out.println("Client URL: " + this.url);
}
public void run() {
--- a/test/jdk/sun/net/www/protocol/http/RedirectOnPost.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/sun/net/www/protocol/http/RedirectOnPost.java Sat Mar 30 09:30:03 2019 +0000
@@ -39,6 +39,7 @@
import java.util.concurrent.*;
import javax.net.ssl.*;
import jdk.test.lib.net.SimpleSSLContext;
+import jdk.test.lib.net.URIBuilder;
public class RedirectOnPost {
@@ -55,8 +56,8 @@
int sslPort = httpsServer.getAddress().getPort();
httpServer.start();
httpsServer.start();
- runTest("http://127.0.0.1:"+port+"/test/", null);
- runTest("https://127.0.0.1:"+sslPort+"/test/", ctx);
+ runTest("http", port, null);
+ runTest("https", sslPort, ctx);
System.out.println("Main thread waiting");
} finally {
httpServer.stop(0);
@@ -65,10 +66,17 @@
}
}
- public static void runTest(String baseURL, SSLContext ctx) throws Exception
+ public static void runTest(String scheme, int port, SSLContext ctx) throws Exception
{
byte[] buf = "Hello world".getBytes();
- URL url = new URL(baseURL + "a");
+
+ URL url = URIBuilder.newBuilder()
+ .scheme(scheme)
+ .loopback()
+ .port(port)
+ .path("/test/a")
+ .toURL();
+ System.out.println("URL: " + url);
HttpURLConnection con = (HttpURLConnection)url.openConnection();
if (con instanceof HttpsURLConnection) {
HttpsURLConnection ssl = (HttpsURLConnection)con;
@@ -107,10 +115,12 @@
static class Handler implements HttpHandler {
- String baseURL;
+ String scheme;
+ int port;
- Handler(String baseURL) {
- this.baseURL = baseURL;
+ Handler(String scheme, int port) {
+ this.scheme = scheme;
+ this.port = port;
}
int calls = 0;
@@ -118,6 +128,12 @@
public void handle(HttpExchange msg) {
try {
String method = msg.getRequestMethod();
+ URL baseURL = URIBuilder.newBuilder()
+ .scheme(scheme)
+ .loopback()
+ .path("/test/b")
+ .port(port)
+ .toURLUnchecked();
System.out.println ("Server: " + baseURL);
if (calls++ == 0) {
System.out.println ("Server: redirecting");
@@ -125,7 +141,7 @@
byte[] buf = readFully(is);
is.close();
Headers h = msg.getResponseHeaders();
- h.add("Location", baseURL + "b");
+ h.add("Location", baseURL.toString());
msg.sendResponseHeaders(302, -1);
msg.close();
} else {
@@ -153,9 +169,9 @@
HttpServer testServer = HttpServer.create(inetAddress, 15);
int port = testServer.getAddress().getPort();
testServer.setExecutor(execs);
- String base = "http://127.0.0.1:"+port+"/test";
+
HttpContext context = testServer.createContext("/test");
- context.setHandler(new Handler(base));
+ context.setHandler(new Handler("http", port));
return testServer;
}
@@ -169,9 +185,9 @@
int port = testServer.getAddress().getPort();
testServer.setExecutor(execs);
testServer.setHttpsConfigurator(new HttpsConfigurator (ctx));
- String base = "https://127.0.0.1:"+port+"/test";
+
HttpContext context = testServer.createContext("/test");
- context.setHandler(new Handler(base));
+ context.setHandler(new Handler("https", port));
return testServer;
}
}
--- a/test/jdk/sun/net/www/protocol/http/ResponseCacheStream.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/sun/net/www/protocol/http/ResponseCacheStream.java Sat Mar 30 09:30:03 2019 +0000
@@ -24,6 +24,7 @@
/*
* @test
* @bug 6262486
+ * @library /test/lib
* @modules java.base/sun.net.www
* @library ../../httptest/
* @build HttpCallback TestHttpServer ClosedChannelList HttpTransaction
@@ -34,6 +35,7 @@
import java.net.*;
import java.io.*;
import java.util.*;
+import jdk.test.lib.net.URIBuilder;
public class ResponseCacheStream implements HttpCallback {
@@ -100,7 +102,12 @@
ResponseCache.setDefault(cache);
server = new TestHttpServer (new ResponseCacheStream());
System.out.println ("Server: listening on port: " + server.getLocalPort());
- URL url = new URL ("http://127.0.0.1:"+server.getLocalPort()+"/");
+ URL url = URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .port(server.getLocalPort())
+ .path("/")
+ .toURL();
System.out.println ("Client: connecting to " + url);
HttpURLConnection urlc = (HttpURLConnection)url.openConnection();
InputStream is = urlc.getInputStream();
--- a/test/jdk/sun/net/www/protocol/http/RetryUponTimeout.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/sun/net/www/protocol/http/RetryUponTimeout.java Sat Mar 30 09:30:03 2019 +0000
@@ -24,12 +24,14 @@
/**
* @test
* @bug 4772077
+ * @library /test/lib
* @summary using defaultReadTimeout appear to retry request upon timeout
* @modules java.base/sun.net.www
*/
import java.net.*;
import java.io.*;
+import jdk.test.lib.net.URIBuilder;
import sun.net.www.*;
public class RetryUponTimeout implements Runnable {
@@ -63,7 +65,12 @@
int port = server.getLocalPort ();
new Thread(new RetryUponTimeout()).start ();
- URL url = new URL("http://127.0.0.1:"+port);
+ URL url = URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .port(port)
+ .toURL();
+ System.out.println("URL: " + url);
java.net.URLConnection uc = url.openConnection();
uc.setReadTimeout(1000);
uc.getInputStream();
--- a/test/jdk/sun/net/www/protocol/http/SetChunkedStreamingMode.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/sun/net/www/protocol/http/SetChunkedStreamingMode.java Sat Mar 30 09:30:03 2019 +0000
@@ -26,6 +26,7 @@
* @bug 5049976
* @modules java.base/sun.net.www
* @library ../../httptest/
+ * @library /test/lib
* @build HttpCallback TestHttpServer ClosedChannelList HttpTransaction
* @run main SetChunkedStreamingMode
* @summary Unspecified NPE is thrown when streaming output mode is enabled
@@ -33,6 +34,7 @@
import java.io.*;
import java.net.*;
+import jdk.test.lib.net.URIBuilder;
public class SetChunkedStreamingMode implements HttpCallback {
@@ -67,7 +69,12 @@
try {
server = new TestHttpServer (new SetChunkedStreamingMode(), 1, 10, 0);
System.out.println ("Server: listening on port: " + server.getLocalPort());
- URL url = new URL ("http://127.0.0.1:"+server.getLocalPort()+"/");
+ URL url = URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .port(server.getLocalPort())
+ .path("/")
+ .toURL();
System.out.println ("Client: connecting to " + url);
HttpURLConnection urlc = (HttpURLConnection)url.openConnection();
urlc.setChunkedStreamingMode (0);
--- a/test/jdk/sun/net/www/protocol/http/UserAgent.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/sun/net/www/protocol/http/UserAgent.java Sat Mar 30 09:30:03 2019 +0000
@@ -24,6 +24,7 @@
/**
* @test
* @bug 4512200
+ * @library /test/lib
* @modules java.base/sun.net.www
* @run main/othervm -Dhttp.agent=foo UserAgent
* @summary HTTP header "User-Agent" format incorrect
@@ -32,6 +33,7 @@
import java.io.*;
import java.util.*;
import java.net.*;
+import jdk.test.lib.net.URIBuilder;
import sun.net.www.MessageHeader;
class Server extends Thread {
@@ -89,7 +91,12 @@
Server s = new Server (server);
s.start ();
int port = server.getLocalPort ();
- URL url = new URL ("http://127.0.0.1:"+port);
+ URL url = URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .port(port)
+ .toURL();
+ System.out.println("URL: " + url);
URLConnection urlc = url.openConnection ();
urlc.getInputStream ();
s.join ();
--- a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPAddressDNSIdentities.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPAddressDNSIdentities.java Sat Mar 30 09:30:03 2019 +0000
@@ -23,6 +23,7 @@
/* @test
* @bug 6766775
+ * @library /test/lib
* @summary X509 certificate hostname checking is broken in JDK1.6.0_10
* @run main/othervm IPAddressDNSIdentities
*
@@ -42,6 +43,7 @@
import java.security.spec.*;
import java.security.interfaces.*;
import java.math.BigInteger;
+import jdk.test.lib.net.URIBuilder;
/*
* Certificates and key used in the test.
@@ -710,7 +712,12 @@
HttpsURLConnection http = null;
/* establish http connection to server */
- URL url = new URL("https://127.0.0.1:" + serverPort+"/");
+ URL url = URIBuilder.newBuilder()
+ .scheme("https")
+ .loopback()
+ .port(serverPort)
+ .path("/")
+ .toURL();
System.out.println("url is "+url.toString());
try {
--- a/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPAddressIPIdentities.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/sun/net/www/protocol/https/HttpsURLConnection/IPAddressIPIdentities.java Sat Mar 30 09:30:03 2019 +0000
@@ -28,6 +28,7 @@
/* @test
* @summary X509 certificate hostname checking is broken in JDK1.6.0_10
+ * @library /test/lib
* @bug 6766775
* @run main/othervm IPAddressIPIdentities
* @author Xuelei Fan
@@ -45,6 +46,7 @@
import java.security.spec.*;
import java.security.interfaces.*;
import java.math.BigInteger;
+import jdk.test.lib.net.URIBuilder;
/*
* Certificates and key used in the test.
@@ -714,7 +716,12 @@
HttpsURLConnection http = null;
/* establish http connection to server */
- URL url = new URL("https://127.0.0.1:" + serverPort+"/");
+ URL url = URIBuilder.newBuilder()
+ .scheme("https")
+ .loopback()
+ .port(serverPort)
+ .path("/")
+ .toURL();
System.out.println("url is "+url.toString());
try {
--- a/test/jdk/sun/tools/jstat/lineCounts3.awk Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/sun/tools/jstat/lineCounts3.awk Sat Mar 30 09:30:03 2019 +0000
@@ -23,7 +23,7 @@
headerlines++;
}
-/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+\.[0-9]+)|-[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ {
+/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ {
datalines++;
}
--- a/test/jdk/sun/tools/jstat/lineCounts4.awk Sat Mar 23 15:11:51 2019 +0000
+++ b/test/jdk/sun/tools/jstat/lineCounts4.awk Sat Mar 30 09:30:03 2019 +0000
@@ -26,7 +26,7 @@
headerlines++;
}
-/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+\.[0-9]+)|-[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ {
+/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ {
if (headerlines == 2) {
datalines2++;
}
--- a/test/langtools/tools/javac/api/file/SJFM_GetFileObjects.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/langtools/tools/javac/api/file/SJFM_GetFileObjects.java Sat Mar 30 09:30:03 2019 +0000
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8059977
+ * @bug 8059977 8220687
* @summary StandardJavaFileManager should support java.nio.file.Path.
* Test getFileObject methods.
* @modules java.compiler
@@ -117,6 +117,40 @@
//----------------------------------------------------------------------------------------------
+ @Test
+ void test_getJavaFileObjectsFromPaths_Iterable(StandardJavaFileManager fm) throws IOException {
+ test_getJavaFileObjectsFromPaths_Iterable(fm, getTestFilePaths());
+ test_getJavaFileObjectsFromPaths_Iterable(fm, getTestZipPaths());
+ }
+
+ /**
+ * Tests the {@code getJavaFileObjectsFromPaths(Iterable)} method for a specific file
+ * manager and a series of paths.
+ *
+ * Note: instances of MyStandardJavaFileManager only support
+ * encapsulating paths for files in the default file system.
+ *
+ * @param fm the file manager to be tested
+ * @param paths the paths to be tested
+ * @throws IOException
+ */
+ void test_getJavaFileObjectsFromPaths_Iterable(StandardJavaFileManager fm, List<Path> paths)
+ throws IOException {
+ boolean expectException = !isGetFileObjectsSupported(fm, paths);
+ try {
+ compile(fm.getJavaFileObjectsFromPaths((Iterable<Path>) paths));
+ if (expectException)
+ error("expected exception not thrown: " + IllegalArgumentException.class.getName());
+ } catch (RuntimeException e) {
+ if (expectException && e instanceof IllegalArgumentException)
+ return;
+ error("unexpected exception thrown: " + e);
+ }
+ }
+
+
+ //----------------------------------------------------------------------------------------------
+
/**
* Compiles a set of files.
*
--- a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java Sat Mar 23 15:11:51 2019 +0000
+++ b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java Sat Mar 30 09:30:03 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, 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
@@ -35,7 +35,6 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import jdk.test.lib.Platform;
import jdk.test.lib.Utils;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
@@ -126,11 +125,6 @@
if (Files.exists(buildDir)) {
throw new RuntimeException("The docker build directory already exists: " + buildDir);
}
- // check for the existance of a platform specific docker file as well
- String platformSpecificDockerfile = dockerfile + "-" + Platform.getOsArch();
- if (Files.exists(Paths.get(Utils.TEST_SRC, platformSpecificDockerfile))) {
- dockerfile = platformSpecificDockerfile;
- }
Path jdkSrcDir = Paths.get(Utils.TEST_JDK);
Path jdkDstDir = buildDir.resolve("jdk");
@@ -158,8 +152,9 @@
public static void
buildDockerImage(String imageName, Path dockerfile, Path buildDir) throws Exception {
- // Copy docker file to the build dir
- Files.copy(dockerfile, buildDir.resolve("Dockerfile"));
+ generateDockerFile(buildDir.resolve("Dockerfile"),
+ DockerfileConfig.getBaseImageName(),
+ DockerfileConfig.getBaseImageVersion());
// Build the docker
execute("docker", "build", "--no-cache", "--tag", imageName, buildDir.toString())
@@ -250,6 +245,18 @@
}
+ private static void generateDockerFile(Path dockerfile, String baseImage,
+ String baseImageVersion) throws Exception {
+ String template =
+ "FROM %s:%s\n" +
+ "COPY /jdk /jdk\n" +
+ "ENV JAVA_HOME=/jdk\n" +
+ "CMD [\"/bin/bash\"]\n";
+ String dockerFileStr = String.format(template, baseImage, baseImageVersion);
+ Files.writeString(dockerfile, dockerFileStr);
+ }
+
+
private static class CopyFileVisitor extends SimpleFileVisitor<Path> {
private final Path src;
private final Path dst;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/containers/docker/DockerfileConfig.java Sat Mar 30 09:30:03 2019 +0000
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package jdk.test.lib.containers.docker;
+
+import jdk.test.lib.Platform;
+
+// Use the following properties to specify docker base image at test execution time:
+// Image name: jdk.test.docker.image.name
+// Image version: jdk.test.docker.image.version
+// Usage:
+// jtreg -Djdk.test.docker.image.name=<BASE_IMAGE_NAME> -Djdk.test.docker.image.version=<BASE_IMAGE_VERSION> test/hotspot/jtreg/runtime/containers/docker/
+// E.g.:
+// jtreg -Djdk.test.docker.image.name=ubuntu -Djdk.test.docker.image.version=latest test/hotspot/jtreg/runtime/containers/docker/
+// Using make:
+// make test TEST="test/hotspot/jtreg/runtime/containers/docker" JTREG="JAVA_OPTIONS=-Djdk.test.docker.image.name=ubuntu -Djdk.test.docker.image.version=latest"
+// Note: base image version should not be an empty string. Use "latest" to get the latest version.
+
+public class DockerfileConfig {
+ static String getBaseImageName() {
+ String name = System.getProperty("jdk.test.docker.image.name");
+ if (name != null) {
+ System.out.println("DockerfileConfig: using custom image name: " + name);
+ return name;
+ }
+
+ switch (Platform.getOsArch()) {
+ case "aarch64":
+ return "aarch64/ubuntu";
+ case "ppc64le":
+ return "ppc64le/ubuntu";
+ case "s390x":
+ return "s390x/ubuntu";
+ default:
+ return "oraclelinux";
+ }
+ }
+
+ static String getBaseImageVersion() {
+ String version = System.getProperty("jdk.test.docker.image.version");
+ if (version != null) {
+ System.out.println("DockerfileConfig: using custom image version: " + version);
+ return version;
+ }
+
+ switch (Platform.getOsArch()) {
+ case "aarch64":
+ case "ppc64le":
+ case "s390x":
+ return "latest";
+ default:
+ return "7.6";
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/jdk/test/lib/net/URIBuilder.java Sat Mar 30 09:30:03 2019 +0000
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Google 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.
+ */
+
+package jdk.test.lib.net;
+
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+public class URIBuilder {
+
+ public static URIBuilder newBuilder() {
+ return new URIBuilder();
+ }
+
+ private String scheme;
+ private String userInfo;
+ private String host;
+ private int port;
+ private String path;
+ private String query;
+ private String fragment;
+
+ private URIBuilder() {}
+
+ public URIBuilder scheme(String scheme) {
+ this.scheme = scheme;
+ return this;
+ }
+
+ public URIBuilder userInfo(String userInfo) {
+ this.userInfo = userInfo;
+ return this;
+ }
+
+ public URIBuilder host(String host) {
+ this.host = host;
+ return this;
+ }
+
+ public URIBuilder loopback() {
+ return host(InetAddress.getLoopbackAddress().getHostAddress());
+ }
+
+ public URIBuilder port(int port) {
+ this.port = port;
+ return this;
+ }
+
+ public URIBuilder path(String path) {
+ this.path = path;
+ return this;
+ }
+
+ public URIBuilder query(String query) {
+ this.query = query;
+ return this;
+ }
+
+ public URIBuilder fragment(String fragment) {
+ this.fragment = fragment;
+ return this;
+ }
+
+ public URI build() throws URISyntaxException {
+ return new URI(scheme, userInfo, host, port, path, query, fragment);
+ }
+
+ public URI buildUnchecked() {
+ try {
+ return build();
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ public URL toURL() throws URISyntaxException, MalformedURLException {
+ return build().toURL();
+ }
+
+ public URL toURLUnchecked() {
+ try {
+ return toURL();
+ } catch (URISyntaxException | MalformedURLException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+}