From a13dbd8cde77538a340df7b9d34780879d264237 Mon Sep 17 00:00:00 2001 From: goetz Date: Mon, 12 Aug 2019 12:27:58 +0200 Subject: [PATCH 001/131] 8229408: Bump update version for OpenJDK: jdk-11.0.6 Reviewed-by: shade --- make/autoconf/version-numbers | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/make/autoconf/version-numbers b/make/autoconf/version-numbers index fec9997e75a..4a63f2dac0c 100644 --- a/make/autoconf/version-numbers +++ b/make/autoconf/version-numbers @@ -27,12 +27,12 @@ DEFAULT_VERSION_FEATURE=11 DEFAULT_VERSION_INTERIM=0 -DEFAULT_VERSION_UPDATE=5 +DEFAULT_VERSION_UPDATE=6 DEFAULT_VERSION_PATCH=0 DEFAULT_VERSION_EXTRA1=0 DEFAULT_VERSION_EXTRA2=0 DEFAULT_VERSION_EXTRA3=0 -DEFAULT_VERSION_DATE=2019-10-15 +DEFAULT_VERSION_DATE=2020-01-14 DEFAULT_VERSION_CLASSFILE_MAJOR=55 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" DEFAULT_VERSION_CLASSFILE_MINOR=0 DEFAULT_ACCEPTABLE_BOOT_VERSIONS="10 11" From 464570dbef001f89b7cc166b3bd8c3b90e4e89f9 Mon Sep 17 00:00:00 2001 From: prr Date: Wed, 28 Aug 2019 09:01:47 -0700 Subject: [PATCH 002/131] 8217731: Font rendering and glyph spacing changed from jdk-8 to jdk-11 Summary: Prefer the older v35 freetype byte code interpreter. Reviewed-by: serb, neugens Contributed-by: alvdavi@amazon.com --- .../native/libfontmanager/freetypeScaler.c | 53 ++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c index 13fc86a6288..b68802f3e37 100644 --- a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c +++ b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c @@ -29,7 +29,10 @@ #include "sunfontids.h" #include "sun_font_FreetypeFontScaler.h" -#include +#include +#if !defined(_WIN32) && !defined(__APPLE_) +#include +#endif #include #include "ft2build.h" #include FT_FREETYPE_H @@ -38,6 +41,7 @@ #include FT_SIZES_H #include FT_OUTLINE_H #include FT_SYNTHESIS_H +#include FT_MODULE_H #include "fontscaler.h" @@ -204,6 +208,52 @@ static unsigned long ReadTTFontFileFunc(FT_Stream stream, } } +typedef FT_Error (*FT_Prop_Set_Func)(FT_Library library, + const FT_String* module_name, + const FT_String* property_name, + const void* value ); + +/** + * Prefer the older v35 freetype byte code interpreter. + */ +static void setInterpreterVersion(FT_Library library) { + + char* props = getenv("FREETYPE_PROPERTIES"); + int version = 35; + const char* module = "truetype"; + const char* property = "interpreter-version"; + + /* If some one is setting this, don't override it */ + if (props != NULL && strstr(property, props)) { + return; + } + /* + * FT_Property_Set was introduced in 2.4.11. + * Some older supported Linux OSes may not include it so look + * this up dynamically. + * And if its not available it doesn't matter, since the reason + * we need it dates from 2.7. + * On Windows & Mac the library is always bundled so it is safe + * to use directly in those cases. + */ +#if defined(_WIN32) || defined(__APPLE__) + FT_Property_Set(library, module, property, (void*)(&version)); +#else + void *lib = dlopen("libfreetype.so", RTLD_LOCAL|RTLD_LAZY); + if (lib == NULL) { + lib = dlopen("libfreetype.so.6", RTLD_LOCAL|RTLD_LAZY); + if (lib == NULL) { + return; + } + } + FT_Prop_Set_Func func = (FT_Prop_Set_Func)dlsym(lib, "FT_Property_Set"); + if (func != NULL) { + func(library, module, property, (void*)(&version)); + } + dlclose(lib); +#endif +} + /* * Class: sun_font_FreetypeFontScaler * Method: initNativeScaler @@ -243,6 +293,7 @@ Java_sun_font_FreetypeFontScaler_initNativeScaler( free(scalerInfo); return 0; } + setInterpreterVersion(scalerInfo->library); #define TYPE1_FROM_JAVA 2 From 21a1eb9c9d2972cc7ba318b27a802c468c68861f Mon Sep 17 00:00:00 2001 From: stuefe Date: Wed, 22 May 2019 09:33:22 +0200 Subject: [PATCH 003/131] 8224193: stringStream should not use Resouce Area Reviewed-by: goetz, coleenp, dholmes --- test/hotspot/gtest/utilities/test_ostream.cpp | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 test/hotspot/gtest/utilities/test_ostream.cpp diff --git a/test/hotspot/gtest/utilities/test_ostream.cpp b/test/hotspot/gtest/utilities/test_ostream.cpp new file mode 100644 index 00000000000..6eff3819274 --- /dev/null +++ b/test/hotspot/gtest/utilities/test_ostream.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * 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. + * + */ + +#include "precompiled.hpp" +#include "memory/resourceArea.hpp" +#include "runtime/os.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/ostream.hpp" + +#include "unittest.hpp" + +static size_t print_lorem(outputStream* st, bool short_len) { + // Create a ResourceMark just to make sure the stream does not use ResourceArea + ResourceMark rm; + static const char* const lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, " + "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lacinia at quis " + "risus sed vulputate odio ut enim blandit. Amet risus nullam eget felis eget. Viverra " + "orci sagittis eu volutpat odio facilisis mauris sit. Erat velit scelerisque in dictum non."; + static const size_t len_lorem = strlen(lorem); + size_t len; + if (short_len) { + len = os::random() % 10; + } else { + len = MAX2(1, (int)(os::random() % len_lorem)); + } + st->write(lorem, len); + return len; +} + +static void do_test_stringStream_dynamic_realloc(bool short_len) { + stringStream ss(2); // small buffer to force lots of reallocations. + size_t written = 0; + for (int i = 0; i < 1000; i ++) { + written += print_lorem(&ss, short_len); + ASSERT_EQ(ss.size(), written); + // Internal buffer should always be zero-terminated. + ASSERT_EQ(ss.base()[ss.size()], '\0'); + } +} + +TEST_VM(ostream, stringStream_dynamic_realloc_1) { + do_test_stringStream_dynamic_realloc(false); +} + +TEST_VM(ostream, stringStream_dynamic_realloc_2) { + do_test_stringStream_dynamic_realloc(true); +} From 1143824a89e307d150beac3527243dcd765594c9 Mon Sep 17 00:00:00 2001 From: ysuenaga Date: Thu, 11 Jul 2019 08:19:56 +0900 Subject: [PATCH 004/131] 8209790: SA tools not providing option to connect to debug server Reviewed-by: sspitsyn, cjplummer --- .../sa/sadebugd/DebugdConnectTest.java | 130 ++++++++++++++++++ .../sa/sadebugd/DebugdUtils.java | 72 ++++++++++ 2 files changed, 202 insertions(+) create mode 100644 test/hotspot/jtreg/serviceability/sa/sadebugd/DebugdConnectTest.java create mode 100644 test/hotspot/jtreg/serviceability/sa/sadebugd/DebugdUtils.java diff --git a/test/hotspot/jtreg/serviceability/sa/sadebugd/DebugdConnectTest.java b/test/hotspot/jtreg/serviceability/sa/sadebugd/DebugdConnectTest.java new file mode 100644 index 00000000000..59a6b98fde3 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/sa/sadebugd/DebugdConnectTest.java @@ -0,0 +1,130 @@ +/* + * 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 8209790 + * @summary Checks ability for connecting to debug server (jstack, jmap, jinfo, jsnap) + * @requires vm.hasSAandCanAttach + * @requires os.family != "windows" + * @modules java.base/jdk.internal.misc + * @library /test/lib + * + * @run main/othervm DebugdConnectTest + */ + +import java.io.IOException; + +import jdk.test.lib.JDKToolLauncher; +import jdk.test.lib.apps.LingeredApp; +import jdk.test.lib.process.OutputAnalyzer; + + +public class DebugdConnectTest { + + private static OutputAnalyzer runJHSDB(String command, String id) throws IOException, InterruptedException { + JDKToolLauncher jhsdbLauncher = JDKToolLauncher.createUsingTestJDK("jhsdb"); + jhsdbLauncher.addToolArg(command); + jhsdbLauncher.addToolArg("--connect"); + if (id != null) { + jhsdbLauncher.addToolArg(id + "@localhost"); + } else { + jhsdbLauncher.addToolArg("localhost"); + } + + Process jhsdb = (new ProcessBuilder(jhsdbLauncher.getCommand())).start(); + OutputAnalyzer out = new OutputAnalyzer(jhsdb); + + jhsdb.waitFor(); + + System.out.println(out.getStdout()); + System.err.println(out.getStderr()); + + return out; + } + + private static void runJSTACK(String id) throws IOException, InterruptedException { + OutputAnalyzer out = runJHSDB("jstack", id); + + out.shouldContain("LingeredApp"); + out.stderrShouldBeEmpty(); + out.shouldHaveExitValue(0); + } + + private static void runJMAP(String id) throws IOException, InterruptedException { + OutputAnalyzer out = runJHSDB("jmap", id); + + out.shouldContain("JVM version is"); + out.stderrShouldBeEmpty(); + out.shouldHaveExitValue(0); + } + + private static void runJINFO(String id) throws IOException, InterruptedException { + OutputAnalyzer out = runJHSDB("jinfo", id); + + out.shouldContain("Java System Properties:"); + out.stderrShouldBeEmpty(); + out.shouldHaveExitValue(0); + } + + private static void runJSNAP(String id) throws IOException, InterruptedException { + OutputAnalyzer out = runJHSDB("jsnap", id); + + out.shouldContain("java.vm.name="); + out.stderrShouldBeEmpty(); + out.shouldHaveExitValue(0); + } + + private static void runTests(String id, long debuggeePid) throws IOException, InterruptedException { + DebugdUtils debugd = new DebugdUtils(id); + debugd.attach(debuggeePid); + + try { + runJSTACK(id); + runJMAP(id); + runJINFO(id); + runJSNAP(id); + } finally { + debugd.detach(); + } + } + + public static void main(String[] args) throws Exception { + LingeredApp app = null; + + try { + app = LingeredApp.startApp(); + System.out.println("Started LingeredApp with pid " + app.getPid()); + + System.out.println("debugd connection test with server id:"); + runTests("test", app.getPid()); + + System.out.println("debugd connection test without server id:"); + runTests(null, app.getPid()); + } finally { + LingeredApp.stopApp(app); + } + + } + +} diff --git a/test/hotspot/jtreg/serviceability/sa/sadebugd/DebugdUtils.java b/test/hotspot/jtreg/serviceability/sa/sadebugd/DebugdUtils.java new file mode 100644 index 00000000000..39bcf023843 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/sa/sadebugd/DebugdUtils.java @@ -0,0 +1,72 @@ +/* + * 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. + */ + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.IOException; + +import jdk.test.lib.JDKToolLauncher; + + +public class DebugdUtils { + + private static final String GOLDEN = "Debugger attached"; + + private final String id; + + private Process debugdProcess; + + public DebugdUtils(String id) { + this.id = id; + debugdProcess = null; + } + + public void attach(long pid) throws IOException { + JDKToolLauncher jhsdbLauncher = JDKToolLauncher.createUsingTestJDK("jhsdb"); + jhsdbLauncher.addToolArg("debugd"); + jhsdbLauncher.addToolArg("--pid"); + jhsdbLauncher.addToolArg(Long.toString(pid)); + if (id != null) { + jhsdbLauncher.addToolArg("--serverid"); + jhsdbLauncher.addToolArg(id); + } + debugdProcess = (new ProcessBuilder(jhsdbLauncher.getCommand())).start(); + + // Wait until debug server attached + try (BufferedReader reader = new BufferedReader(new InputStreamReader(debugdProcess.getErrorStream()))) { + String line; + while ((line = reader.readLine()) != null) { + if (line.contains(GOLDEN)) { + break; + } + } + } + } + + public void detach() throws InterruptedException { + if (debugdProcess != null) { + debugdProcess.destroy(); + debugdProcess.waitFor(); + } + } +} From b60540bd7c77307dac9ab50cbfab16170cbbf623 Mon Sep 17 00:00:00 2001 From: egahlin Date: Mon, 2 Sep 2019 09:56:29 +0200 Subject: [PATCH 005/131] 8205516: JFR tool Reviewed-by: mgronlun --- make/launcher/Launcher-jdk.jfr.gmk | 31 + .../classes/jdk/jfr/ValueDescriptor.java | 2 +- .../classes/jdk/jfr/consumer/ChunkParser.java | 10 +- .../jdk/jfr/consumer/RecordedEvent.java | 3 +- .../jdk/jfr/consumer/RecordedObject.java | 29 +- .../jdk/jfr/consumer/RecordingFile.java | 54 +- .../jdk/jfr/consumer/TimeConverter.java | 23 +- .../jdk/jfr/internal/OldObjectSample.java | 4 +- .../share/classes/jdk/jfr/internal/Type.java | 9 +- .../jfr/internal/consumer/ChunkHeader.java | 2 +- .../internal/consumer/RecordingInternals.java | 47 ++ .../jdk/jfr/internal/tool/Assemble.java | 127 +++++ .../jdk/jfr/internal/tool/Command.java | 306 ++++++++++ .../jdk/jfr/internal/tool/Disassemble.java | 250 ++++++++ .../jfr/internal/tool/EventPrintWriter.java | 139 +++++ .../classes/jdk/jfr/internal/tool/Help.java | 75 +++ .../jdk/jfr/internal/tool/JSONWriter.java | 261 +++++++++ .../classes/jdk/jfr/internal/tool/Main.java | 110 ++++ .../jdk/jfr/internal/tool/Metadata.java | 139 +++++ .../jdk/jfr/internal/tool/PrettyWriter.java | 538 ++++++++++++++++++ .../classes/jdk/jfr/internal/tool/Print.java | 262 +++++++++ .../jfr/internal/tool/StructuredWriter.java | 121 ++++ .../jdk/jfr/internal/tool/Summary.java | 162 ++++++ .../jfr/internal/tool/UserDataException.java | 49 ++ .../internal/tool/UserSyntaxException.java | 45 ++ .../jdk/jfr/internal/tool/Version.java | 50 ++ .../jdk/jfr/internal/tool/XMLWriter.java | 200 +++++++ src/jdk.jfr/share/classes/module-info.java | 6 + .../annotations/TestFormatMissingValue.java | 24 +- test/jdk/jdk/jfr/tool/ExecuteHelper.java | 125 ++++ test/jdk/jdk/jfr/tool/TestAssemble.java | 146 +++++ test/jdk/jdk/jfr/tool/TestDisassemble.java | 126 ++++ test/jdk/jdk/jfr/tool/TestHelp.java | 57 ++ test/jdk/jdk/jfr/tool/TestMetadata.java | 64 +++ test/jdk/jdk/jfr/tool/TestPrint.java | 62 ++ test/jdk/jdk/jfr/tool/TestPrintDefault.java | 54 ++ test/jdk/jdk/jfr/tool/TestPrintJSON.java | 164 ++++++ test/jdk/jdk/jfr/tool/TestPrintXML.java | 261 +++++++++ test/jdk/jdk/jfr/tool/TestSummary.java | 63 ++ test/jdk/jdk/jfr/tool/jfr.xsd | 81 +++ test/jdk/tools/launcher/HelpFlagsTest.java | 2 + test/jdk/tools/launcher/VersionCheck.java | 1 + 42 files changed, 4239 insertions(+), 45 deletions(-) create mode 100644 make/launcher/Launcher-jdk.jfr.gmk create mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInternals.java create mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Assemble.java create mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Command.java create mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Disassemble.java create mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/tool/EventPrintWriter.java create mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Help.java create mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/tool/JSONWriter.java create mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Main.java create mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Metadata.java create mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/tool/PrettyWriter.java create mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Print.java create mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/tool/StructuredWriter.java create mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Summary.java create mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/tool/UserDataException.java create mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/tool/UserSyntaxException.java create mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Version.java create mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/tool/XMLWriter.java create mode 100644 test/jdk/jdk/jfr/tool/ExecuteHelper.java create mode 100644 test/jdk/jdk/jfr/tool/TestAssemble.java create mode 100644 test/jdk/jdk/jfr/tool/TestDisassemble.java create mode 100644 test/jdk/jdk/jfr/tool/TestHelp.java create mode 100644 test/jdk/jdk/jfr/tool/TestMetadata.java create mode 100644 test/jdk/jdk/jfr/tool/TestPrint.java create mode 100644 test/jdk/jdk/jfr/tool/TestPrintDefault.java create mode 100644 test/jdk/jdk/jfr/tool/TestPrintJSON.java create mode 100644 test/jdk/jdk/jfr/tool/TestPrintXML.java create mode 100644 test/jdk/jdk/jfr/tool/TestSummary.java create mode 100644 test/jdk/jdk/jfr/tool/jfr.xsd diff --git a/make/launcher/Launcher-jdk.jfr.gmk b/make/launcher/Launcher-jdk.jfr.gmk new file mode 100644 index 00000000000..f2d504ac373 --- /dev/null +++ b/make/launcher/Launcher-jdk.jfr.gmk @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +include LauncherCommon.gmk + +$(eval $(call SetupBuildLauncher, jfr, \ + MAIN_CLASS := jdk.jfr.internal.tool.Main, \ + CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \ +)) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/ValueDescriptor.java b/src/jdk.jfr/share/classes/jdk/jfr/ValueDescriptor.java index ca4b24839c4..d5ecca9464c 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/ValueDescriptor.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/ValueDescriptor.java @@ -291,7 +291,7 @@ public List getFields() { if (type.isSimpleType()) { return Collections.emptyList(); } - return Collections.unmodifiableList(type.getFields()); + return type.getFields(); } // package private diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/ChunkParser.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/ChunkParser.java index 96319e2f4b4..ee6e00d6ecd 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/ChunkParser.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/ChunkParser.java @@ -53,7 +53,7 @@ final class ChunkParser { private final TimeConverter timeConverter; public ChunkParser(RecordingInput input) throws IOException { - this(new ChunkHeader(input)); + this(new ChunkHeader(input)); } private ChunkParser(ChunkHeader header) throws IOException { @@ -61,7 +61,7 @@ private ChunkParser(ChunkHeader header) throws IOException { this.chunkHeader = header; this.metadata = header.readMetadata(); this.absoluteChunkEnd = header.getEnd(); - this.timeConverter = new TimeConverter(chunkHeader); + this.timeConverter = new TimeConverter(chunkHeader, metadata.getGMTOffset()); ParserFactory factory = new ParserFactory(metadata, timeConverter); LongMap constantPools = factory.getConstantPools(); @@ -114,9 +114,7 @@ private void fillConstantPools(LongMap typeParser, LongMap boolean flush = input.readBoolean(); int poolCount = input.readInt(); Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.TRACE, () -> { - return "New constant pool: startPosition=" + position + - ", size=" + size + ", deltaToNext=" + delta + - ", flush=" + flush + ", poolCount=" + poolCount; + return "New constant pool: startPosition=" + position + ", size=" + size + ", deltaToNext=" + delta + ", flush=" + flush + ", poolCount=" + poolCount; }); for (int i = 0; i < poolCount; i++) { @@ -155,7 +153,7 @@ private void fillConstantPools(LongMap typeParser, LongMap private String getName(long id) { Type type = typeMap.get(id); - return type == null ? ("unknown(" + id +")") : type.getName(); + return type == null ? ("unknown(" + id + ")") : type.getName(); } public Collection getTypes() { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedEvent.java index bbcda7afc93..19691302b8c 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedEvent.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedEvent.java @@ -41,7 +41,8 @@ public final class RecordedEvent extends RecordedObject { private final EventType eventType; private final long startTime; - private final long endTime; + // package private needed for efficient sorting + final long endTime; // package private RecordedEvent(EventType type, List vds, Object[] values, long startTime, long endTime, TimeConverter timeConverter) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java index df1cc224228..5633c6068ce 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java @@ -25,11 +25,11 @@ package jdk.jfr.consumer; -import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.time.Duration; import java.time.Instant; +import java.time.OffsetDateTime; import java.util.List; import java.util.Objects; @@ -37,7 +37,7 @@ import jdk.jfr.Timestamp; import jdk.jfr.ValueDescriptor; import jdk.jfr.internal.PrivateAccess; -import jdk.jfr.internal.cmd.PrettyWriter; +import jdk.jfr.internal.tool.PrettyWriter; /** * A complex data type that consists of one or more fields. @@ -878,20 +878,25 @@ public final RecordedThread getThread(String name) { final public String toString() { StringWriter s = new StringWriter(); PrettyWriter p = new PrettyWriter(new PrintWriter(s)); - try { - if (this instanceof RecordedEvent) { - p.print((RecordedEvent) this); - } else { - p.print(this, ""); - } - - } catch (IOException e) { - // Ignore, should not happen with StringWriter + p.setStackDepth(5); + if (this instanceof RecordedEvent) { + p.print((RecordedEvent) this); + } else { + p.print(this, ""); } - p.flush(); + p.flush(true); return s.toString(); } + // package private for now. Used by EventWriter + OffsetDateTime getOffsetDateTime(String name) { + Instant instant = getInstant(name); + if (instant.equals(Instant.MIN)) { + return OffsetDateTime.MIN; + } + return OffsetDateTime.ofInstant(getInstant(name), timeConverter.getZoneOffset()); + } + private static IllegalArgumentException newIllegalArgumentException(String name, String typeName) { return new IllegalArgumentException("Attempt to get field \"" + name + "\" with illegal data type conversion " + typeName); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java index dde93ed81d8..901f2534a13 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java @@ -32,13 +32,16 @@ import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Collections; import java.util.HashSet; import java.util.List; import jdk.jfr.EventType; import jdk.jfr.internal.MetadataDescriptor; +import jdk.jfr.internal.Type; import jdk.jfr.internal.consumer.ChunkHeader; import jdk.jfr.internal.consumer.RecordingInput; +import jdk.jfr.internal.consumer.RecordingInternals; /** * A recording file. @@ -59,7 +62,29 @@ * @since 9 */ public final class RecordingFile implements Closeable { + static{ + RecordingInternals.INSTANCE = new RecordingInternals() { + public List readTypes(RecordingFile file) throws IOException { + return file.readTypes(); + } + + public boolean isLastEventInChunk(RecordingFile file) { + return file.isLastEventInChunk; + } + + @Override + public Object getOffsetDataTime(RecordedObject event, String name) { + return event.getOffsetDateTime(name); + } + + @Override + public void sort(List events) { + Collections.sort(events, (e1, e2) -> Long.compare(e1.endTime, e2.endTime)); + } + }; + } + private boolean isLastEventInChunk; private final File file; private RecordingInput input; private ChunkParser chunkParser; @@ -98,9 +123,11 @@ public RecordedEvent readEvent() throws IOException { ensureOpen(); throw new EOFException(); } + isLastEventInChunk = false; RecordedEvent event = nextEvent; nextEvent = chunkParser.readEvent(); if (nextEvent == null) { + isLastEventInChunk = true; findNext(); } return event; @@ -129,6 +156,21 @@ public List readEventTypes() throws IOException { ensureOpen(); List types = new ArrayList<>(); HashSet foundIds = new HashSet<>(); + try (RecordingInput ri = new RecordingInput(file)) { + ChunkHeader ch = new ChunkHeader(ri); + aggregateEventTypeForChunk(ch, types, foundIds); + while (!ch.isLastChunk()) { + ch = ch.nextHeader(); + aggregateEventTypeForChunk(ch, types, foundIds); + } + } + return types; + } + + List readTypes() throws IOException { + ensureOpen(); + List types = new ArrayList<>(); + HashSet foundIds = new HashSet<>(); try (RecordingInput ri = new RecordingInput(file)) { ChunkHeader ch = new ChunkHeader(ri); aggregateTypeForChunk(ch, types, foundIds); @@ -140,7 +182,17 @@ public List readEventTypes() throws IOException { return types; } - private static void aggregateTypeForChunk(ChunkHeader ch, List types, HashSet foundIds) throws IOException { + private void aggregateTypeForChunk(ChunkHeader ch, List types, HashSet foundIds) throws IOException { + MetadataDescriptor m = ch.readMetadata(); + for (Type t : m.getTypes()) { + if (!foundIds.contains(t.getId())) { + types.add(t); + foundIds.add(t.getId()); + } + } + } + + private static void aggregateEventTypeForChunk(ChunkHeader ch, List types, HashSet foundIds) throws IOException { MetadataDescriptor m = ch.readMetadata(); for (EventType t : m.getEventTypes()) { if (!foundIds.contains(t.getId())) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/TimeConverter.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/TimeConverter.java index b3b625eb1b4..0397f8a6858 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/TimeConverter.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/TimeConverter.java @@ -25,6 +25,12 @@ package jdk.jfr.consumer; +import java.time.DateTimeException; +import java.time.ZoneOffset; + +import jdk.jfr.internal.LogLevel; +import jdk.jfr.internal.LogTag; +import jdk.jfr.internal.Logger; import jdk.jfr.internal.consumer.ChunkHeader; /** @@ -34,11 +40,22 @@ final class TimeConverter { private final long startTicks; private final long startNanos; private final double divisor; + private final ZoneOffset zoneOffet; - TimeConverter(ChunkHeader chunkHeader) { + TimeConverter(ChunkHeader chunkHeader, int rawOffset) { this.startTicks = chunkHeader.getStartTicks(); this.startNanos = chunkHeader.getStartNanos(); this.divisor = chunkHeader.getTicksPerSecond() / 1000_000_000L; + this.zoneOffet = zoneOfSet(rawOffset); + } + + private ZoneOffset zoneOfSet(int rawOffset) { + try { + return ZoneOffset.ofTotalSeconds(rawOffset / 1000); + } catch (DateTimeException dte) { + Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Could not create ZoneOffset from raw offset " + rawOffset); + } + return ZoneOffset.UTC; } public long convertTimestamp(long ticks) { @@ -48,4 +65,8 @@ public long convertTimestamp(long ticks) { public long convertTimespan(long ticks) { return (long) (ticks / divisor); } + + public ZoneOffset getZoneOffset() { + return zoneOffet; + } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/OldObjectSample.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/OldObjectSample.java index 51e3efc71f8..8ef5355fd32 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/OldObjectSample.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/OldObjectSample.java @@ -24,7 +24,7 @@ public final class OldObjectSample { private static final String OLD_OBJECT_CUTOFF = EVENT_NAME + "#" + Cutoff.NAME; private static final String OLD_OBJECT_ENABLED = EVENT_NAME + "#" + Enabled.NAME; - // Emit if old object is enabled in recoding with cutoff for that recording + // Emit if old object is enabled in recording with cutoff for that recording public static void emit(PlatformRecording recording) { if (isEnabled(recording)) { long nanos = CutoffSetting.parseValueSafe(recording.getSettings().get(OLD_OBJECT_CUTOFF)); @@ -34,7 +34,7 @@ public static void emit(PlatformRecording recording) { } // Emit if old object is enabled for at least one recording, and use the largest - // cutoff for an enabled recoding + // cutoff for an enabled recording public static void emit(List recordings, Boolean pathToGcRoots) { boolean enabled = false; long cutoffNanos = Boolean.TRUE.equals(pathToGcRoots) ? Long.MAX_VALUE : 0L; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/Type.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/Type.java index 967e7e28274..fafd4e7ce09 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/Type.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/Type.java @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -71,7 +72,7 @@ public class Type implements Comparable { private final String name; private final String superType; private final boolean constantPool; - private final ArrayList fields = new ArrayList<>(); + private List fields = new ArrayList<>(); private Boolean simpleType; // calculated lazy private boolean remove = true; private long id; @@ -183,6 +184,10 @@ public String getLogName() { } public List getFields() { + if (fields instanceof ArrayList) { + ((ArrayList) fields).trimToSize(); + fields = Collections.unmodifiableList(fields); + } return fields; } @@ -216,7 +221,7 @@ public void add(ValueDescriptor valueDescriptor) { } void trimFields() { - fields.trimToSize(); + getFields(); } void setAnnotations(List annotations) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java index 9ab1e02297c..fcdf14adf01 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java @@ -161,7 +161,7 @@ public long getSize() { return chunkSize; } - public long getDuration() { + public long getDurationNanos() { return durationNanos; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInternals.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInternals.java new file mode 100644 index 00000000000..34be20f8a09 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/RecordingInternals.java @@ -0,0 +1,47 @@ +/* + * 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. 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. + */ +package jdk.jfr.internal.consumer; + +import java.io.IOException; +import java.util.List; + +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordedObject; +import jdk.jfr.consumer.RecordingFile; +import jdk.jfr.internal.Type; + +public abstract class RecordingInternals { + + public static RecordingInternals INSTANCE; + + public abstract boolean isLastEventInChunk(RecordingFile file); + + public abstract Object getOffsetDataTime(RecordedObject event, String name); + + public abstract List readTypes(RecordingFile file) throws IOException; + + public abstract void sort(List events); + +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Assemble.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Assemble.java new file mode 100644 index 00000000000..44a834d9f86 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Assemble.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +package jdk.jfr.internal.tool; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.nio.channels.FileChannel; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Deque; +import java.util.List; + +final class Assemble extends Command { + + @Override + public String getName() { + return "assemble"; + } + + @Override + public List getOptionSyntax() { + return Collections.singletonList(" "); + } + + @Override + public String getDescription() { + return "Assemble leftover chunks from a disk repository into a recording file"; + } + + @Override + public void displayOptionUsage(PrintStream stream) { + stream.println(" Directory where the repository is located"); + stream.println(); + stream.println(" Name of the recording file (.jfr) to create"); + } + + @Override + public void execute(Deque options) throws UserSyntaxException, UserDataException { + ensureMinArgumentCount(options, 2); + ensureMaxArgumentCount(options, 2); + Path repository = getDirectory(options.pop()); + + Path file = Paths.get(options.pop()); + ensureFileDoesNotExist(file); + ensureJFRFile(file); + + try (FileOutputStream fos = new FileOutputStream(file.toFile())) { + List files = listJFRFiles(repository); + if (files.isEmpty()) { + throw new UserDataException("no *.jfr files found at " + repository); + } + println(); + println("Assembling files... "); + println(); + transferTo(files, file, fos.getChannel()); + println(); + println("Finished."); + } catch (IOException e) { + throw new UserDataException("could not open destination file " + file + ". " + e.getMessage()); + } + } + + private List listJFRFiles(Path path) throws UserDataException { + try { + List files = new ArrayList<>(); + if (Files.isDirectory(path)) { + try (DirectoryStream stream = Files.newDirectoryStream(path, "*.jfr")) { + for (Path p : stream) { + if (!Files.isDirectory(p) && Files.isReadable(p)) { + files.add(p); + } + } + } + } + files.sort((u, v) -> u.getFileName().compareTo(v.getFileName())); + return files; + } catch (IOException ioe) { + throw new UserDataException("could not list *.jfr for directory " + path + ". " + ioe.getMessage()); + } + } + + private void transferTo(List sourceFiles, Path output, FileChannel out) throws UserDataException { + long pos = 0; + for (Path p : sourceFiles) { + println(" " + p.toString()); + try (FileChannel sourceChannel = FileChannel.open(p)) { + long rem = Files.size(p); + while (rem > 0) { + long n = Math.min(rem, 1024 * 1024); + long w = out.transferFrom(sourceChannel, pos, n); + pos += w; + rem -= w; + } + } catch (IOException ioe) { + throw new UserDataException("could not copy recording chunk " + p + " to new file. " + ioe.getMessage()); + } + } + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Command.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Command.java new file mode 100644 index 00000000000..95ac85be6bc --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Command.java @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +package jdk.jfr.internal.tool; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOError; +import java.io.IOException; +import java.io.PrintStream; +import java.io.RandomAccessFile; +import java.nio.file.Files; +import java.nio.file.InvalidPathException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Deque; +import java.util.List; + +abstract class Command { + public final static String title = "Tool for working with Flight Recorder files (.jfr)"; + private final static Command HELP = new Help(); + private final static List COMMANDS = createCommands(); + + private static List createCommands() { + List commands = new ArrayList<>(); + commands.add(new Print()); + commands.add(new Metadata()); + commands.add(new Summary()); + commands.add(new Assemble()); + commands.add(new Disassemble()); + commands.add(new Version()); + commands.add(HELP); + return Collections.unmodifiableList(commands); + } + + static void displayHelp() { + System.out.println(title); + System.out.println(); + displayAvailableCommands(System.out); + } + + abstract public String getName(); + + abstract public String getDescription(); + + abstract public void execute(Deque argList) throws UserSyntaxException, UserDataException; + + protected String getTitle() { + return getDescription(); + } + + static void displayAvailableCommands(PrintStream stream) { + boolean first = true; + for (Command c : Command.COMMANDS) { + if (!first) { + System.out.println(); + } + displayCommand(stream, c); + stream.println(" " + c.getDescription()); + first = false; + } + } + + protected static void displayCommand(PrintStream stream, Command c) { + boolean firstSyntax = true; + String alias = buildAlias(c); + String initial = " jfr " + c.getName(); + for (String syntaxLine : c.getOptionSyntax()) { + if (firstSyntax) { + if (syntaxLine.length() != 0) { + stream.println(initial + " " + syntaxLine + alias); + } else { + stream.println(initial + alias); + } + } else { + for (int i = 0; i < initial.length(); i++) { + stream.print(" "); + } + stream.println(" " + syntaxLine); + } + firstSyntax = false; + } + } + + private static String buildAlias(Command c) { + List aliases = c.getAliases(); + if (aliases.isEmpty()) { + return ""; + } + StringBuilder sb = new StringBuilder(); + if (aliases.size() == 1) { + sb.append(" (alias "); + sb.append(aliases.get(0)); + sb.append(")"); + return sb.toString(); + } + sb.append(" (aliases "); + for (int i = 0; i< aliases.size(); i ++ ) { + sb.append(aliases.get(i)); + if (i < aliases.size() -1) { + sb.append(", "); + } + } + sb.append(")"); + return sb.toString(); + } + + public static List getCommands() { + return COMMANDS; + } + + public static Command valueOf(String commandName) { + for (Command command : COMMANDS) { + if (command.getName().equals(commandName)) { + return command; + } + } + return null; + } + + public List getOptionSyntax() { + return Collections.singletonList(""); + } + + public void displayOptionUsage(PrintStream stream) { + } + + protected boolean acceptOption(Deque options, String expected) throws UserSyntaxException { + if (expected.equals(options.peek())) { + if (options.size() < 2) { + throw new UserSyntaxException("missing value for " + options.peek()); + } + options.remove(); + return true; + } + return false; + } + + protected void warnForWildcardExpansion(String option, String filter) throws UserDataException { + // Users should quote their wildcards to avoid expansion by the shell + try { + if (!filter.contains(File.pathSeparator)) { + Path p = Path.of(".", filter); + if (!Files.exists(p)) { + return; + } + } + throw new UserDataException("wildcards should be quoted, for example " + option + " \"Foo*\""); + } catch (InvalidPathException ipe) { + // ignore + } + } + + protected boolean acceptFilterOption(Deque options, String expected) throws UserSyntaxException { + if (!acceptOption(options, expected)) { + return false; + } + if (options.isEmpty()) { + throw new UserSyntaxException("missing filter after " + expected); + } + String filter = options.peek(); + if (filter.startsWith("--")) { + throw new UserSyntaxException("missing filter after " + expected); + } + return true; + } + + final protected void ensureMaxArgumentCount(Deque options, int maxCount) throws UserSyntaxException { + if (options.size() > maxCount) { + throw new UserSyntaxException("too many arguments"); + } + } + + final protected void ensureMinArgumentCount(Deque options, int minCount) throws UserSyntaxException { + if (options.size() < minCount) { + throw new UserSyntaxException("too few arguments"); + } + } + + final protected Path getDirectory(String pathText) throws UserDataException { + try { + Path path = Paths.get(pathText).toAbsolutePath(); + if (!Files.exists((path))) { + throw new UserDataException("directory does not exist, " + pathText); + } + if (!Files.isDirectory(path)) { + throw new UserDataException("path must be directory, " + pathText); + } + return path; + } catch (InvalidPathException ipe) { + throw new UserDataException("invalid path '" + pathText + "'"); + } + } + + final protected Path getJFRInputFile(Deque options) throws UserSyntaxException, UserDataException { + if (options.isEmpty()) { + throw new UserSyntaxException("missing file"); + } + String file = options.removeLast(); + if (file.startsWith("--")) { + throw new UserSyntaxException("missing file"); + } + try { + Path path = Paths.get(file).toAbsolutePath(); + ensureAccess(path); + ensureJFRFile(path); + return path; + } catch (IOError ioe) { + throw new UserDataException("i/o error reading file '" + file + "', " + ioe.getMessage()); + } catch (InvalidPathException ipe) { + throw new UserDataException("invalid path '" + file + "'"); + } + } + + private void ensureAccess(Path path) throws UserDataException { + try (RandomAccessFile rad = new RandomAccessFile(path.toFile(), "r")) { + if (rad.length() == 0) { + throw new UserDataException("file is empty '" + path + "'"); + } + rad.read(); // try to read 1 byte + } catch (FileNotFoundException e) { + throw new UserDataException("could not find file '" + path + "'"); + } catch (IOException e) { + throw new UserDataException("i/o error reading file '" + path + "', " + e.getMessage()); + } + } + + final protected void couldNotReadError(Path p, IOException e) throws UserDataException { + throw new UserDataException("could not read recording at " + p.toAbsolutePath() + ". " + e.getMessage()); + } + + final protected Path ensureFileDoesNotExist(Path file) throws UserDataException { + if (Files.exists(file)) { + throw new UserDataException("file '" + file + "' already exists"); + } + return file; + } + + final protected void ensureJFRFile(Path path) throws UserDataException { + if (!path.toString().endsWith(".jfr")) { + throw new UserDataException("filename must end with '.jfr'"); + } + } + + protected void displayUsage(PrintStream stream) { + displayCommand(stream, this); + stream.println(); + displayOptionUsage(stream); + } + + final protected void println() { + System.out.println(); + } + + final protected void print(String text) { + System.out.print(text); + } + + final protected void println(String text) { + System.out.println(text); + } + + final protected boolean matches(String command) { + for (String s : getNames()) { + if (s.equals(command)) { + return true; + } + } + return false; + } + + protected List getAliases() { + return Collections.emptyList(); + } + + public List getNames() { + List names = new ArrayList<>(); + names.add(getName()); + names.addAll(getAliases()); + return names; + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Disassemble.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Disassemble.java new file mode 100644 index 00000000000..17ad5d176f1 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Disassemble.java @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +package jdk.jfr.internal.tool; + +import java.io.BufferedInputStream; +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; +import java.nio.file.Files; +import java.nio.file.InvalidPathException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Deque; +import java.util.List; + +import jdk.jfr.internal.consumer.ChunkHeader; +import jdk.jfr.internal.consumer.RecordingInput; + +final class Disassemble extends Command { + + @Override + public String getName() { + return "disassemble"; + } + + @Override + public List getOptionSyntax() { + List list = new ArrayList<>(); + list.add("[--output ]"); + list.add("[--max-chunks ]"); + list.add("[--max-size ]"); + list.add(""); + return list; + } + + @Override + public void displayOptionUsage(PrintStream stream) { + stream.println(" --output The location to write the disassembled file,"); + stream.println(" by default the current directory"); + stream.println(""); + stream.println(" --max-chunks Maximum number of chunks per disassembled file,"); + stream.println(" by default 5. The chunk size varies, but is "); + stream.println(" typically around 15 MB."); + stream.println(""); + stream.println(" --max-size Maximum number of bytes per file."); + stream.println(""); + stream.println(" Location of the recording file (.jfr)"); + } + + @Override + public String getDescription() { + return "Disassamble a recording file into smaller files/chunks"; + } + + @Override + public void execute(Deque options) throws UserSyntaxException, UserDataException { + if (options.isEmpty()) { + throw new UserSyntaxException("missing file"); + } + Path file = getJFRInputFile(options); + int maxChunks = Integer.MAX_VALUE; + int maxsize = Integer.MAX_VALUE; + String output = System.getProperty("user.dir"); + int optionCount = options.size(); + while (optionCount > 0) { + if (acceptOption(options, "--output")) { + output = options.pop(); + } + if (acceptOption(options, "--max-size")) { + String value = options.pop(); + try { + maxsize = Integer.parseInt(value); + if (maxsize < 1) { + throw new UserDataException("max size must be at least 1"); + } + } catch (NumberFormatException nfe) { + throw new UserDataException("not a valid value for --max-size."); + } + } + if (acceptOption(options, "--max-chunks")) { + String value = options.pop(); + try { + maxChunks = Integer.parseInt(value); + if (maxChunks < 1) { + throw new UserDataException("max chunks must be at least 1."); + } + } catch (NumberFormatException nfe) { + throw new UserDataException("not a valid value for --max-size."); + } + } + if (optionCount == options.size()) { + // No progress made + throw new UserSyntaxException("unknown option " + options.peek()); + } + optionCount = options.size(); + } + Path outputPath = getDirectory(output); + + println(); + println("Examining recording " + file + " ..."); + List sizes; + if (maxsize != Integer.MAX_VALUE && maxChunks == Integer.MAX_VALUE) { + try { + long fileSize = Files.size(file); + if (maxsize >=fileSize) { + println(); + println("File size (" + fileSize +") does not exceed max size (" + maxsize + ")"); + return; + } + } catch (IOException e) { + throw new UserDataException("unexpected i/o error when determining file size" + e.getMessage()); + } + } + if (maxsize == Integer.MAX_VALUE && maxChunks == Integer.MAX_VALUE) { + maxChunks = 5; + } + + try { + sizes = findChunkSizes(file); + } catch (IOException e) { + throw new UserDataException("unexpected i/o error. " + e.getMessage()); + } + if (maxsize == Integer.MAX_VALUE == sizes.size() <= maxChunks) { + throw new UserDataException("number of chunks in recording (" + sizes.size() + ") doesn't exceed max chunks (" + maxChunks + ")"); + } + println(); + if (sizes.size() > 0) { + List combinedSizes = combineChunkSizes(sizes, maxChunks, maxsize); + print("File consists of " + sizes.size() + " chunks. The recording will be split into "); + println(combinedSizes.size() + " files"); + println(); + splitFile(outputPath, file, combinedSizes); + } else { + throw new UserDataException("no JFR chunks found in file."); + } + } + + private List findChunkSizes(Path p) throws IOException { + try (RecordingInput input = new RecordingInput(p.toFile())) { + List sizes = new ArrayList<>(); + ChunkHeader ch = new ChunkHeader(input); + sizes.add(ch.getSize()); + while (!ch.isLastChunk()) { + ch = ch.nextHeader(); + sizes.add(ch.getSize()); + } + return sizes; + } + } + + private List combineChunkSizes(List sizes, int maxChunks, long maxSize) { + List reduced = new ArrayList(); + int chunks = 1; + long fileSize = sizes.get(0); + for (int i = 1; i < sizes.size(); i++) { + long size = sizes.get(i); + if (fileSize + size > maxSize) { + reduced.add(fileSize); + chunks = 1; + fileSize = size; + continue; + } + fileSize += size; + if (chunks == maxChunks) { + reduced.add(fileSize); + fileSize = 0; + chunks = 1; + continue; + } + chunks++; + } + if (fileSize != 0) { + reduced.add(fileSize); + } + return reduced; + } + + private void splitFile(Path directory, Path file, List splitPositions) throws UserDataException { + int padAmountZeros = String.valueOf(splitPositions.size() - 1).length(); + String fileName = file.getFileName().toString(); + String fileFormatter = fileName.subSequence(0, fileName.length() - 4) + "_%0" + padAmountZeros + "d.jfr"; + for (int i = 0; i < splitPositions.size(); i++) { + String formattedFilename = String.format(fileFormatter, i); + try { + Path p = directory.resolve(formattedFilename); + if (Files.exists(p)) { + throw new UserDataException("can't create disassembled file " + p + ", a file with that name already exist"); + } + } catch (InvalidPathException ipe) { + throw new UserDataException("can't construct path with filename" + formattedFilename); + } + } + + try (DataInputStream stream = new DataInputStream(new BufferedInputStream(new FileInputStream(file.toFile())))) { + for (int i = 0; i < splitPositions.size(); i++) { + Long l = splitPositions.get(i); + byte[] bytes = readBytes(stream, l.intValue()); + String formattedFilename = String.format(fileFormatter, i); + Path p = directory.resolve(formattedFilename); + File splittedFile = p.toFile(); + println("Writing " + splittedFile + " ... " + bytes.length); + FileOutputStream fos = new FileOutputStream(splittedFile); + fos.write(bytes); + fos.close(); + } + } catch (IOException ioe) { + throw new UserDataException("i/o error writing file " + file); + } + } + + private byte[] readBytes(InputStream stream, int count) throws UserDataException, IOException { + byte[] data = new byte[count]; + int totalRead = 0; + while (totalRead < data.length) { + int read = stream.read(data, totalRead, data.length - totalRead); + if (read == -1) { + throw new UserDataException("unexpected end of data"); + } + totalRead += read; + } + return data; + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/EventPrintWriter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/EventPrintWriter.java new file mode 100644 index 00000000000..546f48117d7 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/EventPrintWriter.java @@ -0,0 +1,139 @@ +/* + * 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. 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. + */ + +package jdk.jfr.internal.tool; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; + +import jdk.jfr.EventType; +import jdk.jfr.Timespan; +import jdk.jfr.Timestamp; +import jdk.jfr.ValueDescriptor; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordedObject; +import jdk.jfr.consumer.RecordingFile; +import jdk.jfr.internal.consumer.RecordingInternals; + +abstract class EventPrintWriter extends StructuredWriter { + + enum ValueType { + TIMESPAN, TIMESTAMP, OTHER + } + + protected static final String STACK_TRACE_FIELD = "stackTrace"; + protected static final String EVENT_THREAD_FIELD = "eventThread"; + + private Predicate eventFilter = x -> true; + private int stackDepth; + + // cach that will speed up annotation lookup + private Map typeOfValues = new HashMap<>(); + + EventPrintWriter(PrintWriter p) { + super(p); + } + + abstract protected void print(List events); + + void print(Path source) throws FileNotFoundException, IOException { + List events = new ArrayList<>(500_000); + printBegin(); + try (RecordingFile file = new RecordingFile(source)) { + while (file.hasMoreEvents()) { + RecordedEvent event = file.readEvent(); + if (acceptEvent(event)) { + events.add(event); + } + if (RecordingInternals.INSTANCE.isLastEventInChunk(file)) { + RecordingInternals.INSTANCE.sort(events); + print(events); + events.clear(); + } + } + } + printEnd(); + flush(true); + } + + protected void printEnd() { + } + + protected void printBegin() { + } + + public final void setEventFilter(Predicate eventFilter) { + this.eventFilter = eventFilter; + } + + protected final boolean acceptEvent(RecordedEvent event) { + return eventFilter.test(event.getEventType()); + } + + protected final int getStackDepth() { + return stackDepth; + } + + protected final boolean isLateField(String name) { + return name.equals(EVENT_THREAD_FIELD) || name.equals(STACK_TRACE_FIELD); + } + + public void setStackDepth(int stackDepth) { + this.stackDepth = stackDepth; + } + + protected Object getValue(RecordedObject object, ValueDescriptor v) { + ValueType valueType = typeOfValues.get(v); + if (valueType == null) { + valueType = determineValueType(v); + typeOfValues.put(v, valueType); + } + switch (valueType) { + case TIMESPAN: + return object.getDuration(v.getName()); + case TIMESTAMP: + return RecordingInternals.INSTANCE.getOffsetDataTime(object, v.getName()); + default: + return object.getValue(v.getName()); + } + } + // It's expensive t check + private ValueType determineValueType(ValueDescriptor v) { + if (v.getAnnotation(Timespan.class) != null) { + return ValueType.TIMESPAN; + } + if (v.getAnnotation(Timestamp.class) != null) { + return ValueType.TIMESTAMP; + } + return ValueType.OTHER; + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Help.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Help.java new file mode 100644 index 00000000000..42e840e8b8a --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Help.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +package jdk.jfr.internal.tool; + +import java.io.PrintStream; +import java.util.Collections; +import java.util.Deque; +import java.util.List; + +final class Help extends Command { + + @Override + public String getName() { + return "help"; + } + + @Override + public List getOptionSyntax() { + return Collections.singletonList("[]"); + } + + protected List getAliases() { + return List.of("--help", "-h", "-?"); + } + + @Override + public void displayOptionUsage(PrintStream stream) { + println(" The name of the command to get help for"); + } + + @Override + public String getDescription() { + return "Display all available commands, or help about a specific command"; + } + + @Override + public void execute(Deque options) throws UserSyntaxException, UserDataException { + if (options.isEmpty()) { + Command.displayHelp(); + return; + } + ensureMaxArgumentCount(options, 1); + String commandName = options.remove(); + Command c = Command.valueOf(commandName); + if (c == null) { + throw new UserDataException("unknown command '" + commandName + "'"); + } + println(c.getTitle()); + println(); + c.displayUsage(System.out); + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/JSONWriter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/JSONWriter.java new file mode 100644 index 00000000000..0e008c87325 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/JSONWriter.java @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +package jdk.jfr.internal.tool; + +import java.io.PrintWriter; +import java.util.List; + +import jdk.jfr.EventType; +import jdk.jfr.ValueDescriptor; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordedFrame; +import jdk.jfr.consumer.RecordedObject; + +final class JSONWriter extends EventPrintWriter { + + private boolean first = true; + + public JSONWriter(PrintWriter writer) { + super(writer); + } + + @Override + protected void printBegin() { + printObjectBegin(); + printDataStructureName("recording"); + printObjectBegin(); + printDataStructureName("events"); + printArrayBegin(); + } + + @Override + protected void print(List events) { + for (RecordedEvent event : events) { + printNewDataStructure(first, true, null); + printEvent(event); + flush(false); + first = false; + } + } + + @Override + protected void printEnd() { + printArrayEnd();; + printObjectEnd(); + printObjectEnd(); + } + + private void printEvent(RecordedEvent event) { + printObjectBegin(); + EventType type = event.getEventType(); + printValue(true, false, "type", type.getName()); + printNewDataStructure(false, false, "values"); + printObjectBegin(); + boolean first = true; + for (ValueDescriptor v : event.getFields()) { + printValueDescriptor(first, false, v, getValue(event, v)); + first = false; + } + printObjectEnd(); + printObjectEnd(); + } + + void printValue(boolean first, boolean arrayElement, String name, Object value) { + printNewDataStructure(first, arrayElement, name); + if (!printIfNull(value)) { + if (value instanceof Boolean) { + printAsString(value); + return; + } + if (value instanceof Double) { + Double dValue = (Double) value; + if (Double.isNaN(dValue) || Double.isInfinite(dValue)) { + printNull(); + return; + } + printAsString(value); + return; + } + if (value instanceof Float) { + Float fValue = (Float) value; + if (Float.isNaN(fValue) || Float.isInfinite(fValue)) { + printNull(); + return; + } + printAsString(value); + return; + } + if (value instanceof Number) { + printAsString(value); + return; + } + print("\""); + printEscaped(String.valueOf(value)); + print("\""); + } + } + + public void printObject(RecordedObject object) { + printObjectBegin(); + boolean first = true; + for (ValueDescriptor v : object.getFields()) { + printValueDescriptor(first, false, v, getValue(object, v)); + first = false; + } + printObjectEnd(); + } + + private void printArray(ValueDescriptor v, Object[] array) { + printArrayBegin(); + boolean first = true; + int depth = 0; + for (Object arrayElement : array) { + if (!(arrayElement instanceof RecordedFrame) || depth < getStackDepth()) { + printValueDescriptor(first, true, v, arrayElement); + } + depth++; + first = false; + } + printArrayEnd(); + } + + private void printValueDescriptor(boolean first, boolean arrayElement, ValueDescriptor vd, Object value) { + if (vd.isArray() && !arrayElement) { + printNewDataStructure(first, arrayElement, vd.getName()); + if (!printIfNull(value)) { + printArray(vd, (Object[]) value); + } + return; + } + if (!vd.getFields().isEmpty()) { + printNewDataStructure(first, arrayElement, vd.getName()); + if (!printIfNull(value)) { + printObject((RecordedObject) value); + } + return; + } + printValue(first, arrayElement, vd.getName(), value); + } + + private void printNewDataStructure(boolean first, boolean arrayElement, String name) { + if (!first) { + print(", "); + if (!arrayElement) { + println(); + } + } + if (!arrayElement) { + printDataStructureName(name); + } + } + + private boolean printIfNull(Object value) { + if (value == null) { + printNull(); + return true; + } + return false; + } + + private void printNull() { + print("null"); + } + + private void printDataStructureName(String text) { + printIndent(); + print("\""); + print(text); + print("\": "); + } + + private void printObjectEnd() { + retract(); + println(); + printIndent(); + print("}"); + } + + private void printObjectBegin() { + println("{"); + indent(); + } + + private void printArrayEnd() { + print("]"); + } + + private void printArrayBegin() { + print("["); + } + + private void printEscaped(String text) { + for (int i = 0; i < text.length(); i++) { + printEscaped(text.charAt(i)); + } + } + + private void printEscaped(char c) { + if (c == '\b') { + print("\\b"); + return; + } + if (c == '\n') { + print("\\n"); + return; + } + if (c == '\t') { + print("\\t"); + return; + } + if (c == '\f') { + print("\\f"); + return; + } + if (c == '\r') { + print("\\r"); + return; + } + if (c == '\"') { + print("\\\""); + return; + } + if (c == '\\') { + print("\\\\"); + return; + } + if (c == '/') { + print("\\/"); + return; + } + if (c > 0x7F || c < 32) { + print("\\u"); + // 0x10000 will pad with zeros. + print(Integer.toHexString(0x10000 + (int) c).substring(1)); + return; + } + print(c); + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Main.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Main.java new file mode 100644 index 00000000000..5324bafb822 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Main.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +package jdk.jfr.internal.tool; + +import java.util.Arrays; +import java.util.Deque; +import java.util.LinkedList; + +/** + * Launcher class for the JDK_HOME\bin\jfr tool + * + */ +public final class Main { + + private static final int EXIT_OK = 0; + private static final int EXIT_FAILED = 1; + private static final int EXIT_WRONG_ARGUMENTS = 2; + + public static void main(String... args) { + Deque argList = new LinkedList<>(Arrays.asList(args)); + if (argList.isEmpty()) { + System.out.println(Command.title); + System.out.println(); + System.out.println("Before using this tool, you must have a recording file."); + System.out.println("A file can be created by starting a recording from command line:"); + System.out.println(); + System.out.println(" java -XX:StartFlightRecording:filename=recording.jfr,duration=30s ... "); + System.out.println(); + System.out.println("A recording can also be started on already running Java Virtual Machine:"); + System.out.println(); + System.out.println(" jcmd (to list available pids)"); + System.out.println(" jcmd JFR.start"); + System.out.println(); + System.out.println("Recording data can be dumped to file using the JFR.dump command:"); + System.out.println(); + System.out.println(" jcmd JFR.dump filename=recording.jfr"); + System.out.println(); + System.out.println("The contents of the recording can then be printed, for example:"); + System.out.println(); + System.out.println(" jfr print recording.jfr"); + System.out.println(); + System.out.println(" jfr print --events CPULoad,GarbageCollection recording.jfr"); + System.out.println(); + System.out.println(" jfr print --json --events CPULoad recording.jfr"); + System.out.println(); + System.out.println(" jfr print --categories \"GC,JVM,Java*\" recording.jfr"); + System.out.println(); + System.out.println(" jfr print --events \"jdk.*\" --stack-depth 64 recording.jfr"); + System.out.println(); + System.out.println(" jfr summary recording.jfr"); + System.out.println(); + System.out.println(" jfr metadata recoding.jfr"); + System.out.println(); + System.out.println("For more information about available commands, use 'jfr help'"); + System.exit(EXIT_OK); + } + String command = argList.remove(); + for (Command c : Command.getCommands()) { + if (c.matches(command)) { + try { + c.execute(argList); + System.exit(EXIT_OK); + } catch (UserDataException ude) { + System.err.println("jfr " + c.getName() + ": " + ude.getMessage()); + System.exit(EXIT_FAILED); + } catch (UserSyntaxException use) { + System.err.println("jfr " + c.getName() + ": " + use.getMessage()); + System.err.println(); + System.err.println("Usage:"); + System.err.println(); + c.displayUsage(System.err); + System.exit(EXIT_WRONG_ARGUMENTS); + } catch (Throwable e) { + System.err.println("jfr " + c.getName() + ": unexpected internal error, " + e.getMessage()); + e.printStackTrace(); + System.exit(EXIT_FAILED); + } + } + } + System.err.println("jfr: unknown command '" + command + "'"); + System.err.println(); + System.err.println("List of available commands:"); + System.err.println(); + Command.displayAvailableCommands(System.err); + System.exit(EXIT_WRONG_ARGUMENTS); + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Metadata.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Metadata.java new file mode 100644 index 00000000000..44c989c6ee0 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Metadata.java @@ -0,0 +1,139 @@ +/* + * 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. 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. + */ + +package jdk.jfr.internal.tool; + +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.file.Path; +import java.util.Collections; +import java.util.Comparator; +import java.util.Deque; +import java.util.List; + +import jdk.jfr.consumer.RecordingFile; +import jdk.jfr.internal.Type; +import jdk.jfr.internal.consumer.RecordingInternals; + +final class Metadata extends Command { + + private static class TypeComparator implements Comparator { + + @Override + public int compare(Type t1, Type t2) { + int g1 = groupValue(t1); + int g2 = groupValue(t2); + if (g1 == g2) { + String n1 = t1.getName(); + String n2 = t2.getName(); + String package1 = n1.substring(0, n1.lastIndexOf('.') + 1); + String package2 = n2.substring(0, n2.lastIndexOf('.') + 1); + + if (package1.equals(package2)) { + return n1.compareTo(n2); + } else { + // Ensure that jdk.* are printed first + // This makes it easier to find user defined events at the end. + if (Type.SUPER_TYPE_EVENT.equals(t1.getSuperType()) && !package1.equals(package2)) { + if (package1.equals("jdk.jfr")) { + return -1; + } + if (package2.equals("jdk.jfr")) { + return 1; + } + } + return package1.compareTo(package2); + } + } else { + return Integer.compare(groupValue(t1), groupValue(t2)); + } + } + + int groupValue(Type t) { + String superType = t.getSuperType(); + if (superType == null) { + return 1; + } + if (Type.SUPER_TYPE_ANNOTATION.equals(superType)) { + return 3; + } + if (Type.SUPER_TYPE_SETTING.equals(superType)) { + return 4; + } + if (Type.SUPER_TYPE_EVENT.equals(superType)) { + return 5; + } + return 2; // reserved for enums in the future + } + } + + @Override + public String getName() { + return "metadata"; + } + + @Override + public List getOptionSyntax() { + return Collections.singletonList(""); + } + + @Override + public String getDescription() { + return "Display event metadata, such as labels, descriptions and field layout"; + } + + @Override + public void execute(Deque options) throws UserSyntaxException, UserDataException { + Path file = getJFRInputFile(options); + + boolean showIds = false; + int optionCount = options.size(); + while (optionCount > 0) { + if (acceptOption(options, "--ids")) { + showIds = true; + } + if (optionCount == options.size()) { + // No progress made + throw new UserSyntaxException("unknown option " + options.peek()); + } + optionCount = options.size(); + } + + try (PrintWriter pw = new PrintWriter(System.out)) { + PrettyWriter prettyWriter = new PrettyWriter(pw); + prettyWriter.setShowIds(showIds); + try (RecordingFile rf = new RecordingFile(file)) { + List types = RecordingInternals.INSTANCE.readTypes(rf); + Collections.sort(types, new TypeComparator()); + for (Type type : types) { + prettyWriter.printType(type); + } + prettyWriter.flush(true); + } catch (IOException ioe) { + couldNotReadError(file, ioe); + } + } + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/PrettyWriter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/PrettyWriter.java new file mode 100644 index 00000000000..1575acea1b8 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/PrettyWriter.java @@ -0,0 +1,538 @@ +/* + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +package jdk.jfr.internal.tool; + +import java.io.PrintWriter; +import java.time.Duration; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.StringJoiner; + +import jdk.jfr.AnnotationElement; +import jdk.jfr.DataAmount; +import jdk.jfr.Frequency; +import jdk.jfr.MemoryAddress; +import jdk.jfr.Percentage; +import jdk.jfr.ValueDescriptor; +import jdk.jfr.consumer.RecordedClass; +import jdk.jfr.consumer.RecordedClassLoader; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordedFrame; +import jdk.jfr.consumer.RecordedMethod; +import jdk.jfr.consumer.RecordedObject; +import jdk.jfr.consumer.RecordedStackTrace; +import jdk.jfr.consumer.RecordedThread; +import jdk.jfr.internal.PrivateAccess; +import jdk.jfr.internal.Type; +import jdk.jfr.internal.Utils; + +/** + * Print events in a human-readable format. + * + * This class is also used by {@link RecordedObject#toString()} + */ +public final class PrettyWriter extends EventPrintWriter { + private final static DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("HH:mm:ss.SSS"); + private final static Long ZERO = 0L; + private boolean showIds; + + public PrettyWriter(PrintWriter destination) { + super(destination); + } + + @Override + protected void print(List events) { + for (RecordedEvent e : events) { + print(e); + flush(false); + } + } + + public void printType(Type t) { + if (showIds) { + print("// id: "); + println(String.valueOf(t.getId())); + } + int commentIndex = t.getName().length() + 10; + String typeName = t.getName(); + int index = typeName.lastIndexOf("."); + if (index != -1) { + println("@Name(\"" + typeName + "\")"); + } + printAnnotations(commentIndex, t.getAnnotationElements()); + print("class " + typeName.substring(index + 1)); + String superType = t.getSuperType(); + if (superType != null) { + print(" extends " + superType); + } + println(" {"); + indent(); + boolean first = true; + for (ValueDescriptor v : t.getFields()) { + printField(commentIndex, v, first); + first = false; + } + retract(); + println("}"); + println(); + } + + private void printField(int commentIndex, ValueDescriptor v, boolean first) { + if (!first) { + println(); + } + printAnnotations(commentIndex, v.getAnnotationElements()); + printIndent(); + Type vType = PrivateAccess.getInstance().getType(v); + if (Type.SUPER_TYPE_SETTING.equals(vType.getSuperType())) { + print("static "); + } + print(makeSimpleType(v.getTypeName())); + if (v.isArray()) { + print("[]"); + } + print(" "); + print(v.getName()); + print(";"); + printCommentRef(commentIndex, v.getTypeId()); + } + + private void printCommentRef(int commentIndex, long typeId) { + if (showIds) { + int column = getColumn(); + if (column > commentIndex) { + print(" "); + } else { + while (column < commentIndex) { + print(" "); + column++; + } + } + println(" // id=" + typeId); + } else { + println(); + } + } + + private void printAnnotations(int commentIndex, List annotations) { + for (AnnotationElement a : annotations) { + printIndent(); + print("@"); + print(makeSimpleType(a.getTypeName())); + List vs = a.getValueDescriptors(); + if (!vs.isEmpty()) { + printAnnotation(a); + printCommentRef(commentIndex, a.getTypeId()); + } else { + println(); + } + } + } + + private void printAnnotation(AnnotationElement a) { + StringJoiner sj = new StringJoiner(", ", "(", ")"); + List vs = a.getValueDescriptors(); + for (ValueDescriptor v : vs) { + Object o = a.getValue(v.getName()); + if (vs.size() == 1 && v.getName().equals("value")) { + sj.add(textify(o)); + } else { + sj.add(v.getName() + "=" + textify(o)); + } + } + print(sj.toString()); + } + + private String textify(Object o) { + if (o.getClass().isArray()) { + Object[] array = (Object[]) o; + if (array.length == 1) { + return quoteIfNeeded(array[0]); + } + StringJoiner s = new StringJoiner(", ", "{", "}"); + for (Object ob : array) { + s.add(quoteIfNeeded(ob)); + } + return s.toString(); + } else { + return quoteIfNeeded(o); + } + } + + private String quoteIfNeeded(Object o) { + if (o instanceof String) { + return "\"" + o + "\""; + } else { + return String.valueOf(o); + } + } + + private String makeSimpleType(String typeName) { + int index = typeName.lastIndexOf("."); + return typeName.substring(index + 1); + } + + public void print(RecordedEvent event) { + print(event.getEventType().getName(), " "); + println("{"); + indent(); + for (ValueDescriptor v : event.getFields()) { + String name = v.getName(); + if (!isZeroDuration(event, name) && !isLateField(name)) { + printFieldValue(event, v); + } + } + if (event.getThread() != null) { + printIndent(); + print(EVENT_THREAD_FIELD + " = "); + printThread(event.getThread(), ""); + } + if (event.getStackTrace() != null) { + printIndent(); + print(STACK_TRACE_FIELD + " = "); + printStackTrace(event.getStackTrace()); + } + retract(); + printIndent(); + println("}"); + println(); + } + + private boolean isZeroDuration(RecordedEvent event, String name) { + return name.equals("duration") && ZERO.equals(event.getValue("duration")); + } + + private void printStackTrace(RecordedStackTrace stackTrace) { + println("["); + List frames = stackTrace.getFrames(); + indent(); + int i = 0; + while (i < frames.size() && i < getStackDepth()) { + RecordedFrame frame = frames.get(i); + if (frame.isJavaFrame()) { + printIndent(); + printValue(frame, null, ""); + println(); + i++; + } + } + if (stackTrace.isTruncated() || i == getStackDepth()) { + printIndent(); + println("..."); + } + retract(); + printIndent(); + println("]"); + } + + public void print(RecordedObject struct, String postFix) { + println("{"); + indent(); + for (ValueDescriptor v : struct.getFields()) { + printFieldValue(struct, v); + } + retract(); + printIndent(); + println("}" + postFix); + } + + private void printFieldValue(RecordedObject struct, ValueDescriptor v) { + printIndent(); + print(v.getName(), " = "); + printValue(getValue(struct, v), v, ""); + } + + private void printArray(Object[] array) { + println("["); + indent(); + for (int i = 0; i < array.length; i++) { + printIndent(); + printValue(array[i], null, i + 1 < array.length ? ", " : ""); + } + retract(); + printIndent(); + println("]"); + } + + private void printValue(Object value, ValueDescriptor field, String postFix) { + if (value == null) { + println("N/A" + postFix); + return; + } + if (value instanceof RecordedObject) { + if (value instanceof RecordedThread) { + printThread((RecordedThread) value, postFix); + return; + } + if (value instanceof RecordedClass) { + printClass((RecordedClass) value, postFix); + return; + } + if (value instanceof RecordedClassLoader) { + printClassLoader((RecordedClassLoader) value, postFix); + return; + } + if (value instanceof RecordedFrame) { + RecordedFrame frame = (RecordedFrame) value; + if (frame.isJavaFrame()) { + printJavaFrame((RecordedFrame) value, postFix); + return; + } + } + if (value instanceof RecordedMethod) { + println(formatMethod((RecordedMethod) value)); + return; + } + print((RecordedObject) value, postFix); + return; + } + if (value.getClass().isArray()) { + printArray((Object[]) value); + return; + } + if (value instanceof Double) { + Double d = (Double) value; + if (Double.isNaN(d) || d == Double.NEGATIVE_INFINITY) { + println("N/A"); + return; + } + } + if (value instanceof Float) { + Float f = (Float) value; + if (Float.isNaN(f) || f == Float.NEGATIVE_INFINITY) { + println("N/A"); + return; + } + } + if (value instanceof Long) { + Long l = (Long) value; + if (l == Long.MIN_VALUE) { + println("N/A"); + return; + } + } + if (value instanceof Integer) { + Integer i = (Integer) value; + if (i == Integer.MIN_VALUE) { + println("N/A"); + return; + } + } + + if (field.getContentType() != null) { + if (printFormatted(field, value)) { + return; + } + } + String text = String.valueOf(value); + if (value instanceof String) { + text = "\"" + text + "\""; + } + println(text); + } + + private void printClassLoader(RecordedClassLoader cl, String postFix) { + // Purposely not printing class loader name to avoid cluttered output + RecordedClass clazz = cl.getType(); + print(clazz == null ? "null" : clazz.getName()); + if (clazz != null) { + print(" ("); + print("id = "); + print(String.valueOf(cl.getId())); + println(")"); + } + } + + private void printJavaFrame(RecordedFrame f, String postFix) { + print(formatMethod(f.getMethod())); + int line = f.getLineNumber(); + if (line >= 0) { + print(" line: " + line); + } + print(postFix); + } + + private String formatMethod(RecordedMethod m) { + StringBuilder sb = new StringBuilder(); + sb.append(m.getType().getName()); + sb.append("."); + sb.append(m.getName()); + sb.append("("); + StringJoiner sj = new StringJoiner(", "); + String md = m.getDescriptor().replace("/", "."); + String parameter = md.substring(1, md.lastIndexOf(")")); + for (String qualifiedName : decodeDescriptors(parameter)) { + String typeName = qualifiedName.substring(qualifiedName.lastIndexOf('.') + 1); + sj.add(typeName); + } + sb.append(sj); + sb.append(")"); + return sb.toString(); + } + + private void printClass(RecordedClass clazz, String postFix) { + RecordedClassLoader classLoader = clazz.getClassLoader(); + String classLoaderName = "null"; + if (classLoader != null) { + if (classLoader.getName() != null) { + classLoaderName = classLoader.getName(); + } else { + classLoaderName = classLoader.getType().getName(); + } + } + String className = clazz.getName(); + if (className.startsWith("[")) { + className = decodeDescriptors(className).get(0); + } + println(className + " (classLoader = " + classLoaderName + ")" + postFix); + } + + List decodeDescriptors(String descriptor) { + List descriptors = new ArrayList<>(); + for (int index = 0; index < descriptor.length(); index++) { + String arrayBrackets = ""; + while (descriptor.charAt(index) == '[') { + arrayBrackets += "[]"; + index++; + } + char c = descriptor.charAt(index); + String type; + switch (c) { + case 'L': + int endIndex = descriptor.indexOf(';', index); + type = descriptor.substring(index + 1, endIndex); + index = endIndex; + break; + case 'I': + type = "int"; + break; + case 'J': + type = "long"; + break; + case 'Z': + type = "boolean"; + break; + case 'D': + type = "double"; + break; + case 'F': + type = "float"; + break; + case 'S': + type = "short"; + break; + case 'C': + type = "char"; + break; + case 'B': + type = "byte"; + break; + default: + type = ""; + } + descriptors.add(type + arrayBrackets); + } + return descriptors; + } + + private void printThread(RecordedThread thread, String postFix) { + long javaThreadId = thread.getJavaThreadId(); + if (javaThreadId > 0) { + println("\"" + thread.getJavaName() + "\" (javaThreadId = " + thread.getJavaThreadId() + ")" + postFix); + } else { + println("\"" + thread.getOSName() + "\" (osThreadId = " + thread.getOSThreadId() + ")" + postFix); + } + } + + private boolean printFormatted(ValueDescriptor field, Object value) { + if (value instanceof Duration) { + Duration d = (Duration) value; + if (d.getSeconds() == Long.MIN_VALUE) { + println("N/A"); + return true; + } + double s = d.toNanosPart() / 1000_000_000.0 + d.toSecondsPart(); + if (s < 1.0) { + if (s < 0.001) { + println(String.format("%.3f", s * 1_000_000) + " us"); + } else { + println(String.format("%.3f", s * 1_000) + " ms"); + } + } else { + if (s < 1000.0) { + println(String.format("%.3f", s) + " s"); + } else { + println(String.format("%.0f", s) + " s"); + } + } + return true; + } + if (value instanceof OffsetDateTime) { + OffsetDateTime odt = (OffsetDateTime) value; + if (odt.equals(OffsetDateTime.MIN)) { + println("N/A"); + return true; + } + println(TIME_FORMAT.format(odt)); + return true; + } + Percentage percentage = field.getAnnotation(Percentage.class); + if (percentage != null) { + if (value instanceof Number) { + double d = ((Number) value).doubleValue(); + println(String.format("%.2f", d * 100) + "%"); + return true; + } + } + DataAmount dataAmount = field.getAnnotation(DataAmount.class); + if (dataAmount != null) { + if (value instanceof Number) { + Number n = (Number) value; + String bytes = Utils.formatBytes(n.longValue()); + if (field.getAnnotation(Frequency.class) != null) { + bytes += "/s"; + } + println(bytes); + return true; + } + } + MemoryAddress memoryAddress = field.getAnnotation(MemoryAddress.class); + if (memoryAddress != null) { + if (value instanceof Number) { + long d = ((Number) value).longValue(); + println(String.format("0x%08X", d)); + return true; + } + } + return false; + } + + public void setShowIds(boolean showIds) { + this.showIds = showIds; + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Print.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Print.java new file mode 100644 index 00000000000..1f9294c7dc6 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Print.java @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +package jdk.jfr.internal.tool; + +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Deque; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.function.Predicate; + +import jdk.jfr.EventType; + +final class Print extends Command { + @Override + public String getName() { + return "print"; + } + + @Override + public List getOptionSyntax() { + List list = new ArrayList<>(); + list.add("[--xml|--json]"); + list.add("[--categories ]"); + list.add("[--events ]"); + list.add("[--stack-depth ]"); + list.add(""); + return list; + } + + @Override + protected String getTitle() { + return "Print contents of a recording file"; + } + + @Override + public String getDescription() { + return getTitle() + ". See 'jfr help print' for details."; + } + + @Override + public void displayOptionUsage(PrintStream stream) { + stream.println(" --xml Print recording in XML format"); + stream.println(); + stream.println(" --json Print recording in JSON format"); + stream.println(); + stream.println(" --categories Select events matching a category name."); + stream.println(" The filter is a comma-separated list of names,"); + stream.println(" simple and/or qualified, and/or quoted glob patterns"); + stream.println(); + stream.println(" --events Select events matching an event name."); + stream.println(" The filter is a comma-separated list of names,"); + stream.println(" simple and/or qualified, and/or quoted glob patterns"); + stream.println(); + stream.println(" --stack-depth Number of frames in stack traces, by default 5"); + stream.println(); + stream.println(" Location of the recording file (.jfr)"); + stream.println(); + stream.println(); + stream.println("Example usage:"); + stream.println(); + stream.println(" jfr print --events OldObjectSample recording.jfr"); + stream.println(); + stream.println(" jfr print --events CPULoad,GarbageCollection recording.jfr"); + stream.println(); + stream.println(" jfr print --categories \"GC,JVM,Java*\" recording.jfr"); + stream.println(); + stream.println(" jfr print --events \"jdk.*\" --stack-depth 64 recording.jfr"); + stream.println(); + stream.println(" jfr print --json --events CPULoad recording.jfr"); + } + + @Override + public void execute(Deque options) throws UserSyntaxException, UserDataException { + Path file = getJFRInputFile(options); + PrintWriter pw = new PrintWriter(System.out, false, Charset.forName("UTF-8")); + Predicate eventFilter = null; + int stackDepth = 5; + EventPrintWriter eventWriter = null; + int optionCount = options.size(); + while (optionCount > 0) { + if (acceptFilterOption(options, "--events")) { + String filter = options.remove(); + warnForWildcardExpansion("--events", filter); + eventFilter = addEventFilter(filter, eventFilter); + } + if (acceptFilterOption(options, "--categories")) { + String filter = options.remove(); + warnForWildcardExpansion("--categories", filter); + eventFilter = addCategoryFilter(filter, eventFilter); + } + if (acceptOption(options, "--stack-depth")) { + String value = options.pop(); + try { + stackDepth = Integer.parseInt(value); + if (stackDepth < 0) { + throw new UserSyntaxException("stack depth must be zero or a positive integer."); + } + } catch (NumberFormatException nfe) { + throw new UserSyntaxException("not a valid value for --stack-depth"); + } + } + if (acceptFormatterOption(options, eventWriter, "--json")) { + eventWriter = new JSONWriter(pw); + } + if (acceptFormatterOption(options, eventWriter, "--xml")) { + eventWriter = new XMLWriter(pw); + } + if (optionCount == options.size()) { + // No progress made + throw new UserSyntaxException("unknown option " + options.peek()); + } + optionCount = options.size(); + } + if (eventWriter == null) { + eventWriter = new PrettyWriter(pw); // default to pretty printer + } + eventWriter.setStackDepth(stackDepth); + if (eventFilter != null) { + eventFilter = addCache(eventFilter, eventType -> eventType.getId()); + eventWriter.setEventFilter(eventFilter); + } + try { + eventWriter.print(file); + } catch (IOException ioe) { + couldNotReadError(file, ioe); + } + pw.flush(); + } + + private static boolean acceptFormatterOption(Deque options, EventPrintWriter eventWriter, String expected) throws UserSyntaxException { + if (expected.equals(options.peek())) { + if (eventWriter != null) { + throw new UserSyntaxException("only one format can be specified at a time"); + } + options.remove(); + return true; + } + return false; + } + + private static Predicate addCache(final Predicate filter, Function cacheFunction) { + Map cache = new HashMap<>(); + return t -> cache.computeIfAbsent(cacheFunction.apply(t), x -> filter.test(t)); + } + + private static Predicate recurseIfPossible(Predicate filter) { + return x -> filter != null && filter.test(x); + } + + private static Predicate addCategoryFilter(String filterText, Predicate eventFilter) throws UserSyntaxException { + List filters = explodeFilter(filterText); + return recurseIfPossible(eventType -> { + for (String category : eventType.getCategoryNames()) { + for (String filter : filters) { + if (match(category, filter)) { + return true; + } + if (category.contains(" ") && acronomify(category).equals(filter)) { + return true; + } + } + } + return false; + }); + } + + private static String acronomify(String multipleWords) { + boolean newWord = true; + String acronym = ""; + for (char c : multipleWords.toCharArray()) { + if (newWord) { + if (Character.isAlphabetic(c) && Character.isUpperCase(c)) { + acronym += c; + } + } + newWord = Character.isWhitespace(c); + } + return acronym; + } + + private static Predicate addEventFilter(String filterText, final Predicate eventFilter) throws UserSyntaxException { + List filters = explodeFilter(filterText); + return recurseIfPossible(eventType -> { + for (String filter : filters) { + String fullEventName = eventType.getName(); + if (match(fullEventName, filter)) { + return true; + } + String eventName = fullEventName.substring(fullEventName.lastIndexOf(".") + 1); + if (match(eventName, filter)) { + return true; + } + } + return false; + }); + } + + private static boolean match(String text, String filter) { + if (filter.length() == 0) { + // empty filter string matches if string is empty + return text.length() == 0; + } + if (filter.charAt(0) == '*') { // recursive check + filter = filter.substring(1); + for (int n = 0; n <= text.length(); n++) { + if (match(text.substring(n), filter)) + return true; + } + } else if (text.length() == 0) { + // empty string and non-empty filter does not match + return false; + } else if (filter.charAt(0) == '?') { + // eat any char and move on + return match(text.substring(1), filter.substring(1)); + } else if (filter.charAt(0) == text.charAt(0)) { + // eat chars and move on + return match(text.substring(1), filter.substring(1)); + } + return false; + } + + private static List explodeFilter(String filter) throws UserSyntaxException { + List list = new ArrayList<>(); + for (String s : filter.split(",")) { + s = s.trim(); + if (!s.isEmpty()) { + list.add(s); + } + } + return list; + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/StructuredWriter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/StructuredWriter.java new file mode 100644 index 00000000000..f6b5ae2d068 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/StructuredWriter.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +package jdk.jfr.internal.tool; + +import java.io.PrintWriter; + +abstract class StructuredWriter { + private final static String LINE_SEPARATOR = String.format("%n"); + + private final PrintWriter out; + private final StringBuilder builder = new StringBuilder(4000); + + private char[] indentionArray = new char[0]; + private int indent = 0; + private int column; + // print first event immediately so tool feels responsive + private boolean first = true; + + StructuredWriter(PrintWriter p) { + out = p; + } + + final protected int getColumn() { + return column; + } + + // Flush to print writer + public final void flush(boolean hard) { + if (hard) { + out.print(builder.toString()); + builder.setLength(0); + return; + } + if (first || builder.length() > 100_000) { + out.print(builder.toString()); + builder.setLength(0); + first = false; + } + } + + final public void printIndent() { + builder.append(indentionArray, 0, indent); + column += indent; + } + + final public void println() { + builder.append(LINE_SEPARATOR); + column = 0; + } + + final public void print(String... texts) { + for (String text : texts) { + print(text); + } + } + + final public void printAsString(Object o) { + print(String.valueOf(o)); + } + + final public void print(String text) { + builder.append(text); + column += text.length(); + } + + final public void print(char c) { + builder.append(c); + column++; + } + + final public void print(int value) { + print(String.valueOf(value)); + } + + final public void indent() { + indent += 2; + updateIndent(); + } + + final public void retract() { + indent -= 2; + updateIndent(); + } + + final public void println(String text) { + print(text); + println(); + } + + private void updateIndent() { + if (indent > indentionArray.length) { + indentionArray = new char[indent]; + for (int i = 0; i < indentionArray.length; i++) { + indentionArray[i] = ' '; + } + } + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Summary.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Summary.java new file mode 100644 index 00000000000..e282d6b7e33 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Summary.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +package jdk.jfr.internal.tool; + +import java.io.IOException; +import java.io.PrintStream; +import java.nio.file.Path; +import java.time.Instant; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Deque; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; + +import jdk.jfr.EventType; +import jdk.jfr.internal.MetadataDescriptor; +import jdk.jfr.internal.Type; +import jdk.jfr.internal.consumer.ChunkHeader; +import jdk.jfr.internal.consumer.RecordingInput; + +final class Summary extends Command { + private final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withLocale(Locale.UK).withZone(ZoneOffset.UTC); + + @Override + public String getName() { + return "summary"; + } + + private static class Statistics { + Statistics(String name) { + this.name = name; + } + String name; + long count; + long size; + } + + @Override + public List getOptionSyntax() { + return Collections.singletonList(""); + } + + @Override + public void displayOptionUsage(PrintStream stream) { + stream.println(" Location of the recording file (.jfr) to display information about"); + } + + @Override + public String getDescription() { + return "Display general information about a recording file (.jfr)"; + } + + @Override + public void execute(Deque options) throws UserSyntaxException, UserDataException { + ensureMaxArgumentCount(options, 1); + Path p = getJFRInputFile(options); + try { + printInformation(p); + } catch (IOException e) { + couldNotReadError(p, e); + } + } + + private void printInformation(Path p) throws IOException { + long totalDuration = 0; + long chunks = 0; + + try (RecordingInput input = new RecordingInput(p.toFile())) { + ChunkHeader first = new ChunkHeader(input); + ChunkHeader ch = first; + String eventPrefix = Type.EVENT_NAME_PREFIX; + if (first.getMajor() == 1) { + eventPrefix = "com.oracle.jdk."; + } + HashMap stats = new HashMap<>(); + stats.put(0L, new Statistics(eventPrefix + "Metadata")); + stats.put(1L, new Statistics(eventPrefix + "CheckPoint")); + int minWidth = 0; + while (true) { + long chunkEnd = ch.getEnd(); + MetadataDescriptor md = ch.readMetadata(); + + for (EventType eventType : md.getEventTypes()) { + stats.computeIfAbsent(eventType.getId(), (e) -> new Statistics(eventType.getName())); + minWidth = Math.max(minWidth, eventType.getName().length()); + } + + totalDuration += ch.getDurationNanos(); + chunks++; + input.position(ch.getEventStart()); + while (input.position() < chunkEnd) { + long pos = input.position(); + int size = input.readInt(); + long eventTypeId = input.readLong(); + Statistics s = stats.get(eventTypeId); + if (s != null) { + s.count++; + s.size += size; + } + input.position(pos + size); + } + if (ch.isLastChunk()) { + break; + } + ch = ch.nextHeader(); + } + println(); + long epochSeconds = first.getStartNanos() / 1_000_000_000L; + long adjustNanos = first.getStartNanos() - epochSeconds * 1_000_000_000L; + println(" Version: " + first.getMajor() + "." + first.getMinor()); + println(" Chunks: " + chunks); + println(" Start: " + DATE_FORMAT.format(Instant.ofEpochSecond(epochSeconds, adjustNanos)) + " (UTC)"); + println(" Duration: " + (totalDuration + 500_000_000) / 1_000_000_000 + " s"); + + List statsList = new ArrayList<>(stats.values()); + Collections.sort(statsList, (u, v) -> Long.compare(v.count, u.count)); + println(); + String header = " Count Size (bytes) "; + String typeHeader = " Event Type"; + minWidth = Math.max(minWidth, typeHeader.length()); + println(typeHeader + pad(minWidth - typeHeader.length(), ' ') + header); + println(pad(minWidth + header.length(), '=')); + for (Statistics s : statsList) { + System.out.printf(" %-" + minWidth + "s%10d %12d\n", s.name, s.count, s.size); + } + } + } + + private String pad(int count, char c) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < count; i++) { + sb.append(c); + } + return sb.toString(); + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/UserDataException.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/UserDataException.java new file mode 100644 index 00000000000..a21ae95f671 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/UserDataException.java @@ -0,0 +1,49 @@ +/* + * 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. 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. + */ + +package jdk.jfr.internal.tool; + +/** + * Exception that is thrown if there is something wrong with the input, for instance + * a file that can't be read or a numerical value that is out of range. + *

+ * When this exception is thrown, a user will typically not want to see the + * command line syntax, but instead information about what was wrong with the + * input. + */ +final class UserDataException extends Exception { + private static final long serialVersionUID = 6656457380115167810L; + /** + * The error message. + * + * The first letter should not be capitalized, so a context can be printed prior + * to the error message. + * + * @param errorMessage + */ + public UserDataException(String errorMessage) { + super(errorMessage); + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/UserSyntaxException.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/UserSyntaxException.java new file mode 100644 index 00000000000..db6224ccee3 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/UserSyntaxException.java @@ -0,0 +1,45 @@ +/* + * 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. 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. + */ + +package jdk.jfr.internal.tool; + +/** + * Exception that is thrown if options don't follow the syntax of the command. + */ +final class UserSyntaxException extends Exception { + private static final long serialVersionUID = 3437009454344160933L; + + /** + * The error message. + * + * The first letter should not be capitalized, so a context can be printed prior + * to the error message. + * + * @param errorMessage + */ + public UserSyntaxException(String message) { + super(message); + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Version.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Version.java new file mode 100644 index 00000000000..2f3eea9902d --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Version.java @@ -0,0 +1,50 @@ +/* + * 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. 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. + */ + +package jdk.jfr.internal.tool; + +import java.util.Deque; +import java.util.List; + +final class Version extends Command { + @Override + public String getName() { + return "version"; + } + + @Override + public String getDescription() { + return "Display version of the jfr tool"; + } + + @Override + public void execute(Deque options) { + System.out.println("1.0"); + } + + protected List getAliases() { + return List.of("--version"); + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/XMLWriter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/XMLWriter.java new file mode 100644 index 00000000000..2db1688239b --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/XMLWriter.java @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +package jdk.jfr.internal.tool; + +import java.io.PrintWriter; +import java.util.List; + +import jdk.jfr.EventType; +import jdk.jfr.ValueDescriptor; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordedFrame; +import jdk.jfr.consumer.RecordedObject; + +final class XMLWriter extends EventPrintWriter { + public XMLWriter(PrintWriter destination) { + super(destination); + } + + @Override + protected void printBegin() { + println(""); + println(""); + indent(); + printIndent(); + println(""); + indent(); + } + + @Override + protected void printEnd() { + retract(); + printIndent(); + println(""); + retract(); + println(""); + } + + @Override + protected void print(List events) { + for (RecordedEvent event : events) { + printEvent(event); + } + } + + private void printEvent(RecordedEvent event) { + EventType type = event.getEventType(); + printIndent(); + print(""); + println(); + indent(); + for (ValueDescriptor v : event.getFields()) { + printValueDescriptor(v, getValue(event, v), -1); + } + retract(); + printIndent(); + println(""); + println(); + } + + private void printAttribute(String name, String value) { + print(" ", name, "=\"", value, "\""); + } + + public void printObject(RecordedObject struct) { + println(); + indent(); + for (ValueDescriptor v : struct.getFields()) { + printValueDescriptor(v, getValue(struct, v), -1); + } + retract(); + } + + private void printArray(ValueDescriptor v, Object[] array) { + println(); + indent(); + int depth = 0; + for (int index = 0; index < array.length; index++) { + Object arrayElement = array[index]; + if (!(arrayElement instanceof RecordedFrame) || depth < getStackDepth()) { + printValueDescriptor(v, array[index], index); + } + depth++; + } + retract(); + } + + private void printValueDescriptor(ValueDescriptor vd, Object value, int index) { + boolean arrayElement = index != -1; + String name = arrayElement ? null : vd.getName(); + if (vd.isArray() && !arrayElement) { + if (printBeginElement("array", name, value, index)) { + printArray(vd, (Object[]) value); + printIndent(); + printEndElement("array"); + } + return; + } + if (!vd.getFields().isEmpty()) { + if (printBeginElement("struct", name, value, index)) { + printObject((RecordedObject) value); + printIndent(); + printEndElement("struct"); + } + return; + } + if (printBeginElement("value", name, value, index)) { + printEscaped(String.valueOf(value)); + printEndElement("value"); + } + } + + private boolean printBeginElement(String elementName, String name, Object value, int index) { + printIndent(); + print("<", elementName); + if (name != null) { + printAttribute("name", name); + } + if (index != -1) { + printAttribute("index", Integer.toString(index)); + } + if (value == null) { + printAttribute("xsi:nil", "true"); + println("/>"); + return false; + } + if (value.getClass().isArray()) { + Object[] array = (Object[]) value; + printAttribute("size", Integer.toString(array.length)); + } + print(">"); + return true; + } + + private void printEndElement(String elementName) { + print(""); + } + + private void printEscaped(String text) { + for (int i = 0; i < text.length(); i++) { + printEscaped(text.charAt(i)); + } + } + + private void printEscaped(char c) { + if (c == 34) { + print("""); + return; + } + if (c == 38) { + print("&"); + return; + } + if (c == 39) { + print("'"); + return; + } + if (c == 60) { + print("<"); + return; + } + if (c == 62) { + print(">"); + return; + } + if (c > 0x7F) { + print("&#"); + print((int) c); + print(';'); + return; + } + print(c); + } +} diff --git a/src/jdk.jfr/share/classes/module-info.java b/src/jdk.jfr/share/classes/module-info.java index 2355126c080..dc65de9eb3b 100644 --- a/src/jdk.jfr/share/classes/module-info.java +++ b/src/jdk.jfr/share/classes/module-info.java @@ -25,6 +25,12 @@ /** * Defines the API for JDK Flight Recorder. + *

+ * + *

+ *
Tool Guides: + *
{@extLink jfr_tool_reference jfr} + *
* * @moduleGraph * @since 9 diff --git a/test/jdk/jdk/jfr/api/metadata/annotations/TestFormatMissingValue.java b/test/jdk/jdk/jfr/api/metadata/annotations/TestFormatMissingValue.java index e920996ed7d..fa17fcdfbc2 100644 --- a/test/jdk/jdk/jfr/api/metadata/annotations/TestFormatMissingValue.java +++ b/test/jdk/jdk/jfr/api/metadata/annotations/TestFormatMissingValue.java @@ -97,24 +97,12 @@ public static void main(String[] args) throws Exception { for (RecordedEvent e : Events.fromRecording(r)) { String t = e.toString(); - // jdk11u shows different output compared to jdk12 or higher - // because PrettyWriter is of an older version. - // Should JDK-8205516 ever get integrated to jdk11u, - // this test will have to be updated. - - // assertContains(t, "a = N/A"); - // assertContains(t, "c = N/A"); - // assertContains(t, "e = N/A"); - // assertContains(t, "g = N/A"); - // assertContains(t, "h = N/A"); - // assertContains(t, "j = N/A"); - - assertContains(t, "a = -9223372036854775808"); - assertContains(t, "c = -2147483648"); - assertContains(t, "e = -Infinity"); - assertContains(t, "g = NaN"); - assertContains(t, "h = -Infinity"); - assertContains(t, "j = NaN"); + assertContains(t, "a = N/A"); + assertContains(t, "c = N/A"); + assertContains(t, "e = N/A"); + assertContains(t, "g = N/A"); + assertContains(t, "h = N/A"); + assertContains(t, "j = N/A"); assertNotContains(t, "b = N/A"); assertNotContains(t, "d = N/A"); diff --git a/test/jdk/jdk/jfr/tool/ExecuteHelper.java b/test/jdk/jdk/jfr/tool/ExecuteHelper.java new file mode 100644 index 00000000000..1531398fe28 --- /dev/null +++ b/test/jdk/jdk/jfr/tool/ExecuteHelper.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +package jdk.jfr.tool; + +import java.nio.file.Path; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import jdk.jfr.Configuration; +import jdk.jfr.Event; +import jdk.jfr.Recording; +import jdk.test.lib.Utils;; + +final class ExecuteHelper { + + public static Object[] array; + + static class CustomEvent extends Event { + int intValue; + long longValue; + double doubliValue; + float floatValue; + String stringValue; + Short shortValue; + boolean booleanValue; + char charValue; + double trickyDouble; + } + + public static void emitCustomEvents() { + // Custom events with potentially tricky values + CustomEvent event1 = new CustomEvent(); + event1.trickyDouble = Double.NaN; + event1.intValue = Integer.MIN_VALUE; + event1.longValue = Long.MIN_VALUE; + event1.doubliValue = Double.MIN_VALUE; + event1.floatValue = Float.MIN_VALUE; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 512; i++) { + sb.append((char) i); + } + sb.append("\u2324"); + event1.stringValue = sb.toString(); + event1.shortValue = Short.MIN_VALUE; + event1.booleanValue = true; + event1.booleanValue = false; + event1.charValue = '\b'; + event1.commit(); + + CustomEvent event2 = new CustomEvent(); + event2.trickyDouble = Double.NEGATIVE_INFINITY; + event2.intValue = Integer.MAX_VALUE; + event2.longValue = Long.MAX_VALUE; + event2.doubliValue = Double.MAX_VALUE; + event2.floatValue = Float.MAX_VALUE; + event2.stringValue = null; + event2.shortValue = Short.MAX_VALUE; + event2.booleanValue = false; + event2.charValue = 0; + event2.commit(); + } + + public static Path createProfilingRecording() throws Exception { + Path file = Utils.createTempFile("profiling-recording", ".jfr"); + // Create a recording with some data + try (Recording r = new Recording(Configuration.getConfiguration("profile"))) { + r.start(); + + // Allocation event + array = new Object[1000000]; + array = null; + + // Class loading event etc + provokeClassLoading(); + + // GC events + System.gc(); + + // ExecutionSample + long t = System.currentTimeMillis(); + while (System.currentTimeMillis() - t < 50) { + // do nothing + } + + // Other periodic events, i.e CPU load + Thread.sleep(1000); + + r.stop(); + r.dump(file); + } + + return file; + } + + private static void provokeClassLoading() { + // Matching a string with regexp + // is expected to load some classes and generate some VM events + Pattern p = Pattern.compile("a*b"); + Matcher m = p.matcher("aaaaab"); + m.matches(); + } +} diff --git a/test/jdk/jdk/jfr/tool/TestAssemble.java b/test/jdk/jdk/jfr/tool/TestAssemble.java new file mode 100644 index 00000000000..b5b714f01ed --- /dev/null +++ b/test/jdk/jdk/jfr/tool/TestAssemble.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +package jdk.jfr.tool; + +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import jdk.jfr.Event; +import jdk.jfr.Name; +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordingFile; +import jdk.jfr.internal.Repository; +import jdk.jfr.internal.SecuritySupport.SafePath; +import jdk.test.lib.Asserts; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +/** + * @test + * @summary Test jfr reconstruct + * @key jfr + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @modules jdk.jfr/jdk.jfr.internal + * @run main/othervm jdk.jfr.tool.TestAssemble + */ +public class TestAssemble { + + @Name("Correlation") + static class CorrelationEvent extends Event { + int id; + } + private static int RECORDING_COUNT = 5; + + @SuppressWarnings("resource") + public static void main(String[] args) throws Throwable { + // Create some disk recordings + Recording[] recordings = new Recording[5]; + for (int i = 0; i < RECORDING_COUNT; i++) { + Recording r = new Recording(); + r.setToDisk(true); + r.start(); + CorrelationEvent ce = new CorrelationEvent(); + ce.id = i; + ce.commit(); + r.stop(); + recordings[i] = r; + } + Path dir = Paths.get("reconstruction-parts"); + Files.createDirectories(dir); + + long expectedCount = 0; + for (int i = 0; i < RECORDING_COUNT; i++) { + Path tmp = dir.resolve("chunk-part-" + i + ".jfr"); + recordings[i].dump(tmp); + expectedCount += countEventInRecording(tmp); + } + + SafePath repository = Repository.getRepository().getRepositoryPath(); + Path destinationPath = Paths.get("reconstructed.jfr"); + + String directory = repository.toString(); + String destination = destinationPath.toAbsolutePath().toString(); + + // Test failure + OutputAnalyzer output = ProcessTools.executeProcess("jfr", "assemble"); + output.shouldContain("too few arguments"); + + output = ProcessTools.executeProcess("jfr", "assemble", directory); + output.shouldContain("too few arguments"); + + output = ProcessTools.executeProcess("jfr", "assemble", "not-a-directory", destination); + output.shouldContain("directory does not exist, not-a-directory"); + + output = ProcessTools.executeProcess("jfr", "assemble", directory, "not-a-destination"); + output.shouldContain("filename must end with '.jfr'"); + + output = ProcessTools.executeProcess("jfr","assemble", "--wrongOption", directory, destination); + output.shouldContain("too many arguments"); + + FileWriter fw = new FileWriter(destination); + fw.write('d'); + fw.close(); + output = ProcessTools.executeProcess("jfr", "assemble", directory, destination); + output.shouldContain("already exists"); + Files.delete(destinationPath); + + // test success + output = ProcessTools.executeProcess("jfr", "assemble", directory, destination); + System.out.println(output.getOutput()); + output.shouldContain("Finished."); + + long reconstructedCount = countEventInRecording(destinationPath); + Asserts.assertEquals(expectedCount, reconstructedCount); + // Cleanup + for (int i = 0; i < RECORDING_COUNT; i++) { + recordings[i].close(); + } + } + + private static long countEventInRecording(Path file) throws IOException { + Integer lastId = -1; + try (RecordingFile rf = new RecordingFile(file)) { + long count = 0; + while (rf.hasMoreEvents()) { + RecordedEvent re = rf.readEvent(); + if (re.getEventType().getName().equals("Correlation")) { + Integer id = re.getValue("id"); + if (id < lastId) { + Asserts.fail("Expected chunk number to increase"); + } + lastId = id; + } + count++; + } + return count; + } + } +} diff --git a/test/jdk/jdk/jfr/tool/TestDisassemble.java b/test/jdk/jdk/jfr/tool/TestDisassemble.java new file mode 100644 index 00000000000..7912c261727 --- /dev/null +++ b/test/jdk/jdk/jfr/tool/TestDisassemble.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +package jdk.jfr.tool; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import jdk.jfr.Configuration; +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordingFile; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +/** + * @test + * @summary Test jfr split + * @key jfr + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @run main/othervm jdk.jfr.tool.TestDisassemble + */ +public class TestDisassemble { + + public static void main(String[] args) throws Throwable { + SimpleDateFormat formatter = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss"); + String dateText = formatter.format(new Date()); + + Path recordingFileA = Paths.get("many-chunks-A-" + dateText + ".jfr"); + Path recordingFileB = Paths.get("many-chunks-B-" + dateText + ".jfr"); + Path recordingFileC = Paths.get("many-chunks-C-" + dateText + ".jfr"); + makeRecordingWithChunks(6, recordingFileA); + Files.copy(recordingFileA, recordingFileB); + Files.copy(recordingFileA, recordingFileC); + + String fileAText = recordingFileA.toAbsolutePath().toString(); + String fileBText = recordingFileB.toAbsolutePath().toString(); + String fileCText = recordingFileC.toAbsolutePath().toString(); + + OutputAnalyzer output = ProcessTools.executeProcess("jfr", "disassemble"); + output.shouldContain("missing file"); + + output = ProcessTools.executeProcess("jfr","disassemble", "--wrongOption", fileAText); + output.shouldContain("unknown option"); + + output = ProcessTools.executeProcess("jfr","disassemble", "--wrongOption", "1", fileAText); + output.shouldContain("unknown option"); + + output = ProcessTools.executeProcess("jfr","disassemble", "--max-chunks", "-3", fileAText); + output.shouldContain("max chunks must be at least 1"); + + output = ProcessTools.executeProcess("jfr","disassemble", "--max-chunks", "1000", fileAText); + output.shouldContain("number of chunks in recording"); + output.shouldContain("doesn't exceed max chunks"); + output = ProcessTools.executeProcess("jfr", "disassemble", fileAText); // maxchunks is 5 by + // default + System.out.println(output.getOutput()); + System.out.println(fileAText); + verifyRecording(fileAText.substring(0, fileAText.length() - 4) + "_1.jfr"); + verifyRecording(fileAText.substring(0, fileAText.length() - 4) + "_2.jfr"); + + output = ProcessTools.executeProcess("jfr","disassemble", "--max-chunks", "2", fileBText); + + verifyRecording(fileBText.substring(0, fileBText.length() - 4) + "_1.jfr"); + verifyRecording(fileBText.substring(0, fileBText.length() - 4) + "_2.jfr"); + verifyRecording(fileBText.substring(0, fileBText.length() - 4) + "_3.jfr"); + + output = ProcessTools.executeProcess("jfr","disassemble", "--max-chunks", "2", fileBText); + output.shouldContain("file with that name already exist"); + + // sanity check + output = ProcessTools.executeProcess("jfr","disassemble", "--max-size", "500000", fileCText); + verifyRecording(fileCText.substring(0, fileCText.length() - 4) + "_1.jfr"); + } + + private static void verifyRecording(String name) throws IOException { + System.out.println("Disassembling: " + name); + try (RecordingFile rf = new RecordingFile(Paths.get(name))) { + rf.readEvent(); + } + } + + // Will create at least 2 * count + 1 chunks. + private static void makeRecordingWithChunks(int count, Path file) throws IOException, ParseException { + Recording main = new Recording(Configuration.getConfiguration("default")); + main.setToDisk(true); + main.start(); + for (int i = 0; i < count; i++) { + Recording r = new Recording(); + r.setToDisk(true); + r.start(); + r.stop(); + r.close(); + } + main.stop(); + main.dump(file); + main.close(); + } +} diff --git a/test/jdk/jdk/jfr/tool/TestHelp.java b/test/jdk/jdk/jfr/tool/TestHelp.java new file mode 100644 index 00000000000..df4319683c4 --- /dev/null +++ b/test/jdk/jdk/jfr/tool/TestHelp.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +package jdk.jfr.tool; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +/** + * @test + * @summary Test help + * @key jfr + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @run main/othervm jdk.jfr.tool.TestHelp + */ +public class TestHelp { + + public static void main(String[] args) throws Throwable { + OutputAnalyzer output = ProcessTools.executeProcess("jfr", "help"); + output.shouldContain("print"); + output.shouldContain("assemble"); + output.shouldContain("disassemble"); + output.shouldContain("metadata"); + output.shouldContain("summary"); + output.shouldContain("help"); + + output = ProcessTools.executeProcess("jfr", "help", "version"); + output.shouldContain("Display version of the jfr tool"); + output.shouldContain("jfr version"); + + output = ProcessTools.executeProcess("jfr", "help", "wrongcommand"); + output.shouldContain("unknown command 'wrongcommand'"); + } +} diff --git a/test/jdk/jdk/jfr/tool/TestMetadata.java b/test/jdk/jdk/jfr/tool/TestMetadata.java new file mode 100644 index 00000000000..d7289648f04 --- /dev/null +++ b/test/jdk/jdk/jfr/tool/TestMetadata.java @@ -0,0 +1,64 @@ +/* + * 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. 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. + */ + +package jdk.jfr.tool; + +import java.nio.file.Path; + +import jdk.jfr.EventType; +import jdk.jfr.consumer.RecordingFile; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +/** + * @test + * @summary Test jfr info + * @key jfr + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @run main/othervm jdk.jfr.tool.TestMetadata + */ +public class TestMetadata { + + public static void main(String[] args) throws Throwable { + Path f = ExecuteHelper.createProfilingRecording().toAbsolutePath(); + String file = f.toAbsolutePath().toString(); + + OutputAnalyzer output = ProcessTools.executeProcess("jfr", "metadata"); + output.shouldContain("missing file"); + + output = ProcessTools.executeProcess("jfr", "metadata", "--wrongOption", file); + output.shouldContain("unknown option --wrongOption"); + + output = ProcessTools.executeProcess("jfr", "metadata", file); + try (RecordingFile rf = new RecordingFile(f)) { + for (EventType t : rf.readEventTypes()) { + String name = t.getName(); + name = name.substring(name.lastIndexOf(".") + 1); + output.shouldContain(name); + } + } + } +} diff --git a/test/jdk/jdk/jfr/tool/TestPrint.java b/test/jdk/jdk/jfr/tool/TestPrint.java new file mode 100644 index 00000000000..1d6eb450491 --- /dev/null +++ b/test/jdk/jdk/jfr/tool/TestPrint.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +package jdk.jfr.tool; + +import java.io.FileWriter; +import java.nio.file.Files; +import java.nio.file.Path; + +import jdk.test.lib.Utils; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +/** + * @test + * @summary Test jfr print + * @key jfr + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @run main/othervm jdk.jfr.tool.TestPrint + */ +public class TestPrint { + + public static void main(String[] args) throws Throwable { + + OutputAnalyzer output = ProcessTools.executeProcess("jfr", "print"); + output.shouldContain("missing file"); + + output = ProcessTools.executeProcess("jfr", "print", "missing.jfr"); + output.shouldContain("could not find file "); + + Path file = Utils.createTempFile("faked-print-file", ".jfr"); + FileWriter fw = new FileWriter(file.toFile()); + fw.write('d'); + fw.close(); + output = ProcessTools.executeProcess("jfr", "print", "--wrongOption", file.toAbsolutePath().toString()); + output.shouldContain("unknown option"); + Files.delete(file); + } +} diff --git a/test/jdk/jdk/jfr/tool/TestPrintDefault.java b/test/jdk/jdk/jfr/tool/TestPrintDefault.java new file mode 100644 index 00000000000..15f38dbeb42 --- /dev/null +++ b/test/jdk/jdk/jfr/tool/TestPrintDefault.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +package jdk.jfr.tool; + +import java.nio.file.Path; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +/** + * @test + * @key jfr + * @summary Tests print --json + * @requires vm.hasJFR + * + * @library /test/lib /test/jdk + * @modules java.scripting + * jdk.jfr + * + * @run main/othervm jdk.jfr.tool.TestPrintDefault + */ +public class TestPrintDefault { + + public static void main(String... args) throws Throwable { + + Path recordingFile = ExecuteHelper.createProfilingRecording().toAbsolutePath(); + + OutputAnalyzer output = ProcessTools.executeProcess("jfr", "print", recordingFile.toString()); + output.shouldContain("JVMInformation"); + } +} diff --git a/test/jdk/jdk/jfr/tool/TestPrintJSON.java b/test/jdk/jdk/jfr/tool/TestPrintJSON.java new file mode 100644 index 00000000000..e086f1c6dfa --- /dev/null +++ b/test/jdk/jdk/jfr/tool/TestPrintJSON.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +package jdk.jfr.tool; + +import java.nio.file.Path; +import java.time.OffsetDateTime; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; + +import jdk.jfr.Timespan; +import jdk.jfr.Timestamp; +import jdk.jfr.ValueDescriptor; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordedObject; +import jdk.jfr.consumer.RecordingFile; +import jdk.nashorn.api.scripting.JSObject; +import jdk.test.lib.Asserts; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +/** + * @test + * @key jfr + * @summary Tests print --json + * @requires vm.hasJFR + * + * @library /test/lib /test/jdk + * @modules jdk.scripting.nashorn + * jdk.jfr + * + * @run main/othervm jdk.jfr.tool.TestPrintJSON + */ +public class TestPrintJSON { + + public static void main(String... args) throws Throwable { + + Path recordingFile = ExecuteHelper.createProfilingRecording().toAbsolutePath(); + + OutputAnalyzer output = ProcessTools.executeProcess("jfr", "print", "--json", "--stack-depth", "999", recordingFile.toString()); + String json = output.getStdout(); + + // Parse JSON using Nashorn + String statement = "var jsonObject = " + json; + ScriptEngineManager factory = new ScriptEngineManager(); + ScriptEngine engine = factory.getEngineByName("nashorn"); + engine.eval(statement); + JSObject o = (JSObject) engine.get("jsonObject"); + JSObject recording = (JSObject) o.getMember("recording"); + JSObject jsonEvents = (JSObject) recording.getMember("events"); + + List events = RecordingFile.readAllEvents(recordingFile); + Collections.sort(events, (e1, e2) -> e1.getEndTime().compareTo(e2.getEndTime())); + // Verify events are equal + Iterator it = events.iterator(); + + for (Object jsonEvent : jsonEvents.values()) { + RecordedEvent recordedEvent = it.next(); + String typeName = recordedEvent.getEventType().getName(); + Asserts.assertEquals(typeName, ((JSObject) jsonEvent).getMember("type").toString()); + assertEquals(jsonEvent, recordedEvent); + } + Asserts.assertFalse(events.size() != jsonEvents.values().size(), "Incorrect number of events"); + } + + private static void assertEquals(Object jsonObject, Object jfrObject) throws Exception { + // Check object + if (jfrObject instanceof RecordedObject) { + JSObject values = (JSObject) ((JSObject) jsonObject).getMember("values"); + RecordedObject recObject = (RecordedObject) jfrObject; + Asserts.assertEquals(values.values().size(), recObject.getFields().size()); + for (ValueDescriptor v : recObject.getFields()) { + String name = v.getName(); + Object jsonValue = values.getMember(name); + Object expectedValue = recObject.getValue(name); + if (v.getAnnotation(Timestamp.class) != null) { + // Make instant of OffsetDateTime + jsonValue = OffsetDateTime.parse("" + jsonValue).toInstant().toString(); + expectedValue = recObject.getInstant(name); + } + if (v.getAnnotation(Timespan.class) != null) { + expectedValue = recObject.getDuration(name); + } + assertEquals(jsonValue, expectedValue); + return; + } + } + // Check array + if (jfrObject != null && jfrObject.getClass().isArray()) { + Object[] jfrArray = (Object[]) jfrObject; + JSObject jsArray = (JSObject) jsonObject; + for (int i = 0; i < jfrArray.length; i++) { + assertEquals(jsArray.getSlot(i), jfrArray[i]); + } + return; + } + String jsonText = String.valueOf(jsonObject); + // Double.NaN / Double.Inifinity is not supported by JSON format, + // use null + if (jfrObject instanceof Double) { + double expected = ((Double) jfrObject); + if (Double.isInfinite(expected) || Double.isNaN(expected)) { + Asserts.assertEquals("null", jsonText); + return; + } + double value = Double.parseDouble(jsonText); + Asserts.assertEquals(expected, value); + return; + } + // Float.NaN / Float.Inifinity is not supported by JSON format, + // use null + if (jfrObject instanceof Float) { + float expected = ((Float) jfrObject); + if (Float.isInfinite(expected) || Float.isNaN(expected)) { + Asserts.assertEquals("null", jsonText); + return; + } + float value = Float.parseFloat(jsonText); + Asserts.assertEquals(expected, value); + return; + } + if (jfrObject instanceof Integer) { + Integer expected = ((Integer) jfrObject); + double value = Double.parseDouble(jsonText); + Asserts.assertEquals(expected.doubleValue(), value); + return; + } + if (jfrObject instanceof Long) { + Long expected = ((Long) jfrObject); + double value = Double.parseDouble(jsonText); + Asserts.assertEquals(expected.doubleValue(), value); + return; + } + + String jfrText = String.valueOf(jfrObject); + Asserts.assertEquals(jfrText, jsonText, "Primitive values don't match. JSON = " + jsonText); + } +} diff --git a/test/jdk/jdk/jfr/tool/TestPrintXML.java b/test/jdk/jdk/jfr/tool/TestPrintXML.java new file mode 100644 index 00000000000..8f9442076bd --- /dev/null +++ b/test/jdk/jdk/jfr/tool/TestPrintXML.java @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +package jdk.jfr.tool; + +import java.io.File; +import java.io.StringReader; +import java.nio.file.Path; +import java.time.OffsetDateTime; +import java.util.AbstractMap.SimpleEntry; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Stack; + +import javax.xml.XMLConstants; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.DefaultHandler; + +import jdk.jfr.Timespan; +import jdk.jfr.Timestamp; +import jdk.jfr.ValueDescriptor; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordedObject; +import jdk.jfr.consumer.RecordingFile; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +/** + * @test + * @key jfr + * @summary Tests print --xml + * @requires vm.hasJFR + * + * @library /test/lib /test/jdk + * @modules java.scripting java.xml jdk.jfr + * + * @run main/othervm jdk.jfr.tool.TestPrintXML + */ +public class TestPrintXML { + + public static void main(String... args) throws Throwable { + + Path recordingFile = ExecuteHelper.createProfilingRecording().toAbsolutePath(); + + OutputAnalyzer output = ProcessTools.executeProcess("jfr", "print", "--xml", "--stack-depth", "9999", recordingFile.toString()); + System.out.println(recordingFile); + String xml = output.getStdout(); + + SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + Schema schema = schemaFactory.newSchema(new File(System.getProperty("test.src"), "jfr.xsd")); + + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setSchema(schema); + factory.setNamespaceAware(true); + + SAXParser sp = factory.newSAXParser(); + XMLReader xr = sp.getXMLReader(); + RecordingHandler handler = new RecordingHandler(); + xr.setContentHandler(handler); + xr.setErrorHandler(handler); + xr.parse(new InputSource(new StringReader(xml))); + + // Verify that all data was written correctly + List events = RecordingFile.readAllEvents(recordingFile); + Collections.sort(events, (e1, e2) -> e1.getEndTime().compareTo(e2.getEndTime())); + Iterator it = events.iterator(); + for (XMLEvent xmlEvent : handler.events) { + RecordedEvent re = it.next(); + if (!compare(re, xmlEvent.values)) { + System.out.println("Expected:"); + System.out.println("----------------------"); + System.out.println(re); + System.out.println(); + System.out.println("Was (XML)"); + System.out.println("----------------------"); + System.out.println(xmlEvent); + System.out.println(); + throw new Exception("Event doesn't match"); + } + } + + } + + @SuppressWarnings("unchecked") + static boolean compare(Object eventObject, Object xmlObject) { + if (eventObject == null) { + return xmlObject == null; + } + if (eventObject instanceof RecordedObject) { + RecordedObject re = (RecordedObject) eventObject; + Map xmlMap = (Map) xmlObject; + List fields = re.getFields(); + if (fields.size() != xmlMap.size()) { + return false; + } + for (ValueDescriptor v : fields) { + String name = v.getName(); + Object xmlValue = xmlMap.get(name); + Object expectedValue = re.getValue(name); + if (v.getAnnotation(Timestamp.class) != null) { + // Make instant of OffsetDateTime + xmlValue = OffsetDateTime.parse("" + xmlValue).toInstant().toString(); + expectedValue = re.getInstant(name); + } + if (v.getAnnotation(Timespan.class) != null) { + expectedValue = re.getDuration(name); + } + if (!compare(expectedValue, xmlValue)) { + return false; + } + } + return true; + } + if (eventObject.getClass().isArray()) { + Object[] array = (Object[]) eventObject; + Object[] xmlArray = (Object[]) xmlObject; + if (array.length != xmlArray.length) { + return false; + } + for (int i = 0; i < array.length; i++) { + if (!compare(array[i], xmlArray[i])) { + return false; + } + } + return true; + } + String s1 = String.valueOf(eventObject); + String s2 = (String) xmlObject; + return s1.equals(s2); + } + + static class XMLEvent { + String name; + private Map values = new HashMap<>(); + + XMLEvent(String name) { + this.name = name; + } + } + + public static final class RecordingHandler extends DefaultHandler { + + private Stack objects = new Stack<>(); + private Stack> elements = new Stack<>(); + private List events = new ArrayList<>(); + + @Override + public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { + elements.push(new SimpleEntry<>(attrs.getValue("name"), attrs.getValue("index"))); + String nil = attrs.getValue("xsi:nil"); + if ("true".equals(nil)) { + objects.push(null); + return; + } + + switch (qName) { + case "event": + objects.push(new XMLEvent(attrs.getValue("type"))); + break; + case "struct": + objects.push(new HashMap()); + break; + case "array": + objects.push(new Object[Integer.parseInt(attrs.getValue("size"))]); + break; + case "value": + objects.push(new StringBuilder()); + break; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + if (!objects.isEmpty()) { + Object o = objects.peek(); + if (o instanceof StringBuilder) { + ((StringBuilder) o).append(ch, start, length); + } + } + } + + @SuppressWarnings("unchecked") + @Override + public void endElement(String uri, String localName, String qName) { + SimpleEntry element = elements.pop(); + switch (qName) { + case "event": + case "struct": + case "array": + case "value": + String name = element.getKey(); + Object value = objects.pop(); + if (objects.isEmpty()) { + events.add((XMLEvent) value); + return; + } + if (value instanceof StringBuilder) { + value = ((StringBuilder) value).toString(); + } + Object parent = objects.peek(); + if (parent instanceof XMLEvent) { + ((XMLEvent) parent).values.put(name, value); + } + if (parent instanceof Map) { + ((Map) parent).put(name, value); + } + if (parent != null && parent.getClass().isArray()) { + int index = Integer.parseInt(element.getValue()); + ((Object[]) parent)[index] = value; + } + } + } + + public void warning(SAXParseException spe) throws SAXException { + throw new SAXException(spe); + } + + public void error(SAXParseException spe) throws SAXException { + throw new SAXException(spe); + } + + public void fatalError(SAXParseException spe) throws SAXException { + throw new SAXException(spe); + } + } +} diff --git a/test/jdk/jdk/jfr/tool/TestSummary.java b/test/jdk/jdk/jfr/tool/TestSummary.java new file mode 100644 index 00000000000..2e6877b93e3 --- /dev/null +++ b/test/jdk/jdk/jfr/tool/TestSummary.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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. + */ + +package jdk.jfr.tool; + +import java.nio.file.Path; + +import jdk.jfr.EventType; +import jdk.jfr.consumer.RecordingFile; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +/** + * @test + * @summary Test jfr info + * @key jfr + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @run main/othervm jdk.jfr.tool.TestSummary + */ +public class TestSummary { + + public static void main(String[] args) throws Throwable { + Path f = ExecuteHelper.createProfilingRecording().toAbsolutePath(); + String file = f.toAbsolutePath().toString(); + + OutputAnalyzer output = ProcessTools.executeProcess("jfr", "summary"); + output.shouldContain("missing file"); + + output = ProcessTools.executeProcess("jfr", "summary", "--wrongOption", file); + output.shouldContain("too many arguments"); + + output = ProcessTools.executeProcess("jfr", "summary", file); + try (RecordingFile rf = new RecordingFile(f)) { + for (EventType t : rf.readEventTypes()) { + output.shouldContain(t.getName()); + } + } + output.shouldContain("Version"); + } +} diff --git a/test/jdk/jdk/jfr/tool/jfr.xsd b/test/jdk/jdk/jfr/tool/jfr.xsd new file mode 100644 index 00000000000..adf44493f86 --- /dev/null +++ b/test/jdk/jdk/jfr/tool/jfr.xsd @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/jdk/tools/launcher/HelpFlagsTest.java b/test/jdk/tools/launcher/HelpFlagsTest.java index b19042fde85..5d7ed9b7191 100644 --- a/test/jdk/tools/launcher/HelpFlagsTest.java +++ b/test/jdk/tools/launcher/HelpFlagsTest.java @@ -140,6 +140,7 @@ private static class ToolHelpSpec { new ToolHelpSpec("jdb", 1, 1, 1, 0, 1, 1, 0), // -?, -h, --help -help, Documents -help new ToolHelpSpec("jdeprscan", 1, 1, 1, 0, 0, 0, 1), // -?, -h, --help new ToolHelpSpec("jdeps", 1, 1, 1, 0, 1, 0, 2), // -?, -h, --help, -help accepted but not documented. + new ToolHelpSpec("jfr", 1, 1, 1, 0, 0, 0, 2), // -?, -h, --help new ToolHelpSpec("jhsdb", 0, 0, 0, 0, 0, 0, 0), // none, prints help message anyways. new ToolHelpSpec("jimage", 1, 1, 1, 0, 0, 0, 2), // -?, -h, --help new ToolHelpSpec("jinfo", 1, 1, 1, 0, 1, 1, 1), // -?, -h, --help -help, Documents -help @@ -224,6 +225,7 @@ static boolean findFlagInLine(String line, String flag) { line.charAt(posAfter) != ',' && line.charAt(posAfter) != '[' && // jar line.charAt(posAfter) != ']' && // jarsigner + line.charAt(posAfter) != ')' && // jfr line.charAt(posAfter) != '|' && // jstatd line.charAt(posAfter) != ':' && // jps line.charAt(posAfter) != '"') { // keytool diff --git a/test/jdk/tools/launcher/VersionCheck.java b/test/jdk/tools/launcher/VersionCheck.java index 4bb2dc72d10..148ecee651e 100644 --- a/test/jdk/tools/launcher/VersionCheck.java +++ b/test/jdk/tools/launcher/VersionCheck.java @@ -88,6 +88,7 @@ public class VersionCheck extends TestHelper { "jcontrol", "jdeprscan", "jdeps", + "jfr", "jimage", "jinfo", "jlink", From e73d095903c7cdf7d54edde81b8440ae61c97da6 Mon Sep 17 00:00:00 2001 From: egahlin Date: Wed, 5 Dec 2018 18:08:50 +0100 Subject: [PATCH 006/131] 8214896: JFR Tool left files behind Reviewed-by: mgronlun --- .../classes/jdk/jfr/internal/cmd/Command.java | 150 ---------- .../classes/jdk/jfr/internal/cmd/Execute.java | 65 ----- .../jdk/jfr/internal/cmd/HelpCommand.java | 68 ----- .../jdk/jfr/internal/cmd/JSONWriter.java | 258 ------------------ .../jdk/jfr/internal/cmd/PrettyWriter.java | 236 ---------------- .../jdk/jfr/internal/cmd/PrintCommand.java | 100 ------- .../jfr/internal/cmd/ReconstructCommand.java | 131 --------- .../jdk/jfr/internal/cmd/SplitCommand.java | 195 ------------- .../jfr/internal/cmd/StructuredWriter.java | 111 -------- .../jdk/jfr/internal/cmd/SummaryCommand.java | 173 ------------ .../jdk/jfr/internal/cmd/XMLWriter.java | 191 ------------- test/jdk/jdk/jfr/cmd/ExecuteHelper.java | 140 ---------- test/jdk/jdk/jfr/cmd/TestHelp.java | 57 ---- test/jdk/jdk/jfr/cmd/TestPrint.java | 66 ----- test/jdk/jdk/jfr/cmd/TestPrintDefault.java | 53 ---- test/jdk/jdk/jfr/cmd/TestPrintJSON.java | 149 ---------- test/jdk/jdk/jfr/cmd/TestPrintXML.java | 222 --------------- test/jdk/jdk/jfr/cmd/TestReconstruct.java | 146 ---------- test/jdk/jdk/jfr/cmd/TestSplit.java | 121 -------- test/jdk/jdk/jfr/cmd/TestSummary.java | 62 ----- 20 files changed, 2694 deletions(-) delete mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/Command.java delete mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/Execute.java delete mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/HelpCommand.java delete mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/JSONWriter.java delete mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/PrettyWriter.java delete mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/PrintCommand.java delete mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/ReconstructCommand.java delete mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/SplitCommand.java delete mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/StructuredWriter.java delete mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/SummaryCommand.java delete mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/XMLWriter.java delete mode 100644 test/jdk/jdk/jfr/cmd/ExecuteHelper.java delete mode 100644 test/jdk/jdk/jfr/cmd/TestHelp.java delete mode 100644 test/jdk/jdk/jfr/cmd/TestPrint.java delete mode 100644 test/jdk/jdk/jfr/cmd/TestPrintDefault.java delete mode 100644 test/jdk/jdk/jfr/cmd/TestPrintJSON.java delete mode 100644 test/jdk/jdk/jfr/cmd/TestPrintXML.java delete mode 100644 test/jdk/jdk/jfr/cmd/TestReconstruct.java delete mode 100644 test/jdk/jdk/jfr/cmd/TestSplit.java delete mode 100644 test/jdk/jdk/jfr/cmd/TestSummary.java diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/Command.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/Command.java deleted file mode 100644 index e9baa02b833..00000000000 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/Command.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package jdk.jfr.internal.cmd; - -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Deque; -import java.util.List; - -abstract class Command { - - private final static Command HELP = new HelpCommand(); - private final static List COMMANDS = createCommands(); - - static void displayHelp() { - System.out.println("Usage: java " + Execute.class.getName() + " []"); - System.out.println(); - displayAvailableCommands(); - } - - static void displayAvailableCommands() { - System.out.println("Available commands are:"); - System.out.println(); - boolean first = true; - for (Command c : Command.COMMANDS) { - if (!first) { - System.out.println(); - } - System.out.println(" " + c.getName() + " " + c.getOptionSyntax()); - System.out.println(" " + c.getDescription()); - first = false; - } - } - - public static List getCommands() { - return COMMANDS; - } - - public static Command valueOf(String commandName) { - for (Command command : COMMANDS) { - if (command.getName().equals(commandName)) { - return command; - } - } - return null; - } - - abstract public String getOptionSyntax(); - - abstract public String getName(); - - abstract public String getDescription(); - - abstract public void displayOptionUsage(); - - abstract public void execute(Deque options); - - final protected void userFailed(String message) { - println(); - println(message); - displayUsage(); - throw new IllegalArgumentException(message); - } - - final protected void ensureMaxArgumentCount(Deque options, int maxCount) { - if (options.size() > maxCount) { - userFailed("Too many arguments"); - } - } - - final protected void ensureMinArgumentCount(Deque options, int minCount) { - if (options.size() < minCount) { - userFailed("Too few arguments"); - } - } - - final protected void ensureFileExist(Path file) { - if (!Files.exists(file)) { - userFailed("Could not find file " + file); - } - } - - final protected Path ensureFileDoesNotExist(Path file) { - if (Files.exists(file)) { - userFailed("File " + file + " already exists"); - } - return file; - } - - final protected void ensureJFRFile(Path path) { - if (!path.toString().endsWith(".jfr")) { - userFailed("Filename must end with .jfr"); - } - } - - final protected void displayUsage() { - String javaText = "java " + Execute.class.getName(); - println(); - println("Usage: " + javaText + " " + getName() + " " + getOptionSyntax()); - println(); - displayOptionUsage(); - } - - final protected void println() { - System.out.println(); - } - - final protected void print(String text) { - System.out.print(text); - } - - final protected void println(String text) { - System.out.println(text); - } - - private static List createCommands() { - List commands = new ArrayList<>(); - commands.add(new PrintCommand()); - commands.add(new SummaryCommand()); - commands.add(new ReconstructCommand()); - commands.add(new SplitCommand()); - commands.add(HELP); - return Collections.unmodifiableList(commands); - } -} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/Execute.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/Execute.java deleted file mode 100644 index 800c589f2c1..00000000000 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/Execute.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package jdk.jfr.internal.cmd; - -import java.util.Arrays; -import java.util.Deque; -import java.util.LinkedList; - -/** - * Launcher class for JFR tools - * - */ -public final class Execute { - - public static void main(String... args) { - Deque argList = new LinkedList<>(Arrays.asList(args)); - if (argList.isEmpty()) { - System.out.println(); - Command.displayHelp(); - return; - } - String command = argList.remove(); - for (Command c : Command.getCommands()) { - if (c.getName().equals(command)) { - try { - c.execute(argList); - } catch (IllegalArgumentException iae) { - return; // already handled by command - } catch (Throwable e) { - System.out.println(); - System.out.println(e.getMessage()); - System.out.println(); - } - return; - } - } - System.out.println(); - System.out.println("Unknown command " + command + "."); - System.out.println(); - Command.displayHelp(); - } -} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/HelpCommand.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/HelpCommand.java deleted file mode 100644 index 44abd5b8801..00000000000 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/HelpCommand.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package jdk.jfr.internal.cmd; - -import java.util.Deque; - -final class HelpCommand extends Command { - - @Override - public String getOptionSyntax() { - return "[]"; - } - - @Override - public void displayOptionUsage() { - println(" The name of the command to get help for"); - println(); - Command.displayAvailableCommands(); - } - - @Override - public String getName() { - return "help"; - } - - @Override - public String getDescription() { - return "Display help about a command"; - } - - @Override - public void execute(Deque options) { - if (options.isEmpty()) { - displayUsage(); - } else { - ensureMaxArgumentCount(options, 1); - String commandName = options.remove(); - Command c = Command.valueOf(commandName); - if (c == null) { - userFailed("Unknown command " + commandName); - } - c.displayUsage(); - } - } -} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/JSONWriter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/JSONWriter.java deleted file mode 100644 index 8f441a38543..00000000000 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/JSONWriter.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package jdk.jfr.internal.cmd; - -import java.io.IOException; -import java.io.PrintWriter; -import java.nio.file.Path; - -import jdk.jfr.EventType; -import jdk.jfr.ValueDescriptor; -import jdk.jfr.consumer.RecordedEvent; -import jdk.jfr.consumer.RecordedObject; -import jdk.jfr.consumer.RecordingFile; - -final class JSONWriter extends StructuredWriter { - - public JSONWriter(PrintWriter writer) { - super(writer); - } - - public void print(Path source) throws IOException { - try (RecordingFile es = new RecordingFile(source)) { - printObjectBegin(); - printRecording(es); - printObjectEnd(); - flush(); - } - } - - private void printRecording(RecordingFile es) throws IOException { - printDataStructureName("recording"); - printObjectBegin(); - printEvents(es); - printObjectEnd(); - } - - private void printEvents(RecordingFile es) throws IOException { - printDataStructureName("events"); - printArrayBegin(); - boolean first = true; - while (es.hasMoreEvents()) { - RecordedEvent e = es.readEvent(); - printNewDataStructure(first, true, null); - printEvent(e); - flush(); - first = false; - } - printArrayEnd(); - } - - private void printEvent(RecordedEvent e) { - printObjectBegin(); - EventType type = e.getEventType(); - printValue(true, false, "name", type.getName()); - printValue(false, false, "typeId", type.getId()); - printValue(false, false, "startTime", e.getStartTime()); - printValue(false, false, "duration", e.getDuration()); - printNewDataStructure(false, false, "values"); - printObject(e); - printObjectEnd(); - } - - void printValue(boolean first, boolean arrayElement, String name, Object value) { - printNewDataStructure(first, arrayElement, name); - if (!printIfNull(value)) { - if (value instanceof Boolean) { - printAsString(value); - return; - } - if (value instanceof Double) { - Double dValue = (Double) value; - if (Double.isNaN(dValue) || Double.isInfinite(dValue)) { - printNull(); - return; - } - printAsString(value); - return; - } - if (value instanceof Float) { - Float fValue = (Float) value; - if (Float.isNaN(fValue) || Float.isInfinite(fValue)) { - printNull(); - return; - } - printAsString(value); - return; - } - if (value instanceof Number) { - printAsString(value); - return; - } - print("\""); - printEscaped(String.valueOf(value)); - print("\""); - } - } - - public void printObject(RecordedObject object) { - printObjectBegin(); - boolean first = true; - for (ValueDescriptor v : object.getFields()) { - printValueDescriptor(first, false, v, object.getValue(v.getName())); - first = false; - } - printObjectEnd(); - } - - private void printArray(ValueDescriptor v, Object[] array) { - printArrayBegin(); - boolean first = true; - for (Object arrayElement : array) { - printValueDescriptor(first, true, v, arrayElement); - first = false; - } - printArrayEnd(); - } - - private void printValueDescriptor(boolean first, boolean arrayElement, ValueDescriptor vd, Object value) { - if (vd.isArray() && !arrayElement) { - printNewDataStructure(first, arrayElement, vd.getName()); - if (!printIfNull(value)) { - printArray(vd, (Object[]) value); - } - return; - } - if (!vd.getFields().isEmpty()) { - printNewDataStructure(first, arrayElement, vd.getName()); - if (!printIfNull(value)) { - printObject((RecordedObject) value); - } - return; - } - printValue(first, arrayElement, vd.getName(), value); - } - - private void printNewDataStructure(boolean first, boolean arrayElement, String name) { - if (!first) { - print(", "); - if (!arrayElement) { - println(); - } - } - if (!arrayElement) { - printDataStructureName(name); - } - } - - private boolean printIfNull(Object value) { - if (value == null) { - printNull(); - return true; - } - return false; - } - - private void printNull() { - print("null"); - } - - private void printDataStructureName(String text) { - printIndent(); - print("\""); - print(text); - print("\": "); - } - - private void printObjectEnd() { - retract(); - println(); - printIndent(); - print("}"); - } - - private void printObjectBegin() { - println("{"); - indent(); - } - - private void printArrayEnd() { - print("]"); - } - - private void printArrayBegin() { - print("["); - } - - private void printEscaped(String text) { - for (int i = 0; i < text.length(); i++) { - printEscaped(text.charAt(i)); - } - } - - private void printEscaped(char c) { - if (c == '\b') { - print("\\b"); - return; - } - if (c == '\n') { - print("\\n"); - return; - } - if (c == '\t') { - print("\\t"); - return; - } - if (c == '\f') { - print("\\f"); - return; - } - if (c == '\r') { - print("\\r"); - return; - } - if (c == '\"') { - print("\\\""); - return; - } - if (c == '\\') { - print("\\\\"); - return; - } - if (c == '/') { - print("\\/"); - return; - } - if (c > 0x7F || c < 32) { - print("\\u"); - // 0x10000 will pad with zeros. - print(Integer.toHexString(0x10000 + (int) c).substring(1)); - return; - } - print(c); - } - -} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/PrettyWriter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/PrettyWriter.java deleted file mode 100644 index 0cdfbf58fbb..00000000000 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/PrettyWriter.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package jdk.jfr.internal.cmd; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.PrintWriter; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.StringJoiner; - -import jdk.jfr.AnnotationElement; -import jdk.jfr.ValueDescriptor; -import jdk.jfr.consumer.RecordedEvent; -import jdk.jfr.consumer.RecordedObject; -import jdk.jfr.consumer.RecordingFile; -import jdk.jfr.internal.PrivateAccess; -import jdk.jfr.internal.Type; -import jdk.jfr.internal.consumer.ChunkHeader; -import jdk.jfr.internal.consumer.RecordingInput; - -public final class PrettyWriter extends StructuredWriter { - - public PrettyWriter(PrintWriter destination) { - super(destination); - } - - void print(Path source) throws FileNotFoundException, IOException { - try (RecordingInput input = new RecordingInput(source.toFile())) { - HashSet typeSet = new HashSet<>(); - for (ChunkHeader ch = new ChunkHeader(input); !ch.isLastChunk(); ch = ch.nextHeader()) { - typeSet.addAll(ch.readMetadata().getTypes()); - } - List types = new ArrayList<>(typeSet); - Collections.sort(types, (c1, c2) -> Long.compare(c1.getId(), c2.getId())); - for (Type t : types) { - printType(t); - } - flush(); - } - - try (RecordingFile es = new RecordingFile(source)) { - while (es.hasMoreEvents()) { - print(es.readEvent()); - flush(); - } - } - flush(); - } - - public void printType(Type t) throws IOException { - print("// id: "); - println(String.valueOf(t.getId())); - int commentIndex = t.getName().length() + 10; - String typeName = t.getName(); - int index = typeName.lastIndexOf("."); - if (index != -1) { - println("package " + typeName.substring(0, index) + ";"); - } - printAnnotations(commentIndex, t.getAnnotationElements()); - print("class " + typeName.substring(index + 1)); - String superType = t.getSuperType(); - if (superType != null) { - print(" extends " + superType); - } - println(" {"); - indent(); - for (ValueDescriptor v : t.getFields()) { - printField(commentIndex, v); - } - retract(); - println("}"); - println(); - } - - private void printField(int commentIndex, ValueDescriptor v) throws IOException { - println(); - printAnnotations(commentIndex, v.getAnnotationElements()); - printIndent(); - Type vType = PrivateAccess.getInstance().getType(v); - if (Type.SUPER_TYPE_SETTING.equals(vType.getSuperType())) { - print("static "); - } - print(makeSimpleType(v.getTypeName())); - if (v.isArray()) { - print("[]"); - } - print(" "); - print(v.getName()); - print(";"); - printCommentRef(commentIndex, v.getTypeId()); - } - - private void printCommentRef(int commentIndex, long typeId) throws IOException { - int column = getColumn(); - if (column > commentIndex) { - print(" "); - } else { - while (column < commentIndex) { - print(" "); - column++; - } - } - println(" // id=" + typeId); - } - - private void printAnnotations(int commentIndex, List annotations) throws IOException { - for (AnnotationElement a : annotations) { - printIndent(); - print("@"); - print(makeSimpleType(a.getTypeName())); - List vs = a.getValueDescriptors(); - if (!vs.isEmpty()) { - printAnnotation(a); - printCommentRef(commentIndex, a.getTypeId()); - } else { - println(); - } - } - } - - private void printAnnotation(AnnotationElement a) throws IOException { - StringJoiner sj = new StringJoiner(", ", "(", ")"); - List vs = a.getValueDescriptors(); - for (ValueDescriptor v : vs) { - Object o = a.getValue(v.getName()); - if (vs.size() == 1 && v.getName().equals("value")) { - sj.add(textify(o)); - } else { - sj.add(v.getName() + "=" + textify(o)); - } - } - print(sj.toString()); - } - - private String textify(Object o) { - if (o.getClass().isArray()) { - Object[] array = (Object[]) o; - if (array.length == 1) { - return quoteIfNeeded(array[0]); - } - StringJoiner s = new StringJoiner(", ", "{", "}") ; - for (Object ob : array) { - s.add(quoteIfNeeded(ob)); - } - return s.toString(); - } else { - return quoteIfNeeded(o); - } - } - - private String quoteIfNeeded(Object o) { - if (o instanceof String) { - return "\"" + o + "\""; - } else { - return String.valueOf(o); - } - } - - private String makeSimpleType(String typeName) { - int index = typeName.lastIndexOf("."); - return typeName.substring(index + 1); - } - - public void print(RecordedEvent event) throws IOException { - print(makeSimpleType(event.getEventType().getName()), " "); - print((RecordedObject) event, ""); - } - - public void print(RecordedObject struct, String postFix) throws IOException { - println("{"); - indent(); - for (ValueDescriptor v : struct.getFields()) { - printIndent(); - print(v.getName(), " = "); - printValue(struct.getValue(v.getName()), ""); - } - retract(); - printIndent(); - println("}" + postFix); - } - - private void printArray(Object[] array) throws IOException { - println("["); - indent(); - for (int i = 0; i < array.length; i++) { - printIndent(); - printValue(array[i], i + 1 < array.length ? ", " : ""); - } - retract(); - printIndent(); - println("]"); - } - - private void printValue(Object value, String postFix) throws IOException { - if (value == null) { - println("null" + postFix); - } else if (value instanceof RecordedObject) { - print((RecordedObject) value, postFix); - } else if (value.getClass().isArray()) { - printArray((Object[]) value); - } else { - String text = String.valueOf(value); - if (value instanceof String) { - text = "\"" + text + "\""; - } - println(text); - } - } -} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/PrintCommand.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/PrintCommand.java deleted file mode 100644 index 5bea4667ddb..00000000000 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/PrintCommand.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package jdk.jfr.internal.cmd; - -import java.io.IOException; -import java.io.PrintWriter; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Deque; - -final class PrintCommand extends Command { - @Override - public String getName() { - return "print"; - } - - @Override - public String getOptionSyntax() { - return "[--xml|--json] "; - } - - @Override - public String getDescription() { - return "Print contents of a recording file (.jfr)"; - } - - @Override - public void displayOptionUsage() { - println(" --xml Print a recording in XML format"); - println(); - println(" --json Print a recording in JSON format"); - println(); - println(" Location of the recording file (.jfr) to print"); - } - - @Override - public void execute(Deque options) { - if (options.isEmpty()) { - userFailed("Missing file"); - } - ensureMaxArgumentCount(options, 2); - - Path file = Paths.get(options.removeLast()); - - ensureFileExist(file); - ensureJFRFile(file); - ensureMaxArgumentCount(options, 1); - - String format = "--pretty"; - if (!options.isEmpty()) { - format = options.remove(); - } - try (PrintWriter pw = new PrintWriter(System.out)) { - try { - switch (format) { - case "--pretty": - PrettyWriter prettyWriter = new PrettyWriter(pw); - prettyWriter.print(file); - break; - case "--xml": - XMLWriter xmlPrinter = new XMLWriter(pw); - xmlPrinter.print(file); - break; - case "--json": - JSONWriter jsonWriter = new JSONWriter(pw); - jsonWriter.print(file); - break; - default: - userFailed("Unknown option " + format); - break; - } - } catch (IOException ioe) { - userFailed("Could not read recording at " + file.toAbsolutePath() + ". " + ioe.getMessage()); - } - } - } -} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/ReconstructCommand.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/ReconstructCommand.java deleted file mode 100644 index cac6d057578..00000000000 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/ReconstructCommand.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package jdk.jfr.internal.cmd; - -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.channels.FileChannel; -import java.nio.file.DirectoryStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Deque; -import java.util.List; - -final class ReconstructCommand extends Command { - - @Override - public String getOptionSyntax() { - return " "; - } - - @Override - public String getName() { - return "reconstruct"; - } - - @Override - public String getDescription() { - return "Assemble leftover chunks, from a disk repository, into a recording file (.jfr)"; - } - - @Override - public void displayOptionUsage() { - println(" Directory where the repository is located"); - println(); - println(" Name of the recording file (.jfr) to create"); - } - - @Override - public void execute(Deque options) { - ensureMinArgumentCount(options, 2); - ensureMaxArgumentCount(options, 2); - - Path repository = Paths.get(options.pop()).toAbsolutePath(); - if (!Files.exists(repository)) { - userFailed("Could not find disk repository at " + repository); - } - if (!Files.isDirectory(repository)) { - userFailed("Must specify a directory as disk repository"); - } - Path output = Paths.get(options.pop()); - ensureFileDoesNotExist(output); - ensureJFRFile(output); - - try (FileOutputStream fos = new FileOutputStream(output.toFile())) { - List files = listJFRFiles(repository); - if (files.isEmpty()) { - throw new IllegalStateException("No *.jfr files found at " + repository); - } - println(); - println("Combining files... "); - println(); - transferTo(files, output, fos.getChannel()); - println(); - println("Reconstruction complete."); - } catch (IOException e) { - userFailed("Could not open destination file " + output + ". " + e.getMessage()); - } - } - - private List listJFRFiles(Path path) throws IOException { - try { - List files = new ArrayList<>(); - if (Files.isDirectory(path)) { - try (DirectoryStream stream = Files.newDirectoryStream(path, "*.jfr")) { - for (Path p : stream) { - if (!Files.isDirectory(p) && Files.isReadable(p)) { - files.add(p); - } - } - } - } - files.sort((u, v) -> u.getFileName().compareTo(v.getFileName())); - return files; - } catch (IOException ioe) { - throw new IllegalStateException("Could not list *.jfr for directory " + path + ". " + ioe.getMessage()); - } - } - - private void transferTo(List sourceFiles, Path output, FileChannel out) { - long pos = 0; - for (Path p : sourceFiles) { - println(" " + p.toString()); - try (FileChannel sourceChannel = FileChannel.open(p)) { - long rem = Files.size(p); - while (rem > 0) { - long n = Math.min(rem, 1024 * 1024); - long w = out.transferFrom(sourceChannel, pos, n); - pos += w; - rem -= w; - } - } catch (IOException ioe) { - throw new IllegalStateException("Could not copy recording chunk " + p + " to new file. " + ioe.getMessage()); - } - } - } -} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/SplitCommand.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/SplitCommand.java deleted file mode 100644 index fa13a947baf..00000000000 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/SplitCommand.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package jdk.jfr.internal.cmd; - -import java.io.BufferedInputStream; -import java.io.DataInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Deque; -import java.util.List; - -import jdk.jfr.internal.consumer.ChunkHeader; -import jdk.jfr.internal.consumer.RecordingInput; - -final class SplitCommand extends Command { - - @Override - public String getOptionSyntax() { - return "[--maxchunks ] "; - } - - @Override - public void displayOptionUsage() { - println(" --maxchunks Maximum number of chunks per splitted file (default 5)."); - println(" The chunk size varies, but is typically around 15 MB."); - println(); - println(" Location of recording file (.jfr) to split"); - } - - @Override - public String getName() { - return "split"; - } - - @Override - public String getDescription() { - return "Splits a recording file into smaller files"; - } - - @Override - public void execute(Deque options) { - if (options.isEmpty()) { - userFailed("Missing file"); - } - ensureMaxArgumentCount(options, 3); - Path file = Paths.get(options.removeLast()); - ensureFileExist(file); - ensureJFRFile(file); - int maxchunks = 5; - if (!options.isEmpty()) { - String option = options.pop(); - if (!"--maxchunks".equals(option)) { - userFailed("Unknown option " + option); - } - if (options.isEmpty()) { - userFailed("Missing value for --maxChunks"); - } - String value = options.pop(); - try { - maxchunks = Integer.parseInt(value); - if (maxchunks < 1) { - userFailed("Must be at least one chunk per file."); - } - } catch (NumberFormatException nfe) { - userFailed("Not a valid value for --maxchunks."); - } - } - ensureMaxArgumentCount(options, 0); - println(); - println("Examining recording " + file + " ..."); - List sizes; - - try { - sizes = findChunkSizes(file); - } catch (IOException e) { - throw new IllegalStateException("Unexpected error. " + e.getMessage()); - } - if (sizes.size() <= maxchunks) { - throw new IllegalStateException("Number of chunks in recording (" + sizes.size() + ") doesn't exceed max chunks (" + maxchunks + ")"); - } - println(); - - println(); - if (sizes.size() > 0) { - print("File consists of " + sizes.size() + " chunks. The recording will be split into "); - sizes = combineChunkSizes(sizes, maxchunks); - println(sizes.size() + " files with at most " + maxchunks + " chunks per file."); - println(); - - try { - splitFile(file, sizes); - } catch (IOException e) { - throw new IllegalStateException("Unexpected error. " + e.getMessage()); - } - } else { - println("No JFR chunks found in file. "); - } - } - - private List findChunkSizes(Path p) throws IOException { - try (RecordingInput input = new RecordingInput(p.toFile())) { - List sizes = new ArrayList<>(); - ChunkHeader ch = new ChunkHeader(input); - sizes.add(ch.getSize()); - while (!ch.isLastChunk()) { - ch = ch.nextHeader(); - sizes.add(ch.getSize()); - } - return sizes; - } - } - - private List combineChunkSizes(List sizes, int chunksPerFile) { - List reduced = new ArrayList(); - long size = sizes.get(0); - for (int n = 1; n < sizes.size(); n++) { - if (n % chunksPerFile == 0) { - reduced.add(size); - size = 0; - } - size += sizes.get(n); - } - reduced.add(size); - return reduced; - } - - private void splitFile(Path file, List splitPositions) throws IOException { - - int padAmountZeros = String.valueOf(splitPositions.size() - 1).length(); - String fileName = file.toString(); - String fileFormatter = fileName.subSequence(0, fileName.length() - 4) + "_%0" + padAmountZeros + "d.jfr"; - for (int i = 0; i < splitPositions.size(); i++) { - Path p = Paths.get(String.format(fileFormatter, i)); - if (Files.exists(p)) { - throw new IllegalStateException("Can't create split file " + p + ", a file with that name already exist"); - } - } - DataInputStream stream = new DataInputStream(new BufferedInputStream(new FileInputStream(file.toFile()))); - - for (int i = 0; i < splitPositions.size(); i++) { - Long l = splitPositions.get(i); - byte[] bytes = readBytes(stream, l.intValue()); - Path p = Paths.get(String.format(fileFormatter, i)); - File splittedFile = p.toFile(); - println("Writing " + splittedFile + " ..."); - FileOutputStream fos = new FileOutputStream(splittedFile); - fos.write(bytes); - fos.close(); - } - stream.close(); - } - - private byte[] readBytes(InputStream stream, int count) throws IOException { - byte[] data = new byte[count]; - int totalRead = 0; - while (totalRead < data.length) { - int read = stream.read(data, totalRead, data.length - totalRead); - if (read == -1) { - throw new IOException("Unexpected end of data."); - } - totalRead += read; - } - return data; - } -} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/StructuredWriter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/StructuredWriter.java deleted file mode 100644 index eef11859e30..00000000000 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/StructuredWriter.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package jdk.jfr.internal.cmd; - -import java.io.PrintWriter; - -abstract class StructuredWriter { - private final static String LINE_SEPARATOR = String.format("%n"); - - private final PrintWriter out; - private final StringBuilder builder = new StringBuilder(4000); - - private char[] indentionArray = new char[0]; - private int indent = 0; - private int column; - - StructuredWriter(PrintWriter p) { - out = p; - } - - final protected int getColumn() { - return column; - } - - // Flush to print writer - public final void flush() { - out.print(builder.toString()); - builder.setLength(0); - } - - final public void printIndent() { - builder.append(indentionArray, 0, indent); - column += indent; - } - - final public void println() { - builder.append(LINE_SEPARATOR); - column = 0; - } - - final public void print(String... texts) { - for (String text : texts) { - print(text); - } - } - - final public void printAsString(Object o) { - print(String.valueOf(o)); - } - - final public void print(String text) { - builder.append(text); - column += text.length(); - } - - final public void print(char c) { - builder.append(c); - column++; - } - - final public void print(int value) { - print(String.valueOf(value)); - } - - final public void indent() { - indent += 2; - updateIndent(); - } - - final public void retract() { - indent -= 2; - updateIndent(); - } - - final public void println(String text) { - print(text); - println(); - } - - private void updateIndent() { - if (indent > indentionArray.length) { - indentionArray = new char[indent]; - for (int i = 0; i < indentionArray.length; i++) { - indentionArray[i] = ' '; - } - } - } -} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/SummaryCommand.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/SummaryCommand.java deleted file mode 100644 index 106409d53bd..00000000000 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/SummaryCommand.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package jdk.jfr.internal.cmd; - -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.time.Duration; -import java.time.Instant; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Deque; -import java.util.HashMap; -import java.util.List; - -import jdk.jfr.EventType; -import jdk.jfr.internal.MetadataDescriptor; -import jdk.jfr.internal.Type; -import jdk.jfr.internal.consumer.ChunkHeader; -import jdk.jfr.internal.consumer.RecordingInput; - -final class SummaryCommand extends Command { - - private static class Statistics { - Statistics(String name) { - this.name = name; - } - - String name; - long count; - long size; - } - - @Override - public String getOptionSyntax() { - return ""; - } - - @Override - public void displayOptionUsage() { - println(" Location of the recording file (.jfr) to display information about"); - } - - @Override - public String getName() { - return "summary"; - } - - @Override - public String getDescription() { - return "Display general information about a recording file (.jfr)"; - } - - @Override - public void execute(Deque options) { - if (options.isEmpty()) { - userFailed("Missing file"); - } - ensureMaxArgumentCount(options, 1); - Path p = Paths.get(options.remove()); - ensureFileExist(p); - ensureJFRFile(p); - try { - printInformation(p); - } catch (IOException e) { - throw new IllegalStateException("Unexpected error. " + e.getMessage()); - } - } - - private void printInformation(Path p) throws IOException { - long totalSize = 0; - long totalDuration = 0; - long chunks = 0; - - try (RecordingInput input = new RecordingInput(p.toFile())) { - ChunkHeader first = new ChunkHeader(input); - ChunkHeader ch = first; - String eventPrefix = Type.EVENT_NAME_PREFIX; - if (first.getMajor() == 1) { - eventPrefix = "com.oracle.jdk."; - } - HashMap stats = new HashMap<>(); - stats.put(0L, new Statistics(eventPrefix + "Metadata")); - stats.put(1L, new Statistics(eventPrefix + "CheckPoint")); - int minWidth = 0; - while (true) { - long chunkEnd = ch.getEnd(); - MetadataDescriptor md = ch.readMetadata(); - - for (EventType eventType : md.getEventTypes()) { - stats.computeIfAbsent(eventType.getId(), (e) -> new Statistics(eventType.getName())); - minWidth = Math.max(minWidth, eventType.getName().length()); - } - - totalSize += ch.getSize(); - totalDuration += ch.getDuration(); - chunks++; - input.position(ch.getEventStart()); - while (input.position() < chunkEnd) { - - long pos = input.position(); - int size = input.readInt(); - long eventTypeId = input.readLong(); - Statistics s = stats.get(eventTypeId); - - if (s != null) { - s.count++; - s.size += size; - } - input.position(pos + size); - } - if (ch.isLastChunk()) { - break; - } - ch = ch.nextHeader(); - } - println(); - long epochSeconds = first.getStartNanos() / 1_000_000_000L; - long adjustNanos = first.getStartNanos() - epochSeconds * 1_000_000_000L; - println(" Version: " + first.getMajor() + "." + first.getMinor()); - println(" Chunks: " + chunks); - println(" Size: " + totalSize + " bytes"); - println(" Start: " + Instant.ofEpochSecond(epochSeconds, adjustNanos)); - println(" Duration: " + Duration.ofNanos(totalDuration)); - println(); - println(" Start Ticks: " + first.getStartTicks()); - println(" Ticks / Second: " + first.getTicksPerSecond()); - - List statsList = new ArrayList<>(stats.values()); - Collections.sort(statsList, (u, v) -> Long.compare(v.count, u.count)); - println(); - String header = " Count Size (bytes) "; - String typeHeader = " Event Type"; - minWidth = Math.max(minWidth, typeHeader.length()); - println(typeHeader + pad(minWidth - typeHeader.length(), ' ') + header); - println(pad(minWidth + header.length(), '=')); - for (Statistics s : statsList) { - System.out.printf(" %-" + minWidth + "s%10d %12d\n", s.name, s.count, s.size); - } - } - } - - private String pad(int count, char c) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < count; i++) { - sb.append(c); - } - return sb.toString(); - } -} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/XMLWriter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/XMLWriter.java deleted file mode 100644 index f765c0dd0c2..00000000000 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/cmd/XMLWriter.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package jdk.jfr.internal.cmd; - -import java.io.IOException; -import java.io.PrintWriter; -import java.nio.file.Path; - -import jdk.jfr.EventType; -import jdk.jfr.ValueDescriptor; -import jdk.jfr.consumer.RecordedEvent; -import jdk.jfr.consumer.RecordedObject; -import jdk.jfr.consumer.RecordingFile; - -final class XMLWriter extends StructuredWriter { - - public XMLWriter(PrintWriter destination) { - super(destination); - } - - public void print(Path source) throws IOException { - try (RecordingFile es = new RecordingFile(source)) { - println(""); - println(""); - indent(); - printIndent(); - println(""); - indent(); - while (es.hasMoreEvents()) { - printEvent(es.readEvent()); - flush(); - } - retract(); - printIndent(); - println(""); - retract(); - println(""); - flush(); - } - } - - private void printEvent(RecordedEvent e) throws IOException { - EventType type = e.getEventType(); - printIndent(); - print(""); - printObject(e); - printIndent(); - println(""); - println(); - } - - private void printAttribute(String name, String value) { - print(" ", name, "=\"", value, "\""); - } - - public void printObject(RecordedObject struct) { - println(); - indent(); - for (ValueDescriptor v : struct.getFields()) { - printValueDescriptor(v, struct.getValue(v.getName()), -1); - } - retract(); - } - - private void printArray(ValueDescriptor v, Object[] array) { - println(); - indent(); - for (int index = 0; index < array.length; index++) { - printValueDescriptor(v, array[index], index); - } - retract(); - } - - private void printValueDescriptor(ValueDescriptor vd, Object value, int index) { - boolean arrayElement = index != -1; - String name = arrayElement ? null : vd.getName(); - if (vd.isArray() && !arrayElement) { - if (printBeginElement("array", name, value, index)) { - printArray(vd, (Object[]) value); - printIndent(); - printEndElement("array"); - } - return; - } - if (!vd.getFields().isEmpty()) { - if (printBeginElement("struct", name, value, index)) { - printObject((RecordedObject) value); - printIndent(); - printEndElement("struct"); - } - return; - } - if (printBeginElement("value", name, value, index)) { - printEscaped(String.valueOf(value)); - printEndElement("value"); - } - } - - private boolean printBeginElement(String elementName, String name, Object value, int index) { - printIndent(); - print("<", elementName); - if (name != null) { - printAttribute("name", name); - } - if (index != -1) { - printAttribute("index", Integer.toString(index)); - } - if (value == null) { - print(">"); - return false; - } - if (value.getClass().isArray()) { - Object[] array = (Object[]) value; - printAttribute("size", Integer.toString(array.length)); - } - print(">"); - return true; - } - - private void printEndElement(String elementName) { - print(""); - } - - private void printEscaped(String text) { - for (int i = 0; i < text.length(); i++) { - printEscaped(text.charAt(i)); - } - } - - private void printEscaped(char c) { - if (c == 34) { - print("""); - return; - } - if (c == 38) { - print("&"); - return; - } - if (c == 39) { - print("'"); - return; - } - if (c == 60) { - print("<"); - return; - } - if (c == 62) { - print(">"); - return; - } - if (c > 0x7F) { - print("&#"); - print((int) c); - print(';'); - return; - } - print(c); - } -} diff --git a/test/jdk/jdk/jfr/cmd/ExecuteHelper.java b/test/jdk/jdk/jfr/cmd/ExecuteHelper.java deleted file mode 100644 index dee5db70460..00000000000 --- a/test/jdk/jdk/jfr/cmd/ExecuteHelper.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package jdk.jfr.cmd; - -import java.nio.file.Path; -import java.util.Arrays; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import jdk.jfr.Configuration; -import jdk.jfr.Event; -import jdk.jfr.Recording; -import jdk.test.lib.Utils; -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.process.ProcessTools;; - -final class ExecuteHelper { - - public static Object[] array; - - static class CustomEvent extends Event { - int intValue; - long longValue; - double doubliValue; - float floatValue; - String stringValue; - Short shortValue; - boolean booleanValue; - char charValue; - double trickyDouble; - } - - public static OutputAnalyzer run(String... args) { - String[] array = new String[args.length + 1]; - System.arraycopy(args, 0, array, 1, args.length); - array[0] = "jdk.jfr.internal.cmd.Execute"; - try { - return ProcessTools.executeTestJava(array); - } catch (Exception e) { - String message = String.format("Caught exception while executing '%s'", Arrays.asList(array)); - throw new RuntimeException(message, e); - } - } - - public static void emitCustomEvents() { - // Custom events with potentially tricky values - CustomEvent event1 = new CustomEvent(); - event1.trickyDouble = Double.NaN; - event1.intValue = Integer.MIN_VALUE; - event1.longValue = Long.MIN_VALUE; - event1.doubliValue = Double.MIN_VALUE; - event1.floatValue = Float.MIN_VALUE; - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < 512; i++) { - sb.append((char) i); - } - sb.append("\u2324"); - event1.stringValue = sb.toString(); - event1.shortValue = Short.MIN_VALUE; - event1.booleanValue = true; - event1.booleanValue = false; - event1.charValue = '\b'; - event1.commit(); - - CustomEvent event2 = new CustomEvent(); - event2.trickyDouble = Double.NEGATIVE_INFINITY; - event2.intValue = Integer.MAX_VALUE; - event2.longValue = Long.MAX_VALUE; - event2.doubliValue = Double.MAX_VALUE; - event2.floatValue = Float.MAX_VALUE; - event2.stringValue = null; - event2.shortValue = Short.MAX_VALUE; - event2.booleanValue = false; - event2.charValue = 0; - event2.commit(); - } - - public static Path createProfilingRecording() throws Exception { - Path file = Utils.createTempFile("profiling-recording", ".jfr"); - // Create a recording with some data - try (Recording r = new Recording(Configuration.getConfiguration("profile"))) { - r.start(); - - // Allocation event - array = new Object[1000000]; - array = null; - - // Class loading event etc - provokeClassLoading(); - - // GC events - System.gc(); - - // ExecutionSample - long t = System.currentTimeMillis(); - while (System.currentTimeMillis() - t < 50) { - // do nothing - } - - // Other periodic events, i.e CPU load - Thread.sleep(1000); - - r.stop(); - r.dump(file); - } - - return file; - } - - private static void provokeClassLoading() { - // Matching a string with regexp - // is expected to load some classes and generate some VM events - Pattern p = Pattern.compile("a*b"); - Matcher m = p.matcher("aaaaab"); - m.matches(); - } -} diff --git a/test/jdk/jdk/jfr/cmd/TestHelp.java b/test/jdk/jdk/jfr/cmd/TestHelp.java deleted file mode 100644 index c6aa2c75379..00000000000 --- a/test/jdk/jdk/jfr/cmd/TestHelp.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package jdk.jfr.cmd; - -import jdk.test.lib.process.OutputAnalyzer; - -/** - * @test - * @summary Test help - * @key jfr - * @requires vm.hasJFR - * @library /test/lib /test/jdk - * @run main/othervm jdk.jfr.cmd.TestHelp - */ -public class TestHelp { - - public static void main(String[] args) throws Exception { - OutputAnalyzer output = ExecuteHelper.run("help"); - output.shouldContain("Available commands are:"); - output.shouldContain("print"); - output.shouldContain("reconstruct"); - output.shouldContain("summary"); - output.shouldContain("help"); - - output = ExecuteHelper.run("help", "help"); - output.shouldContain("Available commands are:"); - - output = ExecuteHelper.run("help", "wrongcommand"); - output.shouldContain("Unknown command"); - - output = ExecuteHelper.run("help", "wrongcommand", "wrongarguments"); - output.shouldContain("Too many arguments"); - } -} diff --git a/test/jdk/jdk/jfr/cmd/TestPrint.java b/test/jdk/jdk/jfr/cmd/TestPrint.java deleted file mode 100644 index b32269f6dfc..00000000000 --- a/test/jdk/jdk/jfr/cmd/TestPrint.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package jdk.jfr.cmd; - -import java.io.FileWriter; -import java.nio.file.Files; -import java.nio.file.Path; - -import jdk.test.lib.Utils; -import jdk.test.lib.process.OutputAnalyzer; - -/** - * @test - * @summary Test jfr print - * @key jfr - * @requires vm.hasJFR - * @library /test/lib /test/jdk - * @run main/othervm jdk.jfr.cmd.TestPrint - */ -public class TestPrint { - - public static void main(String[] args) throws Exception { - - OutputAnalyzer output = ExecuteHelper.run("print"); - output.shouldContain("Missing file"); - - output = ExecuteHelper.run("print", "missing.jfr"); - output.shouldContain("Could not find file "); - - output = ExecuteHelper.run("print", "missing.jfr", "option1", "option2"); - output.shouldContain("Too many arguments"); - - Path file = Utils.createTempFile("faked-print-file", ".jfr"); - FileWriter fw = new FileWriter(file.toFile()); - fw.write('d'); - fw.close(); - output = ExecuteHelper.run("print", "--wrongOption", file.toAbsolutePath().toString()); - output.shouldContain("Unknown option"); - Files.delete(file); - - // Also see TestPrintJSON, TestPrintXML and TestPrintDefault. - } -} diff --git a/test/jdk/jdk/jfr/cmd/TestPrintDefault.java b/test/jdk/jdk/jfr/cmd/TestPrintDefault.java deleted file mode 100644 index 1e7b022b9e6..00000000000 --- a/test/jdk/jdk/jfr/cmd/TestPrintDefault.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package jdk.jfr.cmd; - -import java.nio.file.Path; - -import jdk.test.lib.process.OutputAnalyzer; - -/** - * @test - * @key jfr - * @summary Tests print --json - * @requires vm.hasJFR - * - * @library /test/lib /test/jdk - * @modules java.scripting - * jdk.jfr - * - * @run main/othervm jdk.jfr.cmd.TestPrintDefault - */ -public class TestPrintDefault { - - public static void main(String... args) throws Exception { - - Path recordingFile = ExecuteHelper.createProfilingRecording().toAbsolutePath(); - - OutputAnalyzer output = ExecuteHelper.run("print", recordingFile.toString()); - output.shouldContain("JVMInformation"); - } -} diff --git a/test/jdk/jdk/jfr/cmd/TestPrintJSON.java b/test/jdk/jdk/jfr/cmd/TestPrintJSON.java deleted file mode 100644 index 6cf356c3377..00000000000 --- a/test/jdk/jdk/jfr/cmd/TestPrintJSON.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package jdk.jfr.cmd; - -import java.nio.file.Path; - -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; - -import jdk.jfr.ValueDescriptor; -import jdk.jfr.consumer.RecordedEvent; -import jdk.jfr.consumer.RecordedObject; -import jdk.jfr.consumer.RecordingFile; -import jdk.nashorn.api.scripting.JSObject; -import jdk.test.lib.Asserts; -import jdk.test.lib.process.OutputAnalyzer; - -/** - * @test - * @key jfr - * @summary Tests print --json - * @requires vm.hasJFR - * - * @library /test/lib /test/jdk - * @modules jdk.scripting.nashorn - * jdk.jfr - * - * @run main/othervm jdk.jfr.cmd.TestPrintJSON - */ -public class TestPrintJSON { - - public static void main(String... args) throws Exception { - - Path recordingFile = ExecuteHelper.createProfilingRecording().toAbsolutePath(); - - OutputAnalyzer output = ExecuteHelper.run("print", "--json", recordingFile.toString()); - String json = output.getStdout(); - - // Parse JSON using Nashorn - String statement = "var jsonObject = " + json; - ScriptEngineManager factory = new ScriptEngineManager(); - ScriptEngine engine = factory.getEngineByName("nashorn"); - engine.eval(statement); - JSObject o = (JSObject) engine.get("jsonObject"); - JSObject recording = (JSObject) o.getMember("recording"); - JSObject events = (JSObject) recording.getMember("events"); - - // Verify events are equal - try (RecordingFile rf = new RecordingFile(recordingFile)) { - for (Object jsonEvent : events.values()) { - RecordedEvent recordedEvent = rf.readEvent(); - double typeId = recordedEvent.getEventType().getId(); - String startTime = recordedEvent.getStartTime().toString(); - String duration = recordedEvent.getDuration().toString(); - Asserts.assertEquals(typeId, ((Number) ((JSObject) jsonEvent).getMember("typeId")).doubleValue()); - Asserts.assertEquals(startTime, ((JSObject) jsonEvent).getMember("startTime")); - Asserts.assertEquals(duration, ((JSObject) jsonEvent).getMember("duration")); - assertEquals(jsonEvent, recordedEvent); - } - Asserts.assertFalse(rf.hasMoreEvents(), "Incorrect number of events"); - } - } - - private static void assertEquals(Object jsonObject, Object jfrObject) throws Exception { - // Check object - if (jfrObject instanceof RecordedObject) { - JSObject values = (JSObject) ((JSObject) jsonObject).getMember("values"); - RecordedObject recObject = (RecordedObject) jfrObject; - Asserts.assertEquals(values.values().size(), recObject.getFields().size()); - for (ValueDescriptor v : recObject.getFields()) { - String name = v.getName(); - assertEquals(values.getMember(name), recObject.getValue(name)); - return; - } - } - // Check array - if (jfrObject != null && jfrObject.getClass().isArray()) { - Object[] jfrArray = (Object[]) jfrObject; - JSObject jsArray = (JSObject) jsonObject; - for (int i = 0; i < jfrArray.length; i++) { - assertEquals(jsArray.getSlot(i), jfrArray[i]); - } - return; - } - String jsonText = String.valueOf(jsonObject); - // Double.NaN / Double.Inifinity is not supported by JSON format, - // use null - if (jfrObject instanceof Double) { - double expected = ((Double) jfrObject); - if (Double.isInfinite(expected) || Double.isNaN(expected)) { - Asserts.assertEquals("null", jsonText); - return; - } - double value = Double.parseDouble(jsonText); - Asserts.assertEquals(expected, value); - return; - } - // Float.NaN / Float.Inifinity is not supported by JSON format, - // use null - if (jfrObject instanceof Float) { - float expected = ((Float) jfrObject); - if (Float.isInfinite(expected) || Float.isNaN(expected)) { - Asserts.assertEquals("null", jsonText); - return; - } - float value = Float.parseFloat(jsonText); - Asserts.assertEquals(expected, value); - return; - } - if (jfrObject instanceof Integer) { - Integer expected = ((Integer) jfrObject); - double value = Double.parseDouble(jsonText); - Asserts.assertEquals(expected.doubleValue(), value); - return; - } - if (jfrObject instanceof Long) { - Long expected = ((Long) jfrObject); - double value = Double.parseDouble(jsonText); - Asserts.assertEquals(expected.doubleValue(), value); - return; - } - - String jfrText = String.valueOf(jfrObject); - Asserts.assertEquals(jfrText, jsonText, "Primitive values don't match. JSON = " + jsonText); - } -} diff --git a/test/jdk/jdk/jfr/cmd/TestPrintXML.java b/test/jdk/jdk/jfr/cmd/TestPrintXML.java deleted file mode 100644 index c389953b121..00000000000 --- a/test/jdk/jdk/jfr/cmd/TestPrintXML.java +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package jdk.jfr.cmd; - -import java.io.StringReader; -import java.nio.file.Path; -import java.time.Duration; -import java.time.Instant; -import java.util.AbstractMap.SimpleEntry; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Stack; - -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -import jdk.jfr.ValueDescriptor; -import jdk.jfr.consumer.RecordedEvent; -import jdk.jfr.consumer.RecordedObject; -import jdk.jfr.consumer.RecordingFile; -import jdk.test.lib.process.OutputAnalyzer; - -import org.xml.sax.Attributes; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.XMLReader; -import org.xml.sax.helpers.DefaultHandler; - -/** - * @test - * @key jfr - * @summary Tests print --xml - * @requires vm.hasJFR - * - * @library /test/lib /test/jdk - * @modules java.scripting - * java.xml - * jdk.jfr - * - * @run main/othervm jdk.jfr.cmd.TestPrintXML - */ -public class TestPrintXML { - - public static void main(String... args) throws Exception { - - Path recordingFile = ExecuteHelper.createProfilingRecording().toAbsolutePath(); - - OutputAnalyzer output = ExecuteHelper.run("print", "--xml", recordingFile.toString()); - String xml = output.getStdout(); - System.out.println(xml); - // Parse XML string - SAXParserFactory factory = SAXParserFactory.newInstance(); - SAXParser sp = factory.newSAXParser(); - XMLReader xr = sp.getXMLReader(); - RecordingHandler handler = new RecordingHandler(); - xr.setContentHandler(handler); - xr.parse(new InputSource(new StringReader(xml))); - - // Verify that all data was written correctly - Iterator it = RecordingFile.readAllEvents(recordingFile).iterator(); - for (XMLEvent xmlEvent : handler.events) { - RecordedEvent re = it.next(); - if (!compare(re, xmlEvent.values)) { - System.out.println(re); - System.out.println(xmlEvent.values.toString()); - throw new Exception("Event doesn't match"); - } - } - - } - - @SuppressWarnings("unchecked") - static boolean compare(Object eventObject, Object xmlObject) { - if (eventObject == null) { - return xmlObject == null; - } - if (eventObject instanceof RecordedObject) { - RecordedObject re = (RecordedObject) eventObject; - Map xmlMap = (Map) xmlObject; - List fields = re.getFields(); - if (fields.size() != xmlMap.size()) { - return false; - } - for (ValueDescriptor v : fields) { - String name = v.getName(); - if (!compare(re.getValue(name), xmlMap.get(name))) { - return false; - } - } - return true; - } - if (eventObject.getClass().isArray()) { - Object[] array = (Object[]) eventObject; - Object[] xmlArray = (Object[]) xmlObject; - if (array.length != xmlArray.length) { - return false; - } - for (int i = 0; i < array.length; i++) { - if (!compare(array[i], xmlArray[i])) { - return false; - } - } - return true; - } - String s1 = String.valueOf(eventObject); - String s2 = (String) xmlObject; - return s1.equals(s2); - } - - static class XMLEvent { - String name; - Instant startTime; - Duration duration; - Map values = new HashMap<>(); - - XMLEvent(String name, Instant startTime, Duration duration) { - this.name = name; - this.startTime = startTime; - this.duration = duration; - } - } - - public static final class RecordingHandler extends DefaultHandler { - - private Stack objects = new Stack<>(); - private Stack> elements = new Stack<>(); - private List events = new ArrayList<>(); - - @Override - public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { - elements.push(new SimpleEntry<>(attrs.getValue("name"), attrs.getValue("index"))); - switch (qName) { - case "null": - objects.pop(); - objects.push(null); - break; - case "event": - Instant startTime = Instant.parse(attrs.getValue("startTime")); - Duration duration = Duration.parse(attrs.getValue("duration")); - objects.push(new XMLEvent(attrs.getValue("name"), startTime, duration)); - break; - case "struct": - objects.push(new HashMap()); - break; - case "array": - objects.push(new Object[Integer.parseInt(attrs.getValue("size"))]); - break; - case "value": - objects.push(new StringBuilder()); - break; - } - } - - @Override - public void characters(char[] ch, int start, int length) throws SAXException { - if (!objects.isEmpty()) { - Object o = objects.peek(); - if (o instanceof StringBuilder) { - ((StringBuilder) o).append(ch, start, length); - } - } - } - - @SuppressWarnings("unchecked") - @Override - public void endElement(String uri, String localName, String qName) { - SimpleEntry element = elements.pop(); - switch (qName) { - case "event": - case "struct": - case "array": - case "value": - String name = element.getKey(); - Object value = objects.pop(); - if (objects.isEmpty()) { - events.add((XMLEvent) value); - return; - } - if (value instanceof StringBuilder) { - value = ((StringBuilder) value).toString(); - } - Object parent = objects.peek(); - if (parent instanceof XMLEvent) { - ((XMLEvent) parent).values.put(name, value); - } - if (parent instanceof Map) { - ((Map) parent).put(name, value); - } - if (parent != null && parent.getClass().isArray()) { - int index = Integer.parseInt(element.getValue()); - ((Object[]) parent)[index] = value; - } - } - } - } -} diff --git a/test/jdk/jdk/jfr/cmd/TestReconstruct.java b/test/jdk/jdk/jfr/cmd/TestReconstruct.java deleted file mode 100644 index dc4e4738b96..00000000000 --- a/test/jdk/jdk/jfr/cmd/TestReconstruct.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package jdk.jfr.cmd; - -import java.io.FileWriter; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -import jdk.jfr.Event; -import jdk.jfr.Name; -import jdk.jfr.Recording; -import jdk.jfr.consumer.RecordedEvent; -import jdk.jfr.consumer.RecordingFile; -import jdk.jfr.internal.Repository; -import jdk.jfr.internal.SecuritySupport.SafePath; -import jdk.test.lib.Asserts; -import jdk.test.lib.process.OutputAnalyzer; - -/** - * @test - * @summary Test jfr reconstruct - * @key jfr - * @requires vm.hasJFR - * @library /test/lib /test/jdk - * @modules jdk.jfr/jdk.jfr.internal - * @run main/othervm jdk.jfr.cmd.TestReconstruct - */ -public class TestReconstruct { - - @Name("Correlation") - static class CorrelationEvent extends Event { - int id; - } - private static int RECORDING_COUNT = 5; - - @SuppressWarnings("resource") - public static void main(String[] args) throws Exception { - // Create some disk recordings - Recording[] recordings = new Recording[5]; - for (int i = 0; i < RECORDING_COUNT; i++) { - Recording r = new Recording(); - r.setToDisk(true); - r.start(); - CorrelationEvent ce = new CorrelationEvent(); - ce.id = i; - ce.commit(); - r.stop(); - recordings[i] = r; - } - Path dir = Paths.get("reconstruction-parts"); - Files.createDirectories(dir); - - long expectedCount = 0; - for (int i = 0; i < RECORDING_COUNT; i++) { - Path tmp = dir.resolve("chunk-part-" + i + ".jfr"); - recordings[i].dump(tmp); - expectedCount += countEventInRecording(tmp); - } - - SafePath repository = Repository.getRepository().getRepositoryPath(); - Path destinationPath = Paths.get("reconstructed.jfr"); - - String directory = repository.toString(); - String destination = destinationPath.toAbsolutePath().toString(); - - // Test failure - OutputAnalyzer output = ExecuteHelper.run("reconstruct"); - - output.shouldContain("Too few arguments"); - - output = ExecuteHelper.run("reconstruct", directory); - output.shouldContain("Too few arguments"); - - output = ExecuteHelper.run("reconstruct", "not-a-directory", destination); - output.shouldContain("Could not find disk repository at"); - - output = ExecuteHelper.run("reconstruct", directory, "not-a-destination"); - output.shouldContain("Filename must end with .jfr"); - - output = ExecuteHelper.run("reconstruct", "--wrongOption", directory, destination); - output.shouldContain("Too many arguments"); - - FileWriter fw = new FileWriter(destination); - fw.write('d'); - fw.close(); - output = ExecuteHelper.run("reconstruct", directory, destination); - output.shouldContain("already exists"); - Files.delete(destinationPath); - - // test success - output = ExecuteHelper.run("reconstruct", directory, destination); - System.out.println(output.getOutput()); - output.shouldContain("Reconstruction complete"); - - long reconstructedCount = countEventInRecording(destinationPath); - Asserts.assertEquals(expectedCount, reconstructedCount); - // Cleanup - for (int i = 0; i < RECORDING_COUNT; i++) { - recordings[i].close(); - } - } - - private static long countEventInRecording(Path file) throws IOException { - Integer lastId = -1; - try (RecordingFile rf = new RecordingFile(file)) { - long count = 0; - while (rf.hasMoreEvents()) { - RecordedEvent re = rf.readEvent(); - if (re.getEventType().getName().equals("Correlation")) { - Integer id = re.getValue("id"); - if (id < lastId) { - Asserts.fail("Expected chunk number to increase"); - } - lastId = id; - } - count++; - } - return count; - } - } -} diff --git a/test/jdk/jdk/jfr/cmd/TestSplit.java b/test/jdk/jdk/jfr/cmd/TestSplit.java deleted file mode 100644 index dbce3875314..00000000000 --- a/test/jdk/jdk/jfr/cmd/TestSplit.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package jdk.jfr.cmd; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; - -import jdk.jfr.Configuration; -import jdk.jfr.Recording; -import jdk.jfr.consumer.RecordingFile; -import jdk.test.lib.process.OutputAnalyzer; - -/** - * @test - * @summary Test jfr split - * @key jfr - * @requires vm.hasJFR - * @library /test/lib /test/jdk - * @run main/othervm jdk.jfr.cmd.TestSplit - */ -public class TestSplit { - - public static void main(String[] args) throws Exception { - SimpleDateFormat formatter = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss"); - String dateText = formatter.format(new Date()); - - Path recordingFileA = Paths.get("many-chunks-A-" + dateText + ".jfr"); - Path recordingFileB = Paths.get("many-chunks-B-" + dateText + ".jfr"); - makeRecordingWithChunks(6, recordingFileA); - Files.copy(recordingFileA, recordingFileB); - - String fileAText = recordingFileA.toAbsolutePath().toString(); - String fileBText = recordingFileB.toAbsolutePath().toString(); - - OutputAnalyzer output = ExecuteHelper.run("split"); - output.shouldContain("Missing file"); - - output = ExecuteHelper.run("split", "--wrongOption1", "..wrongOption2", "..wrongOption3", fileAText); - output.shouldContain("Too many arguments"); - - output = ExecuteHelper.run("split", "--wrongOption", fileAText); - output.shouldContain("Unknown option"); - - output = ExecuteHelper.run("split", "--wrongOption", "1", fileAText); - output.shouldContain("Unknown option"); - - output = ExecuteHelper.run("split", "--maxchunks", "-3", fileAText); - output.shouldContain("Must be at least one chunk per file"); - - output = ExecuteHelper.run("split", "--maxchunks", "1000", fileAText); - output.shouldContain("Number of chunks in recording"); - output.shouldContain("doesn't exceed max chunks"); - output = ExecuteHelper.run("split", fileAText); // maxchunks is 5 by - // default - System.out.println(output.getOutput()); - System.out.println(fileAText); - verifyRecording(fileAText.substring(0, fileAText.length() - 4) + "_1.jfr"); - verifyRecording(fileAText.substring(0, fileAText.length() - 4) + "_2.jfr"); - - output = ExecuteHelper.run("split", "--maxchunks", "2", fileBText); - - verifyRecording(fileBText.substring(0, fileBText.length() - 4) + "_1.jfr"); - verifyRecording(fileBText.substring(0, fileBText.length() - 4) + "_2.jfr"); - verifyRecording(fileBText.substring(0, fileBText.length() - 4) + "_3.jfr"); - - output = ExecuteHelper.run("split", "--maxchunks", "2", fileBText); - output.shouldContain("file with that name already exist"); - } - - private static void verifyRecording(String name) throws IOException { - System.out.println("split name " + name); - try (RecordingFile rf = new RecordingFile(Paths.get(name))) { - rf.readEvent(); - } - } - - // Will create at least 2 * count + 1 chunks. - private static void makeRecordingWithChunks(int count, Path file) throws IOException, ParseException { - Recording main = new Recording(Configuration.getConfiguration("default")); - main.setToDisk(true); - main.start(); - for (int i = 0; i < count; i++) { - Recording r = new Recording(); - r.setToDisk(true); - r.start(); - r.stop(); - r.close(); - } - main.stop(); - main.dump(file); - main.close(); - } -} diff --git a/test/jdk/jdk/jfr/cmd/TestSummary.java b/test/jdk/jdk/jfr/cmd/TestSummary.java deleted file mode 100644 index 52a6a90fbbe..00000000000 --- a/test/jdk/jdk/jfr/cmd/TestSummary.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - */ - -package jdk.jfr.cmd; - -import java.nio.file.Path; - -import jdk.jfr.EventType; -import jdk.jfr.consumer.RecordingFile; -import jdk.test.lib.process.OutputAnalyzer; - -/** - * @test - * @summary Test jfr info - * @key jfr - * @requires vm.hasJFR - * @library /test/lib /test/jdk - * @run main/othervm jdk.jfr.cmd.TestSummary - */ -public class TestSummary { - - public static void main(String[] args) throws Exception { - Path f = ExecuteHelper.createProfilingRecording().toAbsolutePath(); - String file = f.toAbsolutePath().toString(); - - OutputAnalyzer output = ExecuteHelper.run("summary"); - output.shouldContain("Missing file"); - - output = ExecuteHelper.run("summary", "--wrongOption", file); - output.shouldContain("Too many arguments"); - - output = ExecuteHelper.run("summary", file); - try (RecordingFile rf = new RecordingFile(f)) { - for (EventType t : rf.readEventTypes()) { - output.shouldContain(t.getName()); - } - } - output.shouldContain("Version"); - } -} From f9fb43d8752aa5c3a09506959c68160a5ee0c7e5 Mon Sep 17 00:00:00 2001 From: egahlin Date: Thu, 6 Dec 2018 23:38:22 +0100 Subject: [PATCH 007/131] 8214925: JFR tool fails to execute Reviewed-by: mgronlun, mseledtsov --- .../classes/jdk/jfr/internal/tool/Main.java | 2 +- test/jdk/jdk/jfr/tool/ExecuteHelper.java | 13 +++++++++++- test/jdk/jdk/jfr/tool/TestAssemble.java | 15 +++++++------ test/jdk/jdk/jfr/tool/TestDisassemble.java | 21 +++++++++---------- test/jdk/jdk/jfr/tool/TestHelp.java | 7 +++---- test/jdk/jdk/jfr/tool/TestMetadata.java | 7 +++---- test/jdk/jdk/jfr/tool/TestPrint.java | 7 +++---- test/jdk/jdk/jfr/tool/TestPrintDefault.java | 3 +-- test/jdk/jdk/jfr/tool/TestPrintJSON.java | 3 +-- test/jdk/jdk/jfr/tool/TestPrintXML.java | 3 +-- test/jdk/jdk/jfr/tool/TestSummary.java | 7 +++---- 11 files changed, 45 insertions(+), 43 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Main.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Main.java index 5324bafb822..785ffda9133 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Main.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Main.java @@ -72,7 +72,7 @@ public static void main(String... args) { System.out.println(); System.out.println(" jfr summary recording.jfr"); System.out.println(); - System.out.println(" jfr metadata recoding.jfr"); + System.out.println(" jfr metadata recording.jfr"); System.out.println(); System.out.println("For more information about available commands, use 'jfr help'"); System.exit(EXIT_OK); diff --git a/test/jdk/jdk/jfr/tool/ExecuteHelper.java b/test/jdk/jdk/jfr/tool/ExecuteHelper.java index 1531398fe28..51347af5bd3 100644 --- a/test/jdk/jdk/jfr/tool/ExecuteHelper.java +++ b/test/jdk/jdk/jfr/tool/ExecuteHelper.java @@ -32,7 +32,10 @@ import jdk.jfr.Configuration; import jdk.jfr.Event; import jdk.jfr.Recording; -import jdk.test.lib.Utils;; +import jdk.test.lib.JDKToolLauncher; +import jdk.test.lib.Utils; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools;; final class ExecuteHelper { @@ -122,4 +125,12 @@ private static void provokeClassLoading() { Matcher m = p.matcher("aaaaab"); m.matches(); } + + public static OutputAnalyzer jfr(String... args) throws Throwable { + JDKToolLauncher l = JDKToolLauncher.createUsingTestJDK("jfr"); + for (String arg : args) { + l.addToolArg(arg); + } + return ProcessTools.executeCommand(l.getCommand()); + } } diff --git a/test/jdk/jdk/jfr/tool/TestAssemble.java b/test/jdk/jdk/jfr/tool/TestAssemble.java index b5b714f01ed..0f21cceecd5 100644 --- a/test/jdk/jdk/jfr/tool/TestAssemble.java +++ b/test/jdk/jdk/jfr/tool/TestAssemble.java @@ -40,7 +40,6 @@ import jdk.jfr.internal.SecuritySupport.SafePath; import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.process.ProcessTools; /** * @test @@ -90,30 +89,30 @@ public static void main(String[] args) throws Throwable { String destination = destinationPath.toAbsolutePath().toString(); // Test failure - OutputAnalyzer output = ProcessTools.executeProcess("jfr", "assemble"); + OutputAnalyzer output = ExecuteHelper.jfr("assemble"); output.shouldContain("too few arguments"); - output = ProcessTools.executeProcess("jfr", "assemble", directory); + output = ExecuteHelper.jfr("assemble", directory); output.shouldContain("too few arguments"); - output = ProcessTools.executeProcess("jfr", "assemble", "not-a-directory", destination); + output = ExecuteHelper.jfr("assemble", "not-a-directory", destination); output.shouldContain("directory does not exist, not-a-directory"); - output = ProcessTools.executeProcess("jfr", "assemble", directory, "not-a-destination"); + output = ExecuteHelper.jfr("assemble", directory, "not-a-destination"); output.shouldContain("filename must end with '.jfr'"); - output = ProcessTools.executeProcess("jfr","assemble", "--wrongOption", directory, destination); + output = ExecuteHelper.jfr("assemble", "--wrongOption", directory, destination); output.shouldContain("too many arguments"); FileWriter fw = new FileWriter(destination); fw.write('d'); fw.close(); - output = ProcessTools.executeProcess("jfr", "assemble", directory, destination); + output = ExecuteHelper.jfr("assemble", directory, destination); output.shouldContain("already exists"); Files.delete(destinationPath); // test success - output = ProcessTools.executeProcess("jfr", "assemble", directory, destination); + output = ExecuteHelper.jfr("assemble", directory, destination); System.out.println(output.getOutput()); output.shouldContain("Finished."); diff --git a/test/jdk/jdk/jfr/tool/TestDisassemble.java b/test/jdk/jdk/jfr/tool/TestDisassemble.java index 7912c261727..29d28531a02 100644 --- a/test/jdk/jdk/jfr/tool/TestDisassemble.java +++ b/test/jdk/jdk/jfr/tool/TestDisassemble.java @@ -37,7 +37,6 @@ import jdk.jfr.Recording; import jdk.jfr.consumer.RecordingFile; import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.process.ProcessTools; /** * @test @@ -64,40 +63,40 @@ public static void main(String[] args) throws Throwable { String fileBText = recordingFileB.toAbsolutePath().toString(); String fileCText = recordingFileC.toAbsolutePath().toString(); - OutputAnalyzer output = ProcessTools.executeProcess("jfr", "disassemble"); + OutputAnalyzer output = ExecuteHelper.jfr("disassemble"); output.shouldContain("missing file"); - output = ProcessTools.executeProcess("jfr","disassemble", "--wrongOption", fileAText); + output = ExecuteHelper.jfr("disassemble", "--wrongOption", fileAText); output.shouldContain("unknown option"); - output = ProcessTools.executeProcess("jfr","disassemble", "--wrongOption", "1", fileAText); + output = ExecuteHelper.jfr("disassemble", "--wrongOption", "1", fileAText); output.shouldContain("unknown option"); - output = ProcessTools.executeProcess("jfr","disassemble", "--max-chunks", "-3", fileAText); + output = ExecuteHelper.jfr("disassemble", "--max-chunks", "-3", fileAText); output.shouldContain("max chunks must be at least 1"); - output = ProcessTools.executeProcess("jfr","disassemble", "--max-chunks", "1000", fileAText); + output = ExecuteHelper.jfr("disassemble", "--max-chunks", "1000", fileAText); output.shouldContain("number of chunks in recording"); output.shouldContain("doesn't exceed max chunks"); - output = ProcessTools.executeProcess("jfr", "disassemble", fileAText); // maxchunks is 5 by + output = ExecuteHelper.jfr("disassemble", fileAText); // maxchunks is 5 by // default System.out.println(output.getOutput()); System.out.println(fileAText); verifyRecording(fileAText.substring(0, fileAText.length() - 4) + "_1.jfr"); verifyRecording(fileAText.substring(0, fileAText.length() - 4) + "_2.jfr"); - output = ProcessTools.executeProcess("jfr","disassemble", "--max-chunks", "2", fileBText); + output = ExecuteHelper.jfr("disassemble", "--max-chunks", "2", fileBText); verifyRecording(fileBText.substring(0, fileBText.length() - 4) + "_1.jfr"); verifyRecording(fileBText.substring(0, fileBText.length() - 4) + "_2.jfr"); verifyRecording(fileBText.substring(0, fileBText.length() - 4) + "_3.jfr"); - output = ProcessTools.executeProcess("jfr","disassemble", "--max-chunks", "2", fileBText); + output = ExecuteHelper.jfr("disassemble", "--max-chunks", "2", fileBText); output.shouldContain("file with that name already exist"); // sanity check - output = ProcessTools.executeProcess("jfr","disassemble", "--max-size", "500000", fileCText); - verifyRecording(fileCText.substring(0, fileCText.length() - 4) + "_1.jfr"); + output = ExecuteHelper.jfr("disassemble", "--max-size", "10000", fileCText); + verifyRecording(fileCText.substring(0, fileCText.length() - 4) + "_01.jfr"); } private static void verifyRecording(String name) throws IOException { diff --git a/test/jdk/jdk/jfr/tool/TestHelp.java b/test/jdk/jdk/jfr/tool/TestHelp.java index df4319683c4..406a68cd74c 100644 --- a/test/jdk/jdk/jfr/tool/TestHelp.java +++ b/test/jdk/jdk/jfr/tool/TestHelp.java @@ -26,7 +26,6 @@ package jdk.jfr.tool; import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.process.ProcessTools; /** * @test @@ -39,7 +38,7 @@ public class TestHelp { public static void main(String[] args) throws Throwable { - OutputAnalyzer output = ProcessTools.executeProcess("jfr", "help"); + OutputAnalyzer output = ExecuteHelper.jfr("help"); output.shouldContain("print"); output.shouldContain("assemble"); output.shouldContain("disassemble"); @@ -47,11 +46,11 @@ public static void main(String[] args) throws Throwable { output.shouldContain("summary"); output.shouldContain("help"); - output = ProcessTools.executeProcess("jfr", "help", "version"); + output = ExecuteHelper.jfr("help", "version"); output.shouldContain("Display version of the jfr tool"); output.shouldContain("jfr version"); - output = ProcessTools.executeProcess("jfr", "help", "wrongcommand"); + output = ExecuteHelper.jfr("help", "wrongcommand"); output.shouldContain("unknown command 'wrongcommand'"); } } diff --git a/test/jdk/jdk/jfr/tool/TestMetadata.java b/test/jdk/jdk/jfr/tool/TestMetadata.java index d7289648f04..45cc55324f4 100644 --- a/test/jdk/jdk/jfr/tool/TestMetadata.java +++ b/test/jdk/jdk/jfr/tool/TestMetadata.java @@ -30,7 +30,6 @@ import jdk.jfr.EventType; import jdk.jfr.consumer.RecordingFile; import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.process.ProcessTools; /** * @test @@ -46,13 +45,13 @@ public static void main(String[] args) throws Throwable { Path f = ExecuteHelper.createProfilingRecording().toAbsolutePath(); String file = f.toAbsolutePath().toString(); - OutputAnalyzer output = ProcessTools.executeProcess("jfr", "metadata"); + OutputAnalyzer output = ExecuteHelper.jfr("metadata"); output.shouldContain("missing file"); - output = ProcessTools.executeProcess("jfr", "metadata", "--wrongOption", file); + output = ExecuteHelper.jfr("metadata", "--wrongOption", file); output.shouldContain("unknown option --wrongOption"); - output = ProcessTools.executeProcess("jfr", "metadata", file); + output = ExecuteHelper.jfr("metadata", file); try (RecordingFile rf = new RecordingFile(f)) { for (EventType t : rf.readEventTypes()) { String name = t.getName(); diff --git a/test/jdk/jdk/jfr/tool/TestPrint.java b/test/jdk/jdk/jfr/tool/TestPrint.java index 1d6eb450491..f6b01e71893 100644 --- a/test/jdk/jdk/jfr/tool/TestPrint.java +++ b/test/jdk/jdk/jfr/tool/TestPrint.java @@ -31,7 +31,6 @@ import jdk.test.lib.Utils; import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.process.ProcessTools; /** * @test @@ -45,17 +44,17 @@ public class TestPrint { public static void main(String[] args) throws Throwable { - OutputAnalyzer output = ProcessTools.executeProcess("jfr", "print"); + OutputAnalyzer output = ExecuteHelper.jfr("print"); output.shouldContain("missing file"); - output = ProcessTools.executeProcess("jfr", "print", "missing.jfr"); + output = ExecuteHelper.jfr("print", "missing.jfr"); output.shouldContain("could not find file "); Path file = Utils.createTempFile("faked-print-file", ".jfr"); FileWriter fw = new FileWriter(file.toFile()); fw.write('d'); fw.close(); - output = ProcessTools.executeProcess("jfr", "print", "--wrongOption", file.toAbsolutePath().toString()); + output = ExecuteHelper.jfr("print", "--wrongOption", file.toAbsolutePath().toString()); output.shouldContain("unknown option"); Files.delete(file); } diff --git a/test/jdk/jdk/jfr/tool/TestPrintDefault.java b/test/jdk/jdk/jfr/tool/TestPrintDefault.java index 15f38dbeb42..a03b76d2f91 100644 --- a/test/jdk/jdk/jfr/tool/TestPrintDefault.java +++ b/test/jdk/jdk/jfr/tool/TestPrintDefault.java @@ -28,7 +28,6 @@ import java.nio.file.Path; import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.process.ProcessTools; /** * @test @@ -48,7 +47,7 @@ public static void main(String... args) throws Throwable { Path recordingFile = ExecuteHelper.createProfilingRecording().toAbsolutePath(); - OutputAnalyzer output = ProcessTools.executeProcess("jfr", "print", recordingFile.toString()); + OutputAnalyzer output = ExecuteHelper.jfr("print", recordingFile.toString()); output.shouldContain("JVMInformation"); } } diff --git a/test/jdk/jdk/jfr/tool/TestPrintJSON.java b/test/jdk/jdk/jfr/tool/TestPrintJSON.java index e086f1c6dfa..71337904c98 100644 --- a/test/jdk/jdk/jfr/tool/TestPrintJSON.java +++ b/test/jdk/jdk/jfr/tool/TestPrintJSON.java @@ -43,7 +43,6 @@ import jdk.nashorn.api.scripting.JSObject; import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.process.ProcessTools; /** * @test @@ -63,7 +62,7 @@ public static void main(String... args) throws Throwable { Path recordingFile = ExecuteHelper.createProfilingRecording().toAbsolutePath(); - OutputAnalyzer output = ProcessTools.executeProcess("jfr", "print", "--json", "--stack-depth", "999", recordingFile.toString()); + OutputAnalyzer output = ExecuteHelper.jfr("print", "--json", "--stack-depth", "999", recordingFile.toString()); String json = output.getStdout(); // Parse JSON using Nashorn diff --git a/test/jdk/jdk/jfr/tool/TestPrintXML.java b/test/jdk/jdk/jfr/tool/TestPrintXML.java index 8f9442076bd..f84ee1372c4 100644 --- a/test/jdk/jdk/jfr/tool/TestPrintXML.java +++ b/test/jdk/jdk/jfr/tool/TestPrintXML.java @@ -58,7 +58,6 @@ import jdk.jfr.consumer.RecordedObject; import jdk.jfr.consumer.RecordingFile; import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.process.ProcessTools; /** * @test @@ -77,7 +76,7 @@ public static void main(String... args) throws Throwable { Path recordingFile = ExecuteHelper.createProfilingRecording().toAbsolutePath(); - OutputAnalyzer output = ProcessTools.executeProcess("jfr", "print", "--xml", "--stack-depth", "9999", recordingFile.toString()); + OutputAnalyzer output = ExecuteHelper.jfr("print", "--xml", "--stack-depth", "9999", recordingFile.toString()); System.out.println(recordingFile); String xml = output.getStdout(); diff --git a/test/jdk/jdk/jfr/tool/TestSummary.java b/test/jdk/jdk/jfr/tool/TestSummary.java index 2e6877b93e3..dcbc5a4da6f 100644 --- a/test/jdk/jdk/jfr/tool/TestSummary.java +++ b/test/jdk/jdk/jfr/tool/TestSummary.java @@ -30,7 +30,6 @@ import jdk.jfr.EventType; import jdk.jfr.consumer.RecordingFile; import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.process.ProcessTools; /** * @test @@ -46,13 +45,13 @@ public static void main(String[] args) throws Throwable { Path f = ExecuteHelper.createProfilingRecording().toAbsolutePath(); String file = f.toAbsolutePath().toString(); - OutputAnalyzer output = ProcessTools.executeProcess("jfr", "summary"); + OutputAnalyzer output = ExecuteHelper.jfr("summary"); output.shouldContain("missing file"); - output = ProcessTools.executeProcess("jfr", "summary", "--wrongOption", file); + output = ExecuteHelper.jfr("summary", "--wrongOption", file); output.shouldContain("too many arguments"); - output = ProcessTools.executeProcess("jfr", "summary", file); + output = ExecuteHelper.jfr("summary", file); try (RecordingFile rf = new RecordingFile(f)) { for (EventType t : rf.readEventTypes()) { output.shouldContain(t.getName()); From 8f004e0a5f73fb6c986fbf89bd1b193bd3ce9d7a Mon Sep 17 00:00:00 2001 From: stuefe Date: Tue, 26 Mar 2019 15:46:15 +0100 Subject: [PATCH 008/131] 8221406: Windows 32bit build error in NetworkInterface_winXP.c Reviewed-by: clanger --- src/java.base/windows/native/libnet/NetworkInterface_winXP.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.base/windows/native/libnet/NetworkInterface_winXP.c b/src/java.base/windows/native/libnet/NetworkInterface_winXP.c index 3b26bacc4ea..85b052b5f58 100644 --- a/src/java.base/windows/native/libnet/NetworkInterface_winXP.c +++ b/src/java.base/windows/native/libnet/NetworkInterface_winXP.c @@ -41,7 +41,7 @@ void printnif (netif *nif) { #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, From 6dc2958544228aa7c45dcb32bba94efa9223d4d4 Mon Sep 17 00:00:00 2001 From: mchung Date: Thu, 15 Aug 2019 13:41:30 -0700 Subject: [PATCH 009/131] 8193325: StackFrameInfo::getByteCodeIndex returns wrong value if bci > 32767 Reviewed-by: coleenp, fparain, shade, plevart --- .../classes/java/lang/StackFrameInfo.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/java.base/share/classes/java/lang/StackFrameInfo.java b/src/java.base/share/classes/java/lang/StackFrameInfo.java index 10a6989d3c7..6ebcf9735b3 100644 --- a/src/java.base/share/classes/java/lang/StackFrameInfo.java +++ b/src/java.base/share/classes/java/lang/StackFrameInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, 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 @@ -32,23 +32,23 @@ import java.lang.invoke.MethodType; class StackFrameInfo implements StackFrame { - private final byte RETAIN_CLASS_REF = 0x01; - private final static JavaLangInvokeAccess JLIA = SharedSecrets.getJavaLangInvokeAccess(); - private final byte flags; - private final Object memberName; - private final short bci; + private final boolean retainClassRef; + private final Object memberName; // MemberName initialized by VM + private int bci; // initialized by VM to >= 0 private volatile StackTraceElement ste; /* - * Create StackFrameInfo for StackFrameTraverser and LiveStackFrameTraverser - * to use + * Construct an empty StackFrameInfo object that will be filled by the VM + * during stack walking. + * + * @see StackStreamFactory.AbstractStackWalker#callStackWalk + * @see StackStreamFactory.AbstractStackWalker#fetchStackFrames */ StackFrameInfo(StackWalker walker) { - this.flags = walker.retainClassRef ? RETAIN_CLASS_REF : 0; - this.bci = -1; + this.retainClassRef = walker.retainClassRef; this.memberName = JLIA.newMemberName(); } @@ -136,7 +136,7 @@ public StackTraceElement toStackTraceElement() { } private void ensureRetainClassRefEnabled() { - if ((flags & RETAIN_CLASS_REF) == 0) { + if (!retainClassRef) { throw new UnsupportedOperationException("No access to RETAIN_CLASS_REFERENCE"); } } From c2dad880501f2b8db72999a4856b49041fdba092 Mon Sep 17 00:00:00 2001 From: thartmann Date: Fri, 24 Aug 2018 08:17:23 +0200 Subject: [PATCH 010/131] 8209833: C2 compilation fails with "assert(ex_map->jvms()->same_calls_as(_exceptions->jvms())) failed: all collected exceptions must come from the same place" Summary: Deoptimize if exception is thrown in _clone intrinsic. Reviewed-by: kvn --- .../compiler/intrinsics/object/TestClone.java | 98 +++++++++++++++++-- 1 file changed, 88 insertions(+), 10 deletions(-) diff --git a/test/hotspot/jtreg/compiler/intrinsics/object/TestClone.java b/test/hotspot/jtreg/compiler/intrinsics/object/TestClone.java index e239f55d597..98cc9a93ff1 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/object/TestClone.java +++ b/test/hotspot/jtreg/compiler/intrinsics/object/TestClone.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ * @library /test/lib * * @run main/othervm -XX:-TieredCompilation -Xbatch - * -XX:CompileCommand=compileonly,compiler.intrinsics.object.TestClone::f + * -XX:CompileCommand=compileonly,compiler.intrinsics.object.TestClone::test* * compiler.intrinsics.object.TestClone */ @@ -37,6 +37,43 @@ import jdk.test.lib.Asserts; +abstract class MyAbstract { + + public Object myClone1() throws CloneNotSupportedException { + return this.clone(); + } + + public Object myClone2() throws CloneNotSupportedException { + return this.clone(); + } + + public Object myClone3() throws CloneNotSupportedException { + return this.clone(); + } +} + +class MyClass1 extends MyAbstract { + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } +} + +class MyClass2 extends MyAbstract { + +} + +class MyClass3 extends MyAbstract implements Cloneable { + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } +} + +class MyClass4 extends MyAbstract implements Cloneable { + +} + public class TestClone implements Cloneable { static class A extends TestClone {} static class B extends TestClone { @@ -56,29 +93,70 @@ public D clone() { } static TestClone a = new A(), b = new B(), c = new C(), d = new D(); - public static Object f(TestClone o) throws CloneNotSupportedException { + public static Object test1(TestClone o) throws CloneNotSupportedException { // Polymorphic call site: >90% Object::clone / <10% other methods return o.clone(); } + public static void test2(MyAbstract obj, boolean shouldThrow) throws Exception { + try { + obj.myClone1(); + } catch (Exception e) { + return; // Expected + } + Asserts.assertFalse(shouldThrow, "No exception thrown"); + } + + public static void test3(MyAbstract obj, boolean shouldThrow) throws Exception { + try { + obj.myClone2(); + } catch (Exception e) { + return; // Expected + } + Asserts.assertFalse(shouldThrow, "No exception thrown"); + } + + public static void test4(MyAbstract obj, boolean shouldThrow) throws Exception { + try { + obj.myClone3(); + } catch (Exception e) { + return; // Expected + } + Asserts.assertFalse(shouldThrow, "No exception thrown"); + } + public static void main(String[] args) throws Exception { TestClone[] params1 = {a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, b, c, d}; + MyClass1 obj1 = new MyClass1(); + MyClass2 obj2 = new MyClass2(); + MyClass3 obj3 = new MyClass3(); + MyClass4 obj4 = new MyClass4(); + for (int i = 0; i < 15000; i++) { - f(params1[i % params1.length]); + test1(params1[i % params1.length]); + + test2(obj1, true); + test2(obj2, true); + + test3(obj3, false); + test3(obj2, true); + + test4(obj3, false); + test4(obj4, false); } - Asserts.assertTrue(f(a) != a); - Asserts.assertTrue(f(b) == b); - Asserts.assertTrue(f(c) == c); - Asserts.assertTrue(f(d) == d); + Asserts.assertTrue(test1(a) != a); + Asserts.assertTrue(test1(b) == b); + Asserts.assertTrue(test1(c) == c); + Asserts.assertTrue(test1(d) == d); try { - f(null); - throw new AssertionError(""); + test1(null); + throw new AssertionError("No exception thrown"); } catch (NullPointerException e) { /* expected */ } System.out.println("TEST PASSED"); From b9903652a2d97692d0f1f083b033ae12b7611bc2 Mon Sep 17 00:00:00 2001 From: thartmann Date: Tue, 20 Aug 2019 07:47:13 +0200 Subject: [PATCH 011/131] 8228888: C2 compilation fails with assert "m has strange control" Summary: Weakened too strong assert. Reviewed-by: kvn, roland --- .../compiler/loopopts/StrangeControl.jasm | 48 ++++++++++++++++++ .../compiler/loopopts/TestStrangeControl.java | 49 +++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/loopopts/StrangeControl.jasm create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestStrangeControl.java diff --git a/test/hotspot/jtreg/compiler/loopopts/StrangeControl.jasm b/test/hotspot/jtreg/compiler/loopopts/StrangeControl.jasm new file mode 100644 index 00000000000..c36217ddb05 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/StrangeControl.jasm @@ -0,0 +1,48 @@ +/* + * 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. + * + */ + +super public class compiler/loopopts/StrangeControl + version 51:0 +{ + +static Field field:"I"; + +public static Method test:"(I)V" + stack 2 locals 2 +{ + iconst_0; + istore 1; + L1: stack_frame_type append; + locals_map int; + iinc 1, 1; + iload 1; + iconst_2; + if_icmple L1; + L2: stack_frame_type same; + iload_0; + putstatic Field field:"I"; + goto L1; +} + +} // end Class StrangeControl diff --git a/test/hotspot/jtreg/compiler/loopopts/TestStrangeControl.java b/test/hotspot/jtreg/compiler/loopopts/TestStrangeControl.java new file mode 100644 index 00000000000..d93ed991073 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestStrangeControl.java @@ -0,0 +1,49 @@ +/* + * 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 8228888 + * @summary Test PhaseIdealLoop::has_local_phi_input() with phi input with non-dominating control. + * @compile StrangeControl.jasm + * @run main/othervm -Xbatch -XX:CompileCommand=inline,compiler.loopopts.StrangeControl::test + * compiler.loopopts.TestStrangeControl + */ + +package compiler.loopopts; + +public class TestStrangeControl { + + public static void main(String[] args) throws Exception { + Thread thread = new Thread() { + public void run() { + // Run this in an own thread because it's basically an endless loop + StrangeControl.test(42); + } + }; + thread.start(); + // Give thread executing strange control loop enough time to trigger OSR compilation + Thread.sleep(4000); + } +} From 8b251d194e93e77ee4cd8bde070c892a733d6c7f Mon Sep 17 00:00:00 2001 From: redestad Date: Tue, 7 Aug 2018 23:08:52 +0200 Subject: [PATCH 012/131] 8209003: Consolidate use of empty collections in java.lang.module Reviewed-by: alanb, mchung --- .../share/classes/java/lang/Module.java | 3 +- .../share/classes/java/lang/ModuleLayer.java | 5 +- .../java/lang/module/Configuration.java | 15 ++- .../java/lang/module/ModuleDescriptor.java | 116 ++++++------------ .../java/lang/module/ModuleFinder.java | 2 +- .../classes/jdk/internal/module/Builder.java | 13 +- .../module/ExplodedSystemModules.java | 5 +- .../jdk/internal/module/ModuleBootstrap.java | 6 +- .../jdk/internal/module/ModuleInfo.java | 7 +- .../jdk/internal/module/ModulePatcher.java | 3 +- .../jdk/internal/module/ModulePath.java | 5 +- .../jdk/internal/module/ServicesCatalog.java | 5 +- .../internal/module/SystemModuleFinders.java | 6 +- .../lang/module/ModuleDescriptorTest.java | 7 +- 14 files changed, 76 insertions(+), 122 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Module.java b/src/java.base/share/classes/java/lang/Module.java index 2f942816ab5..6d474b1ad5c 100644 --- a/src/java.base/share/classes/java/lang/Module.java +++ b/src/java.base/share/classes/java/lang/Module.java @@ -40,7 +40,6 @@ import java.net.URL; import java.security.AccessController; import java.security.PrivilegedAction; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -1123,7 +1122,7 @@ static Map defineModules(Configuration cf, Set reads = new HashSet<>(); // name -> source Module when in parent layer - Map nameToSource = Collections.emptyMap(); + Map nameToSource = Map.of(); for (ResolvedModule other : resolvedModule.reads()) { Module m2 = null; diff --git a/src/java.base/share/classes/java/lang/ModuleLayer.java b/src/java.base/share/classes/java/lang/ModuleLayer.java index f4ea6553e52..213358712db 100644 --- a/src/java.base/share/classes/java/lang/ModuleLayer.java +++ b/src/java.base/share/classes/java/lang/ModuleLayer.java @@ -173,7 +173,7 @@ private ModuleLayer(Configuration cf, Map map; if (parents.isEmpty()) { - map = Collections.emptyMap(); + map = Map.of(); } else { map = Module.defineModules(cf, clf, this); } @@ -811,8 +811,7 @@ Stream layers() { public Set modules() { Set modules = this.modules; if (modules == null) { - this.modules = modules = - Collections.unmodifiableSet(new HashSet<>(nameToModule.values())); + this.modules = modules = Set.copyOf(nameToModule.values()); } return modules; } diff --git a/src/java.base/share/classes/java/lang/module/Configuration.java b/src/java.base/share/classes/java/lang/module/Configuration.java index 24bf3349b85..c0c5c1dc3d4 100644 --- a/src/java.base/share/classes/java/lang/module/Configuration.java +++ b/src/java.base/share/classes/java/lang/module/Configuration.java @@ -31,7 +31,6 @@ import java.util.Collection; import java.util.Collections; import java.util.Deque; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -119,10 +118,10 @@ public final class Configuration { String targetPlatform() { return targetPlatform; } private Configuration() { - this.parents = Collections.emptyList(); - this.graph = Collections.emptyMap(); - this.modules = Collections.emptySet(); - this.nameToModule = Collections.emptyMap(); + this.parents = List.of(); + this.graph = Map.of(); + this.modules = Set.of(); + this.nameToModule = Map.of(); this.targetPlatform = null; } @@ -140,7 +139,7 @@ private Configuration(List parents, Resolver resolver) { i++; } - this.parents = Collections.unmodifiableList(parents); + this.parents = List.copyOf(parents); this.graph = g; this.modules = Set.of(moduleArray); this.nameToModule = Map.ofEntries(nameEntries); @@ -554,7 +553,7 @@ public Optional findModule(String name) { Set descriptors() { if (modules.isEmpty()) { - return Collections.emptySet(); + return Set.of(); } else { return modules.stream() .map(ResolvedModule::reference) @@ -596,7 +595,7 @@ Stream configurations() { } } } - this.allConfigurations = Collections.unmodifiableList(allConfigurations); + this.allConfigurations = allConfigurations; // no need to do defensive copy } return allConfigurations.stream(); } diff --git a/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java b/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java index cb578423cba..fa359348f6c 100644 --- a/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java +++ b/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java @@ -102,7 +102,7 @@ public class ModuleDescriptor * @since 9 * @spec JPMS */ - public static enum Modifier { + public enum Modifier { /** * An open module. An open module does not declare any open packages * but the resulting module is treated as if all packages are open. @@ -149,7 +149,7 @@ public final static class Requires * @since 9 * @spec JPMS */ - public static enum Modifier { + public enum Modifier { /** * The dependence causes any module which depends on the current @@ -185,12 +185,7 @@ public static enum Modifier { private Requires(Set ms, String mn, Version v, String vs) { assert v == null || vs == null; - if (ms.isEmpty()) { - ms = Collections.emptySet(); - } else { - ms = Collections.unmodifiableSet(EnumSet.copyOf(ms)); - } - this.mods = ms; + this.mods = Set.copyOf(ms); this.name = mn; this.compiledVersion = v; this.rawCompiledVersion = vs; @@ -384,7 +379,7 @@ public final static class Exports * @since 9 * @spec JPMS */ - public static enum Modifier { + public enum Modifier { /** * The export was not explicitly or implicitly declared in the @@ -408,14 +403,9 @@ public static enum Modifier { * Constructs an export */ private Exports(Set ms, String source, Set targets) { - if (ms.isEmpty()) { - ms = Collections.emptySet(); - } else { - ms = Collections.unmodifiableSet(EnumSet.copyOf(ms)); - } - this.mods = ms; + this.mods = Set.copyOf(ms); this.source = source; - this.targets = emptyOrUnmodifiableSet(targets); + this.targets = Set.copyOf(targets); } private Exports(Set ms, @@ -596,7 +586,7 @@ public final static class Opens * @since 9 * @spec JPMS */ - public static enum Modifier { + public enum Modifier { /** * The open package was not explicitly or implicitly declared in @@ -620,14 +610,9 @@ public static enum Modifier { * Constructs an Opens */ private Opens(Set ms, String source, Set targets) { - if (ms.isEmpty()) { - ms = Collections.emptySet(); - } else { - ms = Collections.unmodifiableSet(EnumSet.copyOf(ms)); - } - this.mods = ms; + this.mods = Set.copyOf(ms); this.source = source; - this.targets = emptyOrUnmodifiableSet(targets); + this.targets = Set.copyOf(targets); } private Opens(Set ms, @@ -800,7 +785,7 @@ public final static class Provides private Provides(String service, List providers) { this.service = service; - this.providers = Collections.unmodifiableList(providers); + this.providers = List.copyOf(providers); } private Provides(String service, List providers, boolean unused) { @@ -1264,18 +1249,18 @@ private ModuleDescriptor(String name, this.name = name; this.version = version; this.rawVersionString = rawVersionString; - this.modifiers = emptyOrUnmodifiableSet(modifiers); + this.modifiers = Set.copyOf(modifiers); this.open = modifiers.contains(Modifier.OPEN); this.automatic = modifiers.contains(Modifier.AUTOMATIC); assert (requires.stream().map(Requires::name).distinct().count() == requires.size()); - this.requires = emptyOrUnmodifiableSet(requires); - this.exports = emptyOrUnmodifiableSet(exports); - this.opens = emptyOrUnmodifiableSet(opens); - this.uses = emptyOrUnmodifiableSet(uses); - this.provides = emptyOrUnmodifiableSet(provides); + this.requires = Set.copyOf(requires); + this.exports = Set.copyOf(exports); + this.opens = Set.copyOf(opens); + this.uses = Set.copyOf(uses); + this.provides = Set.copyOf(provides); - this.packages = emptyOrUnmodifiableSet(packages); + this.packages = Set.copyOf(packages); this.mainClass = mainClass; } @@ -1734,16 +1719,14 @@ public Builder exports(Set ms, String pn, Set targets) { - Exports e = new Exports(ms, pn, targets); - - // check targets - targets = e.targets(); + targets = new HashSet<>(targets); if (targets.isEmpty()) throw new IllegalArgumentException("Empty target set"); if (strict) { - requirePackageName(e.source()); + requirePackageName(pn); targets.forEach(Checks::requireModuleName); } + Exports e = new Exports(ms, pn, targets); return exports(e); } @@ -1769,7 +1752,7 @@ public Builder exports(Set ms, String pn) { if (strict) { requirePackageName(pn); } - Exports e = new Exports(ms, pn, Collections.emptySet()); + Exports e = new Exports(ms, pn, Set.of()); return exports(e); } @@ -1794,7 +1777,7 @@ public Builder exports(Set ms, String pn) { * or this builder is for an automatic module */ public Builder exports(String pn, Set targets) { - return exports(Collections.emptySet(), pn, targets); + return exports(Set.of(), pn, targets); } /** @@ -1813,7 +1796,7 @@ public Builder exports(String pn, Set targets) { * or this builder is for an automatic module */ public Builder exports(String pn) { - return exports(Collections.emptySet(), pn); + return exports(Set.of(), pn); } /** @@ -1870,16 +1853,14 @@ public Builder opens(Set ms, String pn, Set targets) { - Opens opens = new Opens(ms, pn, targets); - - // check targets - targets = opens.targets(); + targets = new HashSet<>(targets); if (targets.isEmpty()) throw new IllegalArgumentException("Empty target set"); if (strict) { - requirePackageName(opens.source()); + requirePackageName(pn); targets.forEach(Checks::requireModuleName); } + Opens opens = new Opens(ms, pn, targets); return opens(opens); } @@ -1905,7 +1886,7 @@ public Builder opens(Set ms, String pn) { if (strict) { requirePackageName(pn); } - Opens e = new Opens(ms, pn, Collections.emptySet()); + Opens e = new Opens(ms, pn, Set.of()); return opens(e); } @@ -1929,7 +1910,7 @@ public Builder opens(Set ms, String pn) { * builder for an open module or automatic module */ public Builder opens(String pn, Set targets) { - return opens(Collections.emptySet(), pn, targets); + return opens(Set.of(), pn, targets); } /** @@ -1948,7 +1929,7 @@ public Builder opens(String pn, Set targets) { * builder for an open module or automatic module */ public Builder opens(String pn) { - return opens(Collections.emptySet(), pn); + return opens(Set.of(), pn); } /** @@ -2021,15 +2002,12 @@ public Builder provides(Provides p) { * declared */ public Builder provides(String service, List providers) { - Provides p = new Provides(service, providers); - - // check providers after the set has been copied. - List providerNames = p.providers(); - if (providerNames.isEmpty()) + providers = new ArrayList<>(providers); + if (providers.isEmpty()) throw new IllegalArgumentException("Empty providers set"); if (strict) { - requireServiceTypeName(p.service()); - providerNames.forEach(Checks::requireServiceProviderName); + requireServiceTypeName(service); + providers.forEach(Checks::requireServiceProviderName); } else { // Disallow service/providers in unnamed package String pn = packageName(service); @@ -2037,7 +2015,7 @@ public Builder provides(String service, List providers) { throw new IllegalArgumentException(service + ": unnamed package"); } - for (String name : providerNames) { + for (String name : providers) { pn = packageName(name); if (pn.isEmpty()) { throw new IllegalArgumentException(name @@ -2045,6 +2023,7 @@ public Builder provides(String service, List providers) { } } } + Provides p = new Provides(service, providers); return provides(p); } @@ -2574,27 +2553,6 @@ public static ModuleDescriptor read(ByteBuffer bb) { return ModuleInfo.read(bb, null).descriptor(); } - private static Map emptyOrUnmodifiableMap(Map map) { - if (map.isEmpty()) { - return Collections.emptyMap(); - } else if (map.size() == 1) { - Map.Entry entry = map.entrySet().iterator().next(); - return Collections.singletonMap(entry.getKey(), entry.getValue()); - } else { - return Collections.unmodifiableMap(map); - } - } - - private static Set emptyOrUnmodifiableSet(Set set) { - if (set.isEmpty()) { - return Collections.emptySet(); - } else if (set.size() == 1) { - return Collections.singleton(set.iterator().next()); - } else { - return Collections.unmodifiableSet(set); - } - } - private static String packageName(String cn) { int index = cn.lastIndexOf('.'); return (index == -1) ? "" : cn.substring(0, index); @@ -2674,7 +2632,7 @@ public Requires newRequires(Set ms, String mn, Version v) { @Override public Exports newExports(Set ms, String source) { - return new Exports(ms, source, Collections.emptySet(), true); + return new Exports(ms, source, Set.of(), true); } @Override @@ -2693,7 +2651,7 @@ public Opens newOpens(Set ms, @Override public Opens newOpens(Set ms, String source) { - return new Opens(ms, source, Collections.emptySet(), true); + return new Opens(ms, source, Set.of(), true); } @Override diff --git a/src/java.base/share/classes/java/lang/module/ModuleFinder.java b/src/java.base/share/classes/java/lang/module/ModuleFinder.java index b85b2e179da..c556390aa88 100644 --- a/src/java.base/share/classes/java/lang/module/ModuleFinder.java +++ b/src/java.base/share/classes/java/lang/module/ModuleFinder.java @@ -306,7 +306,7 @@ public Optional find(String name) { @Override public Set findAll() { - return Collections.emptySet(); + return Set.of(); } }; } diff --git a/src/java.base/share/classes/jdk/internal/module/Builder.java b/src/java.base/share/classes/jdk/internal/module/Builder.java index 2792ccca19f..fa6fe24ba2f 100644 --- a/src/java.base/share/classes/jdk/internal/module/Builder.java +++ b/src/java.base/share/classes/jdk/internal/module/Builder.java @@ -30,7 +30,6 @@ import java.lang.module.ModuleDescriptor.Provides; import java.lang.module.ModuleDescriptor.Requires; import java.lang.module.ModuleDescriptor.Version; -import java.util.Collections; import java.util.List; import java.util.Set; @@ -148,11 +147,11 @@ public static Provides newProvides(String st, List pcs) { Builder(String name) { this.name = name; - this.requires = Collections.emptySet(); - this.exports = Collections.emptySet(); - this.opens = Collections.emptySet(); - this.provides = Collections.emptySet(); - this.uses = Collections.emptySet(); + this.requires = Set.of(); + this.exports = Set.of(); + this.opens = Set.of(); + this.provides = Set.of(); + this.uses = Set.of(); } Builder open(boolean value) { @@ -253,7 +252,7 @@ private Set modifiers() { if (synthetic) n++; if (mandated) n++; if (n == 0) { - return Collections.emptySet(); + return Set.of(); } else { ModuleDescriptor.Modifier[] mods = new ModuleDescriptor.Modifier[n]; if (open) mods[--n] = ModuleDescriptor.Modifier.OPEN; diff --git a/src/java.base/share/classes/jdk/internal/module/ExplodedSystemModules.java b/src/java.base/share/classes/jdk/internal/module/ExplodedSystemModules.java index b424b9c0ec1..5f241913e70 100644 --- a/src/java.base/share/classes/jdk/internal/module/ExplodedSystemModules.java +++ b/src/java.base/share/classes/jdk/internal/module/ExplodedSystemModules.java @@ -26,7 +26,6 @@ package jdk.internal.module; import java.lang.module.ModuleDescriptor; -import java.util.Collections; import java.util.Map; import java.util.Set; @@ -72,11 +71,11 @@ public Map> moduleReads() { @Override public Map> concealedPackagesToOpen() { - return Collections.emptyMap(); + return Map.of(); } @Override public Map> exportedPackagesToOpen() { - return Collections.emptyMap(); + return Map.of(); } } diff --git a/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java b/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java index 694ec1ea7c8..1321bb38c1e 100644 --- a/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java +++ b/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java @@ -568,7 +568,7 @@ private static Set addModules() { // the system property is removed after decoding String value = getAndRemoveProperty(prefix + index); if (value == null) { - return Collections.emptySet(); + return Set.of(); } else { Set modules = new HashSet<>(); while (value != null) { @@ -589,7 +589,7 @@ private static Set addModules() { private static Set limitModules() { String value = getAndRemoveProperty("jdk.module.limitmods"); if (value == null) { - return Collections.emptySet(); + return Set.of(); } else { Set names = new HashSet<>(); for (String name : value.split(",")) { @@ -841,7 +841,7 @@ private static Map> decode(String prefix, // the system property is removed after decoding String value = getAndRemoveProperty(prefix + index); if (value == null) - return Collections.emptyMap(); + return Map.of(); Map> map = new HashMap<>(); diff --git a/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java b/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java index 230695206f0..33e5b33f963 100644 --- a/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java +++ b/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java @@ -40,7 +40,6 @@ import java.nio.ByteBuffer; import java.nio.BufferUnderflowException; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -374,7 +373,7 @@ private Builder readModuleAttribute(DataInput in, ConstantPool cpool, int major) int requires_flags = in.readUnsignedShort(); Set mods; if (requires_flags == 0) { - mods = Collections.emptySet(); + mods = Set.of(); } else { mods = new HashSet<>(); if ((requires_flags & ACC_TRANSITIVE) != 0) @@ -430,7 +429,7 @@ private Builder readModuleAttribute(DataInput in, ConstantPool cpool, int major) Set mods; int exports_flags = in.readUnsignedShort(); if (exports_flags == 0) { - mods = Collections.emptySet(); + mods = Set.of(); } else { mods = new HashSet<>(); if ((exports_flags & ACC_SYNTHETIC) != 0) @@ -470,7 +469,7 @@ private Builder readModuleAttribute(DataInput in, ConstantPool cpool, int major) Set mods; int opens_flags = in.readUnsignedShort(); if (opens_flags == 0) { - mods = Collections.emptySet(); + mods = Set.of(); } else { mods = new HashSet<>(); if ((opens_flags & ACC_SYNTHETIC) != 0) diff --git a/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java b/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java index 8b50e12dec6..e37e5cf3437 100644 --- a/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java +++ b/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java @@ -42,7 +42,6 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -78,7 +77,7 @@ public final class ModulePatcher { */ public ModulePatcher(Map> input) { if (input.isEmpty()) { - this.map = Collections.emptyMap(); + this.map = Map.of(); } else { Map> map = new HashMap<>(); for (Map.Entry> e : input.entrySet()) { diff --git a/src/java.base/share/classes/jdk/internal/module/ModulePath.java b/src/java.base/share/classes/jdk/internal/module/ModulePath.java index 2e5918627b5..0718336093b 100644 --- a/src/java.base/share/classes/jdk/internal/module/ModulePath.java +++ b/src/java.base/share/classes/jdk/internal/module/ModulePath.java @@ -45,7 +45,6 @@ import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -217,7 +216,7 @@ private Map scan(Path entry) { try { attrs = Files.readAttributes(entry, BasicFileAttributes.class); } catch (NoSuchFileException e) { - return Collections.emptyMap(); + return Map.of(); } catch (IOException ioe) { throw new FindException(ioe); } @@ -236,7 +235,7 @@ private Map scan(Path entry) { ModuleReference mref = readModule(entry, attrs); if (mref != null) { String name = mref.descriptor().name(); - return Collections.singletonMap(name, mref); + return Map.of(name, mref); } // not recognized diff --git a/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java b/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java index f0d7126adc8..9e39e5ee479 100644 --- a/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java +++ b/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java @@ -28,7 +28,6 @@ import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleDescriptor.Provides; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; @@ -147,7 +146,7 @@ public void addProvider(Module module, Class service, Class impl) { * the given service type. */ public List findServices(String service) { - return map.getOrDefault(service, Collections.emptyList()); + return map.getOrDefault(service, List.of()); } /** @@ -175,4 +174,4 @@ public static ServicesCatalog getServicesCatalog(ClassLoader loader) { // the ServicesCatalog registered to a class loader private static final ClassLoaderValue CLV = new ClassLoaderValue<>(); -} \ No newline at end of file +} diff --git a/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java b/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java index 9ed3b54c01c..4775e719cd0 100644 --- a/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java +++ b/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java @@ -282,8 +282,8 @@ private static class SystemModuleFinder implements ModuleFinder { SystemModuleFinder(Set mrefs, Map nameToModule) { - this.mrefs = Collections.unmodifiableSet(mrefs); - this.nameToModule = Collections.unmodifiableMap(nameToModule); + this.mrefs = Set.copyOf(mrefs); + this.nameToModule = Map.copyOf(nameToModule); } @Override @@ -353,7 +353,7 @@ static Map generateNameToHash(ModuleHashes[] recordedHashes) { } } } - return (nameToHash != null) ? nameToHash : Collections.emptyMap(); + return (nameToHash != null) ? nameToHash : Map.of(); } /** diff --git a/test/jdk/java/lang/module/ModuleDescriptorTest.java b/test/jdk/java/lang/module/ModuleDescriptorTest.java index 83518001b37..839b51cf193 100644 --- a/test/jdk/java/lang/module/ModuleDescriptorTest.java +++ b/test/jdk/java/lang/module/ModuleDescriptorTest.java @@ -147,7 +147,12 @@ private Requires requires(String mn) { public void testRequiresWithRequires() { Requires r1 = requires("foo"); ModuleDescriptor descriptor = ModuleDescriptor.newModule("m").requires(r1).build(); - Requires r2 = descriptor.requires().iterator().next(); + assertEquals(descriptor.requires().size(), 2); + var iterator = descriptor.requires().iterator(); + Requires r2 = iterator.next(); + if (r2.name().equals("java.base")) { + r2 = iterator.next(); + } assertEquals(r1, r2); } From 73de8f722c25a86243082148b4353220316582d5 Mon Sep 17 00:00:00 2001 From: jiangli Date: Fri, 10 Aug 2018 00:35:57 -0400 Subject: [PATCH 013/131] 8207263: Store the Configuration for system modules into CDS archive. Summary: Archive boot layer Configuration. Reviewed-by: redestad, iklam, ccheung --- .../java/lang/module/Configuration.java | 14 +++- .../java/util/ImmutableCollections.java | 31 ++++++- .../internal/module/ArchivedModuleGraph.java | 25 ++++-- .../jdk/internal/module/ModuleBootstrap.java | 23 +++--- .../cacheObject/ArchivedModuleComboTest.java | 80 +++++++++++++++---- .../ArchivedModuleWithCustomImageTest.java | 1 + .../cacheObject/CheckArchivedModuleApp.java | 71 +++++++++++++++- 7 files changed, 209 insertions(+), 36 deletions(-) diff --git a/src/java.base/share/classes/java/lang/module/Configuration.java b/src/java.base/share/classes/java/lang/module/Configuration.java index c0c5c1dc3d4..288c12cb5f9 100644 --- a/src/java.base/share/classes/java/lang/module/Configuration.java +++ b/src/java.base/share/classes/java/lang/module/Configuration.java @@ -41,8 +41,10 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import jdk.internal.misc.VM; import jdk.internal.module.ModuleReferenceImpl; import jdk.internal.module.ModuleTarget; +import jdk.internal.vm.annotation.Stable; /** * A configuration that is the result of @@ -103,7 +105,17 @@ public final class Configuration { // @see Configuration#empty() - private static final Configuration EMPTY_CONFIGURATION = new Configuration(); + // EMPTY_CONFIGURATION may be initialized from the CDS archive. + private static @Stable Configuration EMPTY_CONFIGURATION; + + static { + // Initialize EMPTY_CONFIGURATION from the archive. + VM.initializeFromArchive(Configuration.class); + // Create a new empty Configuration if there is no archived version. + if (EMPTY_CONFIGURATION == null) { + EMPTY_CONFIGURATION = new Configuration(); + } + } // parent configurations, in search order private final List parents; diff --git a/src/java.base/share/classes/java/util/ImmutableCollections.java b/src/java.base/share/classes/java/util/ImmutableCollections.java index 1b8c4acce71..0f11c741f0f 100644 --- a/src/java.base/share/classes/java/util/ImmutableCollections.java +++ b/src/java.base/share/classes/java/util/ImmutableCollections.java @@ -36,6 +36,7 @@ import java.util.function.Predicate; import java.util.function.UnaryOperator; import jdk.internal.misc.SharedSecrets; +import jdk.internal.misc.VM; import jdk.internal.vm.annotation.Stable; /** @@ -409,7 +410,15 @@ private Object writeReplace() { static final class ListN extends AbstractImmutableList implements Serializable { - static final List EMPTY_LIST = new ListN<>(); + // EMPTY_LIST may be initialized from the CDS archive. + static @Stable List EMPTY_LIST; + + static { + VM.initializeFromArchive(ListN.class); + if (EMPTY_LIST == null) { + EMPTY_LIST = new ListN<>(); + } + } @Stable private final E[] elements; @@ -567,7 +576,15 @@ private Object writeReplace() { static final class SetN extends AbstractImmutableSet implements Serializable { - static final Set EMPTY_SET = new SetN<>(); + // EMPTY_SET may be initialized from the CDS archive. + static @Stable Set EMPTY_SET; + + static { + VM.initializeFromArchive(SetN.class); + if (EMPTY_SET == null) { + EMPTY_SET = new SetN<>(); + } + } @Stable final E[] elements; @@ -777,7 +794,15 @@ public int hashCode() { */ static final class MapN extends AbstractImmutableMap { - static final Map EMPTY_MAP = new MapN<>(); + // EMPTY_MAP may be initialized from the CDS archive. + static @Stable Map EMPTY_MAP; + + static { + VM.initializeFromArchive(MapN.class); + if (EMPTY_MAP == null) { + EMPTY_MAP = new MapN<>(); + } + } @Stable final Object[] table; // pairs of key, value diff --git a/src/java.base/share/classes/jdk/internal/module/ArchivedModuleGraph.java b/src/java.base/share/classes/jdk/internal/module/ArchivedModuleGraph.java index 35b4d09718b..e433d85c5b7 100644 --- a/src/java.base/share/classes/jdk/internal/module/ArchivedModuleGraph.java +++ b/src/java.base/share/classes/jdk/internal/module/ArchivedModuleGraph.java @@ -25,6 +25,7 @@ package jdk.internal.module; +import java.lang.module.Configuration; import java.lang.module.ModuleFinder; import java.util.Objects; import jdk.internal.misc.VM; @@ -36,13 +37,18 @@ final class ArchivedModuleGraph { private static String archivedMainModule; private static SystemModules archivedSystemModules; private static ModuleFinder archivedModuleFinder; + private static Configuration archivedConfiguration; private final SystemModules systemModules; private final ModuleFinder finder; + private final Configuration configuration; - private ArchivedModuleGraph(SystemModules modules, ModuleFinder finder) { + private ArchivedModuleGraph(SystemModules modules, + ModuleFinder finder, + Configuration configuration) { this.systemModules = modules; this.finder = finder; + this.configuration = configuration; } SystemModules systemModules() { @@ -53,27 +59,36 @@ ModuleFinder finder() { return finder; } + Configuration configuration() { + return configuration; + } + // A factory method that ModuleBootstrap can use to obtain the // ArchivedModuleGraph. static ArchivedModuleGraph get(String mainModule) { if (Objects.equals(mainModule, archivedMainModule) && archivedSystemModules != null - && archivedModuleFinder != null) { + && archivedModuleFinder != null + && archivedConfiguration != null) { return new ArchivedModuleGraph(archivedSystemModules, - archivedModuleFinder); + archivedModuleFinder, + archivedConfiguration); } else { return null; } } // Used at CDS dump time - static void archive(String mainModule, SystemModules systemModules, - ModuleFinder finder) { + static void archive(String mainModule, + SystemModules systemModules, + ModuleFinder finder, + Configuration configuration) { if (archivedMainModule != null) throw new UnsupportedOperationException(); archivedMainModule = mainModule; archivedSystemModules = systemModules; archivedModuleFinder = finder; + archivedConfiguration = configuration; } static { diff --git a/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java b/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java index 1321bb38c1e..de227eb92e5 100644 --- a/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java +++ b/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java @@ -172,6 +172,7 @@ public static ModuleLayer boot() throws Exception { boolean haveModulePath = (appModulePath != null || upgradeModulePath != null); boolean needResolution = true; + boolean canArchive = false; // If the java heap was archived at CDS dump time and the environment // at dump time matches the current environment then use the archived @@ -186,7 +187,6 @@ public static ModuleLayer boot() throws Exception { systemModuleFinder = archivedModuleGraph.finder(); needResolution = (traceOutput != null); } else { - boolean canArchive = false; if (!haveModulePath && addModules.isEmpty() && limitModules.isEmpty()) { systemModules = SystemModuleFinders.systemModules(mainModule); if (systemModules != null && !isPatched) { @@ -206,12 +206,6 @@ public static ModuleLayer boot() throws Exception { systemModules = new ExplodedSystemModules(); systemModuleFinder = SystemModuleFinders.ofSystem(); } - - // Module graph can be archived at CDS dump time. Only allow the - // unnamed module case for now. - if (canArchive && (mainModule == null)) { - ArchivedModuleGraph.archive(mainModule, systemModules, systemModuleFinder); - } } Counters.add("jdk.module.boot.1.systemModulesTime", t1); @@ -353,8 +347,12 @@ public static ModuleLayer boot() throws Exception { if (needResolution) { cf = JLMA.resolveAndBind(finder, roots, traceOutput); } else { - Map> map = systemModules.moduleReads(); - cf = JLMA.newConfiguration(systemModuleFinder, map); + if (archivedModuleGraph != null) { + cf = archivedModuleGraph.configuration(); + } else { + Map> map = systemModules.moduleReads(); + cf = JLMA.newConfiguration(systemModuleFinder, map); + } } // check that modules specified to --patch-module are resolved @@ -436,6 +434,13 @@ public static ModuleLayer boot() throws Exception { limitedFinder = new SafeModuleFinder(finder); } + // Module graph can be archived at CDS dump time. Only allow the + // unnamed module case for now. + if (canArchive && (mainModule == null)) { + ArchivedModuleGraph.archive(mainModule, systemModules, + systemModuleFinder, cf); + } + // total time to initialize Counters.add("jdk.module.boot.totalTime", t0); Counters.publish(); diff --git a/test/hotspot/jtreg/runtime/appcds/cacheObject/ArchivedModuleComboTest.java b/test/hotspot/jtreg/runtime/appcds/cacheObject/ArchivedModuleComboTest.java index accf3327096..de1034d6f3a 100644 --- a/test/hotspot/jtreg/runtime/appcds/cacheObject/ArchivedModuleComboTest.java +++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/ArchivedModuleComboTest.java @@ -54,41 +54,49 @@ public static void main(String[] args) throws Exception { Path userDir = Paths.get(System.getProperty("user.dir")); Path moduleDir = Files.createTempDirectory(userDir, "mods"); - // Dump without --module-path + // + // Dump without --module-path, without --show-module-resolution + // OutputAnalyzer output = TestCommon.dump(appJar, TestCommon.list("CheckArchivedModuleApp"), use_whitebox_jar); TestCommon.checkDump(output); // Test case 1) - // - Dump without --module-path - // - Run from -cp only, archived boot layer module ModuleDescriptors - // should be used. + // - Dump without --module-path, without --show-module-resolution + // - Run from -cp only and without --show-module-resolution + // + archived boot layer module ModuleDescriptors should be used + // + archived boot layer configuration should be used System.out.println("----------------------- Test case 1 ----------------------"); output = TestCommon.exec(appJar, use_whitebox_jar, "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", "CheckArchivedModuleApp", + "yes", "yes"); TestCommon.checkExec(output); // Test case 2) - // - Dump without --module-path - // - Run from -cp only, archived boot layer module ModuleDescriptors - // should be used with --show-module-resolution (requires resolution). + // - Dump without --module-path, without --show-module-resolution + // - Run from -cp only and with --show-module-resolution + // + archived boot layer module ModuleDescriptors should be used with + // --show-module-resolution (requires resolution) + // + archived boot layer Configuration should not be disabled System.out.println("----------------------- Test case 2 ----------------------"); output = TestCommon.exec(appJar, use_whitebox_jar, "--show-module-resolution", "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", "CheckArchivedModuleApp", - "yes"); - TestCommon.checkExec(output); + "yes", + "no"); + TestCommon.checkExec(output, "root java.base jrt:/java.base"); // Test case 3) - // - Dump without --module-path - // - Run with --module-path, archived boot layer module ModuleDescriptors - // should be disabled. + // - Dump without --module-path, without --show-module-resolution + // - Run with --module-path + // + archived boot layer module ModuleDescriptors should be disabled + // + archived boot layer Configuration should be disabled System.out.println("----------------------- Test case 3 ----------------------"); output = TestCommon.exec(appJar, use_whitebox_jar, "--module-path", @@ -96,12 +104,15 @@ public static void main(String[] args) throws Exception { "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", "CheckArchivedModuleApp", + "no", "no"); TestCommon.checkExec(output); + // // Dump with --module-path specified (test case 4, 5). Use an // empty directory as it's simple and still triggers the case // where system module objects are not archived. + // output = TestCommon.dump(appJar, TestCommon.list("CheckArchivedModuleApp"), "--module-path", @@ -112,19 +123,20 @@ public static void main(String[] args) throws Exception { // Test case 4) // - Dump with --module-path // - Run from -cp only, no archived boot layer module ModuleDescriptors - // should be found. + // and Configuration should be found. System.out.println("----------------------- Test case 4 ----------------------"); output = TestCommon.exec(appJar, use_whitebox_jar, "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", "CheckArchivedModuleApp", + "no", "no"); TestCommon.checkExec(output); // Test case 5) // - Dump with --module-path // - Run with --module-path, no archived boot layer module ModuleDescriptors - // should be found. + // and Configuration should be found. System.out.println("----------------------- Test case 5 ----------------------"); output = TestCommon.exec(appJar, use_whitebox_jar, "--module-path", @@ -132,7 +144,47 @@ public static void main(String[] args) throws Exception { "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", "CheckArchivedModuleApp", + "no", "no"); TestCommon.checkExec(output); + + // + // Dump without --module-path, with --show-module-resolution + // + output = TestCommon.dump(appJar, + TestCommon.list("CheckArchivedModuleApp"), + "--show-module-resolution", + use_whitebox_jar); + TestCommon.checkDump(output, "root java.base jrt:/java.base"); + + // Test case 6) + // - Dump without --module-path, with --show-module-resolution + // - Run from -cp only and without --show-module-resolution + // + archived boot layer module ModuleDescriptors should be used + // + archived boot layer Configuration should be used + System.out.println("----------------------- Test case 6 ----------------------"); + output = TestCommon.exec(appJar, use_whitebox_jar, + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "CheckArchivedModuleApp", + "yes", + "yes"); + TestCommon.checkExec(output); + + // Test case 7) + // - Dump without --module-path, with --show-module-resolution + // - Run from -cp only and with --show-module-resolution + // + archived boot layer module ModuleDescriptors should be used with + // --show-module-resolution (requires resolution) + // + archived boot layer Configuration should be disabled + System.out.println("----------------------- Test case 7 ----------------------"); + output = TestCommon.exec(appJar, use_whitebox_jar, + "--show-module-resolution", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "CheckArchivedModuleApp", + "yes", + "no"); + TestCommon.checkExec(output, "root java.base jrt:/java.base"); } } diff --git a/test/hotspot/jtreg/runtime/appcds/cacheObject/ArchivedModuleWithCustomImageTest.java b/test/hotspot/jtreg/runtime/appcds/cacheObject/ArchivedModuleWithCustomImageTest.java index 1a2e07103d3..c393d7ec325 100644 --- a/test/hotspot/jtreg/runtime/appcds/cacheObject/ArchivedModuleWithCustomImageTest.java +++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/ArchivedModuleWithCustomImageTest.java @@ -130,6 +130,7 @@ private static void testArchivedModuleUsingImage(Path image) "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", "CheckArchivedModuleApp", + "yes", "yes"}; printCommand(runCmd); ProcessBuilder pbRun = new ProcessBuilder(); diff --git a/test/hotspot/jtreg/runtime/appcds/cacheObject/CheckArchivedModuleApp.java b/test/hotspot/jtreg/runtime/appcds/cacheObject/CheckArchivedModuleApp.java index 144c71b9983..57eb2d67db1 100644 --- a/test/hotspot/jtreg/runtime/appcds/cacheObject/CheckArchivedModuleApp.java +++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/CheckArchivedModuleApp.java @@ -23,7 +23,9 @@ */ import java.io.File; +import java.lang.module.Configuration; import java.lang.module.ModuleDescriptor; +import java.util.List; import java.util.Set; import sun.hotspot.WhiteBox; @@ -41,16 +43,23 @@ public static void main(String args[]) throws Exception { return; } - boolean expectArchived = "yes".equals(args[0]); - checkModuleDescriptors(expectArchived); + if (args.length != 2) { + throw new RuntimeException( + "FAILED. Incorrect argument length: " + args.length); + } + boolean expectArchivedDescriptors = "yes".equals(args[0]); + boolean expectArchivedConfiguration = "yes".equals(args[1]); + checkModuleDescriptors(expectArchivedDescriptors); + checkConfiguration(expectArchivedConfiguration); + checkEmptyConfiguration(expectArchivedConfiguration); } - private static void checkModuleDescriptors(boolean expectArchived) { + private static void checkModuleDescriptors(boolean expectArchivedDescriptors) { Set modules = ModuleLayer.boot().modules(); for (Module m : modules) { ModuleDescriptor md = m.getDescriptor(); String name = md.name(); - if (expectArchived) { + if (expectArchivedDescriptors) { if (wb.isShared(md)) { System.out.println(name + " is archived. Expected."); } else { @@ -67,4 +76,58 @@ private static void checkModuleDescriptors(boolean expectArchived) { } } } + + private static void checkEmptyConfiguration(boolean expectArchivedConfiguration) { + // Configuration.EMPTY_CONFIGURATION uses the singletons, + // ListN.EMPTY_LIST, SetN.EMPTY_SET and MapN.EMPTY_MAP in + // ImmutableCollections for the 'parents', 'modules' and + // 'graph' fields. The ImmutableCollections singletons + // can be accessed via List.of(), Set.of() and Map.of() APIs. + // Configuration public APIs also allow access to the + // EMPTY_CONFIGURATION's 'parents' and 'modules'. When the + // archived java heap data is enabled at runtime, make sure + // the EMPTY_CONFIGURATION.parents and EMPTY_CONFIGURATION.modules + // are the archived ImmutableCollections singletons. + Configuration emptyCf = Configuration.empty(); + List emptyCfParents = emptyCf.parents(); + Set emptyCfModules = emptyCf.modules(); + if (expectArchivedConfiguration) { + if (emptyCfParents == List.of() && + wb.isShared(emptyCfParents)) { + System.out.println("Empty Configuration has expected parents."); + } else { + throw new RuntimeException( + "FAILED. Unexpected parents for empty Configuration."); + } + if (emptyCfModules == Set.of() && + wb.isShared(emptyCfModules)) { + System.out.println("Empty Configuration has expected module set."); + } else { + throw new RuntimeException( + "FAILED. Unexpected module set for empty Configuration."); + } + } + } + + + + private static void checkConfiguration(boolean expectArchivedConfiguration) { + Configuration cf = ModuleLayer.boot().configuration(); + + if (expectArchivedConfiguration) { + if (wb.isShared(cf)) { + System.out.println("Boot layer configuration is archived. Expected."); + } else { + throw new RuntimeException( + "FAILED. Boot layer configuration is not archived."); + } + } else { + if (!wb.isShared(cf)) { + System.out.println("Boot layer configuration is not archived. Expected."); + } else { + throw new RuntimeException( + "FAILED. Boot layer configuration is archived."); + } + } + } } From dac06b0602878b73cee5b8b328c2f441843950b0 Mon Sep 17 00:00:00 2001 From: redestad Date: Mon, 13 Aug 2018 19:21:43 +0200 Subject: [PATCH 014/131] 8209120: Archive the Integer.IntegerCache Reviewed-by: jiangli, alanb, plevart, iklam, mchung --- .../share/classes/java/lang/Integer.java | 21 ++- .../cacheObject/ArchivedIntegerCacheTest.java | 141 ++++++++++++++++++ .../cacheObject/CheckIntegerCacheApp.java | 88 +++++++++++ 3 files changed, 244 insertions(+), 6 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/appcds/cacheObject/ArchivedIntegerCacheTest.java create mode 100644 test/hotspot/jtreg/runtime/appcds/cacheObject/CheckIntegerCacheApp.java diff --git a/src/java.base/share/classes/java/lang/Integer.java b/src/java.base/share/classes/java/lang/Integer.java index 959a434e969..43cd0f3e6a4 100644 --- a/src/java.base/share/classes/java/lang/Integer.java +++ b/src/java.base/share/classes/java/lang/Integer.java @@ -997,7 +997,8 @@ public static Integer valueOf(String s) throws NumberFormatException { private static class IntegerCache { static final int low = -128; static final int high; - static final Integer cache[]; + static final Integer[] cache; + static Integer[] archivedCache; static { // high value may be configured by property @@ -1016,11 +1017,19 @@ private static class IntegerCache { } high = h; - cache = new Integer[(high - low) + 1]; - int j = low; - for(int k = 0; k < cache.length; k++) - cache[k] = new Integer(j++); - + // Load IntegerCache.archivedCache from archive, if possible + VM.initializeFromArchive(IntegerCache.class); + int size = (high - low) + 1; + + // Use the archived cache if it exists and is large enough + if (archivedCache == null || size > archivedCache.length) { + Integer[] c = new Integer[size]; + int j = low; + for(int k = 0; k < c.length; k++) + c[k] = new Integer(j++); + archivedCache = c; + } + cache = archivedCache; // range [-128, 127] must be interned (JLS7 5.1.7) assert IntegerCache.high >= 127; } diff --git a/test/hotspot/jtreg/runtime/appcds/cacheObject/ArchivedIntegerCacheTest.java b/test/hotspot/jtreg/runtime/appcds/cacheObject/ArchivedIntegerCacheTest.java new file mode 100644 index 00000000000..ee865fd353e --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/ArchivedIntegerCacheTest.java @@ -0,0 +1,141 @@ +/* + * 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 + * @summary Test IntegerCache integrity in various scenarios + * @requires vm.cds.archived.java.heap + * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @build sun.hotspot.WhiteBox + * @compile CheckIntegerCacheApp.java + * @run driver ClassFileInstaller -jar integer.jar CheckIntegerCacheApp + * @run driver ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox + * @run main ArchivedIntegerCacheTest + */ + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import jdk.test.lib.process.OutputAnalyzer; + +public class ArchivedIntegerCacheTest { + + public static void main(String[] args) throws Exception { + String wbJar = ClassFileInstaller.getJarPath("WhiteBox.jar"); + String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar; + String appJar = ClassFileInstaller.getJarPath("integer.jar"); + + Path userDir = Paths.get(System.getProperty("user.dir")); + Path moduleDir = Files.createTempDirectory(userDir, "mods"); + + // + // Dump default archive + // + OutputAnalyzer output = TestCommon.dump(appJar, + TestCommon.list("CheckIntegerCacheApp"), + use_whitebox_jar); + TestCommon.checkDump(output); + + // Test case 1) + // - Default options + System.out.println("----------------------- Test case 1 ----------------------"); + output = TestCommon.exec(appJar, use_whitebox_jar, + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "CheckIntegerCacheApp", + "127", + "true"); + TestCommon.checkExec(output); + + // Test case 2) + // - Default archive + // - Larger -XX:AutoBoxCacheMax + System.out.println("----------------------- Test case 2 ----------------------"); + output = TestCommon.exec(appJar, use_whitebox_jar, + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-XX:AutoBoxCacheMax=20000", + "CheckIntegerCacheApp", + "20000", + "false"); + TestCommon.checkExec(output); + + // + // Dump with -XX:AutoBoxCacheMax specified + // + output = TestCommon.dump(appJar, + TestCommon.list("CheckIntegerCacheApp"), + "-XX:AutoBoxCacheMax=20000", + use_whitebox_jar); + TestCommon.checkDump(output); + + // Test case 3) + // - Large archived cache + // - Default options + System.out.println("----------------------- Test case 3 ----------------------"); + output = TestCommon.exec(appJar, use_whitebox_jar, + "--module-path", + moduleDir.toString(), + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "CheckIntegerCacheApp", + "127", + "true"); + TestCommon.checkExec(output); + + + // Test case 4) + // - Large archived cache + // - Matching options + System.out.println("----------------------- Test case 4 ----------------------"); + output = TestCommon.exec(appJar, use_whitebox_jar, + "--module-path", + moduleDir.toString(), + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-XX:AutoBoxCacheMax=20000", + "CheckIntegerCacheApp", + "20000", + "true"); + TestCommon.checkExec(output); + + // Test case 5) + // - Large archived cache + // - Larger requested cache + System.out.println("----------------------- Test case 5 ----------------------"); + output = TestCommon.exec(appJar, use_whitebox_jar, + "--module-path", + moduleDir.toString(), + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-XX:AutoBoxCacheMax=30000", + "CheckIntegerCacheApp", + "30000", + "false"); + TestCommon.checkExec(output); + } +} diff --git a/test/hotspot/jtreg/runtime/appcds/cacheObject/CheckIntegerCacheApp.java b/test/hotspot/jtreg/runtime/appcds/cacheObject/CheckIntegerCacheApp.java new file mode 100644 index 00000000000..0c6545e6e2f --- /dev/null +++ b/test/hotspot/jtreg/runtime/appcds/cacheObject/CheckIntegerCacheApp.java @@ -0,0 +1,88 @@ +/* + * 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. + * + */ + +import sun.hotspot.WhiteBox; + +// +// Help test archived integer cache consistency. +// +// Takes two arguments: +// 0: the expected AutoBoxCacheMax setting +// 1: if the values are expected to be retrieved from the archive or not +// +public class CheckIntegerCacheApp { + static WhiteBox wb; + + public static void main(String[] args) throws Exception { + wb = WhiteBox.getWhiteBox(); + + if (!wb.areOpenArchiveHeapObjectsMapped()) { + System.out.println("This may happen during normal operation. Test Skipped."); + return; + } + + if (args.length != 2) { + throw new RuntimeException( + "FAILED. Incorrect argument length: " + args.length); + } + + boolean archivedExpected = Boolean.parseBoolean(args[1]); + + // Base JLS compliance check + for (int i = -128; i <= 127; i++) { + if (Integer.valueOf(i) != Integer.valueOf(i)) { + throw new RuntimeException( + "FAILED. All values in range [-128, 127] should be interned in cache: " + i); + } + checkArchivedAsExpected(archivedExpected, i); + } + + int high = Integer.parseInt(args[0]); + if (Integer.valueOf(high) != Integer.valueOf(high)) { + throw new RuntimeException( + "FAILED. Value expected to be retrieved from cache: " + high); + } + checkArchivedAsExpected(archivedExpected, Integer.valueOf(high)); + + if (Integer.valueOf(high + 1) == Integer.valueOf(high + 1)) { + throw new RuntimeException( + "FAILED. Value not expected to be retrieved from cache: " + high); + } + checkArchivedAsExpected(false, Integer.valueOf(high + 1)); + } + + private static void checkArchivedAsExpected(boolean archivedExpected, Integer value) { + if (archivedExpected) { + if (!wb.isShared(Integer.valueOf(value))) { + throw new RuntimeException( + "FAILED. Value expected to be archived: " + value); + } + } else { + if (wb.isShared(Integer.valueOf(value))) { + throw new RuntimeException( + "FAILED. Value not expected to be archived: " + value); + } + } + } +} From 1bc2804ed1c1abb7a1f708f45b495867281499a6 Mon Sep 17 00:00:00 2001 From: mseledtsov Date: Thu, 7 Mar 2019 12:15:48 -0800 Subject: [PATCH 015/131] 8213448: [TESTBUG] enhance jfr/jvm/TestDumpOnCrash Summary: added 2 more crash scenarios, removed dumponexit, and more Reviewed-by: egahlin --- test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java | 73 ++++++++++++++--------- 1 file changed, 46 insertions(+), 27 deletions(-) diff --git a/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java b/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java index 29fc877cb75..79c27b29a3d 100644 --- a/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java +++ b/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -24,6 +24,7 @@ */ package jdk.jfr.jvm; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -54,49 +55,67 @@ public class TestDumpOnCrash { private static final CharSequence LOG_FILE_EXTENSION = ".log"; private static final CharSequence JFR_FILE_EXTENSION = ".jfr"; - static class Crasher { + static class CrasherIllegalAccess { public static void main(String[] args) { Unsafe.getUnsafe().putInt(0L, 0); } } + static class CrasherHalt { + public static void main(String[] args) { + System.out.println("Running Runtime.getRuntime.halt"); + Runtime.getRuntime().halt(17); + } + } + + static class CrasherSig { + public static void main(String[] args) throws Exception { + String signalName = args[0]; + System.out.println("Sending SIG" + signalName + " to process " + ProcessHandle.current().pid()); + Runtime.getRuntime().exec("kill -" + signalName + " " + ProcessHandle.current().pid()).waitFor(); + } + } + public static void main(String[] args) throws Exception { - processOutput(runProcess()); + verify(runProcess(CrasherIllegalAccess.class.getName(), "")); + verify(runProcess(CrasherHalt.class.getName(), "")); + + // Verification is excluded for the test case below until 8219680 is fixed + long pid = runProcess(CrasherSig.class.getName(), "FPE"); + // @ignore 8219680 + // verify(pid); } - private static OutputAnalyzer runProcess() throws Exception { - return new OutputAnalyzer( - ProcessTools.createJavaProcessBuilder(true, + private static long runProcess(String crasher, String signal) throws Exception { + System.out.println("Test case for crasher " + crasher); + Process p = ProcessTools.createJavaProcessBuilder(true, "-Xmx64m", - "-Xint", "-XX:-TransmitErrorReport", "-XX:-CreateCoredumpOnCrash", "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", - "-XX:StartFlightRecording=dumponexit=true", - Crasher.class.getName()).start()); + "-XX:StartFlightRecording", + crasher, + signal) + .start(); + + OutputAnalyzer output = new OutputAnalyzer(p); + System.out.println("========== Crasher process output:"); + System.out.println(output.getOutput()); + System.out.println("=================================="); + + return p.pid(); } - private static void processOutput(OutputAnalyzer output) throws Exception { - output.shouldContain("CreateCoredumpOnCrash turned off, no core file dumped"); + private static void verify(long pid) throws IOException { + String fileName = "hs_err_pid" + pid + ".jfr"; + Path file = Paths.get(fileName).toAbsolutePath().normalize(); - final Path jfrEmergencyFilePath = getHsErrJfrPath(output); - Asserts.assertTrue(Files.exists(jfrEmergencyFilePath), "No emergency jfr recording file " + jfrEmergencyFilePath + " exists"); - Asserts.assertNotEquals(Files.size(jfrEmergencyFilePath), 0L, "File length 0. Should at least be some bytes"); - System.out.printf("File size=%d%n", Files.size(jfrEmergencyFilePath)); + Asserts.assertTrue(Files.exists(file), "No emergency jfr recording file " + file + " exists"); + Asserts.assertNotEquals(Files.size(file), 0L, "File length 0. Should at least be some bytes"); + System.out.printf("File size=%d%n", Files.size(file)); - List events = RecordingFile.readAllEvents(jfrEmergencyFilePath); + List events = RecordingFile.readAllEvents(file); Asserts.assertFalse(events.isEmpty(), "No event found"); System.out.printf("Found event %s%n", events.get(0).getEventType().getName()); } - - private static Path getHsErrJfrPath(OutputAnalyzer output) throws Exception { - // extract to find hs-err_pid log file location - final String hs_err_pid_log_file = output.firstMatch("# *(\\S*hs_err_pid\\d+\\.log)", 1); - if (hs_err_pid_log_file == null) { - throw new RuntimeException("Did not find hs_err_pid.log file in output.\n"); - } - // the dumped out jfr file should have the same name and location but with a .jfr extension - final String hs_err_pid_jfr_file = hs_err_pid_log_file.replace(LOG_FILE_EXTENSION, JFR_FILE_EXTENSION); - return Paths.get(hs_err_pid_jfr_file); - } } From 120d8c67c3bb848b049a1adf3470382e38ac60db Mon Sep 17 00:00:00 2001 From: stuefe Date: Fri, 24 May 2019 09:02:33 +0200 Subject: [PATCH 016/131] 8220394: bufferedStream does not honor size limit Reviewed-by: dholmes, clanger --- test/hotspot/gtest/utilities/test_ostream.cpp | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/test/hotspot/gtest/utilities/test_ostream.cpp b/test/hotspot/gtest/utilities/test_ostream.cpp index 6eff3819274..14a902638c1 100644 --- a/test/hotspot/gtest/utilities/test_ostream.cpp +++ b/test/hotspot/gtest/utilities/test_ostream.cpp @@ -67,3 +67,51 @@ TEST_VM(ostream, stringStream_dynamic_realloc_1) { TEST_VM(ostream, stringStream_dynamic_realloc_2) { do_test_stringStream_dynamic_realloc(true); } + +TEST_VM(ostream, bufferedStream_static) { + char buf[100]; + bufferedStream bs(buf, sizeof(buf)); + size_t written = 0; + for (int i = 0; i < 100; i ++) { + written += print_lorem(&bs, true); + if (written < sizeof(buf)) { + ASSERT_EQ(bs.size(), written); + } else { + ASSERT_EQ(bs.size(), sizeof(buf) - 1); + } + } +} + +TEST_VM(ostream, bufferedStream_dynamic_small) { + bufferedStream bs(1); // small to excercise realloc. + size_t written = 0; + // The max cap imposed is 100M, we should be safely below this in this test. + for (int i = 0; i < 10; i ++) { + written += print_lorem(&bs, true); + ASSERT_EQ(bs.size(), written); + } +} + +/* Activate to manually test bufferedStream dynamic cap. + +TEST_VM(ostream, bufferedStream_dynamic_large) { + bufferedStream bs(1); // small to excercise realloc. + size_t written = 0; + // The max cap imposed is 100M. Writing this much should safely hit it. + // Note that this will assert in debug builds which is the expected behavior. + size_t expected_cap_at = 100 * M; + for (int i = 0; i < 10000000; i ++) { + written += print_lorem(&bs, false); + if (written < expected_cap_at) { + ASSERT_EQ(bs.size(), written); + } else { + ASSERT_EQ(bs.size(), expected_cap_at - 1); + } + } +} + +*/ + + + + From e2ea0c258c8bffa9295fe0947cd17e79d04f27cd Mon Sep 17 00:00:00 2001 From: stuefe Date: Wed, 5 Jun 2019 19:34:43 +0200 Subject: [PATCH 017/131] 8225225: stringStream internal buffer should always be zero terminated Reviewed-by: coleenp, dholmes --- test/hotspot/gtest/utilities/test_ostream.cpp | 51 +++++++++++++++---- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/test/hotspot/gtest/utilities/test_ostream.cpp b/test/hotspot/gtest/utilities/test_ostream.cpp index 14a902638c1..164f0d34b2b 100644 --- a/test/hotspot/gtest/utilities/test_ostream.cpp +++ b/test/hotspot/gtest/utilities/test_ostream.cpp @@ -49,37 +49,66 @@ static size_t print_lorem(outputStream* st, bool short_len) { return len; } -static void do_test_stringStream_dynamic_realloc(bool short_len) { - stringStream ss(2); // small buffer to force lots of reallocations. +static void test_stringStream_is_zero_terminated(const stringStream* ss) { + ASSERT_EQ(ss->base()[ss->size()], '\0'); +} + + +static void do_test_stringStream(stringStream* ss, bool short_len, size_t expected_cap) { + test_stringStream_is_zero_terminated(ss); size_t written = 0; for (int i = 0; i < 1000; i ++) { - written += print_lorem(&ss, short_len); - ASSERT_EQ(ss.size(), written); + written += print_lorem(ss, short_len); + if (expected_cap > 0 && written >= expected_cap) { + ASSERT_EQ(ss->size(), expected_cap - 1); + } else { + ASSERT_EQ(ss->size(), written); + } // Internal buffer should always be zero-terminated. - ASSERT_EQ(ss.base()[ss.size()], '\0'); + test_stringStream_is_zero_terminated(ss); } + // Reset should zero terminate too + ss->reset(); + ASSERT_EQ(ss->size(), (size_t)0); + test_stringStream_is_zero_terminated(ss); } TEST_VM(ostream, stringStream_dynamic_realloc_1) { - do_test_stringStream_dynamic_realloc(false); + stringStream ss(2); // dynamic buffer with very small starting size + do_test_stringStream(&ss, false, 0); } TEST_VM(ostream, stringStream_dynamic_realloc_2) { - do_test_stringStream_dynamic_realloc(true); + stringStream ss(2); // dynamic buffer with very small starting size + do_test_stringStream(&ss, true, 0); +} + +TEST_VM(ostream, stringStream_static) { + char buffer[128 + 1]; + char* canary_at = buffer + sizeof(buffer) - 1; + *canary_at = 'X'; + size_t stream_buf_size = sizeof(buffer) - 1; + stringStream ss(buffer, stream_buf_size); + do_test_stringStream(&ss, false, stream_buf_size); + ASSERT_EQ(*canary_at, 'X'); // canary } TEST_VM(ostream, bufferedStream_static) { - char buf[100]; - bufferedStream bs(buf, sizeof(buf)); + char buf[100 + 1]; + char* canary_at = buf + sizeof(buf) - 1; + *canary_at = 'X'; + size_t stream_buf_size = sizeof(buf) - 1; + bufferedStream bs(buf, stream_buf_size); size_t written = 0; for (int i = 0; i < 100; i ++) { written += print_lorem(&bs, true); - if (written < sizeof(buf)) { + if (written < stream_buf_size) { ASSERT_EQ(bs.size(), written); } else { - ASSERT_EQ(bs.size(), sizeof(buf) - 1); + ASSERT_EQ(bs.size(), stream_buf_size - 1); } } + ASSERT_EQ(*canary_at, 'X'); // canary } TEST_VM(ostream, bufferedStream_dynamic_small) { From 4c267ba069d457710458e462715afa704edd4466 Mon Sep 17 00:00:00 2001 From: thartmann Date: Tue, 13 Aug 2019 09:54:40 +0200 Subject: [PATCH 018/131] 8228772: C2 compilation fails due to unschedulable graph if DominatorSearchLimit is reached Summary: Ignore membar if the load is already control dependent on it. Reviewed-by: neliasso, kvn --- .../TestAntiDependentMembar.java | 450 ++++++++++++++++++ 1 file changed, 450 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/controldependency/TestAntiDependentMembar.java diff --git a/test/hotspot/jtreg/compiler/controldependency/TestAntiDependentMembar.java b/test/hotspot/jtreg/compiler/controldependency/TestAntiDependentMembar.java new file mode 100644 index 00000000000..0ce689883ff --- /dev/null +++ b/test/hotspot/jtreg/compiler/controldependency/TestAntiDependentMembar.java @@ -0,0 +1,450 @@ +/* + * 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 8228772 + * @summary Test correct insertion of anti-dependencies if load is already control dependent on membar. + * @run main/othervm -Xbatch -XX:-TieredCompilation + * -XX:CompileCommand=inline,compiler.controldependency.TestAntiDependentMembar::hitSearchLimit + * compiler.controldependency.TestAntiDependentMembar + * @run main/othervm -Xbatch -XX:-TieredCompilation + * -XX:CompileCommand=inline,compiler.controldependency.TestAntiDependentMembar::hitSearchLimit + * -XX:+UnlockDiagnosticVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:DominatorSearchLimit=0 + * compiler.controldependency.TestAntiDependentMembar + */ + +package compiler.controldependency; + +public class TestAntiDependentMembar { + + static volatile int step1 = 0; + static volatile int step2 = 0; + + public static int test1(int count, int b1, int b2) { + int[] result = {0}; + + // Complex control flow to generate Region with 4 paths and therefore bail out of Node::dominates + if (b1 == 0) { + count += 1; + } else if (b1 == 1) { + if (b2 == 1) { + count += 2; + } + } + + for (int i = 0; i < count; ++i) { + // Volatile field write adds a membar + step1 = i; + // Load that is dependent on the membar + result[0] += count; + } + return result[0]; + } + + // Same as test1 but bailing out of Node::dominates due to hitting DominatorSearchLimit + public static int test2(int count) { + int[] result = {0}; + + // Large method with regions to hit the DominatorSearchLimit + hitSearchLimit(); + + for (int i = 0; i < count; ++i) { + step1 = i; + result[0] += count; + } + return result[0]; + } + + // Same as test2 but with multiple membars before the load + public static int test3(int count) { + int[] result = {0}; + + hitSearchLimit(); + + for (int i = 0; i < count; ++i) { + step1 = i; + step2 = i; + step1 = i; + step2 = i; + result[0] += count; + } + return result[0]; + } + + public static void main(String[] args) { + for (int i = 0; i < 50_000; ++i) { + test1(10, 0, 0); + test1(10, 1, 1); + test1(10, 1, 0); + test1(10, 0, 1); + test2(10); + test3(10); + } + } + + public static void hitSearchLimit() { + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + step1++; + step2++; + } +} From a5659ff20369c337b67d409f4337f9094081b11e Mon Sep 17 00:00:00 2001 From: ascarpino Date: Mon, 10 Dec 2018 09:19:30 -0800 Subject: [PATCH 019/131] 8214098: sun.security.ssl.HandshakeHash.T12HandshakeHash constructor check backwards. Reviewed-by: xuelei --- .../sun/security/ssl/HandshakeHash.java | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java b/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java index 7e7731f27a8..9b485a5269f 100644 --- a/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java +++ b/src/java.base/share/classes/sun/security/ssl/HandshakeHash.java @@ -518,10 +518,10 @@ static final class T12HandshakeHash implements TranscriptHash { JsseJce.getMessageDigest(cipherSuite.hashAlg.name); if (md instanceof Cloneable) { transcriptHash = new CloneableHash(md); - this.baos = null; + this.baos = new ByteArrayOutputStream(); } else { transcriptHash = new NonCloneableHash(md); - this.baos = new ByteArrayOutputStream(); + this.baos = null; } } @@ -550,26 +550,20 @@ public byte[] archived() { static final class T13HandshakeHash implements TranscriptHash { private final TranscriptHash transcriptHash; - private final ByteArrayOutputStream baos; T13HandshakeHash(CipherSuite cipherSuite) { MessageDigest md = JsseJce.getMessageDigest(cipherSuite.hashAlg.name); if (md instanceof Cloneable) { transcriptHash = new CloneableHash(md); - this.baos = null; } else { transcriptHash = new NonCloneableHash(md); - this.baos = new ByteArrayOutputStream(); } } @Override public void update(byte[] input, int offset, int length) { transcriptHash.update(input, offset, length); - if (baos != null) { - baos.write(input, offset, length); - } } @Override @@ -579,13 +573,9 @@ public byte[] digest() { @Override public byte[] archived() { - if (baos != null) { - return baos.toByteArray(); - } else { - return transcriptHash.archived(); - } - - // throw new UnsupportedOperationException("Not supported yet."); + // This method is not necessary in T13 + throw new UnsupportedOperationException( + "TLS 1.3 does not require archived."); } } From 769395820956670ccb5a73bbfb75b14c0717c007 Mon Sep 17 00:00:00 2001 From: thartmann Date: Wed, 12 Sep 2018 09:23:36 +0200 Subject: [PATCH 020/131] 8210387: C2 compilation fails with "assert(node->_last_del == _last) failed: must have deleted the edge just produced" Summary: Refresh iterator and start from the beginning while there is progress when removing dead regions. Reviewed-by: kvn --- .../c2/TestUnreachableRegionDuringCCP.java | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/c2/TestUnreachableRegionDuringCCP.java diff --git a/test/hotspot/jtreg/compiler/c2/TestUnreachableRegionDuringCCP.java b/test/hotspot/jtreg/compiler/c2/TestUnreachableRegionDuringCCP.java new file mode 100644 index 00000000000..86209f27a9b --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestUnreachableRegionDuringCCP.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8210387 + * @summary Test removal of unreachable regions during CCP. + * @library /test/lib + * @run main/othervm -Xcomp -XX:-TieredCompilation + * -XX:CompileOnly=compiler.c2.TestUnreachableRegionDuringCCP::test + * compiler.c2.TestUnreachableRegionDuringCCP + */ + +package compiler.c2; + +import jdk.test.lib.Asserts; + +public class TestUnreachableRegionDuringCCP { + static int iFld1 = -1; + static int iFld2 = -1; + static int iArrFld[] = new int[100]; + + public static void test() { + int i = 1; + do { + iArrFld[i] = iFld1; + iFld1 = 42; + for (int j = 1; j < 5; j++) { + if (i != 0) { + return; // Always returns + } + iFld2 += j; + } + } while (++i < 10); + } + + public static void main(String[] args) { + test(); + Asserts.assertEQ(iFld1, 42); + Asserts.assertEQ(iFld2, -1); + Asserts.assertEQ(iArrFld[1], -1); + } +} From f729061b5ead34f378422172c636c5d0106def70 Mon Sep 17 00:00:00 2001 From: ctornqvi Date: Mon, 1 Apr 2019 14:34:24 -0700 Subject: [PATCH 021/131] 8212627: [TESTBUG] runtime/CreateMirror/ArraysNewInstanceBug.java timed out Reviewed-by: coleenp, dcubed, hseigel --- .../jtreg/runtime/CreateMirror/ArraysNewInstanceBug.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/hotspot/jtreg/runtime/CreateMirror/ArraysNewInstanceBug.java b/test/hotspot/jtreg/runtime/CreateMirror/ArraysNewInstanceBug.java index 870e8ea94bf..cb45f00d666 100644 --- a/test/hotspot/jtreg/runtime/CreateMirror/ArraysNewInstanceBug.java +++ b/test/hotspot/jtreg/runtime/CreateMirror/ArraysNewInstanceBug.java @@ -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 @@ -31,6 +31,7 @@ // This test crashes in compiled code with race, because the compiler generates code that assumes this ordering. import java.lang.reflect.Array; +import java.io.File; import java.net.URL; import java.net.URLClassLoader; @@ -55,13 +56,13 @@ public void run() { public static void main(String[] args) throws Throwable { Class c = ArraysNewInstanceBug.class; - ClassLoader apploader = c.getClassLoader(); + ClassLoader apploader = c.getClassLoader(); + File testClasses = new File(System.getProperty("test.classes")); for (int iter = 0; iter < 10 ; iter++) { // 10 is enough to get it to crash on my machine. System.err.print('['); classes = new Class[1000]; - String urlpath = "file://" + System.getProperty("test.classes") + "/"; for (int i = 0; i < classes.length; i++) { - ClassLoader loader = new URLClassLoader(new URL[] { new URL(urlpath) }, apploader.getParent()); + ClassLoader loader = new URLClassLoader(new URL[] { testClasses.toURI().toURL() }, apploader.getParent()); classes[i] = loader.loadClass(c.getSimpleName()); } System.err.print(']'); From da376441fc933170c1fe0db19966188c665b72eb Mon Sep 17 00:00:00 2001 From: naoto Date: Tue, 9 Jul 2019 08:05:38 -0700 Subject: [PATCH 022/131] 8227127: Era designator not displayed correctly using the COMPAT provider Reviewed-by: rriggs --- .../sun/text/resources/ext/FormatData_ja.java | 12 ++++++------ .../sun/text/resources/ext/FormatData_zh.java | 14 +++++++------- .../sun/text/resources/ext/FormatData_zh_TW.java | 14 +++++++------- test/jdk/sun/text/resources/LocaleData | 10 +++++++++- test/jdk/sun/text/resources/LocaleDataTest.java | 2 +- 5 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ja.java b/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ja.java index 93d35187c51..61df7263f69 100644 --- a/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ja.java +++ b/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ja.java @@ -97,6 +97,10 @@ protected final Object[][] getContents() { "\u6c11\u56fd\u524d", "\u6c11\u56fd", }; + final String[] gregoryEras = { + "\u7d00\u5143\u524d", + "\u897f\u66a6", + }; return new Object[][] { { "MonthNames", new String[] { @@ -171,12 +175,8 @@ protected final Object[][] getContents() { "\u5348\u5f8c" // pm marker } }, - { "Eras", - new String[] { // era strings for GregorianCalendar - "\u7d00\u5143\u524d", - "\u897f\u66a6" - } - }, + { "Eras", gregoryEras }, + { "short.Eras", gregoryEras }, { "buddhist.Eras", new String[] { // era strings for Thai Buddhist calendar "\u7d00\u5143\u524d", // Kigenzen diff --git a/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_zh.java b/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_zh.java index 7b05db6e955..e902bfcbd26 100644 --- a/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_zh.java +++ b/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_zh.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, 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 @@ -88,6 +88,10 @@ protected final Object[][] getContents() { "\u6c11\u56fd\u524d", "\u6c11\u56fd", }; + final String[] gregoryEras = { + "\u516c\u5143\u524d", + "\u516c\u5143", + }; return new Object[][] { { "MonthNames", new String[] { @@ -263,12 +267,8 @@ protected final Object[][] getContents() { "\u4e0b\u5348" // pm marker } }, - { "Eras", - new String[] { // era strings - "\u516c\u5143\u524d", - "\u516c\u5143" - } - }, + { "Eras", gregoryEras }, + { "short.Eras", gregoryEras }, { "buddhist.Eras", new String[] { "BC", diff --git a/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_zh_TW.java b/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_zh_TW.java index 69003106237..fd4b8872b80 100644 --- a/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_zh_TW.java +++ b/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_zh_TW.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, 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 @@ -88,13 +88,13 @@ protected final Object[][] getContents() { "\u6c11\u570b\u524d", "\u6c11\u570b", }; + final String[] gregoryEras = { + "\u897f\u5143\u524d", + "\u897f\u5143", + }; return new Object[][] { - { "Eras", - new String[] { // era strings - "\u897f\u5143\u524d", - "\u897f\u5143" - } - }, + { "Eras", gregoryEras }, + { "short.Eras", gregoryEras }, { "standalone.MonthAbbreviations", new String[] { "1\u6708", diff --git a/test/jdk/sun/text/resources/LocaleData b/test/jdk/sun/text/resources/LocaleData index b71bc3ac9ef..123928c0803 100644 --- a/test/jdk/sun/text/resources/LocaleData +++ b/test/jdk/sun/text/resources/LocaleData @@ -8322,7 +8322,15 @@ CurrencyNames//mru=Mauritanian Ouguiya # bug #8208746 CurrencyNames//ves=Venezuelan Bol\u00edvar Soberano -# bug# 8206879 +# bug #8206879 # For Peru decimal separator is changed to dot(.) and grouping separator is changed to comma(,) FormatData/es_PE/NumberElements/0=. FormatData/es_PE/NumberElements/1=, + +# bug #8227127 +FormatData/ja/short.Eras/0=\u7d00\u5143\u524d +FormatData/ja/short.Eras/1=\u897f\u66a6 +FormatData/zh/short.Eras/0=\u516c\u5143\u524d +FormatData/zh/short.Eras/1=\u516c\u5143 +FormatData/zh_TW/short.Eras/0=\u897f\u5143\u524d +FormatData/zh_TW/short.Eras/1=\u897f\u5143 diff --git a/test/jdk/sun/text/resources/LocaleDataTest.java b/test/jdk/sun/text/resources/LocaleDataTest.java index 54c5b5b7bb7..910f2ad4c39 100644 --- a/test/jdk/sun/text/resources/LocaleDataTest.java +++ b/test/jdk/sun/text/resources/LocaleDataTest.java @@ -39,7 +39,7 @@ * 8017142 8037343 8055222 8042126 8074791 8075173 8080774 8129361 8134916 * 8145136 8145952 8164784 8037111 8081643 7037368 8178872 8185841 8190918 * 8187946 8195478 8181157 8179071 8193552 8202026 8204269 8202537 8208746 - * 8209775 + * 8209775 8227127 * @summary Verify locale data * @modules java.base/sun.util.resources * @modules jdk.localedata From efcb13709cf8df8178adfd238156dfdb5ffb46a5 Mon Sep 17 00:00:00 2001 From: xliu Date: Wed, 4 Sep 2019 16:39:12 +0200 Subject: [PATCH 023/131] 8229450: C2 compilation fails with assert(found_sfpt) failed Reviewed-by: roland, thartmann --- .../LoadDependsOnIfIdenticalToLoopExit.java | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/loopstripmining/LoadDependsOnIfIdenticalToLoopExit.java diff --git a/test/hotspot/jtreg/compiler/loopstripmining/LoadDependsOnIfIdenticalToLoopExit.java b/test/hotspot/jtreg/compiler/loopstripmining/LoadDependsOnIfIdenticalToLoopExit.java new file mode 100644 index 00000000000..44c38ec5bc1 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopstripmining/LoadDependsOnIfIdenticalToLoopExit.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2019, Red Hat, 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. + * + * 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 8229450 + * @summary shared an identical bool node with a strip-mined loop + * + * @run main/othervm -XX:-TieredCompilation -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:LoopMaxUnroll=0 -XX:CompileCommand=dontinline,LoadDependsOnIfIdenticalToLoopExit::not_inlined -XX:CompileCommand=compileonly,LoadDependsOnIfIdenticalToLoopExit::test1 LoadDependsOnIfIdenticalToLoopExit + * + */ + +public class LoadDependsOnIfIdenticalToLoopExit { + public static void main(String[] args) { + for (int i = 0; i < 20_000; i++) { + test1(false, false); + test1(true, true); + } + } + + private static int test1(boolean flag1, boolean flag2) { + int res = 1; + int[] array = new int[10]; + not_inlined(array); + int i; + for (i = 0; i < 2000; i++) { + res *= i; + } + + if (flag1) { + if (flag2) { + res++; + } + } + + if (i >= 2000) { + res *= array[0]; + } + return res; + } + + private static void not_inlined(int[] array) { + } +} From b96e170961e62c37c1599c51b9f6e5faf1e4da0b Mon Sep 17 00:00:00 2001 From: cjplummer Date: Wed, 13 Mar 2019 19:42:23 -0700 Subject: [PATCH 024/131] 8220352: Crash with assert(external_guard || result != __null) failed: Invalid JNI handle Summary: Don't delete globalrefs that might still be referenced Reviewed-by: gadams, jcbeyler, sspitsyn --- .../nsk/jvmti/MonitorWait/monitorwait001/monitorwait001.c | 6 +----- .../jvmti/MonitorWaited/monitorwaited001/monitorwaited001.c | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/MonitorWait/monitorwait001/monitorwait001.c b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/MonitorWait/monitorwait001/monitorwait001.c index b8dcd2646b4..86d0d8d828b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/MonitorWait/monitorwait001/monitorwait001.c +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/MonitorWait/monitorwait001/monitorwait001.c @@ -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 @@ -159,10 +159,6 @@ static int clean() { JVMTI_EVENT_MONITOR_WAIT, NULL))) nsk_jvmti_setFailStatus(); - /* dispose global references */ - NSK_CPP_STUB2(DeleteGlobalRef, jni, object); - NSK_CPP_STUB2(DeleteGlobalRef, jni, thread); - return NSK_TRUE; } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/MonitorWaited/monitorwaited001/monitorwaited001.c b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/MonitorWaited/monitorwaited001/monitorwaited001.c index bfb09355f43..efccdec5122 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/MonitorWaited/monitorwaited001/monitorwaited001.c +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/MonitorWaited/monitorwaited001/monitorwaited001.c @@ -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 @@ -160,10 +160,6 @@ static int clean() { JVMTI_EVENT_MONITOR_WAITED, NULL))) nsk_jvmti_setFailStatus(); - /* dispose global references */ - NSK_CPP_STUB2(DeleteGlobalRef, jni, object); - NSK_CPP_STUB2(DeleteGlobalRef, jni, thread); - return NSK_TRUE; } From 8f50eff946e582c9e549e8df53fefee86eb31c7f Mon Sep 17 00:00:00 2001 From: rkennke Date: Thu, 18 Oct 2018 21:14:49 +0200 Subject: [PATCH 025/131] 8212673: jtreg/applications/runthese/RunThese30M.java fails in C2 with "assert(!had_error) failed: bad dominance" Reviewed-by: thartmann, kvn, shade --- .../gcbarriers/EqvUncastStepOverBarrier.java | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/gcbarriers/EqvUncastStepOverBarrier.java diff --git a/test/hotspot/jtreg/compiler/gcbarriers/EqvUncastStepOverBarrier.java b/test/hotspot/jtreg/compiler/gcbarriers/EqvUncastStepOverBarrier.java new file mode 100644 index 00000000000..532f490a112 --- /dev/null +++ b/test/hotspot/jtreg/compiler/gcbarriers/EqvUncastStepOverBarrier.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018, Red Hat, 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. + * + * 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 8212673 + * @summary Node::eqv_uncast() shouldn't step over load barriers unconditionally + * @library /test/lib / + * @modules java.base/jdk.internal.misc + * + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-UseOnStackReplacement -XX:-TieredCompilation -XX:-BackgroundCompilation EqvUncastStepOverBarrier + */ + +import sun.hotspot.WhiteBox; +import java.lang.reflect.Method; + +public class EqvUncastStepOverBarrier { + static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + + private static Object field = new A(); + + public static void main(String[] args) throws Exception { + for (int i = 0; i < 20_000; i++) { + test(); + test(); + test_helper(null, 0); + } + Method m = EqvUncastStepOverBarrier.class.getDeclaredMethod("test"); + WHITE_BOX.enqueueMethodForCompilation(m, 4); + if (!WHITE_BOX.isMethodCompiled(m, false)) { + throw new RuntimeException("Method compilation failed"); + } + } + + private static Object test() { + Object o = field; + if (o == null) {} + for (int i = 1; i < 100; i *= 2) { + int j = 0; + for (; j < 4; j++) ; + o = test_helper(o, j); + } + return o; + } + + private static Object test_helper(Object o, int j) { + if (j == 4) { + A a = (A) o; + o = a; + } else { + o = new Object(); + } + return o; + } + + private static class A { + } +} From 6e435e0df579e245c79e4ccc0afe969d44bb0107 Mon Sep 17 00:00:00 2001 From: thartmann Date: Wed, 7 Aug 2019 12:09:55 +0200 Subject: [PATCH 026/131] 8229016: C2 scalarization crashes with assert(node->Opcode() == Op_CastP2X) failed: ConvP2XNode required Summary: Detect array copy to self to avoid emitting another load to the to-be-removed allocation. Reviewed-by: kvn --- .../escapeAnalysis/TestSelfArrayCopy.java | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/escapeAnalysis/TestSelfArrayCopy.java diff --git a/test/hotspot/jtreg/compiler/escapeAnalysis/TestSelfArrayCopy.java b/test/hotspot/jtreg/compiler/escapeAnalysis/TestSelfArrayCopy.java new file mode 100644 index 00000000000..cf08a59bcea --- /dev/null +++ b/test/hotspot/jtreg/compiler/escapeAnalysis/TestSelfArrayCopy.java @@ -0,0 +1,64 @@ +/* + * 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 8229016 + * @summary Test correct elimination of array allocation with arraycopy to itself. + * @library /test/lib + * @run main/othervm -Xbatch -XX:CompileCommand=compileonly,compiler.escapeAnalysis.TestSelfArrayCopy::test + * compiler.escapeAnalysis.TestSelfArrayCopy + */ + +package compiler.escapeAnalysis; + +import jdk.test.lib.Utils; + +public class TestSelfArrayCopy { + private static boolean b = false; + private static final int rI1 = Utils.getRandomInstance().nextInt(); + private static final int rI2 = Utils.getRandomInstance().nextInt(); + + private static int test() { + // Non-escaping allocation + Integer[] array = {rI1, rI2}; + // Arraycopy with src == dst + System.arraycopy(array, 0, array, 0, array.length - 1); + if (b) { + // Uncommon trap + System.out.println(array[0]); + } + return array[0] + array[1]; + } + + public static void main(String[] args) { + int expected = rI1 + rI2; + // Trigger compilation + for (int i = 0; i < 20_000; ++i) { + int result = test(); + if (result != expected) { + throw new RuntimeException("Incorrect result: " + result + " != " + expected); + } + } + } +} From ca90a65385327626d26ad2ea4a56667b9b6b9939 Mon Sep 17 00:00:00 2001 From: ysuenaga Date: Sat, 16 Mar 2019 21:27:15 +0900 Subject: [PATCH 027/131] 8220555: JFR tool shows potentially misleading message when it cannot access a file Reviewed-by: egahlin, mseledtsov --- src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Command.java | 4 ++-- test/jdk/jdk/jfr/tool/TestPrint.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Command.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Command.java index 95ac85be6bc..a7013579938 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Command.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Command.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -243,7 +243,7 @@ private void ensureAccess(Path path) throws UserDataException { } rad.read(); // try to read 1 byte } catch (FileNotFoundException e) { - throw new UserDataException("could not find file '" + path + "'"); + throw new UserDataException("could not open file " + e.getMessage()); } catch (IOException e) { throw new UserDataException("i/o error reading file '" + path + "', " + e.getMessage()); } diff --git a/test/jdk/jdk/jfr/tool/TestPrint.java b/test/jdk/jdk/jfr/tool/TestPrint.java index f6b01e71893..88c5ac0840a 100644 --- a/test/jdk/jdk/jfr/tool/TestPrint.java +++ b/test/jdk/jdk/jfr/tool/TestPrint.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -48,7 +48,7 @@ public static void main(String[] args) throws Throwable { output.shouldContain("missing file"); output = ExecuteHelper.jfr("print", "missing.jfr"); - output.shouldContain("could not find file "); + output.shouldContain("could not open file "); Path file = Utils.createTempFile("faked-print-file", ".jfr"); FileWriter fw = new FileWriter(file.toFile()); From c812cebc27190f3545f2272e2a0553db0c705852 Mon Sep 17 00:00:00 2001 From: mseledtsov Date: Mon, 15 Apr 2019 11:44:07 -0700 Subject: [PATCH 028/131] 8221711: [TESTBUG] create more tests for JFR in container environment Summary: Added test cases for environment and network events Reviewed-by: egahlin --- .../jtreg/containers/docker/JfrNetwork.java | 163 ++++++++++++++++++ .../jtreg/containers/docker/JfrReporter.java | 55 ++---- .../containers/docker/TestJFREvents.java | 44 +++-- .../docker/TestJFRNetworkEvents.java | 73 ++++++++ test/jtreg-ext/requires/VMProps.java | 2 +- 5 files changed, 287 insertions(+), 50 deletions(-) create mode 100644 test/hotspot/jtreg/containers/docker/JfrNetwork.java create mode 100644 test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java diff --git a/test/hotspot/jtreg/containers/docker/JfrNetwork.java b/test/hotspot/jtreg/containers/docker/JfrNetwork.java new file mode 100644 index 00000000000..c1cbbb208f3 --- /dev/null +++ b/test/hotspot/jtreg/containers/docker/JfrNetwork.java @@ -0,0 +1,163 @@ +/* + * 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. 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. + */ +import java.io.InputStream; +import java.io.OutputStream; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketAddress; +import java.nio.file.Paths; +import java.util.List; +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordingFile; +import jdk.test.lib.process.OutputAnalyzer; + + +// This class is intended to run inside a container +public class JfrNetwork { + // use a unique hostname for container + public static final String HOST_NAME = "container-unique-8221711"; + public static final String JFR_REPORTED_CONTAINER_HOSTNAME_TAG = "jfr_reported_container_hostname="; + + public static void main(String[] args) throws Exception { + String event = args[0]; + try (ServerSocket ss = new ServerSocket()) { + testNetworkInfo(ss, event); + } + } + + private static void assertTrue(boolean expr, String msg) { + if (!expr) { + throw new RuntimeException(msg); + } + } + + private static void testNetworkInfo(ServerSocket ss, String event) throws Exception { + ServerSocketListener server = new ServerSocketListener(ss); + server.start(); + SocketWriter writer = new SocketWriter(ss.getLocalSocketAddress()); + + // setup and start the recording + String recordingPath = event + ".jfr"; + log("========= Recording event: " + event); + Recording r = new Recording(); + r.enable(event); + r.setDestination(Paths.get("/", "tmp", recordingPath)); + r.start(); + + // start the socker writer thread, write some data into the socket + writer.start(); + + // wait for writer thread to terminate, then for server thread, then stop recording + writer.joinAndThrow(); + server.joinAndThrow(); + r.stop(); + + // analyze the recording + List events = RecordingFile.readAllEvents(r.getDestination()); + events.forEach(e -> log ("event = " + e)); + assertTrue(!events.isEmpty(), "No recorded network events"); + RecordedEvent e = events.get(0); + log(JFR_REPORTED_CONTAINER_HOSTNAME_TAG + e.getString("host")); + verifyIpAddress(e.getString("address")); + } + + private static void verifyIpAddress(String eventIp) throws Exception { + ProcessBuilder pb = new ProcessBuilder("hostname", "--ip-address"); + OutputAnalyzer out = new OutputAnalyzer(pb.start()); + out.shouldHaveExitValue(0); + log("hostname --ip-address returned: " + out.getOutput()); + out.shouldContain(eventIp); + } + + private static void log(String msg) { + System.out.println(msg); + } + + + private static class ServerSocketListener extends Thread { + Exception exception; + ServerSocket ss; + + ServerSocketListener(ServerSocket socket) throws Exception { + ss = socket; + ss.setReuseAddress(true); + ss.bind(null); + log("ServerSocker Local Address: " + ss.getLocalSocketAddress()); + } + + public void joinAndThrow() throws Exception { + join(); + if (exception != null) { + throw exception; + } + } + + public void run() { + try { + try (Socket s = ss.accept(); InputStream is = s.getInputStream()) { + System.out.println("ServerSocketListener: accepted socket connection: s = " + s); + is.read(); + is.read(); + is.read(); + } + } catch (Exception e) { + exception = e; + } + } + } + + + private static class SocketWriter extends Thread { + Exception exception; + private SocketAddress ssAddr; + + public SocketWriter(SocketAddress sa) { + this.ssAddr = sa; + System.out.println("SocketWriter(): sa = " + sa); + } + + public void joinAndThrow() throws Exception { + join(); + if (exception != null) { + throw exception; + } + } + + public void run() { + try (Socket s = new Socket()) { + s.connect(ssAddr); + try (OutputStream os = s.getOutputStream()) { + os.write('A'); + os.write('B'); + os.write('C'); + } + } catch (Exception e) { + exception = e; + } + } + } + +} diff --git a/test/hotspot/jtreg/containers/docker/JfrReporter.java b/test/hotspot/jtreg/containers/docker/JfrReporter.java index 983fb50ba0a..0c3537f1073 100644 --- a/test/hotspot/jtreg/containers/docker/JfrReporter.java +++ b/test/hotspot/jtreg/containers/docker/JfrReporter.java @@ -22,53 +22,30 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - +import java.nio.file.Path; import java.nio.file.Paths; import jdk.jfr.Recording; +import jdk.jfr.ValueDescriptor; import jdk.jfr.consumer.RecordedEvent; import jdk.jfr.consumer.RecordingFile; - // This class is intended to run inside a container public class JfrReporter { - public static final String TEST_REPORTED_CORES="TEST_REPORTED_CORES"; - public static final String TEST_REPORTED_MEMORY="TEST_REPORTED_MEMORY"; - public static final String TEST_REPORTED_PID="TEST_REPORTED_PID"; - public static final String TESTCASE_CPU="cpu"; - public static final String TESTCASE_MEMORY="memory"; - public static final String TESTCASE_PROCESS="process"; - public static void main(String[] args) throws Exception { - String testCase = args[0]; - System.out.println("Testcase: " + testCase); - switch (testCase) { - case TESTCASE_CPU: - RecordedEvent event = testEvent("jdk.CPUInformation", "cpu.jfr"); - System.out.println(TEST_REPORTED_CORES + "=" + event.getInt("cores")); - break; - case TESTCASE_MEMORY: - event = testEvent("jdk.PhysicalMemory", "memory.jfr"); - System.out.println(TEST_REPORTED_MEMORY + "=" + event.getLong("totalSize")); - break; - case TESTCASE_PROCESS: - event = testEvent("jdk.SystemProcess", "process.jfr"); - System.out.println(TEST_REPORTED_PID + "=" + event.getString("pid")); - break; - default: - throw new IllegalArgumentException("Invalid test case"); + String eventName = args[0]; + try(Recording r = new Recording()) { + r.enable(eventName); + r.start(); + r.stop(); + Path p = Paths.get("/", "tmp", eventName + ".jfr"); + r.dump(p); + for (RecordedEvent e : RecordingFile.readAllEvents(p)) { + System.out.println("===== EventType: " + e.getEventType().getName()); + for (ValueDescriptor v : e.getEventType().getFields()) { + System.out.println(v.getName() + " = " + e.getValue(v.getName())); + } + } } } - - private static RecordedEvent testEvent(String event, String recordingPath) throws Exception { - System.out.println("========= Testing event: " + event); - Recording r = new Recording(); - r.enable(event); - r.setDestination(Paths.get("tmp", recordingPath)); - r.start(); - r.stop(); - - RecordedEvent recordedEvent = RecordingFile.readAllEvents(r.getDestination()).get(0); - System.out.println("RecordedEvent: " + recordedEvent); - return recordedEvent; - } } + \ No newline at end of file diff --git a/test/hotspot/jtreg/containers/docker/TestJFREvents.java b/test/hotspot/jtreg/containers/docker/TestJFREvents.java index 73e6ac178fa..888ef6ff07a 100644 --- a/test/hotspot/jtreg/containers/docker/TestJFREvents.java +++ b/test/hotspot/jtreg/containers/docker/TestJFREvents.java @@ -39,6 +39,8 @@ 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.Asserts; +import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.Utils; @@ -68,6 +70,7 @@ public static void main(String[] args) throws Exception { testProcessInfo(); + testEnvironmentVariables(); } finally { DockerTestUtils.removeDockerImage(imageName); } @@ -79,14 +82,12 @@ private static void testCPUInfo(int valueToSet, int expectedValue) throws Except DockerTestUtils.dockerRunJava( commonDockerOpts() .addDockerOpts("--cpus=" + valueToSet) - .addClassOptions(JfrReporter.TESTCASE_CPU)) - .shouldHaveExitValue(0) - .shouldContain(JfrReporter.TEST_REPORTED_CORES); - + .addClassOptions("jdk.CPUInformation")) + .shouldHaveExitValue(0); // The following assertion is currently disabled due to JFR reporting incorrect values. // JFR reports values for the host system as opposed to values for the container. // @ignore 8219999 - // .shouldContain(JfrReporter.TEST_REPORTED_CORES + "=" + expectedValue); + // .shouldContain("cores = " + expectedValue"); } @@ -95,9 +96,9 @@ private static void testMemory(String valueToSet, String expectedValue) throws E DockerTestUtils.dockerRunJava( commonDockerOpts() .addDockerOpts("--memory=" + valueToSet) - .addClassOptions(JfrReporter.TESTCASE_MEMORY)) + .addClassOptions("jdk.PhysicalMemory")) .shouldHaveExitValue(0) - .shouldContain(JfrReporter.TEST_REPORTED_MEMORY + "=" + expectedValue); + .shouldContain("totalSize = " + expectedValue); } @@ -105,10 +106,9 @@ private static void testProcessInfo() throws Exception { Common.logNewTestCase("ProcessInfo"); DockerTestUtils.dockerRunJava( commonDockerOpts() - .addClassOptions(JfrReporter.TESTCASE_PROCESS)) + .addClassOptions("jdk.SystemProcess")) .shouldHaveExitValue(0) - .shouldContain(JfrReporter.TEST_REPORTED_PID + "=1"); - + .shouldContain("pid = 1"); } @@ -117,4 +117,28 @@ private static DockerRunOptions commonDockerOpts() { .addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/") .addJavaOpts("-cp", "/test-classes/"); } + + + // JTReg always defines the environment variable JAVA_MAIN_CLASS_. + // This variable fits well for use in this test, since it is rather unique. + private static String getTestEnvironmentVariable() throws Exception { + for (String key : System.getenv().keySet()) { + if (key.startsWith("JAVA_MAIN_CLASS")) { + return key; + } + } + throw new RuntimeException("JAVA_MAIN_CLASS_* is not defined"); + } + + + private static void testEnvironmentVariables() throws Exception { + Common.logNewTestCase("EnvironmentVariables"); + + DockerTestUtils.dockerRunJava( + commonDockerOpts() + .addClassOptions("jdk.InitialEnvironmentVariable")) + .shouldHaveExitValue(0) + .shouldContain("key = JAVA_HOME") + .shouldNotContain(getTestEnvironmentVariable()); + } } diff --git a/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java b/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java new file mode 100644 index 00000000000..2f9f6305a00 --- /dev/null +++ b/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java @@ -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. + */ + + +/* + * @test + * @summary Test JFR network related events inside a container; make sure + * the reported host ip and host name are correctly reported within + * the container. + * @requires docker.support + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @build JfrNetwork + * @run driver TestJFRNetworkEvents + */ +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.Utils; + + +public class TestJFRNetworkEvents { + private static final String imageName = Common.imageName("jfr-network"); + private static final int availableCPUs = Runtime.getRuntime().availableProcessors(); + + public static void main(String[] args) throws Exception { + System.out.println("Test Environment: detected availableCPUs = " + availableCPUs); + if (!DockerTestUtils.canTestDocker()) { + return; + } + + DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker"); + + try { + runTest("jdk.SocketWrite"); + } finally { + DockerTestUtils.removeDockerImage(imageName); + } + } + + private static void runTest(String event) throws Exception { + DockerRunOptions opts = new DockerRunOptions(imageName, "/jdk/bin/java", "JfrNetwork") + .addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/") + .addJavaOpts("-cp", "/test-classes/") + .addDockerOpts("--hostname", JfrNetwork.HOST_NAME) + .addClassOptions(event); + DockerTestUtils.dockerRunJava(opts) + .shouldHaveExitValue(0) + .shouldContain(JfrNetwork.JFR_REPORTED_CONTAINER_HOSTNAME_TAG + JfrNetwork.HOST_NAME); + } +} diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java index dbef9d77e82..bd1f85f1efd 100644 --- a/test/jtreg-ext/requires/VMProps.java +++ b/test/jtreg-ext/requires/VMProps.java @@ -416,7 +416,7 @@ protected String isCompiler2Enabled() { * @return true if docker is supported in a given environment */ protected String dockerSupport() { - boolean isSupported = false; + boolean isSupported = true; if (Platform.isLinux()) { // currently docker testing is only supported for Linux, // on certain platforms From bd6392e689bbbac9d4ab0e676372d29270926ceb Mon Sep 17 00:00:00 2001 From: mseledtsov Date: Thu, 25 Apr 2019 11:45:52 -0700 Subject: [PATCH 029/131] 8222888: [TESTBUG] docker/TestJFREvents.java fails due to "RuntimeException: JAVA_MAIN_CLASS_ is not defined" Summary: Introduced unique environment variable Reviewed-by: egahlin, lmesnik, sgehwolf --- .../containers/docker/TestJFREvents.java | 38 +++++++++++-------- .../containers/docker/DockerTestUtils.java | 22 ++++++++--- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/test/hotspot/jtreg/containers/docker/TestJFREvents.java b/test/hotspot/jtreg/containers/docker/TestJFREvents.java index 888ef6ff07a..0b30e66b20f 100644 --- a/test/hotspot/jtreg/containers/docker/TestJFREvents.java +++ b/test/hotspot/jtreg/containers/docker/TestJFREvents.java @@ -36,6 +36,7 @@ * @build JfrReporter * @run driver TestJFREvents */ +import java.util.List; import jdk.test.lib.containers.docker.Common; import jdk.test.lib.containers.docker.DockerRunOptions; import jdk.test.lib.containers.docker.DockerTestUtils; @@ -46,6 +47,8 @@ public class TestJFREvents { private static final String imageName = Common.imageName("jfr-events"); + private static final String TEST_ENV_VARIABLE = "UNIQUE_VARIABLE_ABC592903XYZ"; + private static final String TEST_ENV_VALUE = "unique_value_abc592903xyz"; private static final int availableCPUs = Runtime.getRuntime().availableProcessors(); public static void main(String[] args) throws Exception { @@ -119,26 +122,29 @@ private static DockerRunOptions commonDockerOpts() { } - // JTReg always defines the environment variable JAVA_MAIN_CLASS_. - // This variable fits well for use in this test, since it is rather unique. - private static String getTestEnvironmentVariable() throws Exception { - for (String key : System.getenv().keySet()) { - if (key.startsWith("JAVA_MAIN_CLASS")) { - return key; - } - } - throw new RuntimeException("JAVA_MAIN_CLASS_* is not defined"); - } - - private static void testEnvironmentVariables() throws Exception { Common.logNewTestCase("EnvironmentVariables"); - DockerTestUtils.dockerRunJava( + List cmd = DockerTestUtils.buildJavaCommand( commonDockerOpts() - .addClassOptions("jdk.InitialEnvironmentVariable")) - .shouldHaveExitValue(0) + .addClassOptions("jdk.InitialEnvironmentVariable")); + + ProcessBuilder pb = new ProcessBuilder(cmd); + // Container has JAVA_HOME defined via the Dockerfile; make sure + // it is reported by JFR event. + // Environment variable set in host system should not be visible inside a container, + // and should not be reported by JFR. + pb.environment().put(TEST_ENV_VARIABLE, TEST_ENV_VALUE); + + System.out.println("[COMMAND]\n" + Utils.getCommandLine(pb)); + OutputAnalyzer out = new OutputAnalyzer(pb.start()); + System.out.println("[STDERR]\n" + out.getStderr()); + System.out.println("[STDOUT]\n" + out.getStdout()); + + out.shouldHaveExitValue(0) .shouldContain("key = JAVA_HOME") - .shouldNotContain(getTestEnvironmentVariable()); + .shouldContain("value = /jdk") + .shouldNotContain(TEST_ENV_VARIABLE) + .shouldNotContain(TEST_ENV_VALUE); } } diff --git a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java index ff3674fe6b2..1044e57fc4f 100644 --- a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java +++ b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java @@ -192,15 +192,15 @@ private static boolean isDockerEngineAvailableCheck() throws Exception { /** - * Run Java inside the docker image with specified parameters and options. + * Build the docker command to run java inside a container * * @param DockerRunOptions optins for running docker * - * @return output of the run command + * @return command * @throws Exception */ - public static OutputAnalyzer dockerRunJava(DockerRunOptions opts) throws Exception { - ArrayList cmd = new ArrayList<>(); + public static List buildJavaCommand(DockerRunOptions opts) throws Exception { + List cmd = new ArrayList<>(); cmd.add(DOCKER_COMMAND); cmd.add("run"); @@ -221,7 +221,19 @@ public static OutputAnalyzer dockerRunJava(DockerRunOptions opts) throws Excepti cmd.add(opts.classToRun); cmd.addAll(opts.classParams); - return execute(cmd); + return cmd; + } + + /** + * Run Java inside the docker image with specified parameters and options. + * + * @param DockerRunOptions optins for running docker + * + * @return output of the run command + * @throws Exception + */ + public static OutputAnalyzer dockerRunJava(DockerRunOptions opts) throws Exception { + return execute(buildJavaCommand(opts)); } From a3f8a62d61c6b7450eb70e8c6a953a24e1219aa1 Mon Sep 17 00:00:00 2001 From: cito Date: Fri, 10 May 2019 20:56:37 +0200 Subject: [PATCH 030/131] 8221569: JFR tool produces incorrect output when both --categories and --events are specified Reviewed-by: mgronlun Contributed-by: chihiro.ito@oracle.com, erik.gahlin@oracle.com --- .../classes/jdk/jfr/internal/tool/Print.java | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Print.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Print.java index 1f9294c7dc6..7b5d89f9e2f 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Print.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Print.java @@ -107,13 +107,23 @@ public void execute(Deque options) throws UserSyntaxException, UserDataE int stackDepth = 5; EventPrintWriter eventWriter = null; int optionCount = options.size(); + boolean foundEventFilter = false; + boolean foundCategoryFilter = false; while (optionCount > 0) { if (acceptFilterOption(options, "--events")) { + if (foundEventFilter) { + throw new UserSyntaxException("use --events event1,event2,event3 to include multiple events"); + } + foundEventFilter = true; String filter = options.remove(); warnForWildcardExpansion("--events", filter); eventFilter = addEventFilter(filter, eventFilter); } if (acceptFilterOption(options, "--categories")) { + if (foundCategoryFilter) { + throw new UserSyntaxException("use --categories category1,category2 to include multiple categories"); + } + foundCategoryFilter = true; String filter = options.remove(); warnForWildcardExpansion("--categories", filter); eventFilter = addCategoryFilter(filter, eventFilter); @@ -137,6 +147,8 @@ public void execute(Deque options) throws UserSyntaxException, UserDataE } if (optionCount == options.size()) { // No progress made + checkCommonError(options, "--event", "--events"); + checkCommonError(options, "--category", "--categories"); throw new UserSyntaxException("unknown option " + options.peek()); } optionCount = options.size(); @@ -157,6 +169,12 @@ public void execute(Deque options) throws UserSyntaxException, UserDataE pw.flush(); } + private void checkCommonError(Deque options, String typo, String correct) throws UserSyntaxException { + if (typo.equals(options.peek())) { + throw new UserSyntaxException("unknown option " + typo + ", did you mean " + correct + "?"); + } + } + private static boolean acceptFormatterOption(Deque options, EventPrintWriter eventWriter, String expected) throws UserSyntaxException { if (expected.equals(options.peek())) { if (eventWriter != null) { @@ -179,7 +197,7 @@ private static Predicate recurseIfPossible(Predicate filter) { private static Predicate addCategoryFilter(String filterText, Predicate eventFilter) throws UserSyntaxException { List filters = explodeFilter(filterText); - return recurseIfPossible(eventType -> { + Predicate newFilter = recurseIfPossible(eventType -> { for (String category : eventType.getCategoryNames()) { for (String filter : filters) { if (match(category, filter)) { @@ -192,6 +210,7 @@ private static Predicate addCategoryFilter(String filterText, Predica } return false; }); + return eventFilter == null ? newFilter : eventFilter.or(newFilter); } private static String acronomify(String multipleWords) { @@ -210,7 +229,7 @@ private static String acronomify(String multipleWords) { private static Predicate addEventFilter(String filterText, final Predicate eventFilter) throws UserSyntaxException { List filters = explodeFilter(filterText); - return recurseIfPossible(eventType -> { + Predicate newFilter = recurseIfPossible(eventType -> { for (String filter : filters) { String fullEventName = eventType.getName(); if (match(fullEventName, filter)) { @@ -223,6 +242,7 @@ private static Predicate addEventFilter(String filterText, final Pred } return false; }); + return eventFilter == null ? newFilter : eventFilter.or(newFilter); } private static boolean match(String text, String filter) { From ba3f0257fdf9b0afdb9e9cf25ae75552467dfa2b Mon Sep 17 00:00:00 2001 From: egahlin Date: Thu, 6 Jun 2019 20:19:03 +0200 Subject: [PATCH 031/131] 8216283: Allow shorter method sampling interval than 10 ms Reviewed-by: mgronlun --- src/jdk.jfr/share/conf/jfr/default.jfc | 41 ++++++++++++++++++++---- src/jdk.jfr/share/conf/jfr/profile.jfc | 43 +++++++++++++++++++++----- 2 files changed, 71 insertions(+), 13 deletions(-) diff --git a/src/jdk.jfr/share/conf/jfr/default.jfc b/src/jdk.jfr/share/conf/jfr/default.jfc index 04e02e93134..02e2f2171ac 100644 --- a/src/jdk.jfr/share/conf/jfr/default.jfc +++ b/src/jdk.jfr/share/conf/jfr/default.jfc @@ -115,12 +115,12 @@ true - 20 ms + 20 ms true - 20 ms + 20 ms @@ -773,13 +773,42 @@ - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/src/jdk.jfr/share/conf/jfr/profile.jfc b/src/jdk.jfr/share/conf/jfr/profile.jfc index fec835f1493..5b9ca8d67de 100644 --- a/src/jdk.jfr/share/conf/jfr/profile.jfc +++ b/src/jdk.jfr/share/conf/jfr/profile.jfc @@ -115,12 +115,12 @@ true - 10 ms + 10 ms true - 10 ms + 20 ms @@ -773,14 +773,43 @@ - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + From 010d0c62ef546512c645862b9f646ae5eb6ee3f8 Mon Sep 17 00:00:00 2001 From: smarks Date: Wed, 11 Sep 2019 17:15:01 -0700 Subject: [PATCH 032/131] 8227368: EnumSet.class serialization broken in JDK 9+ Reviewed-by: plevart, clanger --- .../share/classes/java/util/EnumSet.java | 16 ++- test/jdk/java/util/EnumSet/BogusEnumSet.java | 13 +-- .../EnumSet/EnumSetClassSerialization.java | 101 ++++++++++++++++++ 3 files changed, 119 insertions(+), 11 deletions(-) create mode 100644 test/jdk/java/util/EnumSet/EnumSetClassSerialization.java diff --git a/src/java.base/share/classes/java/util/EnumSet.java b/src/java.base/share/classes/java/util/EnumSet.java index 70da034a8b3..69da1680de6 100644 --- a/src/java.base/share/classes/java/util/EnumSet.java +++ b/src/java.base/share/classes/java/util/EnumSet.java @@ -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 @@ -76,20 +76,26 @@ * @since 1.5 * @see EnumMap */ -@SuppressWarnings("serial") // No serialVersionUID due to usage of - // serial proxy pattern +@SuppressWarnings("serial") // No serialVersionUID declared public abstract class EnumSet> extends AbstractSet implements Cloneable, java.io.Serializable { + // The following must be present in order to preserve the same computed + // serialVersionUID value as JDK 8, and to prevent the appearance of + // the fields in the Serialized Form documentation. See JDK-8227368. + static Enum[] access$000() { return null; } + private static final java.io.ObjectStreamField[] serialPersistentFields + = new java.io.ObjectStreamField[0]; + /** * The class of all the elements of this set. */ - final transient Class elementType; + final Class elementType; /** * All of the values comprising E. (Cached for performance.) */ - final transient Enum[] universe; + final Enum[] universe; EnumSet(ClasselementType, Enum[] universe) { this.elementType = elementType; diff --git a/test/jdk/java/util/EnumSet/BogusEnumSet.java b/test/jdk/java/util/EnumSet/BogusEnumSet.java index c24bbfbbbee..9ee5d80aa15 100644 --- a/test/jdk/java/util/EnumSet/BogusEnumSet.java +++ b/test/jdk/java/util/EnumSet/BogusEnumSet.java @@ -32,11 +32,12 @@ public class BogusEnumSet { public static void main(String[] args) throws Throwable { - // This test depends on the current serialVersionUID of EnumSet, - // which may change if the EnumSet class is modified. - // The current value is -2409567991088730183L = 0xde8f7eadb5012fb9L - // If the value changes, it will have to be patched into the - // serialized byte stream below at the location noted. + // This test depends on the computed serialVersionUID of EnumSet, + // which is 1009687484059888093L = 0x0e03216acd8c29ddL. This + // value should remain the same in order to remain compatible + // with JDK 8. If this value changes, then EnumSet has changed + // incompatibly. The value is embedded within the serialized + // byte stream below at the location noted. byte[] serializedForm = { (byte)0xac, (byte)0xed, 0x0, 0x5, 0x73, 0x72, 0x0, 0x18, 0x6a, 0x61, 0x76, 0x61, 0x2e, 0x75, 0x74, 0x69, @@ -47,7 +48,7 @@ public static void main(String[] args) throws Throwable { 0x11, 0x6a, 0x61, 0x76, 0x61, 0x2e, 0x75, 0x74, 0x69, 0x6c, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x53, 0x65, 0x74, // EnumSet's serialVersionUID is the following eight bytes (big-endian) - (byte)0xde, (byte)0x8f, 0x7e, (byte)0xad, (byte)0xb5, (byte)0x01, 0x2f, (byte)0xb9, + 0x0e, 0x03, 0x21, 0x6a, (byte)0xcd, (byte)0x8c, 0x29, (byte)0xdd, 0x2, 0x0, 0x2, 0x4c, 0x0, 0xb, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x74, 0x0, 0x11, 0x4c, 0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x43, 0x6c, 0x61, 0x73, diff --git a/test/jdk/java/util/EnumSet/EnumSetClassSerialization.java b/test/jdk/java/util/EnumSet/EnumSetClassSerialization.java new file mode 100644 index 00000000000..3f8fc5f17a5 --- /dev/null +++ b/test/jdk/java/util/EnumSet/EnumSetClassSerialization.java @@ -0,0 +1,101 @@ +/* + * 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 8227368 + * @summary Test deserialization of a stream containing EnumSet.class object + */ + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.EnumSet; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class EnumSetClassSerialization { + + public static void main(String[] args) throws Exception { + // EnumSet.class object serialized with JDK 8 + int[] bytes = { + 0xac, 0xed, 0x00, 0x05, 0x76, 0x72, 0x00, 0x11, 0x6a, 0x61, 0x76, 0x61, 0x2e, 0x75, 0x74, 0x69, + 0x6c, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x53, 0x65, 0x74, 0x0e, 0x03, 0x21, 0x6a, 0xcd, 0x8c, 0x29, + 0xdd, 0x02, 0x00, 0x02, 0x4c, 0x00, 0x0b, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x79, + 0x70, 0x65, 0x74, 0x00, 0x11, 0x4c, 0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, + 0x43, 0x6c, 0x61, 0x73, 0x73, 0x3b, 0x5b, 0x00, 0x08, 0x75, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, + 0x65, 0x74, 0x00, 0x11, 0x5b, 0x4c, 0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, + 0x45, 0x6e, 0x75, 0x6d, 0x3b, 0x78, 0x70 + }; + + InputStream in = new InputStream() { + int i = 0; + + @Override + public int read() { + return i < bytes.length ? bytes[i++] & 0xFF : -1; + } + }; + ObjectInputStream ois = new ObjectInputStream(in); + + Object res = ois.readObject(); + + if (res != EnumSet.class) { + throw new AssertionError( + "Expected: " + EnumSet.class + ", got: " + res); + } + } + + /** + * This class can be used to print out lines that constitute + * the 'bytes' variable initializer in the test. + */ + public static class Serializer { + public static void main(String[] args) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(EnumSet.class); + oos.close(); + byte[] bytes = baos.toByteArray(); + int bpl = 16; + System.out.print( + IntStream + .range(0, (bytes.length + bpl - 1) / bpl) + .mapToObj(i -> IntStream + .range( + i * bpl, + Math.min(i * bpl + bpl, bytes.length) + ) + .mapToObj(ii -> { + String s = Integer.toHexString(bytes[ii] & 0xFF); + return s.length() == 1 ? "0x0" + s : "0x" + s; + }) + .collect(Collectors.joining(", ")) + ) + .collect(Collectors.joining(",\n ", "int[] bytes = {\n ", "\n};")) + ); + } + } +} From 02d857d0f3d7e3ca52a72e366be5859d20c2d09c Mon Sep 17 00:00:00 2001 From: shade Date: Mon, 2 Sep 2019 11:31:12 +0200 Subject: [PATCH 033/131] 8230238: Add another regression test for JDK-8134739 Reviewed-by: kvn --- .../loopopts/superword/TestFuzzPreLoop.java | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/loopopts/superword/TestFuzzPreLoop.java diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestFuzzPreLoop.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestFuzzPreLoop.java new file mode 100644 index 00000000000..1108755b65e --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestFuzzPreLoop.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2019, Red Hat, 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. + * + * 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 8134739 + * @summary SEGV in SuperWord::get_pre_loop_end + * @run main/othervm compiler.loopopts.superword.TestFuzzPreLoop + */ + +package compiler.loopopts.superword; + +public class TestFuzzPreLoop { + static Object sink; + short sFld = -19206; + + void doTest() { + int[] arr = new int[400]; + + for (int i1 = 0; i1 < 200; i1++) { + for (int i2 = 0; i2 < 100; i2++) { + sink = new int[400]; + } + arr[i1] = 0; + } + + float f1 = 0; + for (int i3 = 0; i3 < 200; i3++) { + f1 += i3 * i3; + } + for (int i4 = 0; i4 < 200; i4++) { + f1 += i4 - sFld; + } + + System.out.println(arr); + System.out.println(f1); + } + + public static void main(String... args) throws Exception { + TestFuzzPreLoop test = new TestFuzzPreLoop(); + for (int i = 0; i < 100; i++) { + test.doTest(); + } + } +} From 2d63ac93a14909edec8371617e5d22bb46dc8d96 Mon Sep 17 00:00:00 2001 From: shade Date: Tue, 10 Sep 2019 19:58:22 +0200 Subject: [PATCH 034/131] 8230813: Add JDK-8010500 to compiler/loopopts/superword/TestFuzzPreLoop.java bug list Reviewed-by: zgu --- .../jtreg/compiler/loopopts/superword/TestFuzzPreLoop.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestFuzzPreLoop.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestFuzzPreLoop.java index 1108755b65e..61fd78d3a0a 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestFuzzPreLoop.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestFuzzPreLoop.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8134739 + * @bug 8134739 8010500 * @summary SEGV in SuperWord::get_pre_loop_end * @run main/othervm compiler.loopopts.superword.TestFuzzPreLoop */ From bb515f4458a38073f7b7d08da3daf4cd80a9756a Mon Sep 17 00:00:00 2001 From: coleenp Date: Fri, 14 Sep 2018 12:10:28 -0400 Subject: [PATCH 035/131] 8210559: ClassLoaderData Symbols can leak Summary: unrefcount the symbol names when the CLD is destroyed Reviewed-by: lfoltan, jiangli, iklam --- .../hotspot/jtreg/runtime/ClassUnload/UnloadTest.java | 11 ++++++++++- .../jtreg/runtime/testlibrary/ClassUnloadCommon.java | 4 ++-- test/lib/sun/hotspot/WhiteBox.java | 1 + 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/test/hotspot/jtreg/runtime/ClassUnload/UnloadTest.java b/test/hotspot/jtreg/runtime/ClassUnload/UnloadTest.java index 972d2ea014e..ef1d29eeba6 100644 --- a/test/hotspot/jtreg/runtime/ClassUnload/UnloadTest.java +++ b/test/hotspot/jtreg/runtime/ClassUnload/UnloadTest.java @@ -23,6 +23,7 @@ /* * @test UnloadTest + * @bug 8210559 * @requires vm.opt.final.ClassUnloading * @modules java.base/jdk.internal.misc * @library /runtime/testlibrary /test/lib @@ -30,7 +31,7 @@ * @build sun.hotspot.WhiteBox test.Empty * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm -Xbootclasspath/a:. -Xmn8m -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI UnloadTest + * @run main/othervm -Xbootclasspath/a:. -Xmn8m -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xlog:class+unload=debug UnloadTest */ import sun.hotspot.WhiteBox; @@ -60,8 +61,16 @@ private static void run() throws Exception { ClassUnloadCommon.failIf(!wb.isClassAlive(className), "should be live here"); + String loaderName = cl.getName(); + int loadedRefcount = wb.getSymbolRefcount(loaderName); + System.out.println("Refcount of symbol " + loaderName + " is " + loadedRefcount); + cl = null; c = null; o = null; ClassUnloadCommon.triggerUnloading(); ClassUnloadCommon.failIf(wb.isClassAlive(className), "should have been unloaded"); + + int unloadedRefcount = wb.getSymbolRefcount(loaderName); + System.out.println("Refcount of symbol " + loaderName + " is " + unloadedRefcount); + ClassUnloadCommon.failIf(unloadedRefcount != (loadedRefcount - 1), "Refcount must be decremented"); } } diff --git a/test/hotspot/jtreg/runtime/testlibrary/ClassUnloadCommon.java b/test/hotspot/jtreg/runtime/testlibrary/ClassUnloadCommon.java index 33e2d6c56ea..254411efeeb 100644 --- a/test/hotspot/jtreg/runtime/testlibrary/ClassUnloadCommon.java +++ b/test/hotspot/jtreg/runtime/testlibrary/ClassUnloadCommon.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -73,7 +73,7 @@ public static ClassLoader newClassLoader() { .map(Paths::get) .map(ClassUnloadCommon::toURL) .toArray(URL[]::new); - return new URLClassLoader(urls) { + return new URLClassLoader("ClassUnloadCommonClassLoader", urls, new ClassUnloadCommon().getClass().getClassLoader()) { @Override public Class loadClass(String cn, boolean resolve) throws ClassNotFoundException diff --git a/test/lib/sun/hotspot/WhiteBox.java b/test/lib/sun/hotspot/WhiteBox.java index 003c987bd40..034ddc5a099 100644 --- a/test/lib/sun/hotspot/WhiteBox.java +++ b/test/lib/sun/hotspot/WhiteBox.java @@ -103,6 +103,7 @@ public boolean isClassAlive(String name) { return isClassAlive0(name.replace('.', '/')); } private native boolean isClassAlive0(String name); + public native int getSymbolRefcount(String name); private native boolean isMonitorInflated0(Object obj); public boolean isMonitorInflated(Object obj) { From 9650fb11b695c82991fbfe18592409746a7bc08e Mon Sep 17 00:00:00 2001 From: mbaesken Date: Mon, 9 Sep 2019 16:34:45 +0200 Subject: [PATCH 036/131] 8230769: BufImg_SetupICM add ReleasePrimitiveArrayCritical call in early return Reviewed-by: prr, stuefe --- .../share/native/libawt/awt/image/BufImgSurfaceData.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/java.desktop/share/native/libawt/awt/image/BufImgSurfaceData.c b/src/java.desktop/share/native/libawt/awt/image/BufImgSurfaceData.c index b53b2e379c7..c15795203a1 100644 --- a/src/java.desktop/share/native/libawt/awt/image/BufImgSurfaceData.c +++ b/src/java.desktop/share/native/libawt/awt/image/BufImgSurfaceData.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2018, 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 @@ -351,6 +351,7 @@ static ColorData *BufImg_SetupICM(JNIEnv *env, cData->img_clr_tbl = initCubemap(pRgb, bisdo->lutsize, 32); if (cData->img_clr_tbl == NULL) { + (*env)->ReleasePrimitiveArrayCritical(env, bisdo->lutarray, pRgb, JNI_ABORT); free(cData); return (ColorData*)NULL; } From ada3ad4a602bf6ce912e0211cf99849e55a9dae4 Mon Sep 17 00:00:00 2001 From: mbaesken Date: Tue, 3 Sep 2019 17:52:36 +0200 Subject: [PATCH 037/131] 8229182: runtime/containers/docker/TestMemoryAwareness.java test fails on SLES12 Reviewed-by: clanger, mseledtsov --- .../docker/TestMemoryAwareness.java | 27 +++++++++++++------ .../containers/docker/DockerRunOptions.java | 15 ++++++++--- .../containers/docker/DockerTestUtils.java | 3 +-- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java b/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java index 45c83de781b..f89fa81ffd6 100644 --- a/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java +++ b/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java @@ -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 @@ -37,7 +37,7 @@ 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.process.OutputAnalyzer; public class TestMemoryAwareness { private static final String imageName = Common.imageName("memory"); @@ -98,15 +98,26 @@ private static void testMemorySoftLimit(String valueToSet, String expectedTraceV private static void testOOM(String dockerMemLimit, int sizeToAllocInMb) throws Exception { Common.logNewTestCase("OOM"); + // add "--memory-swappiness 0" so as to disable anonymous page swapping. DockerRunOptions opts = Common.newOpts(imageName, "AttemptOOM") - .addDockerOpts("--memory", dockerMemLimit, "--memory-swap", dockerMemLimit); + .addDockerOpts("--memory", dockerMemLimit, "--memory-swappiness", "0", "--memory-swap", dockerMemLimit); opts.classParams.add("" + sizeToAllocInMb); - DockerTestUtils.dockerRunJava(opts) - .shouldHaveExitValue(1) - .shouldContain("Entering AttemptOOM main") - .shouldNotContain("AttemptOOM allocation successful") - .shouldContain("java.lang.OutOfMemoryError"); + // make sure we avoid inherited Xmx settings from the jtreg vmoptions + // set Xmx ourselves instead + System.out.println("sizeToAllocInMb is:" + sizeToAllocInMb + " sizeToAllocInMb/2 is:" + sizeToAllocInMb/2); + String javaHeapSize = sizeToAllocInMb/2 + "m"; + opts.addJavaOptsAppended("-Xmx" + javaHeapSize); + + OutputAnalyzer out = DockerTestUtils.dockerRunJava(opts); + + if (out.getExitValue() == 0) { + throw new RuntimeException("We exited successfully, but we wanted to provoke an OOM inside the container"); + } + + out.shouldContain("Entering AttemptOOM main") + .shouldNotContain("AttemptOOM allocation successful") + .shouldContain("java.lang.OutOfMemoryError"); } } diff --git a/test/lib/jdk/test/lib/containers/docker/DockerRunOptions.java b/test/lib/jdk/test/lib/containers/docker/DockerRunOptions.java index e7da42ff780..508c17fc399 100644 --- a/test/lib/jdk/test/lib/containers/docker/DockerRunOptions.java +++ b/test/lib/jdk/test/lib/containers/docker/DockerRunOptions.java @@ -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 @@ -31,11 +31,13 @@ // in test environment. public class DockerRunOptions { public String imageNameAndTag; - public ArrayList dockerOpts = new ArrayList(); + public ArrayList dockerOpts = new ArrayList<>(); public String command; // normally a full path to java - public ArrayList javaOpts = new ArrayList(); + public ArrayList javaOpts = new ArrayList<>(); + // more java options, but to be set AFTER the test Java options + public ArrayList javaOptsAppended = new ArrayList<>(); public String classToRun; // class or "-version" - public ArrayList classParams = new ArrayList(); + public ArrayList classParams = new ArrayList<>(); public boolean tty = true; public boolean removeContainerAfterUse = true; @@ -70,6 +72,11 @@ public DockerRunOptions addJavaOpts(String... opts) { return this; } + public DockerRunOptions addJavaOptsAppended(String... opts) { + Collections.addAll(javaOptsAppended, opts); + return this; + } + public DockerRunOptions addClassOptions(String... opts) { Collections.addAll(classParams,opts); return this; diff --git a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java index 1044e57fc4f..bb040826aa3 100644 --- a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java +++ b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java @@ -39,12 +39,10 @@ import java.util.List; import jdk.test.lib.Utils; import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.process.ProcessTools; import jtreg.SkippedException; public class DockerTestUtils { - private static final String FS = File.separator; private static boolean isDockerEngineAvailable = false; private static boolean wasDockerEngineChecked = false; @@ -217,6 +215,7 @@ public static List buildJavaCommand(DockerRunOptions opts) throws Except if (opts.appendTestJavaOptions) { Collections.addAll(cmd, Utils.getTestJavaOpts()); } + cmd.addAll(opts.javaOptsAppended); cmd.add(opts.classToRun); cmd.addAll(opts.classParams); From bfa43620c301ac8cf6b48c1883f130e48b1df1ca Mon Sep 17 00:00:00 2001 From: roland Date: Mon, 5 Nov 2018 12:53:55 +0100 Subject: [PATCH 038/131] 8209835: Aarch64: elide barriers on all volatile operations Reviewed-by: aph, adinn --- .../c2/aarch64/TestUnsafeVolatileCAE.java | 133 ++++ .../c2/aarch64/TestUnsafeVolatileCAS.java | 54 ++ .../c2/aarch64/TestUnsafeVolatileGAA.java | 76 ++ .../c2/aarch64/TestUnsafeVolatileGAS.java | 90 +++ .../c2/aarch64/TestUnsafeVolatileWeakCAS.java | 139 ++++ .../compiler/c2/aarch64/TestVolatiles.java | 649 +++++++++++++++--- .../compiler/c2/aarch64/TestVolatilesCMS.java | 12 + .../c2/aarch64/TestVolatilesCMSCondMark.java | 12 + .../compiler/c2/aarch64/TestVolatilesG1.java | 17 + .../c2/aarch64/TestVolatilesParallel.java | 12 + .../c2/aarch64/TestVolatilesSerial.java | 12 + 11 files changed, 1099 insertions(+), 107 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/aarch64/TestUnsafeVolatileCAE.java create mode 100644 test/hotspot/jtreg/compiler/c2/aarch64/TestUnsafeVolatileGAA.java create mode 100644 test/hotspot/jtreg/compiler/c2/aarch64/TestUnsafeVolatileGAS.java create mode 100644 test/hotspot/jtreg/compiler/c2/aarch64/TestUnsafeVolatileWeakCAS.java diff --git a/test/hotspot/jtreg/compiler/c2/aarch64/TestUnsafeVolatileCAE.java b/test/hotspot/jtreg/compiler/c2/aarch64/TestUnsafeVolatileCAE.java new file mode 100644 index 00000000000..f9bec79d62b --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/aarch64/TestUnsafeVolatileCAE.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2018, Red Hat, 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. + * + * 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.c2.aarch64; + +import java.lang.reflect.Field; +import jdk.internal.misc.Unsafe; + +class TestUnsafeVolatileCAE +{ + public volatile int f_int = 0; + public volatile Integer f_obj = Integer.valueOf(0); + public volatile long f_long = 0; + public volatile byte f_byte = 0; + public volatile short f_short = 0; + + public static Unsafe unsafe = Unsafe.getUnsafe(); + public static Field f_int_field; + public static Field f_obj_field; + public static Field f_long_field; + public static Field f_byte_field; + public static Field f_short_field; + public static long f_int_off; + public static long f_obj_off; + public static long f_long_off; + public static long f_byte_off; + public static long f_short_off; + + static { + try { + f_int_field = TestUnsafeVolatileCAE.class.getField("f_int"); + f_obj_field = TestUnsafeVolatileCAE.class.getField("f_obj"); + f_long_field = TestUnsafeVolatileCAE.class.getField("f_long"); + f_byte_field = TestUnsafeVolatileCAE.class.getField("f_byte"); + f_short_field = TestUnsafeVolatileCAE.class.getField("f_short"); + f_int_off = unsafe.objectFieldOffset(f_int_field); + f_obj_off = unsafe.objectFieldOffset(f_obj_field); + f_long_off = unsafe.objectFieldOffset(f_long_field); + f_byte_off = unsafe.objectFieldOffset(f_byte_field); + f_short_off = unsafe.objectFieldOffset(f_short_field); + } catch (Exception e) { + System.out.println("reflection failed " + e); + e.printStackTrace(); + } + } + + public static void main(String[] args) + { + final TestUnsafeVolatileCAE t = new TestUnsafeVolatileCAE(); + for (int i = 0; i < 100_000; i++) { + t.f_int = -1; + int res = t.testInt(-1, i); + if (res != -1 || t.f_int != i) { + throw new RuntimeException("bad result!"); + } + } + for (int i = 0; i < 100_000; i++) { + t.f_long = -1; + long res = t.testLong(-1, i); + if (res != -1 || t.f_long != i) { + throw new RuntimeException("bad result!"); + } + } + for (int i = 0; i < 100_000; i++) { + t.f_byte = -1; + byte i_b = (byte)i; + byte res = t.testByte((byte)-1, i_b); + if (res != (byte)-1 || t.f_byte != i_b) { + throw new RuntimeException("bad result!"); + } + } + for (int i = 0; i < 100_000; i++) { + t.f_short = -1; + short i_s = (short)i; + short res = t.testShort((byte)-1, i_s); + if (res != (short)-1 || t.f_short != i_s) { + throw new RuntimeException("bad result!"); + } + } + Integer minusOne = Integer.valueOf(-1); + for (int i = 0; i < 100_000; i++) { + t.f_obj = minusOne; + Object res = t.testObj(minusOne, Integer.valueOf(i)); + if (res != minusOne || t.f_obj != i) { + throw new RuntimeException("bad result!"); + } + } + } + + public int testInt(int x, int i) + { + return unsafe.compareAndExchangeInt(this, f_int_off, x, i); + } + + public Object testObj(Object x, Object o) + { + return unsafe.compareAndExchangeObject(this, f_obj_off, x, o); + } + public long testLong(long x, long i) + { + return unsafe.compareAndExchangeLong(this, f_long_off, x, i); + } + + public byte testByte(byte x, byte i) + { + return unsafe.compareAndExchangeByte(this, f_byte_off, x, i); + } + + public short testShort(short x, short i) + { + return unsafe.compareAndExchangeShort(this, f_short_off, x, i); + } +} diff --git a/test/hotspot/jtreg/compiler/c2/aarch64/TestUnsafeVolatileCAS.java b/test/hotspot/jtreg/compiler/c2/aarch64/TestUnsafeVolatileCAS.java index 0539af2db79..50913705aa1 100644 --- a/test/hotspot/jtreg/compiler/c2/aarch64/TestUnsafeVolatileCAS.java +++ b/test/hotspot/jtreg/compiler/c2/aarch64/TestUnsafeVolatileCAS.java @@ -30,19 +30,34 @@ class TestUnsafeVolatileCAS { public volatile int f_int = 0; public volatile Integer f_obj = Integer.valueOf(0); + public volatile long f_long = 0; + public volatile byte f_byte = 0; + public volatile short f_short = 0; public static Unsafe unsafe = Unsafe.getUnsafe(); public static Field f_int_field; public static Field f_obj_field; + public static Field f_long_field; + public static Field f_byte_field; + public static Field f_short_field; public static long f_int_off; public static long f_obj_off; + public static long f_long_off; + public static long f_byte_off; + public static long f_short_off; static { try { f_int_field = TestUnsafeVolatileCAS.class.getField("f_int"); f_obj_field = TestUnsafeVolatileCAS.class.getField("f_obj"); + f_long_field = TestUnsafeVolatileCAS.class.getField("f_long"); + f_byte_field = TestUnsafeVolatileCAS.class.getField("f_byte"); + f_short_field = TestUnsafeVolatileCAS.class.getField("f_short"); f_int_off = unsafe.objectFieldOffset(f_int_field); f_obj_off = unsafe.objectFieldOffset(f_obj_field); + f_long_off = unsafe.objectFieldOffset(f_long_field); + f_byte_off = unsafe.objectFieldOffset(f_byte_field); + f_short_off = unsafe.objectFieldOffset(f_short_field); } catch (Exception e) { System.out.println("reflection failed " + e); e.printStackTrace(); @@ -59,6 +74,29 @@ public static void main(String[] args) throw new RuntimeException("bad result!"); } } + for (int i = 0; i < 100_000; i++) { + t.f_long = -1; + t.testLong(-1, i); + if (t.f_long != i) { + throw new RuntimeException("bad result!"); + } + } + for (int i = 0; i < 100_000; i++) { + t.f_byte = -1; + byte i_b = (byte)i; + t.testByte((byte)-1, i_b); + if (t.f_byte != i_b) { + throw new RuntimeException("bad result!"); + } + } + for (int i = 0; i < 100_000; i++) { + t.f_short = -1; + short i_s = (short)i; + t.testShort((byte)-1, i_s); + if (t.f_short != i_s) { + throw new RuntimeException("bad result!"); + } + } Integer minusOne = Integer.valueOf(-1); for (int i = 0; i < 100_000; i++) { t.f_obj = minusOne; @@ -68,6 +106,7 @@ public static void main(String[] args) } } } + public void testInt(int x, int i) { unsafe.compareAndSetInt(this, f_int_off, x, i); @@ -77,4 +116,19 @@ public void testObj(Object x, Object o) { unsafe.compareAndSetObject(this, f_obj_off, x, o); } + + public void testLong(long x, long i) + { + unsafe.compareAndSetLong(this, f_long_off, x, i); + } + + public void testByte(byte x, byte i) + { + unsafe.compareAndSetByte(this, f_byte_off, x, i); + } + + public void testShort(short x, short i) + { + unsafe.compareAndSetShort(this, f_short_off, x, i); + } } diff --git a/test/hotspot/jtreg/compiler/c2/aarch64/TestUnsafeVolatileGAA.java b/test/hotspot/jtreg/compiler/c2/aarch64/TestUnsafeVolatileGAA.java new file mode 100644 index 00000000000..25a8af804de --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/aarch64/TestUnsafeVolatileGAA.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, Red Hat, 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. + * + * 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.c2.aarch64; + +import java.lang.reflect.Field; +import jdk.internal.misc.Unsafe; + +class TestUnsafeVolatileGAA +{ + public volatile int f_int = -1; + public volatile long f_long = -1; + + public static Unsafe unsafe = Unsafe.getUnsafe(); + public static Field f_int_field; + public static Field f_long_field; + public static long f_int_off; + public static long f_long_off; + + static { + try { + f_int_field = TestUnsafeVolatileGAA.class.getField("f_int"); + f_long_field = TestUnsafeVolatileGAA.class.getField("f_long"); + f_int_off = unsafe.objectFieldOffset(f_int_field); + f_long_off = unsafe.objectFieldOffset(f_long_field); + } catch (Exception e) { + System.out.println("reflection failed " + e); + e.printStackTrace(); + } + } + + public static void main(String[] args) + { + final TestUnsafeVolatileGAA t = new TestUnsafeVolatileGAA(); + for (int i = 0; i < 100_000; i++) { + if (t.testInt() != i-1) { + throw new RuntimeException("bad result!"); + } + } + for (int i = 0; i < 100_000; i++) { + if (t.testLong() != i-1) { + throw new RuntimeException("bad result!"); + } + } + } + + public int testInt() + { + return unsafe.getAndAddInt(this, f_int_off, 1); + } + + public long testLong() + { + return unsafe.getAndAddLong(this, f_long_off, 1); + } +} diff --git a/test/hotspot/jtreg/compiler/c2/aarch64/TestUnsafeVolatileGAS.java b/test/hotspot/jtreg/compiler/c2/aarch64/TestUnsafeVolatileGAS.java new file mode 100644 index 00000000000..c74ce048453 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/aarch64/TestUnsafeVolatileGAS.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2018, Red Hat, 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. + * + * 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.c2.aarch64; + +import java.lang.reflect.Field; +import jdk.internal.misc.Unsafe; + +class TestUnsafeVolatileGAS +{ + public volatile int f_int = -1; + public volatile Integer f_obj = Integer.valueOf(-1); + public volatile long f_long = -1; + + public static Unsafe unsafe = Unsafe.getUnsafe(); + public static Field f_int_field; + public static Field f_obj_field; + public static Field f_long_field; + public static long f_int_off; + public static long f_obj_off; + public static long f_long_off; + + static { + try { + f_int_field = TestUnsafeVolatileGAS.class.getField("f_int"); + f_obj_field = TestUnsafeVolatileGAS.class.getField("f_obj"); + f_long_field = TestUnsafeVolatileGAS.class.getField("f_long"); + f_int_off = unsafe.objectFieldOffset(f_int_field); + f_obj_off = unsafe.objectFieldOffset(f_obj_field); + f_long_off = unsafe.objectFieldOffset(f_long_field); + } catch (Exception e) { + System.out.println("reflection failed " + e); + e.printStackTrace(); + } + } + + public static void main(String[] args) + { + final TestUnsafeVolatileGAS t = new TestUnsafeVolatileGAS(); + for (int i = 0; i < 100_000; i++) { + if (t.testInt(i) != i-1) { + throw new RuntimeException("bad result!"); + } + } + for (int i = 0; i < 100_000; i++) { + if (t.testLong(i) != i-1) { + throw new RuntimeException("bad result!"); + } + } + for (int i = 0; i < 100_000; i++) { + if ((Integer)t.testObj(Integer.valueOf(i)) != i-1) { + throw new RuntimeException("bad result!"); + } + } + } + + public int testInt(int i) + { + return unsafe.getAndSetInt(this, f_int_off, i); + } + + public Object testObj(Object o) + { + return unsafe.getAndSetObject(this, f_obj_off, o); + } + public long testLong(long i) + { + return unsafe.getAndSetLong(this, f_long_off, i); + } +} diff --git a/test/hotspot/jtreg/compiler/c2/aarch64/TestUnsafeVolatileWeakCAS.java b/test/hotspot/jtreg/compiler/c2/aarch64/TestUnsafeVolatileWeakCAS.java new file mode 100644 index 00000000000..39f4baf9c7f --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/aarch64/TestUnsafeVolatileWeakCAS.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2018, Red Hat, 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. + * + * 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.c2.aarch64; + +import java.lang.reflect.Field; +import jdk.internal.misc.Unsafe; + +class TestUnsafeVolatileWeakCAS +{ + public volatile int f_int = 0; + public volatile Integer f_obj = Integer.valueOf(0); + public volatile long f_long = 0; + public volatile byte f_byte = 0; + public volatile short f_short = 0; + + public static Unsafe unsafe = Unsafe.getUnsafe(); + public static Field f_int_field; + public static Field f_obj_field; + public static Field f_long_field; + public static Field f_byte_field; + public static Field f_short_field; + public static long f_int_off; + public static long f_obj_off; + public static long f_long_off; + public static long f_byte_off; + public static long f_short_off; + + static { + try { + f_int_field = TestUnsafeVolatileWeakCAS.class.getField("f_int"); + f_obj_field = TestUnsafeVolatileWeakCAS.class.getField("f_obj"); + f_long_field = TestUnsafeVolatileWeakCAS.class.getField("f_long"); + f_byte_field = TestUnsafeVolatileWeakCAS.class.getField("f_byte"); + f_short_field = TestUnsafeVolatileWeakCAS.class.getField("f_short"); + f_int_off = unsafe.objectFieldOffset(f_int_field); + f_obj_off = unsafe.objectFieldOffset(f_obj_field); + f_long_off = unsafe.objectFieldOffset(f_long_field); + f_byte_off = unsafe.objectFieldOffset(f_byte_field); + f_short_off = unsafe.objectFieldOffset(f_short_field); + } catch (Exception e) { + System.out.println("reflection failed " + e); + e.printStackTrace(); + } + } + + public static void main(String[] args) + { + final TestUnsafeVolatileWeakCAS t = new TestUnsafeVolatileWeakCAS(); + for (int i = 0; i < 100_000; i++) { + t.f_int = -1; + if (t.testInt(-1, i)) { + if (t.f_int != i) { + throw new RuntimeException("bad result!"); + } + } + } + for (int i = 0; i < 100_000; i++) { + t.f_long = -1; + if (t.testLong(-1, i)) { + if (t.f_long != i) { + throw new RuntimeException("bad result!"); + } + } + } + for (int i = 0; i < 100_000; i++) { + t.f_byte = -1; + byte i_b = (byte)i; + if (t.testByte((byte)-1, i_b)) { + if (t.f_byte != i_b) { + throw new RuntimeException("bad result!"); + } + } + } + for (int i = 0; i < 100_000; i++) { + t.f_short = -1; + short i_s = (short)i; + if (t.testShort((byte)-1, i_s)) { + if (t.f_short != i_s) { + throw new RuntimeException("bad result!"); + } + } + } + Integer minusOne = Integer.valueOf(-1); + for (int i = 0; i < 100_000; i++) { + t.f_obj = minusOne; + if (t.testObj(minusOne, Integer.valueOf(i))) { + if (t.f_obj != i) { + throw new RuntimeException("bad result!"); + } + } + } + } + + public boolean testInt(int x, int i) + { + return unsafe.weakCompareAndSetInt(this, f_int_off, x, i); + } + + public boolean testObj(Object x, Object o) + { + return unsafe.weakCompareAndSetObject(this, f_obj_off, x, o); + } + + public boolean testLong(long x, long i) + { + return unsafe.weakCompareAndSetLong(this, f_long_off, x, i); + } + + public boolean testByte(byte x, byte i) + { + return unsafe.weakCompareAndSetByte(this, f_byte_off, x, i); + } + + public boolean testShort(short x, short i) + { + return unsafe.weakCompareAndSetShort(this, f_short_off, x, i); + } +} diff --git a/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatiles.java b/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatiles.java index f8c90d2c500..72e0312518e 100644 --- a/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatiles.java +++ b/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatiles.java @@ -31,7 +31,10 @@ * TestVolatileStore, * TestUnsafeVolatileLoad, * TestUnsafeVolatileStore, - * TestUnsafeVolatileCAS} + * TestUnsafeVolatileCAS, + * TestUnsafeVolatileWeakCAS, + * TestUnsafeVolatileCAE, + * TestUnsafeVolatileGAS} * and in {G1, * CMS, * CMSCondMark, @@ -43,13 +46,16 @@ package compiler.c2.aarch64; import java.util.List; +import java.util.ListIterator; import java.util.Iterator; +import java.util.regex.Pattern; import java.io.*; import jdk.test.lib.Asserts; import jdk.test.lib.compiler.InMemoryJavaCompiler; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; +import sun.hotspot.WhiteBox; // runner class that spawns a new JVM to exercises a combination of // volatile MemOp and GC. The ops are compiled with the dmb --> @@ -68,28 +74,28 @@ public void runtest(String classname, String testType) throws Throwable { // i.e. GC type plus GC conifg switch(testType) { case "G1": - argcount = 8; + argcount = 9; procArgs = new String[argcount]; procArgs[argcount - 2] = "-XX:+UseG1GC"; break; case "Parallel": - argcount = 8; + argcount = 9; procArgs = new String[argcount]; procArgs[argcount - 2] = "-XX:+UseParallelGC"; break; case "Serial": - argcount = 8; + argcount = 9; procArgs = new String[argcount]; procArgs[argcount - 2] = "-XX:+UseSerialGC"; break; case "CMS": - argcount = 9 ; + argcount = 10; procArgs = new String[argcount]; procArgs[argcount - 3] = "-XX:+UseConcMarkSweepGC"; procArgs[argcount - 2] = "-XX:-UseCondCardMark"; break; case "CMSCondMark": - argcount = 9 ; + argcount = 10; procArgs = new String[argcount]; procArgs[argcount - 3] = "-XX:+UseConcMarkSweepGC"; procArgs[argcount - 2] = "-XX:+UseCondCardMark"; @@ -106,42 +112,46 @@ public void runtest(String classname, String testType) throws Throwable { // disable the transform. procArgs[0] = "-XX:-UseBarriersForVolatile"; + procArgs[1] = "-XX:+UseCompressedOops"; - procArgs[1] = "-XX:-TieredCompilation"; - procArgs[2] = "-XX:+PrintOptoAssembly"; - procArgs[3] = "-XX:CompileCommand=compileonly," + fullclassname + "::" + "test*"; - procArgs[4] = "--add-exports"; - procArgs[5] = "java.base/jdk.internal.misc=ALL-UNNAMED"; + procArgs[2] = "-XX:-TieredCompilation"; + procArgs[3] = "-XX:+PrintOptoAssembly"; + procArgs[4] = "-XX:CompileCommand=compileonly," + fullclassname + "::" + "test*"; + procArgs[5] = "--add-exports"; + procArgs[6] = "java.base/jdk.internal.misc=ALL-UNNAMED"; procArgs[argcount - 1] = fullclassname; - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(procArgs); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - - output.stderrShouldBeEmptyIgnoreVMWarnings(); - output.stdoutShouldNotBeEmpty(); - output.shouldHaveExitValue(0); - - // check the output for the correct asm sequence as - // appropriate to test class, test type and whether transform - // was applied - - checkoutput(output, classname, testType, false); - + runtest(classname, testType, false, true, procArgs); // rerun the test class without the transform applied and // check the alternative generation is as expected procArgs[0] = "-XX:+UseBarriersForVolatile"; + runtest(classname, testType, true, true, procArgs); + + if (!classname.equals("TestUnsafeVolatileGAA")) { + procArgs[0] = "-XX:-UseBarriersForVolatile"; + procArgs[1] = "-XX:-UseCompressedOops"; + runtest(classname, testType, false, false, procArgs); + + procArgs[0] = "-XX:+UseBarriersForVolatile"; + runtest(classname, testType, true, false, procArgs); + } + } - pb = ProcessTools.createJavaProcessBuilder(procArgs); - output = new OutputAnalyzer(pb.start()); + + public void runtest(String classname, String testType, boolean useBarriersForVolatile, boolean useCompressedOops, String[] procArgs) throws Throwable { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(procArgs); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.stderrShouldBeEmptyIgnoreVMWarnings(); output.stdoutShouldNotBeEmpty(); output.shouldHaveExitValue(0); - // again check the output for the correct asm sequence + // check the output for the correct asm sequence as + // appropriate to test class, test type and whether transform + // was applied - checkoutput(output, classname, testType, true); + checkoutput(output, classname, testType, useBarriersForVolatile, useCompressedOops); } // skip through output returning a line containing the desireed @@ -150,7 +160,7 @@ private String skipTo(Iterator iter, String substring) { while (iter.hasNext()) { String nextLine = iter.next(); - if (nextLine.contains(substring)) { + if (nextLine.matches(".*" + substring + ".*")) { return nextLine; } } @@ -163,7 +173,7 @@ private String skipTo(Iterator iter, String substring) // n.b. the spawned JVM's output is included in the exception // message to make it easeir to identify what is missing. - private void checkCompile(Iterator iter, String methodname, String[] expected, OutputAnalyzer output) + private boolean checkCompile(Iterator iter, String methodname, String[] expected, OutputAnalyzer output, boolean do_throw) { // trace call to allow eyeball check of what we are checking against System.out.println("checkCompile(" + methodname + ","); @@ -176,30 +186,43 @@ private void checkCompile(Iterator iter, String methodname, String[] exp System.out.println(" })"); // look for the start of an opto assembly print block - String match = skipTo(iter, "{method}"); + String match = skipTo(iter, Pattern.quote("{method}")); if (match == null) { - throw new RuntimeException("Missing compiler output for " + methodname + "!\n\n" + output.getOutput()); + if (do_throw) { + throw new RuntimeException("Missing compiler output for " + methodname + "!\n\n" + output.getOutput()); + } + return false; } // check the compiled method name is right - match = skipTo(iter, "- name:"); + match = skipTo(iter, Pattern.quote("- name:")); if (match == null) { - throw new RuntimeException("Missing compiled method name!\n\n" + output.getOutput()); + if (do_throw) { + throw new RuntimeException("Missing compiled method name!\n\n" + output.getOutput()); + } + return false; } if (!match.contains(methodname)) { - throw new RuntimeException("Wrong method " + match + "!\n -- expecting " + methodname + "\n\n" + output.getOutput()); + if (do_throw) { + throw new RuntimeException("Wrong method " + match + "!\n -- expecting " + methodname + "\n\n" + output.getOutput()); + } + return false; } // make sure we can match each expected term in order for (String s : expected) { match = skipTo(iter, s); if (match == null) { - throw new RuntimeException("Missing expected output " + s + "!\n\n" + output.getOutput()); + if (do_throw) { + throw new RuntimeException("Missing expected output " + s + "!\n\n" + output.getOutput()); + } + return false; } } + return true; } // check for expected asm output from a volatile load - private void checkload(OutputAnalyzer output, String testType, boolean useBarriersForVolatile) throws Throwable + private void checkload(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable { Iterator iter = output.asLines().listIterator(); @@ -211,7 +234,7 @@ private void checkload(OutputAnalyzer output, String testType, boolean useBarrie if (!useBarriersForVolatile) { matches = new String[] { "ldarw", - "membar_acquire (elided)", + "membar_acquire \\(elided\\)", "ret" }; } else { @@ -223,15 +246,30 @@ private void checkload(OutputAnalyzer output, String testType, boolean useBarrie }; } - checkCompile(iter, "testInt", matches, output); + checkCompile(iter, "testInt", matches, output, true); - checkCompile(iter, "testObj", matches, output) ; + if (!useBarriersForVolatile) { + matches = new String[] { + useCompressedOops ? "ldarw?" : "ldar", + "membar_acquire \\(elided\\)", + "ret" + }; + } else { + matches = new String[] { + useCompressedOops ? "ldrw?" : "ldr", + "membar_acquire", + "dmb ish", + "ret" + }; + } + + checkCompile(iter, "testObj", matches, output, true); } // check for expected asm output from a volatile store - private void checkstore(OutputAnalyzer output, String testType, boolean useBarriersForVolatile) throws Throwable + private void checkstore(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable { Iterator iter = output.asLines().listIterator(); @@ -241,9 +279,9 @@ private void checkstore(OutputAnalyzer output, String testType, boolean useBarri if (!useBarriersForVolatile) { // this is the sequence of instructions for all cases matches = new String[] { - "membar_release (elided)", + "membar_release \\(elided\\)", "stlrw", - "membar_volatile (elided)", + "membar_volatile \\(elided\\)", "ret" }; } else { @@ -258,7 +296,7 @@ private void checkstore(OutputAnalyzer output, String testType, boolean useBarri }; } - checkCompile(iter, "testInt", matches, output); + checkCompile(iter, "testInt", matches, output, true); // object stores will be as above except for when the GC // introduces barriers for card marking @@ -268,9 +306,9 @@ private void checkstore(OutputAnalyzer output, String testType, boolean useBarri default: // this is the basic sequence of instructions matches = new String[] { - "membar_release (elided)", - "stlrw", - "membar_volatile (elided)", + "membar_release \\(elided\\)", + useCompressedOops ? "stlrw?" : "stlr", + "membar_volatile \\(elided\\)", "ret" }; break; @@ -278,12 +316,12 @@ private void checkstore(OutputAnalyzer output, String testType, boolean useBarri // a card mark volatile barrier should be generated // before the card mark strb matches = new String[] { - "membar_release (elided)", - "stlrw", + "membar_release \\(elided\\)", + useCompressedOops ? "stlrw?" : "stlr", "membar_volatile", "dmb ish", "strb", - "membar_volatile (elided)", + "membar_volatile \\(elided\\)", "ret" }; break; @@ -292,13 +330,13 @@ private void checkstore(OutputAnalyzer output, String testType, boolean useBarri // before the card mark strb from the StoreCM and the // storestore barrier from the StoreCM should be elided matches = new String[] { - "membar_release (elided)", - "stlrw", + "membar_release \\(elided\\)", + useCompressedOops ? "stlrw?" : "stlr", "membar_volatile", "dmb ish", - "storestore (elided)", + "storestore \\(elided\\)", "strb", - "membar_volatile (elided)", + "membar_volatile \\(elided\\)", "ret" }; break; @@ -308,12 +346,12 @@ private void checkstore(OutputAnalyzer output, String testType, boolean useBarri // storestore barrier from the StoreCM should be // generated as "dmb ishst" matches = new String[] { - "membar_release (elided)", - "stlrw", + "membar_release \\(elided\\)", + useCompressedOops ? "stlrw?" : "stlr", "storestore", "dmb ishst", "strb", - "membar_volatile (elided)", + "membar_volatile \\(elided\\)", "ret" }; break; @@ -325,7 +363,7 @@ private void checkstore(OutputAnalyzer output, String testType, boolean useBarri matches = new String[] { "membar_release", "dmb ish", - "strw", + useCompressedOops ? "strw?" : "str", "membar_volatile", "dmb ish", "ret" @@ -337,7 +375,7 @@ private void checkstore(OutputAnalyzer output, String testType, boolean useBarri matches = new String[] { "membar_release", "dmb ish", - "strw", + useCompressedOops ? "strw?" : "str", "membar_volatile", "dmb ish", "strb", @@ -353,10 +391,10 @@ private void checkstore(OutputAnalyzer output, String testType, boolean useBarri matches = new String[] { "membar_release", "dmb ish", - "strw", + useCompressedOops ? "strw?" : "str", "membar_volatile", "dmb ish", - "storestore (elided)", + "storestore \\(elided\\)", "strb", "membar_volatile", "dmb ish", @@ -371,7 +409,7 @@ private void checkstore(OutputAnalyzer output, String testType, boolean useBarri matches = new String[] { "membar_release", "dmb ish", - "strw", + useCompressedOops ? "strw?" : "str", "storestore", "dmb ishst", "strb", @@ -383,39 +421,389 @@ private void checkstore(OutputAnalyzer output, String testType, boolean useBarri } } - checkCompile(iter, "testObj", matches, output); + checkCompile(iter, "testObj", matches, output, true); } // check for expected asm output from a volatile cas - private void checkcas(OutputAnalyzer output, String testType, boolean useBarriersForVolatile) throws Throwable + private void checkcas(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable { Iterator iter = output.asLines().listIterator(); String[] matches; + String[][] tests = { + { "testInt", "cmpxchgw" }, + { "testLong", "cmpxchg" }, + { "testByte", "cmpxchgb" }, + { "testShort", "cmpxchgs" }, + }; + + for (String[] test : tests) { + // non object stores are straightforward + if (!useBarriersForVolatile) { + // this is the sequence of instructions for all cases + matches = new String[] { + "membar_release \\(elided\\)", + test[1] + "_acq", + "membar_acquire \\(elided\\)", + "ret" + }; + } else { + // this is the alternative sequence of instructions + matches = new String[] { + "membar_release", + "dmb ish", + test[1] + " ", + "membar_acquire", + "dmb ish", + "ret" + }; + } + + checkCompile(iter, test[0], matches, output, true); + } + + // object stores will be as above except for when the GC + // introduces barriers for card marking - // non object stores are straightforward if (!useBarriersForVolatile) { - // this is the sequence of instructions for all cases - matches = new String[] { - "membar_release (elided)", - "cmpxchgw_acq", - "membar_acquire (elided)", - "ret" - }; + switch (testType) { + default: + // this is the basic sequence of instructions + matches = new String[] { + "membar_release \\(elided\\)", + useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq", + "strb", + "membar_acquire \\(elided\\)", + "ret" + }; + break; + case "G1": + // a card mark volatile barrier should be generated + // before the card mark strb + matches = new String[] { + "membar_release \\(elided\\)", + useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq", + "membar_volatile", + "dmb ish", + "strb", + "membar_acquire \\(elided\\)", + "ret" + }; + break; + case "CMSCondMark": + // a card mark volatile barrier should be generated + // before the card mark strb from the StoreCM and the + // storestore barrier from the StoreCM should be elided + matches = new String[] { + "membar_release \\(elided\\)", + useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq", + "membar_volatile", + "dmb ish", + "storestore \\(elided\\)", + "strb", + "membar_acquire \\(elided\\)", + "ret" + }; + break; + case "CMS": + // a volatile card mark membar should not be generated + // before the card mark strb from the StoreCM and the + // storestore barrier from the StoreCM should be elided + matches = new String[] { + "membar_release \\(elided\\)", + useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq", + "storestore", + "dmb ishst", + "strb", + "membar_acquire \\(elided\\)", + "ret" + }; + break; + } } else { - // this is the alternative sequence of instructions - matches = new String[] { - "membar_release", - "dmb ish", - "cmpxchgw", - "membar_acquire", - "dmb ish", - "ret" - }; + switch (testType) { + default: + // this is the basic sequence of instructions + matches = new String[] { + "membar_release", + "dmb ish", + useCompressedOops ? "cmpxchgw? " : "cmpxchg ", + "membar_acquire", + "dmb ish", + "ret" + }; + break; + case "G1": + // a card mark volatile barrier should be generated + // before the card mark strb + matches = new String[] { + "membar_release", + "dmb ish", + useCompressedOops ? "cmpxchgw? " : "cmpxchg ", + "membar_volatile", + "dmb ish", + "strb", + "membar_acquire", + "dmb ish", + "ret" + }; + break; + case "CMSCondMark": + // a card mark volatile barrier should be generated + // before the card mark strb from the StoreCM and the + // storestore barrier from the StoreCM should be elided + matches = new String[] { + "membar_release", + "dmb ish", + useCompressedOops ? "cmpxchgw? " : "cmpxchg ", + "membar_volatile", + "dmb ish", + "storestore \\(elided\\)", + "strb", + "membar_acquire", + "dmb ish", + "ret" + }; + break; + case "CMS": + // a volatile card mark membar should not be generated + // before the card mark strb from the StoreCM and the + // storestore barrier from the StoreCM should be generated + // as "dmb ishst" + matches = new String[] { + "membar_release", + "dmb ish", + useCompressedOops ? "cmpxchgw? " : "cmpxchg ", + "storestore", + "dmb ishst", + "strb", + "membar_acquire", + "dmb ish", + "ret" + }; + break; + } } - checkCompile(iter, "testInt", matches, output); + checkCompile(iter, "testObj", matches, output, true); + } + + private void checkcae(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable + { + ListIterator iter = output.asLines().listIterator(); + + String[] matches; + String[][] tests = { + { "testInt", "cmpxchgw" }, + { "testLong", "cmpxchg" }, + { "testByte", "cmpxchgb" }, + { "testShort", "cmpxchgs" }, + }; + + for (String[] test : tests) { + // non object stores are straightforward + if (!useBarriersForVolatile) { + // this is the sequence of instructions for all cases + matches = new String[] { + "membar_release \\(elided\\)", + test[1] + "_acq", + "membar_acquire \\(elided\\)", + "ret" + }; + } else { + // this is the alternative sequence of instructions + matches = new String[] { + "membar_release", + "dmb ish", + test[1] + " ", + "membar_acquire", + "dmb ish", + "ret" + }; + } + + checkCompile(iter, test[0], matches, output, true); + } + + // object stores will be as above except for when the GC + // introduces barriers for card marking + + if (!useBarriersForVolatile) { + switch (testType) { + default: + // this is the basic sequence of instructions + matches = new String[] { + "membar_release \\(elided\\)", + "strb", + useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq", + "membar_acquire \\(elided\\)", + "ret" + }; + + // card marking store may be scheduled before or after + // the cmpxchg so try both sequences. + int idx = iter.nextIndex(); + if (!checkCompile(iter, "testObj", matches, output, false)) { + iter = output.asLines().listIterator(idx); + + matches = new String[] { + "membar_release \\(elided\\)", + useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq", + "strb", + "membar_acquire \\(elided\\)", + "ret" + }; + + checkCompile(iter, "testObj", matches, output, true); + } + return; + + case "G1": + // a card mark volatile barrier should be generated + // before the card mark strb + matches = new String[] { + "membar_release \\(elided\\)", + useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq", + "membar_volatile", + "dmb ish", + "strb", + "membar_acquire \\(elided\\)", + "ret" + }; + break; + case "CMSCondMark": + // a card mark volatile barrier should be generated + // before the card mark strb from the StoreCM and the + // storestore barrier from the StoreCM should be elided + matches = new String[] { + "membar_release \\(elided\\)", + useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq", + "membar_volatile", + "dmb ish", + "storestore \\(elided\\)", + "strb", + "membar_acquire \\(elided\\)", + "ret" + }; + break; + case "CMS": + // a volatile card mark membar should not be generated + // before the card mark strb from the StoreCM and the + // storestore barrier from the StoreCM should be elided + matches = new String[] { + "membar_release \\(elided\\)", + useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq", + "storestore", + "dmb ishst", + "strb", + "membar_acquire \\(elided\\)", + "ret" + }; + break; + } + } else { + switch (testType) { + default: + // this is the basic sequence of instructions + matches = new String[] { + "membar_release", + "dmb ish", + useCompressedOops ? "cmpxchgw? " : "cmpxchg ", + "membar_acquire", + "dmb ish", + "ret" + }; + break; + case "G1": + // a card mark volatile barrier should be generated + // before the card mark strb + matches = new String[] { + "membar_release", + "dmb ish", + useCompressedOops ? "cmpxchgw? " : "cmpxchg ", + "membar_volatile", + "dmb ish", + "strb", + "membar_acquire", + "dmb ish", + "ret" + }; + break; + case "CMSCondMark": + // a card mark volatile barrier should be generated + // before the card mark strb from the StoreCM and the + // storestore barrier from the StoreCM should be elided + matches = new String[] { + "membar_release", + "dmb ish", + useCompressedOops ? "cmpxchgw? " : "cmpxchg ", + "membar_volatile", + "dmb ish", + "storestore \\(elided\\)", + "strb", + "membar_acquire", + "dmb ish", + "ret" + }; + break; + case "CMS": + // a volatile card mark membar should not be generated + // before the card mark strb from the StoreCM and the + // storestore barrier from the StoreCM should be generated + // as "dmb ishst" + matches = new String[] { + "membar_release", + "dmb ish", + useCompressedOops ? "cmpxchgw? " : "cmpxchg ", + "storestore", + "dmb ishst", + "strb", + "membar_acquire", + "dmb ish", + "ret" + }; + break; + } + } + + checkCompile(iter, "testObj", matches, output, true); + } + + private void checkgas(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable + { + Iterator iter = output.asLines().listIterator(); + + String[] matches; + String[][] tests = { + { "testInt", "atomic_xchgw" }, + { "testLong", "atomic_xchg" }, + }; + + for (String[] test : tests) { + // non object stores are straightforward + if (!useBarriersForVolatile) { + // this is the sequence of instructions for all cases + matches = new String[] { + "membar_release \\(elided\\)", + test[1] + "_acq", + "membar_acquire \\(elided\\)", + "ret" + }; + } else { + // this is the alternative sequence of instructions + matches = new String[] { + "membar_release", + "dmb ish", + test[1] + " ", + "membar_acquire", + "dmb ish", + "ret" + }; + } + + checkCompile(iter, test[0], matches, output, true); + } // object stores will be as above except for when the GC // introduces barriers for card marking @@ -425,10 +813,10 @@ private void checkcas(OutputAnalyzer output, String testType, boolean useBarrier default: // this is the basic sequence of instructions matches = new String[] { - "membar_release (elided)", - "cmpxchgw_acq", + "membar_release \\(elided\\)", + useCompressedOops ? "atomic_xchgw?_acq" : "atomic_xchg_acq", "strb", - "membar_acquire (elided)", + "membar_acquire \\(elided\\)", "ret" }; break; @@ -436,12 +824,12 @@ private void checkcas(OutputAnalyzer output, String testType, boolean useBarrier // a card mark volatile barrier should be generated // before the card mark strb matches = new String[] { - "membar_release (elided)", - "cmpxchgw_acq", + "membar_release \\(elided\\)", + useCompressedOops ? "atomic_xchgw?_acq" : "atomic_xchg_acq", "membar_volatile", "dmb ish", "strb", - "membar_acquire (elided)", + "membar_acquire \\(elided\\)", "ret" }; break; @@ -450,13 +838,13 @@ private void checkcas(OutputAnalyzer output, String testType, boolean useBarrier // before the card mark strb from the StoreCM and the // storestore barrier from the StoreCM should be elided matches = new String[] { - "membar_release (elided)", - "cmpxchgw_acq", + "membar_release \\(elided\\)", + useCompressedOops ? "atomic_xchgw?_acq" : "atomic_xchg_acq", "membar_volatile", "dmb ish", - "storestore (elided)", + "storestore \\(elided\\)", "strb", - "membar_acquire (elided)", + "membar_acquire \\(elided\\)", "ret" }; break; @@ -465,12 +853,12 @@ private void checkcas(OutputAnalyzer output, String testType, boolean useBarrier // before the card mark strb from the StoreCM and the // storestore barrier from the StoreCM should be elided matches = new String[] { - "membar_release (elided)", - "cmpxchgw_acq", + "membar_release \\(elided\\)", + useCompressedOops ? "atomic_xchgw?_acq" : "atomic_xchg_acq", "storestore", "dmb ishst", "strb", - "membar_acquire (elided)", + "membar_acquire \\(elided\\)", "ret" }; break; @@ -482,7 +870,7 @@ private void checkcas(OutputAnalyzer output, String testType, boolean useBarrier matches = new String[] { "membar_release", "dmb ish", - "cmpxchgw", + useCompressedOops ? "atomic_xchgw? " : "atomic_xchg ", "membar_acquire", "dmb ish", "ret" @@ -494,7 +882,7 @@ private void checkcas(OutputAnalyzer output, String testType, boolean useBarrier matches = new String[] { "membar_release", "dmb ish", - "cmpxchgw", + useCompressedOops ? "atomic_xchgw? " : "atomic_xchg ", "membar_volatile", "dmb ish", "strb", @@ -510,10 +898,10 @@ private void checkcas(OutputAnalyzer output, String testType, boolean useBarrier matches = new String[] { "membar_release", "dmb ish", - "cmpxchgw", + useCompressedOops ? "atomic_xchgw? " : "atomic_xchg ", "membar_volatile", "dmb ish", - "storestore (elided)", + "storestore \\(elided\\)", "strb", "membar_acquire", "dmb ish", @@ -528,7 +916,7 @@ private void checkcas(OutputAnalyzer output, String testType, boolean useBarrier matches = new String[] { "membar_release", "dmb ish", - "cmpxchgw", + useCompressedOops ? "atomic_xchgw? " : "atomic_xchg ", "storestore", "dmb ishst", "strb", @@ -540,12 +928,49 @@ private void checkcas(OutputAnalyzer output, String testType, boolean useBarrier } } - checkCompile(iter, "testObj", matches, output); + checkCompile(iter, "testObj", matches, output, true); + } + + private void checkgaa(OutputAnalyzer output, String testType, boolean useBarriersForVolatile) throws Throwable + { + Iterator iter = output.asLines().listIterator(); + + String[] matches; + String[][] tests = { + { "testInt", "get_and_addI" }, + { "testLong", "get_and_addL" }, + }; + + for (String[] test : tests) { + // non object stores are straightforward + if (!useBarriersForVolatile) { + // this is the sequence of instructions for all cases + matches = new String[] { + "membar_release \\(elided\\)", + test[1] + "_acq", + "membar_acquire \\(elided\\)", + "ret" + }; + } else { + // this is the alternative sequence of instructions + matches = new String[] { + "membar_release", + "dmb ish", + test[1] + " ", + "membar_acquire", + "dmb ish", + "ret" + }; + } + + checkCompile(iter, test[0], matches, output, true); + } + } // perform a check appropriate to the classname - private void checkoutput(OutputAnalyzer output, String classname, String testType, boolean useBarriersForVolatile) throws Throwable + private void checkoutput(OutputAnalyzer output, String classname, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable { // trace call to allow eyeball check of what is being checked System.out.println("checkoutput(" + @@ -556,19 +981,29 @@ private void checkoutput(OutputAnalyzer output, String classname, String testTyp switch (classname) { case "TestVolatileLoad": - checkload(output, testType, useBarriersForVolatile); + checkload(output, testType, useBarriersForVolatile, useCompressedOops); break; case "TestVolatileStore": - checkstore(output, testType, useBarriersForVolatile); + checkstore(output, testType, useBarriersForVolatile, useCompressedOops); break; case "TestUnsafeVolatileLoad": - checkload(output, testType, useBarriersForVolatile); + checkload(output, testType, useBarriersForVolatile, useCompressedOops); break; case "TestUnsafeVolatileStore": - checkstore(output, testType, useBarriersForVolatile); + checkstore(output, testType, useBarriersForVolatile, useCompressedOops); break; case "TestUnsafeVolatileCAS": - checkcas(output, testType, useBarriersForVolatile); + case "TestUnsafeVolatileWeakCAS": + checkcas(output, testType, useBarriersForVolatile, useCompressedOops); + break; + case "TestUnsafeVolatileCAE": + checkcae(output, testType, useBarriersForVolatile, useCompressedOops); + break; + case "TestUnsafeVolatileGAS": + checkgas(output, testType, useBarriersForVolatile, useCompressedOops); + break; + case "TestUnsafeVolatileGAA": + checkgaa(output, testType, useBarriersForVolatile); break; } } diff --git a/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatilesCMS.java b/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatilesCMS.java index e65250ff579..3397fda6a4d 100644 --- a/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatilesCMS.java +++ b/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatilesCMS.java @@ -38,6 +38,9 @@ * compiler.c2.aarch64.TestVolatileStore * compiler.c2.aarch64.TestUnsafeVolatileStore * compiler.c2.aarch64.TestUnsafeVolatileCAS + * compiler.c2.aarch64.TestUnsafeVolatileWeakCAS + * compiler.c2.aarch64.TestUnsafeVolatileCAE + * compiler.c2.aarch64.TestUnsafeVolatileGAS * * @run driver compiler.c2.aarch64.TestVolatilesCMS * TestVolatileLoad CMS @@ -53,6 +56,15 @@ * * @run driver compiler.c2.aarch64.TestVolatilesCMS * TestUnsafeVolatileCAS CMS + * + * @run driver compiler.c2.aarch64.TestVolatilesCMS + * TestUnsafeVolatileWeakCAS CMS + * + * @run driver compiler.c2.aarch64.TestVolatilesCMS + * TestUnsafeVolatileCAE CMS + * + * @run driver compiler.c2.aarch64.TestVolatilesCMS + * TestUnsafeVolatileGAS CMS */ package compiler.c2.aarch64; diff --git a/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatilesCMSCondMark.java b/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatilesCMSCondMark.java index b0931b1631b..29ce80493c8 100644 --- a/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatilesCMSCondMark.java +++ b/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatilesCMSCondMark.java @@ -38,6 +38,9 @@ * compiler.c2.aarch64.TestVolatileStore * compiler.c2.aarch64.TestUnsafeVolatileStore * compiler.c2.aarch64.TestUnsafeVolatileCAS + * compiler.c2.aarch64.TestUnsafeVolatileWeakCAS + * compiler.c2.aarch64.TestUnsafeVolatileCAE + * compiler.c2.aarch64.TestUnsafeVolatileGAS * * @run driver compiler.c2.aarch64.TestVolatilesCMSCondMark * TestVolatileLoad CMSCondMark @@ -53,6 +56,15 @@ * * @run driver compiler.c2.aarch64.TestVolatilesCMSCondMark * TestUnsafeVolatileCAS CMSCondMark + * + * @run driver compiler.c2.aarch64.TestVolatilesCMSCondMark + * TestUnsafeVolatileWeakCAS CMSCondMark + * + * @run driver compiler.c2.aarch64.TestVolatilesCMSCondMark + * TestUnsafeVolatileCAE CMSCondMark + * + * @run driver compiler.c2.aarch64.TestVolatilesCMSCondMark + * TestUnsafeVolatileGAS CMSCondMark */ package compiler.c2.aarch64; diff --git a/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatilesG1.java b/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatilesG1.java index 658e5ad9d39..88d747e44d9 100644 --- a/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatilesG1.java +++ b/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatilesG1.java @@ -38,6 +38,10 @@ * compiler.c2.aarch64.TestVolatileStore * compiler.c2.aarch64.TestUnsafeVolatileStore * compiler.c2.aarch64.TestUnsafeVolatileCAS + * compiler.c2.aarch64.TestUnsafeVolatileWeakCAS + * compiler.c2.aarch64.TestUnsafeVolatileCAE + * compiler.c2.aarch64.TestUnsafeVolatileGAS + * compiler.c2.aarch64.TestUnsafeVolatileGAA * * @run driver compiler.c2.aarch64.TestVolatilesG1 * TestVolatileLoad G1 @@ -53,8 +57,21 @@ * * @run driver compiler.c2.aarch64.TestVolatilesG1 * TestUnsafeVolatileCAS G1 + * + * @run driver compiler.c2.aarch64.TestVolatilesG1 + * TestUnsafeVolatileWeakCAS G1 + * + * @run driver compiler.c2.aarch64.TestVolatilesG1 + * TestUnsafeVolatileCAE G1 + * + * @run driver compiler.c2.aarch64.TestVolatilesG1 + * TestUnsafeVolatileGAS G1 + * + * @run driver compiler.c2.aarch64.TestVolatilesG1 + * TestUnsafeVolatileGAA G1 */ + package compiler.c2.aarch64; public class TestVolatilesG1 { diff --git a/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatilesParallel.java b/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatilesParallel.java index 8f6a78efcf2..c3203c0b276 100644 --- a/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatilesParallel.java +++ b/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatilesParallel.java @@ -38,6 +38,9 @@ * compiler.c2.aarch64.TestVolatileStore * compiler.c2.aarch64.TestUnsafeVolatileStore * compiler.c2.aarch64.TestUnsafeVolatileCAS + * compiler.c2.aarch64.TestUnsafeVolatileWeakCAS + * compiler.c2.aarch64.TestUnsafeVolatileCAE + * compiler.c2.aarch64.TestUnsafeVolatileGAS * * @run driver compiler.c2.aarch64.TestVolatilesParallel * TestVolatileLoad Parallel @@ -53,6 +56,15 @@ * * @run driver compiler.c2.aarch64.TestVolatilesParallel * TestUnsafeVolatileCAS Parallel + * + * @run driver compiler.c2.aarch64.TestVolatilesParallel + * TestUnsafeVolatileWeakCAS Parallel + * + * @run driver compiler.c2.aarch64.TestVolatilesParallel + * TestUnsafeVolatileCAE Parallel + * + * @run driver compiler.c2.aarch64.TestVolatilesParallel + * TestUnsafeVolatileGAS Parallel */ package compiler.c2.aarch64; diff --git a/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatilesSerial.java b/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatilesSerial.java index 470ae748e12..c04c3594497 100644 --- a/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatilesSerial.java +++ b/test/hotspot/jtreg/compiler/c2/aarch64/TestVolatilesSerial.java @@ -38,6 +38,9 @@ * compiler.c2.aarch64.TestVolatileStore * compiler.c2.aarch64.TestUnsafeVolatileStore * compiler.c2.aarch64.TestUnsafeVolatileCAS + * compiler.c2.aarch64.TestUnsafeVolatileWeakCAS + * compiler.c2.aarch64.TestUnsafeVolatileCAE + * compiler.c2.aarch64.TestUnsafeVolatileGAS * * @run driver compiler.c2.aarch64.TestVolatilesSerial * TestVolatileLoad Serial @@ -53,6 +56,15 @@ * * @run driver compiler.c2.aarch64.TestVolatilesSerial * TestUnsafeVolatileCAS Serial + * + * @run driver compiler.c2.aarch64.TestVolatilesSerial + * TestUnsafeVolatileWeakCAS Serial + * + * @run driver compiler.c2.aarch64.TestVolatilesSerial + * TestUnsafeVolatileCAE Serial + * + * @run driver compiler.c2.aarch64.TestVolatilesSerial + * TestUnsafeVolatileGAS Serial */ package compiler.c2.aarch64; From e8a092c99aada95757d6defd115e0846393274d1 Mon Sep 17 00:00:00 2001 From: stuefe Date: Sat, 8 Dec 2018 12:09:59 +0100 Subject: [PATCH 039/131] 8214975: No hs-err file if fatal error is raised during dynamic initialization Reviewed-by: dholmes, dcubed, clanger --- .../ErrorHandling/VeryEarlyAssertTest.java | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 test/hotspot/jtreg/runtime/ErrorHandling/VeryEarlyAssertTest.java diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/VeryEarlyAssertTest.java b/test/hotspot/jtreg/runtime/ErrorHandling/VeryEarlyAssertTest.java new file mode 100644 index 00000000000..69c343b8328 --- /dev/null +++ b/test/hotspot/jtreg/runtime/ErrorHandling/VeryEarlyAssertTest.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, SAP. 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 8214975 + * @summary No hs-err file if fatal error is raised during dynamic initialization. + * @library /test/lib + * @modules java.base/jdk.internal.misc + * @requires (vm.debug == true) + * @requires os.family == "linux" + */ + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.util.regex.Pattern; +import java.util.Map; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class VeryEarlyAssertTest { + + public static void main(String[] args) throws Exception { + + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-Xmx64M", + "-XX:-CreateCoredumpOnCrash", + "-version"); + Map env = pb.environment(); + env.put("HOTSPOT_FATAL_ERROR_DURING_DYNAMIC_INITIALIZATION", "1"); + + OutputAnalyzer output_detail = new OutputAnalyzer(pb.start()); + + // we should have crashed with an assert with a specific message: + output_detail.shouldMatch("# A fatal error has been detected by the Java Runtime Environment:.*"); + output_detail.shouldMatch("#.*HOTSPOT_FATAL_ERROR_DURING_DYNAMIC_INITIALIZATION.*"); + + // extract hs-err file + String hs_err_file = output_detail.firstMatch("# *(\\S*hs_err_pid\\d+\\.log)", 1); + if (hs_err_file == null) { + throw new RuntimeException("Did not find hs-err file in output.\n"); + } + + // scan hs-err file: File should contain the same assertion message. Other than that, + // do not expect too much: file will be littered with secondary errors. The test + // should test that we get a hs-err file at all. + File f = new File(hs_err_file); + if (!f.exists()) { + throw new RuntimeException("hs-err file missing at " + + f.getAbsolutePath() + ".\n"); + } + + System.out.println("Found hs_err file. Scanning..."); + + FileInputStream fis = new FileInputStream(f); + BufferedReader br = new BufferedReader(new InputStreamReader(fis)); + String line = null; + + Pattern[] pattern = new Pattern[]{ + Pattern.compile(".*HOTSPOT_FATAL_ERROR_DURING_DYNAMIC_INITIALIZATION.*") + }; + int currentPattern = 0; + + String lastLine = null; + while ((line = br.readLine()) != null) { + if (currentPattern < pattern.length) { + if (pattern[currentPattern].matcher(line).matches()) { + System.out.println("Found: " + line + "."); + currentPattern++; + } + } + lastLine = line; + } + br.close(); + + if (currentPattern < pattern.length) { + throw new RuntimeException("hs-err file incomplete (first missing pattern: " + currentPattern + ")"); + } + + if (!lastLine.equals("END.")) { + throw new RuntimeException("hs-err file incomplete (missing END marker.)"); + } else { + System.out.println("End marker found."); + } + + System.out.println("OK."); + + } + +} + + From 7430855f7efc4a5b2cce1d8b6c0058472702eed4 Mon Sep 17 00:00:00 2001 From: kaddepalli Date: Thu, 25 Apr 2019 15:19:09 +0530 Subject: [PATCH 040/131] 8219914: Change the environment variable for Java Access Bridge logging to have a directory. Reviewed-by: prr --- .../native/common/AccessBridgeDebug.cpp | 42 +++++++------------ .../windows/native/common/AccessBridgeDebug.h | 4 +- .../libjavaaccessbridge/JavaAccessBridge.cpp | 4 +- .../WinAccessBridge.cpp | 4 +- 4 files changed, 22 insertions(+), 32 deletions(-) diff --git a/src/jdk.accessibility/windows/native/common/AccessBridgeDebug.cpp b/src/jdk.accessibility/windows/native/common/AccessBridgeDebug.cpp index 2fc4e557f3a..4bf96669574 100644 --- a/src/jdk.accessibility/windows/native/common/AccessBridgeDebug.cpp +++ b/src/jdk.accessibility/windows/native/common/AccessBridgeDebug.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, 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 @@ -41,34 +41,24 @@ extern "C" { static FILE* logFP = nullptr; -void initializeFileLogger(char * suffix) { - auto var = "JAVA_ACCESSBRIDGE_LOGFILE"; +void initializeFileLogger(char * fileName) { + auto var = "JAVA_ACCESSBRIDGE_LOGDIR"; const auto envfilePath = getenv(var); - if (envfilePath != nullptr) { - auto ext = const_cast(strrchr(envfilePath, '.')); - auto filePath = static_cast(nullptr); - auto len = strlen(envfilePath); - auto suffixlen = suffix != nullptr ? strlen(suffix) : (decltype(strlen(nullptr)))0; - - if (ext == nullptr) { - filePath = new char[len + suffixlen + 5]; - memset(filePath, 0, len + suffixlen + 5); - memcpy(filePath, envfilePath, len); - memcpy(filePath + len, suffix, suffixlen); - memcpy(filePath + len + suffixlen, ".log", 4); - } else { - auto extLen = strlen(ext); - - filePath = new char[len + suffixlen + 1]; - memset(filePath, 0, len + suffixlen + 1); - memcpy(filePath, envfilePath, len - extLen); - memcpy(filePath + len - extLen, suffix, suffixlen); - memcpy(filePath + len + suffixlen - extLen, ext, extLen); - } + if (envfilePath != nullptr && fileName != nullptr) { + auto envFilePathLength = strlen(envfilePath); + auto fileNameLength = strlen(fileName); + auto filePathSize = envFilePathLength + 1 + fileNameLength + 5; //1 for "/", 5 for ".log" and 0; + auto filePath = new char[filePathSize]; + memset(filePath, 0, filePathSize*sizeof(char)); + memcpy(filePath, envfilePath, envFilePathLength*sizeof(char)); + filePath[envFilePathLength] = '/'; + memcpy(filePath + envFilePathLength + 1, fileName, fileNameLength*sizeof(char)); + memcpy(filePath + envFilePathLength + 1 + fileNameLength, ".log", 4*sizeof(char)); logFP = fopen(filePath, "w"); if (logFP == nullptr) { - PrintDebugString("couldnot open file %s", filePath); + printf("\n%s\n", filePath); + PrintDebugString("Could not open file %s", filePath); } delete [] filePath; @@ -143,7 +133,7 @@ char *printError(char *msg) { #endif #endif if (logFP) { - fprintf(logFP, "[%lldu] ", getTimeStamp()); + fprintf(logFP, "[%llu] ", getTimeStamp()); va_list args; va_start(args, msg); vfprintf(logFP, msg, args); diff --git a/src/jdk.accessibility/windows/native/common/AccessBridgeDebug.h b/src/jdk.accessibility/windows/native/common/AccessBridgeDebug.h index 7950b3482e6..92459d30789 100644 --- a/src/jdk.accessibility/windows/native/common/AccessBridgeDebug.h +++ b/src/jdk.accessibility/windows/native/common/AccessBridgeDebug.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, 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 @@ -54,7 +54,7 @@ extern "C" { void PrintJavaDebugString(char *msg, ...); void wPrintJavaDebugString(wchar_t *msg, ...); void wPrintDebugString(wchar_t *msg, ...); - void initializeFileLogger(char * suffix); + void initializeFileLogger(char * fileName); void finalizeFileLogger(); #ifdef __cplusplus diff --git a/src/jdk.accessibility/windows/native/libjavaaccessbridge/JavaAccessBridge.cpp b/src/jdk.accessibility/windows/native/libjavaaccessbridge/JavaAccessBridge.cpp index cebf172ba8a..6bb0f3600d9 100644 --- a/src/jdk.accessibility/windows/native/libjavaaccessbridge/JavaAccessBridge.cpp +++ b/src/jdk.accessibility/windows/native/libjavaaccessbridge/JavaAccessBridge.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, 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 @@ -165,7 +165,7 @@ extern "C" { JavaAccessBridge::JavaAccessBridge(HINSTANCE hInstance) { windowsInstance = hInstance; ATs = (AccessBridgeATInstance *) 0; - initializeFileLogger("_java_access_bridge"); + initializeFileLogger("java_access_bridge"); initBroadcastMessageIDs(); // get the unique to us broadcast msg. IDs } diff --git a/src/jdk.accessibility/windows/native/libwindowsaccessbridge/WinAccessBridge.cpp b/src/jdk.accessibility/windows/native/libwindowsaccessbridge/WinAccessBridge.cpp index 9a1c8612e9a..d5c0b887ffe 100644 --- a/src/jdk.accessibility/windows/native/libwindowsaccessbridge/WinAccessBridge.cpp +++ b/src/jdk.accessibility/windows/native/libwindowsaccessbridge/WinAccessBridge.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, 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 @@ -130,7 +130,7 @@ extern "C" { switch (fdwReason) { case DLL_PROCESS_ATTACH: // A Windows executable loaded us - initializeFileLogger("_windows_access_bridge"); + initializeFileLogger("windows_access_bridge"); PrintDebugString("[INFO]: DLL_PROCESS_ATTACH"); theWindowsAccessBridge = new WinAccessBridge(hinstDll); break; From 82639e94b154bba498191453ac59181f9fd415d7 Mon Sep 17 00:00:00 2001 From: coleenp Date: Thu, 29 Aug 2019 08:52:22 -0400 Subject: [PATCH 041/131] 8216977: ShowHiddenFrames use in java_lang_StackTraceElement::fill_in appears broken Summary: Return NULL source file and negative line number for hidden frames. Reviewed-by: dholmes, hseigel --- .../runtime/StackTrace/HiddenFrameTest.java | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 test/hotspot/jtreg/runtime/StackTrace/HiddenFrameTest.java diff --git a/test/hotspot/jtreg/runtime/StackTrace/HiddenFrameTest.java b/test/hotspot/jtreg/runtime/StackTrace/HiddenFrameTest.java new file mode 100644 index 00000000000..ff9bf898276 --- /dev/null +++ b/test/hotspot/jtreg/runtime/StackTrace/HiddenFrameTest.java @@ -0,0 +1,80 @@ +/* + * 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 8216977 + * @summary Test null source file and negative line number from hidden frame produces correct output. + * @library /test/lib + * @run main/othervm -XX:+ShowHiddenFrames HiddenFrameTest visible + * @run main/othervm -XX:-ShowHiddenFrames HiddenFrameTest hidden + */ + +import jdk.test.lib.Asserts; + +public class HiddenFrameTest { + + @FunctionalInterface + private static interface SomeFunctionalInterface { + String someMethod(String a, String b); + } + + static void assertContains(String expected, String actual, Exception e, boolean framesAreHidden) throws Exception { + if (!framesAreHidden && !actual.contains(expected)) { + throw new RuntimeException("Expected: " + expected + "; Actual: " + actual, e); + } else if (framesAreHidden && actual.contains(expected)) { + throw new RuntimeException("Unexpected: " + expected + "; Actual: " + actual, e); + } + } + + static void checkException(Exception e, boolean framesAreHidden) throws Exception { + StackTraceElement[] fs = e.getStackTrace(); + + if (fs.length < 2) { + throw new RuntimeException("Exception should have at least two frames", e); + } + + assertContains("someMethod(Unknown Source)", fs[0].toString(), e, framesAreHidden); + } + + public static void main(String[] args) throws Exception { + boolean framesAreHidden = false; + if (args.length > 0) { + String arg = args[0]; + if (arg.equals("hidden")) framesAreHidden = true; + } + + try { + final SomeFunctionalInterface concatter = String::concat; + final String nullString = null; + if (concatter != null) { + // This throws NPE from the lambda expression which is a hidden frame + concatter.someMethod(nullString, "validString"); + } + } catch (NullPointerException e) { + e.printStackTrace(); + checkException(e, framesAreHidden); + } + } +} + From e81144d4121419de64d08068d4bd543ec1d07c63 Mon Sep 17 00:00:00 2001 From: jiefu Date: Fri, 30 Aug 2019 01:21:14 -0400 Subject: [PATCH 042/131] 8230376: [TESTBUG] runtime/StackTrace/HiddenFrameTest.java fails with release VM Reviewed-by: dholmes --- test/hotspot/jtreg/runtime/StackTrace/HiddenFrameTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/runtime/StackTrace/HiddenFrameTest.java b/test/hotspot/jtreg/runtime/StackTrace/HiddenFrameTest.java index ff9bf898276..540a1e31efb 100644 --- a/test/hotspot/jtreg/runtime/StackTrace/HiddenFrameTest.java +++ b/test/hotspot/jtreg/runtime/StackTrace/HiddenFrameTest.java @@ -26,8 +26,8 @@ * @bug 8216977 * @summary Test null source file and negative line number from hidden frame produces correct output. * @library /test/lib - * @run main/othervm -XX:+ShowHiddenFrames HiddenFrameTest visible - * @run main/othervm -XX:-ShowHiddenFrames HiddenFrameTest hidden + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+ShowHiddenFrames HiddenFrameTest visible + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:-ShowHiddenFrames HiddenFrameTest hidden */ import jdk.test.lib.Asserts; From 9d326782deac6c4c57d2be210f61f13161ce2bbf Mon Sep 17 00:00:00 2001 From: roland Date: Fri, 23 Aug 2019 14:22:29 +0200 Subject: [PATCH 043/131] 8229701: aarch64: C2 OSR compilation fails with "shouldn't process one node several times" in final graph reshaping Reviewed-by: thartmann, kvn --- .../ConvI2LWideningAssertTooStrong.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/c2/aarch64/ConvI2LWideningAssertTooStrong.java diff --git a/test/hotspot/jtreg/compiler/c2/aarch64/ConvI2LWideningAssertTooStrong.java b/test/hotspot/jtreg/compiler/c2/aarch64/ConvI2LWideningAssertTooStrong.java new file mode 100644 index 00000000000..b291675b08a --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/aarch64/ConvI2LWideningAssertTooStrong.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2019, Red Hat, 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. + * + * 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 8229701 + * @summary C2 OSR compilation fails with "shouldn't process one node several times" in final graph reshaping + * + * @run main/othervm ConvI2LWideningAssertTooStrong + * + */ + +public class ConvI2LWideningAssertTooStrong { + + public static final int N = 400; + + public static long instanceCount=708L; + public static volatile int iFld1=30517; + public static int iArrFld[]=new int[N]; + + public static void vMeth(short s) { + int i9=29117, i11=-6; + + for (i9 = 11; i9 < 377; i9++) { + switch ((i9 % 8) + 22) { + case 24: + instanceCount = i9; + instanceCount += instanceCount; + break; + case 25: + try { + i11 = (20705 % i11); + iArrFld[i9 - 1] = (55094 / iFld1); + } catch (ArithmeticException a_e) {} + break; + default: + } + } + } + + public static void main(String[] strArr) { + ConvI2LWideningAssertTooStrong _instance = new ConvI2LWideningAssertTooStrong(); + for (int i = 0; i < 10 * 202 * 8; i++ ) { + _instance.vMeth((short)20806); + } + } +} From bab74bd223a7d347118debe5f1bc373bfa19b1b9 Mon Sep 17 00:00:00 2001 From: sgehwolf Date: Mon, 8 Jul 2019 17:44:34 +0200 Subject: [PATCH 044/131] 8227397: Add --with-extra-asflags configure option Reviewed-by: phh --- make/autoconf/flags.m4 | 10 ++++++++++ make/autoconf/spec.gmk.in | 1 + make/hotspot/lib/CompileJvm.gmk | 2 ++ 3 files changed, 13 insertions(+) diff --git a/make/autoconf/flags.m4 b/make/autoconf/flags.m4 index 1ffc437268e..5e2243c0a31 100644 --- a/make/autoconf/flags.m4 +++ b/make/autoconf/flags.m4 @@ -162,6 +162,10 @@ AC_DEFUN_ONCE([FLAGS_SETUP_USER_SUPPLIED_FLAGS], AC_MSG_WARN([Ignoring LDFLAGS($LDFLAGS) found in environment. Use --with-extra-ldflags]) fi + if test "x$ASFLAGS" != "x"; then + AC_MSG_WARN([Ignoring ASFLAGS($ASFLAGS) found in environment. Use --with-extra-asflags]) + fi + AC_ARG_WITH(extra-cflags, [AS_HELP_STRING([--with-extra-cflags], [extra flags to be used when compiling jdk c-files])]) @@ -171,9 +175,13 @@ AC_DEFUN_ONCE([FLAGS_SETUP_USER_SUPPLIED_FLAGS], AC_ARG_WITH(extra-ldflags, [AS_HELP_STRING([--with-extra-ldflags], [extra flags to be used when linking jdk])]) + AC_ARG_WITH(extra-asflags, [AS_HELP_STRING([--with-extra-asflags], + [extra flags to be passed to the assembler])]) + USER_CFLAGS="$with_extra_cflags" USER_CXXFLAGS="$with_extra_cxxflags" USER_LDFLAGS="$with_extra_ldflags" + USER_ASFLAGS="$with_extra_asflags" ]) # Setup the sysroot flags and add them to global CFLAGS and LDFLAGS so @@ -265,10 +273,12 @@ AC_DEFUN_ONCE([FLAGS_PRE_TOOLCHAIN], EXTRA_CFLAGS="$MACHINE_FLAG $USER_CFLAGS" EXTRA_CXXFLAGS="$MACHINE_FLAG $USER_CXXFLAGS" EXTRA_LDFLAGS="$MACHINE_FLAG $USER_LDFLAGS" + EXTRA_ASFLAGS="$USER_ASFLAGS" AC_SUBST(EXTRA_CFLAGS) AC_SUBST(EXTRA_CXXFLAGS) AC_SUBST(EXTRA_LDFLAGS) + AC_SUBST(EXTRA_ASFLAGS) # For autoconf testing to work, the global flags must also be stored in the # "unnamed" CFLAGS etc. diff --git a/make/autoconf/spec.gmk.in b/make/autoconf/spec.gmk.in index 390b9d6f412..c6523d7bd71 100644 --- a/make/autoconf/spec.gmk.in +++ b/make/autoconf/spec.gmk.in @@ -462,6 +462,7 @@ JVM_RCFLAGS := @JVM_RCFLAGS@ EXTRA_CFLAGS = @EXTRA_CFLAGS@ EXTRA_CXXFLAGS = @EXTRA_CXXFLAGS@ EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ +EXTRA_ASFLAGS = @EXTRA_ASFLAGS@ CXX:=@FIXPATH@ @CCACHE@ @ICECC@ @CXX@ diff --git a/make/hotspot/lib/CompileJvm.gmk b/make/hotspot/lib/CompileJvm.gmk index a4b67f09fd5..297c106b71c 100644 --- a/make/hotspot/lib/CompileJvm.gmk +++ b/make/hotspot/lib/CompileJvm.gmk @@ -47,6 +47,8 @@ JVM_LDFLAGS += \ $(EXTRA_LDFLAGS) \ # +JVM_ASFLAGS += $(EXTRA_ASFLAGS) + JVM_LIBS += \ $(JVM_LIBS_FEATURES) \ # From e0b31687644145679c1ab7e3945e320d1f448dba Mon Sep 17 00:00:00 2001 From: sherman Date: Wed, 3 Oct 2018 12:54:54 -0700 Subject: [PATCH 045/131] 8211385: (zipfs) ZipDirectoryStream yields a stream of absolute paths when directory is relative Reviewed-by: alanb, lancea --- .../jdk/nio/zipfs/ZipDirectoryStream.java | 15 +++++++------- .../classes/jdk/nio/zipfs/ZipFileSystem.java | 19 +++++++++++++----- test/jdk/jdk/nio/zipfs/Basic.java | 20 +++++++++++++++++-- 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipDirectoryStream.java b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipDirectoryStream.java index 21b3b60a950..ae1909a85f4 100644 --- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipDirectoryStream.java +++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipDirectoryStream.java @@ -40,21 +40,21 @@ class ZipDirectoryStream implements DirectoryStream { private final ZipFileSystem zipfs; - private final byte[] path; + private final ZipPath dir; private final DirectoryStream.Filter filter; private volatile boolean isClosed; private volatile Iterator itr; - ZipDirectoryStream(ZipPath zipPath, + ZipDirectoryStream(ZipPath dir, DirectoryStream.Filter filter) throws IOException { - this.zipfs = zipPath.getFileSystem(); - this.path = zipPath.getResolvedPath(); + this.zipfs = dir.getFileSystem(); + this.dir = dir; this.filter = filter; // sanity check - if (!zipfs.isDirectory(path)) - throw new NotDirectoryException(zipPath.toString()); + if (!zipfs.isDirectory(dir.getResolvedPath())) + throw new NotDirectoryException(dir.toString()); } @Override @@ -65,7 +65,7 @@ public synchronized Iterator iterator() { throw new IllegalStateException("Iterator has already been returned"); try { - itr = zipfs.iteratorOf(path, filter); + itr = zipfs.iteratorOf(dir, filter); } catch (IOException e) { throw new IllegalStateException(e); } @@ -96,5 +96,4 @@ public void remove() { public synchronized void close() throws IOException { isClosed = true; } - } diff --git a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java index 4c1074ef211..a87fe328dfe 100644 --- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java +++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java @@ -409,23 +409,32 @@ boolean isDirectory(byte[] path) } // returns the list of child paths of "path" - Iterator iteratorOf(byte[] path, + Iterator iteratorOf(ZipPath dir, DirectoryStream.Filter filter) throws IOException { beginWrite(); // iteration of inodes needs exclusive lock try { ensureOpen(); + byte[] path = dir.getResolvedPath(); IndexNode inode = getInode(path); if (inode == null) throw new NotDirectoryException(getString(path)); List list = new ArrayList<>(); IndexNode child = inode.child; while (child != null) { - // assume all path from zip file itself is "normalized" - ZipPath zp = new ZipPath(this, child.name, true); - if (filter == null || filter.accept(zp)) - list.add(zp); + // (1) assume all path from zip file itself is "normalized" + // (2) IndexNode.name is absolute. see IndexNode(byte[],int,int) + // (3) if parent "dir" is relative when ZipDirectoryStream + // is created, the returned child path needs to be relative + // as well. + byte[] cname = child.name; + if (!dir.isAbsolute()) { + cname = Arrays.copyOfRange(cname, 1, cname.length); + } + ZipPath zpath = new ZipPath(this, cname, true); + if (filter == null || filter.accept(zpath)) + list.add(zpath); child = child.sibling; } return list.iterator(); diff --git a/test/jdk/jdk/nio/zipfs/Basic.java b/test/jdk/jdk/nio/zipfs/Basic.java index 54c10c136f5..6ec19a5fa0e 100644 --- a/test/jdk/jdk/nio/zipfs/Basic.java +++ b/test/jdk/jdk/nio/zipfs/Basic.java @@ -43,7 +43,7 @@ import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE; /** * @test - * @bug 8038500 8040059 8150366 8150496 8147539 + * @bug 8038500 8040059 8150366 8150496 8147539 8211385 * @summary Basic test for zip provider * * @modules jdk.zipfs @@ -89,16 +89,30 @@ public static void main(String[] args) throws Exception { // Test: DirectoryStream found = false; + try (DirectoryStream stream = Files.newDirectoryStream(fs.getPath("/"))) { for (Path entry: stream) { found = entry.toString().equals("/META-INF"); if (found) break; } } - if (!found) throw new RuntimeException("Expected file not found"); + try (DirectoryStream stream = Files.newDirectoryStream(fs.getPath("META-INF"))) { + for (Path entry: stream) { + if (entry.toString().equals("/META-INF/services")) + throw new RuntimeException("child path should be relative"); + } + } + + try (DirectoryStream stream = Files.newDirectoryStream(fs.getPath("/META-INF"))) { + for (Path entry: stream) { + if (entry.toString().equals("META-INF/services")) + throw new RuntimeException("child path should be absolute"); + } + } + // Test: copy file from zip file to current (scratch) directory Path source = fs.getPath("/META-INF/services/java.nio.file.spi.FileSystemProvider"); if (Files.exists(source)) { @@ -133,6 +147,8 @@ public static void main(String[] args) throws Exception { try { fs.provider().checkAccess(fs.getPath("/missing"), AccessMode.READ); } catch (ClosedFileSystemException x) { } + + Files.deleteIfExists(jarFile); } // FileVisitor that pretty prints a file tree From 79ae25d9da093815559846b3fb3e81c993fd10a9 Mon Sep 17 00:00:00 2001 From: lancea Date: Wed, 16 Jan 2019 17:37:09 -0500 Subject: [PATCH 046/131] 8211919: ZipDirectoryStream should provide a stream of paths that are relative to the directory Reviewed-by: alanb, clanger --- .../jdk/nio/zipfs/ZipDirectoryStream.java | 5 +- .../classes/jdk/nio/zipfs/ZipFileSystem.java | 13 +- .../share/classes/jdk/nio/zipfs/ZipPath.java | 6 +- test/jdk/jdk/nio/zipfs/Basic.java | 31 +- .../jdk/nio/zipfs/DirectoryStreamTests.java | 357 ++++++++++++++++++ 5 files changed, 371 insertions(+), 41 deletions(-) create mode 100644 test/jdk/jdk/nio/zipfs/DirectoryStreamTests.java diff --git a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipDirectoryStream.java b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipDirectoryStream.java index ae1909a85f4..935ed3f327f 100644 --- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipDirectoryStream.java +++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipDirectoryStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -27,6 +27,7 @@ import java.io.IOException; import java.nio.file.ClosedDirectoryStreamException; +import java.nio.file.DirectoryIteratorException; import java.nio.file.DirectoryStream; import java.nio.file.NotDirectoryException; import java.nio.file.Path; @@ -67,7 +68,7 @@ public synchronized Iterator iterator() { try { itr = zipfs.iteratorOf(dir, filter); } catch (IOException e) { - throw new IllegalStateException(e); + throw new DirectoryIteratorException(e); } return new Iterator() { diff --git a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java index a87fe328dfe..6381d578d50 100644 --- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java +++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -423,16 +423,15 @@ Iterator iteratorOf(ZipPath dir, List list = new ArrayList<>(); IndexNode child = inode.child; while (child != null) { - // (1) assume all path from zip file itself is "normalized" + // (1) Assume each path from the zip file itself is "normalized" // (2) IndexNode.name is absolute. see IndexNode(byte[],int,int) - // (3) if parent "dir" is relative when ZipDirectoryStream + // (3) If parent "dir" is relative when ZipDirectoryStream // is created, the returned child path needs to be relative // as well. byte[] cname = child.name; - if (!dir.isAbsolute()) { - cname = Arrays.copyOfRange(cname, 1, cname.length); - } - ZipPath zpath = new ZipPath(this, cname, true); + ZipPath childPath = new ZipPath(this, cname, true); + ZipPath childFileName = childPath.getFileName(); + ZipPath zpath = dir.resolve(childFileName); if (filter == null || filter.accept(zpath)) list.add(zpath); child = child.sibling; diff --git a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java index d8bf67fbff9..8d8d705ea0f 100644 --- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java +++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -92,8 +92,8 @@ public ZipPath getRoot() { return null; } - @Override - public Path getFileName() { + @Override + public ZipPath getFileName() { int off = path.length; if (off == 0 || off == 1 && path[0] == '/') return null; diff --git a/test/jdk/jdk/nio/zipfs/Basic.java b/test/jdk/jdk/nio/zipfs/Basic.java index 6ec19a5fa0e..e3831ff75ea 100644 --- a/test/jdk/jdk/nio/zipfs/Basic.java +++ b/test/jdk/jdk/nio/zipfs/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -23,7 +23,6 @@ import java.nio.file.AccessMode; import java.nio.file.ClosedFileSystemException; -import java.nio.file.DirectoryStream; import java.nio.file.FileStore; import java.nio.file.FileSystem; import java.nio.file.FileSystems; @@ -43,7 +42,7 @@ import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE; /** * @test - * @bug 8038500 8040059 8150366 8150496 8147539 8211385 + * @bug 8038500 8040059 8150366 8150496 8147539 * @summary Basic test for zip provider * * @modules jdk.zipfs @@ -87,32 +86,6 @@ public static void main(String[] args) throws Exception { // Test: exercise directory iterator and retrieval of basic attributes Files.walkFileTree(fs.getPath("/"), new FileTreePrinter()); - // Test: DirectoryStream - found = false; - - try (DirectoryStream stream = Files.newDirectoryStream(fs.getPath("/"))) { - for (Path entry: stream) { - found = entry.toString().equals("/META-INF"); - if (found) break; - } - } - if (!found) - throw new RuntimeException("Expected file not found"); - - try (DirectoryStream stream = Files.newDirectoryStream(fs.getPath("META-INF"))) { - for (Path entry: stream) { - if (entry.toString().equals("/META-INF/services")) - throw new RuntimeException("child path should be relative"); - } - } - - try (DirectoryStream stream = Files.newDirectoryStream(fs.getPath("/META-INF"))) { - for (Path entry: stream) { - if (entry.toString().equals("META-INF/services")) - throw new RuntimeException("child path should be absolute"); - } - } - // Test: copy file from zip file to current (scratch) directory Path source = fs.getPath("/META-INF/services/java.nio.file.spi.FileSystemProvider"); if (Files.exists(source)) { diff --git a/test/jdk/jdk/nio/zipfs/DirectoryStreamTests.java b/test/jdk/jdk/nio/zipfs/DirectoryStreamTests.java new file mode 100644 index 00000000000..a8fc0ebad47 --- /dev/null +++ b/test/jdk/jdk/nio/zipfs/DirectoryStreamTests.java @@ -0,0 +1,357 @@ +/* + * 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. + */ + +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.nio.file.*; +import java.nio.file.spi.FileSystemProvider; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.regex.PatternSyntaxException; +import java.util.zip.ZipException; + +import static org.testng.Assert.*; + +/** + * @test + * @bug 8211385 8211919 + * @summary ZIP File System tests that leverage DirectoryStream + * @modules jdk.zipfs + * @compile DirectoryStreamTests.java + * @run testng DirectoryStreamTests + * @run testng/othervm/java.security.policy=test.policy DirectoryStreamTests + */ +public class DirectoryStreamTests { + + // Map to used for creating a ZIP archive + private static final Map ZIPFS_MAP = Map.of("create", "true"); + + // Map to used for extracting a ZIP archive + private static final Map UNZIPFS_MAP = Map.of(); + + // The ZIP file system provider + private static final FileSystemProvider ZIPFS_PROVIDER = getZipFSProvider(); + + // Primary jar file used for testing + private static Path jarFile; + + // Jar file used to validate the behavior of the navigation of an empty directory + private static Path emptyJarFile; + + /** + * Create the JAR files used by the tests + */ + @BeforeClass + public void setUp() throws Exception { + emptyJarFile = Paths.get("emptyDir.jar"); + try (FileSystem zipfs = ZIPFS_PROVIDER.newFileSystem(emptyJarFile, ZIPFS_MAP)) { + + jarFile = Utils.createJarFile("basic.jar", + "META-INF/services/java.nio.file.spi.FileSystemProvider"); + + Files.createDirectory(zipfs.getPath("emptyDir")); + } + } + + /** + * Remove JAR files used by test as part of clean-up + */ + @AfterClass + public void tearDown() throws Exception { + Files.deleteIfExists(jarFile); + Files.deleteIfExists(emptyJarFile); + } + + /** + * Validate that you can specify a DirectoryStream filter using the ZIP File + * System and that the returned Iterator correctly indicates whether the + * filter has been matched + */ + @Test(dataProvider = "filterTestValues") + public void test0000(String glob, boolean expectedResult, String errMsg) + throws Exception { + + try (FileSystem zipfs = + ZIPFS_PROVIDER.newFileSystem(Paths.get("basic.jar"), UNZIPFS_MAP); + DirectoryStream ds = Files.newDirectoryStream(zipfs.getPath("/"), + new DirectoryStream.Filter() { + private PathMatcher matcher = + zipfs.getPathMatcher("glob:" + glob); + public boolean accept(Path file) { + return matcher.matches(file.getFileName()); + } + })) + { + assertEquals(ds.iterator().hasNext(), expectedResult, errMsg); + } + } + + /** + * Validate that you can specify a glob using the ZIP File System and that the + * returned Iterator correctly indicates whether the glob pattern has been matched + */ + @Test(dataProvider = "filterTestValues") + public void test0001(String glob, boolean expectedResult, String errMsg) + throws Exception { + + try (FileSystem zipfs = + ZIPFS_PROVIDER.newFileSystem(Paths.get("basic.jar"), UNZIPFS_MAP); + DirectoryStream ds = + Files.newDirectoryStream(zipfs.getPath("/"), glob)) { + assertEquals(ds.iterator().hasNext(), expectedResult, errMsg); + } + } + + /** + * Validate a PatternSyntaxException is thrown when specifying an invalid + * glob pattern with the ZIP File system + */ + @Test + public void test0002() throws Exception { + + try (FileSystem zipfs = + ZIPFS_PROVIDER.newFileSystem(Paths.get("basic.jar"), UNZIPFS_MAP)) { + assertThrows(PatternSyntaxException.class, () -> + Files.newDirectoryStream(zipfs.getPath("/"), "*[a-z")); + } + } + + /** + * Validate that the correct type of paths are returned when creating a + * DirectoryStream + */ + @Test(dataProvider = "startPaths") + public void test0003(String startPath, String expectedPath) + throws IOException { + try (FileSystem zipfs = + ZIPFS_PROVIDER.newFileSystem(Paths.get("basic.jar"), UNZIPFS_MAP); + DirectoryStream stream = + Files.newDirectoryStream(zipfs.getPath(startPath))) { + + for (Path entry : stream) { + assertTrue(entry.toString().equals(expectedPath), + String.format("Error: Expected path %s not found when" + + " starting at %s%n", expectedPath, entry)); + } + } + } + + /** + * Validate a NotDirectoryException is thrown when specifying a file for the + * starting path for creating a DirectoryStream with the ZIP File System + */ + @Test + public void test0004() throws Exception { + + try (FileSystem zipfs = + ZIPFS_PROVIDER.newFileSystem(Paths.get("basic.jar"), UNZIPFS_MAP)) { + assertThrows(NotDirectoryException.class, + () -> Files.newDirectoryStream( + zipfs.getPath("META-INF/services/java.nio.file.spi." + + "FileSystemProvider"))); + } + } + + /** + * Validate an IllegalStateException is thrown when accessing the Iterator + * more than once with the ZIP File System + */ + @Test + public void test0005() throws Exception { + + try (FileSystem zipfs = + ZIPFS_PROVIDER.newFileSystem(Paths.get("basic.jar"), UNZIPFS_MAP); + DirectoryStream ds = + Files.newDirectoryStream(zipfs.getPath("/"))) { + ds.iterator(); + assertThrows(IllegalStateException.class, () -> ds.iterator()); + + } + } + + /** + * Validate an IllegalStateException is thrown when accessing the Iterator + * after the DirectoryStream has been closed with the ZIP File System + */ + @Test + public void test0006() throws Exception { + + try (FileSystem zipfs = + ZIPFS_PROVIDER.newFileSystem(Paths.get("basic.jar"), UNZIPFS_MAP); + DirectoryStream ds = + Files.newDirectoryStream(zipfs.getPath("/"))) { + ds.close(); + assertThrows(IllegalStateException.class, () -> ds.iterator()); + + // ZipDirectoryStream.iterator() throws ClosedDirectoryStream when + // obtaining an Iterator when the DirectoryStream is closed + assertThrows(ClosedDirectoryStreamException.class, () -> ds.iterator()); + + } + } + + /** + * Validate an UnsupportedOperationException is thrown when invoking an + * Iterator operation that is not supported with the ZIP File System + */ + @Test + public void test0007() throws Exception { + + try (FileSystem zipfs = + ZIPFS_PROVIDER.newFileSystem(Paths.get("basic.jar"), UNZIPFS_MAP); + DirectoryStream ds = + Files.newDirectoryStream(zipfs.getPath("/"))) { + Iterator i = ds.iterator(); + + assertThrows(UnsupportedOperationException.class, () -> i.remove()); + } + } + + /** + * Validate an NoSuchElementException is thrown when invoking an + * Iterator.next() on a closed DirectoryStream with the ZIP File System + */ + @Test + public void test0008() throws Exception { + + try (FileSystem zipfs = + ZIPFS_PROVIDER.newFileSystem(Paths.get("basic.jar"), UNZIPFS_MAP); + DirectoryStream ds = + Files.newDirectoryStream(zipfs.getPath("/"))) { + Iterator i = ds.iterator(); + ds.close(); + assertThrows(NoSuchElementException.class, () -> i.next()); + } + } + + /** + * Validate Iterator.hasNext() returns false when the directory is empty with + * the ZIP File System + */ + @Test + public void test0009() throws Exception { + try (FileSystem zipfs = + ZIPFS_PROVIDER.newFileSystem(emptyJarFile, UNZIPFS_MAP); + DirectoryStream ds = + Files.newDirectoryStream(zipfs.getPath("emptyDir"))) { + assertFalse(ds.iterator().hasNext(), "Error: directory was not empty!"); + + } + } + + /** + * Validate Iterator.hasNext() returns false when the DirectoryStream is closed + * with the ZIP File System + */ + @Test + public void test0010() throws Exception { + + try (FileSystem zipfs = + ZIPFS_PROVIDER.newFileSystem(Paths.get("basic.jar"), UNZIPFS_MAP); + DirectoryStream ds = + Files.newDirectoryStream(zipfs.getPath("/"))) { + Iterator i = ds.iterator(); + ds.close(); + assertFalse(i.hasNext(), + "Error: false should be returned as DirectoryStream is closed!"); + } + } + + /** + * Validate that an IOException thrown by a filter is returned as the cause + * via a DirectoryIteratorException + */ + @Test + public void test0011() throws Exception { + + try (FileSystem zipfs = + ZIPFS_PROVIDER.newFileSystem(Paths.get("basic.jar"), UNZIPFS_MAP); + DirectoryStream ds = Files.newDirectoryStream(zipfs.getPath("/"), + new DirectoryStream.Filter() { + public boolean accept(Path file) throws IOException { + throw new java.util.zip.ZipException(); + } + })) + { + ds.iterator().hasNext(); + throw new RuntimeException("Expected DirectoryIteratorException not thrown"); + + } catch (DirectoryIteratorException x) { + IOException cause = x.getCause(); + if (!(cause instanceof ZipException)) + throw new RuntimeException("Expected IOException not propagated"); + } + } + + /** + * Glob values to use to validate filtering + */ + @DataProvider(name = "filterTestValues") + public static Object[][] filterValues() { + + String expectedMsg = "Error: Matching entries were expected but not found!!!"; + String notExpectedMsg = "Error: No matching entries expected but were found!!!"; + return new Object[][]{ + + {"M*", true, expectedMsg}, + {"I*", false, notExpectedMsg} + }; + } + + /** + * Starting Path for the DirectoryStream and the expected path to be returned + * when traversing the stream + */ + @DataProvider(name = "startPaths") + public static Object[][] Name() { + return new Object[][]{ + + {"META-INF", "META-INF/services"}, + {"/META-INF", "/META-INF/services"}, + {"/META-INF/../META-INF","/META-INF/../META-INF/services" }, + {"./META-INF", "./META-INF/services"}, + {"", "META-INF"}, + {"/", "/META-INF"}, + {".", "./META-INF"}, + {"./", "./META-INF"} + }; + } + + /** + * Returns the Zip FileSystem Provider + */ + private static FileSystemProvider getZipFSProvider() { + for (FileSystemProvider fsProvider : FileSystemProvider.installedProviders()) { + if ("jar".equals(fsProvider.getScheme())) { + return fsProvider; + } + } + return null; + } + +} From d98b2eb726599a50b6355ee4ee8016d172a51f1a Mon Sep 17 00:00:00 2001 From: clanger Date: Fri, 26 Apr 2019 08:53:29 +0100 Subject: [PATCH 047/131] 8222440: (zipfs) JarFileSystem does not correctly handle versioned entries if no root entry is present Reviewed-by: lancea --- .../classes/jdk/nio/zipfs/JarFileSystem.java | 120 ++++++++++++------ .../classes/jdk/nio/zipfs/ZipFileSystem.java | 8 +- test/jdk/jdk/nio/zipfs/jarfs/JFSTester.java | 111 +++++++++------- .../jdk/nio/zipfs/jarfs/root/dir1/leaf1.txt | 1 - .../jdk/nio/zipfs/jarfs/root/dir1/leaf2.txt | 1 - .../jdk/nio/zipfs/jarfs/root/dir2/leaf3.txt | 1 - .../jdk/nio/zipfs/jarfs/root/dir2/leaf4.txt | 1 - .../nio/zipfs/jarfs/v9/root/dir1/leaf1.txt | 1 - .../nio/zipfs/jarfs/v9/root/dir1/leaf2.txt | 1 - .../nio/zipfs/jarfs/v9/root/dir2/leaf3.txt | 1 - .../nio/zipfs/jarfs/v9/root/dir2/leaf4.txt | 1 - 11 files changed, 151 insertions(+), 96 deletions(-) delete mode 100644 test/jdk/jdk/nio/zipfs/jarfs/root/dir1/leaf1.txt delete mode 100644 test/jdk/jdk/nio/zipfs/jarfs/root/dir1/leaf2.txt delete mode 100644 test/jdk/jdk/nio/zipfs/jarfs/root/dir2/leaf3.txt delete mode 100644 test/jdk/jdk/nio/zipfs/jarfs/root/dir2/leaf4.txt delete mode 100644 test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf1.txt delete mode 100644 test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf2.txt delete mode 100644 test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf3.txt delete mode 100644 test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf4.txt diff --git a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java index ec138e471f3..2ee2c70198d 100644 --- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java +++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java @@ -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 @@ -49,20 +49,17 @@ * @author Steve Drach */ class JarFileSystem extends ZipFileSystem { - private Function lookup; + // lookup needs to be initialized because isMultiReleaseJar is called before createVersionedLinks + private Function lookup = path -> path; @Override IndexNode getInode(byte[] path) { // check for an alias to a versioned entry - byte[] versionedPath = lookup.apply(path); - return versionedPath == null ? super.getInode(path) : super.getInode(versionedPath); + return super.getInode(lookup.apply(path)); } - JarFileSystem(ZipFileSystemProvider provider, Path zfpath, Map env) - throws IOException { + JarFileSystem(ZipFileSystemProvider provider, Path zfpath, Map env) throws IOException { super(provider, zfpath, env); - lookup = path -> path; // lookup needs to be set before isMultiReleaseJar is called - // because it eventually calls getEntry if (isMultiReleaseJar()) { int version; Object o = env.get("multi-release"); @@ -81,7 +78,7 @@ IndexNode getInode(byte[] path) { throw new IllegalArgumentException("env parameter must be String, Integer, " + "or Version"); } - lookup = createVersionedLinks(version < 0 ? 0 : version); + createVersionedLinks(version < 0 ? 0 : version); setReadOnly(); } } @@ -89,7 +86,7 @@ IndexNode getInode(byte[] path) { private boolean isMultiReleaseJar() throws IOException { try (InputStream is = newInputStream(getBytes("/META-INF/MANIFEST.MF"))) { String multiRelease = new Manifest(is).getMainAttributes() - .getValue(Attributes.Name.MULTI_RELEASE); + .getValue(Attributes.Name.MULTI_RELEASE); return "true".equalsIgnoreCase(multiRelease); } catch (NoSuchFileException x) { return false; @@ -106,27 +103,71 @@ private boolean isMultiReleaseJar() throws IOException { * then wrap the map in a function that getEntry can use to override root * entry lookup for entries that have corresponding versioned entries */ - private Function createVersionedLinks(int version) { - HashMap aliasMap = new HashMap<>(); + private void createVersionedLinks(int version) { IndexNode verdir = getInode(getBytes("/META-INF/versions")); - if (verdir != null) { - getVersionMap(version, verdir).values() - .forEach(versionNode -> { // for each META-INF/versions/{n} directory - // put all the leaf inodes, i.e. entries, into the alias map - // possibly shadowing lower versioned entries - walk(versionNode, entryNode -> { - byte[] rootName = getRootName(versionNode, entryNode); - if (rootName != null) { - IndexNode rootNode = getInode(rootName); - if (rootNode == null) { // no matching root node, make a virtual one - rootNode = IndexNode.keyOf(rootName); - } - aliasMap.put(rootNode, entryNode.name); - } - }); - }); + // nothing to do, if no /META-INF/versions + if (verdir == null) { + return; + } + // otherwise, create a map and for each META-INF/versions/{n} directory + // put all the leaf inodes, i.e. entries, into the alias map + // possibly shadowing lower versioned entries + HashMap aliasMap = new HashMap<>(); + getVersionMap(version, verdir).values().forEach(versionNode -> + walk(versionNode.child, entryNode -> + aliasMap.put( + getNodeInRootTree(getRootName(entryNode, versionNode), entryNode.isdir), + entryNode.name)) + ); + lookup = path -> { + byte[] entry = aliasMap.get(IndexNode.keyOf(path)); + return entry == null ? path : entry; + }; + } + + /** + * Return the node from the root tree. Create it, if it doesn't exist. + */ + private IndexNode getNodeInRootTree(byte[] path, boolean isdir) { + IndexNode node = getInode(path); + if (node != null) { + return node; + } + IndexNode parent = getParentDir(path); + beginWrite(); + try { + node = new IndexNode(path, isdir); + node.sibling = parent.child; + parent.child = node; + inodes.put(node, node); + return node; + } finally { + endWrite(); + } + } + + /** + * Return the parent directory node of a path. If the node doesn't exist, + * it will be created. Parent directories will be created recursively. + * Recursion fuse: We assume at latest the root path can be resolved to a node. + */ + private IndexNode getParentDir(byte[] path) { + byte[] parentPath = getParent(path); + IndexNode node = inodes.get(IndexNode.keyOf(parentPath)); + if (node != null) { + return node; + } + IndexNode parent = getParentDir(parentPath); + beginWrite(); + try { + node = new IndexNode(parentPath, true); + node.sibling = parent.child; + parent.child = node; + inodes.put(node, node); + return node; + } finally { + endWrite(); } - return path -> aliasMap.get(IndexNode.keyOf(path)); } /** @@ -138,7 +179,7 @@ private TreeMap getVersionMap(int version, IndexNode metaInf TreeMap map = new TreeMap<>(); IndexNode child = metaInfVersions.child; while (child != null) { - Integer key = getVersion(child.name, metaInfVersions.name.length + 1); + Integer key = getVersion(child, metaInfVersions); if (key != null && key <= version) { map.put(key, child); } @@ -150,9 +191,11 @@ private TreeMap getVersionMap(int version, IndexNode metaInf /** * extract the integer version number -- META-INF/versions/9 returns 9 */ - private Integer getVersion(byte[] name, int offset) { + private Integer getVersion(IndexNode inode, IndexNode metaInfVersions) { try { - return Integer.parseInt(getString(Arrays.copyOfRange(name, offset, name.length))); + byte[] fullName = inode.name; + return Integer.parseInt(getString(Arrays + .copyOfRange(fullName, metaInfVersions.name.length + 1, fullName.length))); } catch (NumberFormatException x) { // ignore this even though it might indicate issues with the JAR structure return null; @@ -162,14 +205,14 @@ private Integer getVersion(byte[] name, int offset) { /** * walk the IndexNode tree processing all leaf nodes */ - private void walk(IndexNode inode, Consumer process) { + private void walk(IndexNode inode, Consumer consumer) { if (inode == null) return; if (inode.isDir()) { - walk(inode.child, process); + walk(inode.child, consumer); } else { - process.accept(inode); + consumer.accept(inode); } - walk(inode.sibling, process); + walk(inode.sibling, consumer); } /** @@ -178,9 +221,8 @@ private void walk(IndexNode inode, Consumer process) { * and prefix META-INF/versions/9/ * returns foo/bar.class */ - private byte[] getRootName(IndexNode prefix, IndexNode inode) { - int offset = prefix.name.length; + private byte[] getRootName(IndexNode inode, IndexNode prefix) { byte[] fullName = inode.name; - return Arrays.copyOfRange(fullName, offset, fullName.length); + return Arrays.copyOfRange(fullName, prefix.name.length, fullName.length); } } diff --git a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java index 6381d578d50..f3de7571468 100644 --- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java +++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java @@ -884,7 +884,7 @@ private void checkParents(byte[] path) throws IOException { } private static byte[] ROOTPATH = new byte[] { '/' }; - private static byte[] getParent(byte[] path) { + static byte[] getParent(byte[] path) { int off = getParentOff(path); if (off <= 1) return ROOTPATH; @@ -899,11 +899,11 @@ private static int getParentOff(byte[] path) { return off; } - private final void beginWrite() { + final void beginWrite() { rwlock.writeLock().lock(); } - private final void endWrite() { + final void endWrite() { rwlock.writeLock().unlock(); } @@ -926,7 +926,7 @@ private final void endRead() { private final ReadWriteLock rwlock = new ReentrantReadWriteLock(); // name -> pos (in cen), IndexNode itself can be used as a "key" - private LinkedHashMap inodes; + LinkedHashMap inodes; final byte[] getBytes(String name) { return zc.getBytes(name); diff --git a/test/jdk/jdk/nio/zipfs/jarfs/JFSTester.java b/test/jdk/jdk/nio/zipfs/jarfs/JFSTester.java index 78a663f7a7f..8bd2a2d9fc5 100644 --- a/test/jdk/jdk/nio/zipfs/jarfs/JFSTester.java +++ b/test/jdk/jdk/nio/zipfs/jarfs/JFSTester.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -23,15 +23,16 @@ /* * @test - * @bug 8164389 + * @bug 8164389 8222440 * @summary walk entries in a jdk.nio.zipfs.JarFileSystem - * @modules jdk.jartool/sun.tools.jar + * @library /lib/testlibrary/java/util/jar + * @modules jdk.jartool * jdk.zipfs + * @build Compiler JarBuilder * @run testng JFSTester */ import org.testng.Assert; -import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -50,57 +51,76 @@ public class JFSTester { private URI jarURI; - private Path jarfile; + + final private String root_dir1_leaf1_txt = "This is leaf 1." + System.lineSeparator(); + final private String root_dir1_leaf2_txt = "This is leaf 2." + System.lineSeparator(); + final private String root_dir2_leaf3_txt = "This is leaf 3." + System.lineSeparator(); + final private String root_dir2_leaf4_txt = "This is leaf 4." + System.lineSeparator(); + final private String v9_root_dir2_leaf3_txt = "This is version 9 leaf 3." + System.lineSeparator(); + final private String v9_root_dir2_leaf4_txt = "This is version 9 leaf 4." + System.lineSeparator(); + final private String v9_root_dir3_leaf5_txt = "This is version 9 leaf 5." + System.lineSeparator(); + final private String v9_root_dir3_leaf6_txt = "This is version 9 leaf 6." + System.lineSeparator(); + final private String v10_root_dir3_leaf5_txt = "This is version 10 leaf 5." + System.lineSeparator(); + final private String v10_root_dir3_leaf6_txt = "This is version 10 leaf 6." + System.lineSeparator(); @BeforeClass public void initialize() throws Exception { - String userdir = System.getProperty("user.dir","."); - jarfile = Paths.get(userdir, "test.jar"); - String srcdir = System.getProperty("test.src"); - String[] args = ( - "-cf " - + jarfile.toString() - + " -C " - + srcdir - + " root --release 9 -C " - + srcdir - + System.getProperty("file.separator") - + "v9 root" - ).split(" +"); - new sun.tools.jar.Main(System.out, System.err, "jar").run(args); - String ssp = jarfile.toUri().toString(); - jarURI = new URI("jar", ssp, null); - } - - @AfterClass - public void close() throws IOException { - Files.deleteIfExists(jarfile); + Path jarfile = Paths.get("test.jar"); + JarBuilder jb = new JarBuilder(jarfile.toString()); + jb.addAttribute("Multi-Release", "true"); + jb.addEntry("root/dir1/leaf1.txt", root_dir1_leaf1_txt.getBytes()); + jb.addEntry("root/dir1/leaf2.txt", root_dir1_leaf2_txt.getBytes()); + jb.addEntry("root/dir2/leaf3.txt", root_dir2_leaf3_txt.getBytes()); + jb.addEntry("root/dir2/leaf4.txt", root_dir2_leaf4_txt.getBytes()); + jb.addEntry("META-INF/versions/9/root/dir2/leaf3.txt", v9_root_dir2_leaf3_txt.getBytes()); + jb.addEntry("META-INF/versions/9/root/dir2/leaf4.txt", v9_root_dir2_leaf4_txt.getBytes()); + jb.addEntry("META-INF/versions/9/root/dir3/leaf5.txt", v9_root_dir3_leaf5_txt.getBytes()); + jb.addEntry("META-INF/versions/9/root/dir3/leaf6.txt", v9_root_dir3_leaf6_txt.getBytes()); + jb.addEntry("META-INF/versions/10/root/dir3/leaf5.txt", v10_root_dir3_leaf5_txt.getBytes()); + jb.addEntry("META-INF/versions/10/root/dir3/leaf6.txt", v10_root_dir3_leaf6_txt.getBytes()); + jb.build(); + System.out.println("Created " + jarfile + ": " + Files.exists(jarfile)); + jarURI = new URI("jar", jarfile.toUri().toString(), null); } @Test public void testWalk() throws IOException { - - // no configuration, treat multi-release jar as unversioned - Map env = new HashMap<>(); + // treat multi-release jar as unversioned + Map env = new HashMap<>(); Set contents = doTest(env); - Set baseContents = Set.of( - "This is leaf 1.\n", - "This is leaf 2.\n", - "This is leaf 3.\n", - "This is leaf 4.\n" + Set expectedContents = Set.of( + root_dir1_leaf1_txt, + root_dir1_leaf2_txt, + root_dir2_leaf3_txt, + root_dir2_leaf4_txt ); - Assert.assertEquals(contents, baseContents); + Assert.assertEquals(contents, expectedContents); - // a configuration and jar file is multi-release + // open file as multi-release for version 9 env.put("multi-release", "9"); contents = doTest(env); - Set versionedContents = Set.of( - "This is versioned leaf 1.\n", - "This is versioned leaf 2.\n", - "This is versioned leaf 3.\n", - "This is versioned leaf 4.\n" + expectedContents = Set.of( + root_dir1_leaf1_txt, + root_dir1_leaf2_txt, + v9_root_dir2_leaf3_txt, + v9_root_dir2_leaf4_txt, + v9_root_dir3_leaf5_txt, + v9_root_dir3_leaf6_txt + ); + Assert.assertEquals(contents, expectedContents); + + // open file as multi-release for version 10 + env.put("multi-release", "10"); + contents = doTest(env); + expectedContents = Set.of( + root_dir1_leaf1_txt, + root_dir1_leaf2_txt, + v9_root_dir2_leaf3_txt, + v9_root_dir2_leaf4_txt, + v10_root_dir3_leaf5_txt, + v10_root_dir3_leaf6_txt ); - Assert.assertEquals(contents, versionedContents); + Assert.assertEquals(contents, expectedContents); } private Set doTest(Map env) throws IOException { @@ -108,9 +128,10 @@ private Set doTest(Map env) throws IOException { try (FileSystem fs = FileSystems.newFileSystem(jarURI, env)) { Path root = fs.getPath("root"); contents = Files.walk(root) - .filter(p -> !Files.isDirectory(p)) - .map(this::pathToContents) - .collect(Collectors.toSet()); + .filter(p -> !Files.isDirectory(p)) + .map(this::pathToContents) + .sorted() + .collect(Collectors.toSet()); } return contents; } diff --git a/test/jdk/jdk/nio/zipfs/jarfs/root/dir1/leaf1.txt b/test/jdk/jdk/nio/zipfs/jarfs/root/dir1/leaf1.txt deleted file mode 100644 index 05f9592a818..00000000000 --- a/test/jdk/jdk/nio/zipfs/jarfs/root/dir1/leaf1.txt +++ /dev/null @@ -1 +0,0 @@ -This is leaf 1. diff --git a/test/jdk/jdk/nio/zipfs/jarfs/root/dir1/leaf2.txt b/test/jdk/jdk/nio/zipfs/jarfs/root/dir1/leaf2.txt deleted file mode 100644 index 19229fa2322..00000000000 --- a/test/jdk/jdk/nio/zipfs/jarfs/root/dir1/leaf2.txt +++ /dev/null @@ -1 +0,0 @@ -This is leaf 2. diff --git a/test/jdk/jdk/nio/zipfs/jarfs/root/dir2/leaf3.txt b/test/jdk/jdk/nio/zipfs/jarfs/root/dir2/leaf3.txt deleted file mode 100644 index 724fae66d88..00000000000 --- a/test/jdk/jdk/nio/zipfs/jarfs/root/dir2/leaf3.txt +++ /dev/null @@ -1 +0,0 @@ -This is leaf 3. diff --git a/test/jdk/jdk/nio/zipfs/jarfs/root/dir2/leaf4.txt b/test/jdk/jdk/nio/zipfs/jarfs/root/dir2/leaf4.txt deleted file mode 100644 index 3fafaadeda0..00000000000 --- a/test/jdk/jdk/nio/zipfs/jarfs/root/dir2/leaf4.txt +++ /dev/null @@ -1 +0,0 @@ -This is leaf 4. diff --git a/test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf1.txt b/test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf1.txt deleted file mode 100644 index 9092c1883d3..00000000000 --- a/test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf1.txt +++ /dev/null @@ -1 +0,0 @@ -This is versioned leaf 1. diff --git a/test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf2.txt b/test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf2.txt deleted file mode 100644 index 9a2d266edf1..00000000000 --- a/test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir1/leaf2.txt +++ /dev/null @@ -1 +0,0 @@ -This is versioned leaf 2. diff --git a/test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf3.txt b/test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf3.txt deleted file mode 100644 index 6491cae8b83..00000000000 --- a/test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf3.txt +++ /dev/null @@ -1 +0,0 @@ -This is versioned leaf 3. diff --git a/test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf4.txt b/test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf4.txt deleted file mode 100644 index aa5563cb709..00000000000 --- a/test/jdk/jdk/nio/zipfs/jarfs/v9/root/dir2/leaf4.txt +++ /dev/null @@ -1 +0,0 @@ -This is versioned leaf 4. From f8300e47b6eca1b1331f1733c92893d72b613535 Mon Sep 17 00:00:00 2001 From: rschmelter Date: Wed, 17 Apr 2019 01:21:56 -0700 Subject: [PATCH 048/131] 8222529: sun.jdwp.listenerAddress agent property uses wrong encoding Reviewed-by: sspitsyn, amenkov, clanger, erikj --- make/lib/Lib-jdk.jdwp.agent.gmk | 3 ++- src/jdk.jdwp.agent/share/native/libjdwp/util.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/make/lib/Lib-jdk.jdwp.agent.gmk b/make/lib/Lib-jdk.jdwp.agent.gmk index 0bc93e0d352..f00f0760fb6 100644 --- a/make/lib/Lib-jdk.jdwp.agent.gmk +++ b/make/lib/Lib-jdk.jdwp.agent.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 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 @@ -64,6 +64,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJDWP, \ LIBS_solaris := $(LIBDL), \ LIBS_macosx := -liconv, \ LIBS_aix := -liconv, \ + LIBS_windows := $(WIN_JAVA_LIB), \ )) $(BUILD_LIBJDWP): $(call FindLib, java.base, java) diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/util.c b/src/jdk.jdwp.agent/share/native/libjdwp/util.c index 07c38e6694e..625427b3bb5 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/util.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/util.c @@ -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 @@ -1673,7 +1673,7 @@ setAgentPropertyValue(JNIEnv *env, char *propertyName, char* propertyValue) /* Create jstrings for property name and value */ nameString = JNI_FUNC_PTR(env,NewStringUTF)(env, propertyName); if (nameString != NULL) { - valueString = JNI_FUNC_PTR(env,NewStringUTF)(env, propertyValue); + valueString = JNU_NewStringPlatform(env, propertyValue); if (valueString != NULL) { /* invoke Properties.setProperty */ JNI_FUNC_PTR(env,CallObjectMethod) From bfc7517a3b4795e97a70ecabf4e741950edac677 Mon Sep 17 00:00:00 2001 From: lancea Date: Mon, 20 May 2019 12:24:05 -0400 Subject: [PATCH 049/131] 8222807: Address iteration with invalid ZIP header entries Reviewed-by: redestad, clanger --- .../classes/jdk/nio/zipfs/ZipFileSystem.java | 45 +++++- .../jdk/nio/zipfs/InvalidZipHeaderTests.java | 129 ++++++++++++++++++ 2 files changed, 172 insertions(+), 2 deletions(-) create mode 100644 test/jdk/jdk/nio/zipfs/InvalidZipHeaderTests.java diff --git a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java index f3de7571468..354a52992b6 100644 --- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java +++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java @@ -1872,7 +1872,7 @@ static class IndexNode { this.pos = pos; } - // constructor for cenInit() (1) remove trailing '/' (2) pad leading '/' + // constructor for initCEN() (1) remove trailing '/' (2) pad leading '/' IndexNode(byte[] cen, int pos, int nlen) { int noff = pos + CENHDR; if (cen[noff + nlen - 1] == '/') { @@ -1886,10 +1886,51 @@ static class IndexNode { System.arraycopy(cen, noff, name, 1, nlen); name[0] = '/'; } - name(name); + name(normalize(name)); this.pos = pos; } + // Normalize the IndexNode.name field. + private byte[] normalize(byte[] path) { + int len = path.length; + if (len == 0) + return path; + byte prevC = 0; + for (int pathPos = 0; pathPos < len; pathPos++) { + byte c = path[pathPos]; + if (c == '/' && prevC == '/') + return normalize(path, pathPos - 1); + prevC = c; + } + if (len > 1 && prevC == '/') { + return Arrays.copyOf(path, len - 1); + } + return path; + } + + private byte[] normalize(byte[] path, int off) { + // As we know we have at least one / to trim, we can reduce + // the size of the resulting array + byte[] to = new byte[path.length - 1]; + int pathPos = 0; + while (pathPos < off) { + to[pathPos] = path[pathPos]; + pathPos++; + } + int toPos = pathPos; + byte prevC = 0; + while (pathPos < path.length) { + byte c = path[pathPos++]; + if (c == '/' && prevC == '/') + continue; + to[toPos++] = c; + prevC = c; + } + if (toPos > 1 && to[toPos - 1] == '/') + toPos--; + return (toPos == to.length) ? to : Arrays.copyOf(to, toPos); + } + private static final ThreadLocal cachedKey = new ThreadLocal<>(); final static IndexNode keyOf(byte[] name) { // get a lookup key; diff --git a/test/jdk/jdk/nio/zipfs/InvalidZipHeaderTests.java b/test/jdk/jdk/nio/zipfs/InvalidZipHeaderTests.java new file mode 100644 index 00000000000..d89494e3125 --- /dev/null +++ b/test/jdk/jdk/nio/zipfs/InvalidZipHeaderTests.java @@ -0,0 +1,129 @@ +/* + * 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. + */ + +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; +import java.util.stream.Collectors; + +import static java.nio.file.Files.walk; +import static org.testng.Assert.*; + +/** + * @test + * @bug 8222807 + * @summary Validate that you can iterate a ZIP file with invalid ZIP header entries + * @modules jdk.zipfs + * @compile InvalidZipHeaderTests.java + * @run testng InvalidZipHeaderTests + * @run testng/othervm/java.security.policy=test.policy InvalidZipHeaderTests + */ +public class InvalidZipHeaderTests { + + + // Name of Jar file used in tests + private static final String INVALID_JAR_FILE = "invalid.jar"; + + /** + * Create the JAR files used by the tests + */ + @BeforeClass + public void setUp() throws Exception { + createInvalidJarFile(); + } + + /** + * Remove JAR files used by test as part of clean-up + */ + @AfterClass + public void tearDown() throws Exception { + Files.deleteIfExists(Path.of(INVALID_JAR_FILE)); + } + + + /** + * Validate that you can walk a ZIP archive with header entries + * such as "foo//" + */ + @Test(dataProvider = "startPaths") + public void walkInvalidHeaderTest(String startPath, List expectedPaths) + throws IOException { + try (FileSystem zipfs = + FileSystems.newFileSystem(Path.of(INVALID_JAR_FILE))) { + List result = walk(zipfs.getPath(startPath)) + .map(f -> f.toString()).collect(Collectors.toList()); + assertTrue(result.equals(expectedPaths), + String.format("Error: Expected paths not found when walking" + + "%s, starting at %s%n", INVALID_JAR_FILE, + startPath)); + } + } + + + /** + * Starting Path for walking the ZIP archive and the expected paths to be returned + * when traversing the archive + */ + @DataProvider(name = "startPaths") + public static Object[][] Name() { + return new Object[][]{ + + {"luckydog", List.of("luckydog", "luckydog/outfile.txt")}, + {"/luckydog", List.of("/luckydog", "/luckydog/outfile.txt")}, + {"./luckydog", List.of("./luckydog", "./luckydog/outfile.txt")}, + {"", List.of( "", "luckydog", "luckydog/outfile.txt")}, + {"/", List.of("/", "/luckydog", "/luckydog/outfile.txt")}, + {".", List.of(".", "./luckydog", "./luckydog/outfile.txt")}, + {"./", List.of(".", "./luckydog", "./luckydog/outfile.txt")} + }; + } + + /** + * Create a jar file with invalid CEN and LOC headers + * @throws IOException + */ + static void createInvalidJarFile() throws IOException { + + try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(INVALID_JAR_FILE))) { + JarEntry je = new JarEntry("luckydog//"); + jos.putNextEntry(je); + jos.closeEntry(); + je = new JarEntry("luckydog//outfile.txt"); + jos.putNextEntry(je); + jos.write("Tennis Anyone!!".getBytes()); + jos.closeEntry(); + } + } + +} From 53e0251a5f975eef7778e930417cb85f3102211f Mon Sep 17 00:00:00 2001 From: mbaesken Date: Thu, 16 May 2019 09:21:49 +0200 Subject: [PATCH 050/131] 8223438: add VirtualizationInformation JFR event Reviewed-by: clanger, egahlin --- src/jdk.jfr/share/conf/jfr/default.jfc | 5 ++ src/jdk.jfr/share/conf/jfr/profile.jfc | 5 ++ .../jfr/event/os/TestVirtualizationInfo.java | 57 +++++++++++++++++++ test/lib/jdk/test/lib/jfr/EventNames.java | 3 +- 4 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 test/jdk/jdk/jfr/event/os/TestVirtualizationInfo.java diff --git a/src/jdk.jfr/share/conf/jfr/default.jfc b/src/jdk.jfr/share/conf/jfr/default.jfc index 02e2f2171ac..d55eeeafc0d 100644 --- a/src/jdk.jfr/share/conf/jfr/default.jfc +++ b/src/jdk.jfr/share/conf/jfr/default.jfc @@ -488,6 +488,11 @@ beginChunk + + true + beginChunk + + true beginChunk diff --git a/src/jdk.jfr/share/conf/jfr/profile.jfc b/src/jdk.jfr/share/conf/jfr/profile.jfc index 5b9ca8d67de..9023cd020f7 100644 --- a/src/jdk.jfr/share/conf/jfr/profile.jfc +++ b/src/jdk.jfr/share/conf/jfr/profile.jfc @@ -488,6 +488,11 @@ beginChunk + + true + beginChunk + + true beginChunk diff --git a/test/jdk/jdk/jfr/event/os/TestVirtualizationInfo.java b/test/jdk/jdk/jfr/event/os/TestVirtualizationInfo.java new file mode 100644 index 00000000000..b3a09191873 --- /dev/null +++ b/test/jdk/jdk/jfr/event/os/TestVirtualizationInfo.java @@ -0,0 +1,57 @@ +/* + * 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 + * 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. + */ + +package jdk.jfr.event.os; + +import java.util.List; + +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedEvent; +import jdk.test.lib.jfr.EventNames; +import jdk.test.lib.jfr.Events; + +/** + * @test + * @key jfr + * @requires vm.hasJFR + * @library /test/lib + * @run main/othervm jdk.jfr.event.os.TestVirtualizationInfo + */ +public class TestVirtualizationInfo { + private final static String EVENT_NAME = EventNames.VirtualizationInformation; + + public static void main(String[] args) throws Throwable { + Recording recording = new Recording(); + recording.enable(EVENT_NAME); + recording.start(); + recording.stop(); + List events = Events.fromRecording(recording); + Events.hasEvents(events); + for (RecordedEvent event : events) { + System.out.println("Event: " + event); + Events.assertField(event, "name").notEmpty(); + } + } +} diff --git a/test/lib/jdk/test/lib/jfr/EventNames.java b/test/lib/jdk/test/lib/jfr/EventNames.java index 74c185d2514..d729ff9c10d 100644 --- a/test/lib/jdk/test/lib/jfr/EventNames.java +++ b/test/lib/jdk/test/lib/jfr/EventNames.java @@ -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 @@ -147,6 +147,7 @@ public class EventNames { // OS public final static String OSInformation = PREFIX + "OSInformation"; + public final static String VirtualizationInformation = PREFIX + "VirtualizationInformation"; public final static String CPUInformation = PREFIX + "CPUInformation"; public final static String CPULoad = PREFIX + "CPULoad"; public final static String ThreadCPULoad = PREFIX + "ThreadCPULoad"; From b17074cbb1a33b3e2fff72ab6c30a836dcfe3449 Mon Sep 17 00:00:00 2001 From: egahlin Date: Wed, 12 Dec 2018 18:43:16 +0100 Subject: [PATCH 051/131] 8214750: Unnecessary

tags in jfr classes Reviewed-by: mgronlun --- src/jdk.jfr/share/classes/jdk/jfr/package-info.java | 1 - .../share/classes/jdk/management/jfr/FlightRecorderMXBean.java | 1 - 2 files changed, 2 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/package-info.java b/src/jdk.jfr/share/classes/jdk/jfr/package-info.java index 2af1651d956..a33e6b041d0 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/package-info.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/package-info.java @@ -105,7 +105,6 @@ * {@link jdk.jfr.ValueDescriptor#getName()}. *

* Predefined settings - *

* * * diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBean.java b/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBean.java index 8ddde88569a..8b1231b2773 100644 --- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBean.java +++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBean.java @@ -517,7 +517,6 @@ public interface FlightRecorderMXBean extends PlatformManagedObject { * event type is obtained by invoking * {@link jdk.jfr.EventType#getSettingDescriptors()} and * {@link jdk.jfr.ValueDescriptor#getName()}. - *

* * @param recordingId ID of the recording * From c0fcbb7a20a3a53a5f4bb25813f1361dc3422b69 Mon Sep 17 00:00:00 2001 From: mseledtsov Date: Thu, 22 Aug 2019 10:35:31 -0700 Subject: [PATCH 052/131] 8226779: [TESTBUG] Test JFR API from Java agent Summary: Created new tests for JFR plus Java Agent Reviewed-by: egahlin --- .../jdk/jfr/javaagent/EventEmitterAgent.java | 106 ++++++++++++++++++ .../jdk/jfr/javaagent/JavaAgentBuilder.java | 87 ++++++++++++++ .../jdk/jfr/javaagent/TestLoadedAgent.java | 58 ++++++++++ .../jdk/jfr/javaagent/TestPremainAgent.java | 48 ++++++++ 4 files changed, 299 insertions(+) create mode 100644 test/jdk/jdk/jfr/javaagent/EventEmitterAgent.java create mode 100644 test/jdk/jdk/jfr/javaagent/JavaAgentBuilder.java create mode 100644 test/jdk/jdk/jfr/javaagent/TestLoadedAgent.java create mode 100644 test/jdk/jdk/jfr/javaagent/TestPremainAgent.java diff --git a/test/jdk/jdk/jfr/javaagent/EventEmitterAgent.java b/test/jdk/jdk/jfr/javaagent/EventEmitterAgent.java new file mode 100644 index 00000000000..0e19589d65d --- /dev/null +++ b/test/jdk/jdk/jfr/javaagent/EventEmitterAgent.java @@ -0,0 +1,106 @@ +/* + * 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.jfr.javaagent; + +import java.lang.instrument.Instrumentation; +import java.nio.file.Path; +import java.nio.file.Paths; + +import jdk.jfr.Configuration; +import jdk.jfr.Event; +import jdk.jfr.Name; +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordingFile; +import jdk.test.lib.Asserts; +import jdk.test.lib.jfr.EventNames; + +// Java agent that emits in multiple threads +public class EventEmitterAgent { + + private static final int THREADS = 5; + private static final int EVENTS_PER_THREAD = 150_000; + private static final int EXPECTED_COUNT = THREADS * EVENTS_PER_THREAD; + private static final Path DUMP_PATH = Paths.get("dump.jfr").toAbsolutePath(); + + // Called when agent is loaded from command line + public static void agentmain(String agentArgs, Instrumentation inst) throws Exception { + agentWork(); + } + + // Called when agent is dynamically loaded + public static void premain(String agentArgs, Instrumentation inst) throws Exception { + agentWork(); + } + + private static void agentWork() throws Exception { + try (Recording r = new Recording(Configuration.getConfiguration("default"))) { + r.enable(EventNames.JavaExceptionThrow); + r.setDestination(DUMP_PATH); + r.start(); + Thread[] threads = new Thread[THREADS]; + for (int i = 0; i < THREADS; i++) { + threads[i] = new Thread(EventEmitterAgent::emitEvents); + threads[i].start(); + } + for (int i = 0; i < THREADS; i++) { + threads[i].join(); + } + r.stop(); + } + } + + public static void emitEvents() { + for (int i = 0; i < EVENTS_PER_THREAD; i++) { + TestEvent e = new TestEvent(); + e.msg = "Long message that puts pressure on the string pool " + i % 100; + e.count = i; + e.thread = Thread.currentThread(); + e.clazz = String.class; + e.commit(); + if (i % 10000 == 0) { + try { + Thread.sleep(1); + } catch (InterruptedException ie) { + // ignore + } + } + } + } + + @Name("Test") + static class TestEvent extends Event { + String msg; + int count; + Thread thread; + Class clazz; + } + + public static void validateRecording() throws Exception { + long testEventCount = RecordingFile.readAllEvents(DUMP_PATH) + .stream() + .filter(e -> e.getEventType().getName().equals("Test")) + .count(); + Asserts.assertTrue(testEventCount == EXPECTED_COUNT, "Mismatch in TestEvent count"); + } +} diff --git a/test/jdk/jdk/jfr/javaagent/JavaAgentBuilder.java b/test/jdk/jdk/jfr/javaagent/JavaAgentBuilder.java new file mode 100644 index 00000000000..22b7304d8b4 --- /dev/null +++ b/test/jdk/jdk/jfr/javaagent/JavaAgentBuilder.java @@ -0,0 +1,87 @@ +/* + * 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.util; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.jar.Attributes; +import java.util.jar.Manifest; + +import jdk.test.lib.Utils; +import jdk.test.lib.util.JarUtils; + +/** + * A builder for a common Java agent. + * Can be used directly from the jtreg test header to + * build a java agent before the test is executed. + * + * E.g.: + * @run driver jdk.test.lib.util.JavaAgentBuilder + * jdk.jfr.javaagent.EventEmitterAgent EventEmitterAgent.jar + * + */ +public class JavaAgentBuilder { + + /** + * Build a java agent jar file with a given agent class. + * + * @param args[0] fully qualified name of an agent class + * @param args[1] file name of the agent jar to be created + * @throws IOException + */ + public static void main(String... args) throws IOException { + String agentClass = args[0]; + String agentJar = args[1]; + System.out.println("Building " + agentJar + " with agent class " + agentClass); + build(agentClass, agentJar); + } + + /** + * Build a java agent jar file with a given agent class. + * The agent class will be added as both premain class and agent class. + * + * @param agentClass fully qualified name of an agent class + * @param agentJar file name of the agent jar to be created + * the file will be placed in a current work directory + * @throws IOException + */ + public static void build(String agentClass, String agentJar) throws IOException { + Manifest mf = new Manifest(); + Attributes attrs = mf.getMainAttributes(); + attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0"); + attrs.putValue("Premain-Class", agentClass); + attrs.putValue("Agent-Class", agentClass); + + Path jarFile = Paths.get(".", agentJar); + String testClasses = Utils.TEST_CLASSES; + String agentPath = agentClass.replace(".", File.separator) + ".class"; + Path agentFile = Paths.get(testClasses, agentPath); + Path dir = Paths.get(testClasses); + JarUtils.createJarFile(jarFile, mf, dir, agentFile); + System.out.println("Agent built:" + jarFile.toAbsolutePath()); + } +} diff --git a/test/jdk/jdk/jfr/javaagent/TestLoadedAgent.java b/test/jdk/jdk/jfr/javaagent/TestLoadedAgent.java new file mode 100644 index 00000000000..5cf428b3626 --- /dev/null +++ b/test/jdk/jdk/jfr/javaagent/TestLoadedAgent.java @@ -0,0 +1,58 @@ +/* + * 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 + * @key jfr + * @summary Tests emitting events in a dynamically loaded Java agent + * @requires vm.hasJFR + * + * @library /test/lib /test/jdk + * @modules java.instrument + * + * @build jdk.jfr.javaagent.EventEmitterAgent + * + * @run driver jdk.test.lib.util.JavaAgentBuilder + * jdk.jfr.javaagent.EventEmitterAgent EventEmitterAgent.jar + * + * @run main/othervm -Djdk.attach.allowAttachSelf=true jdk.jfr.javaagent.TestLoadedAgent + */ + +package jdk.jfr.javaagent; + +import com.sun.tools.attach.VirtualMachine; +import jdk.jfr.FlightRecorder; +import jdk.jfr.FlightRecorderListener; +import jdk.jfr.Recording; +import jdk.jfr.RecordingState; + + +public class TestLoadedAgent { + public static void main(String... arg) throws Exception { + long pid = ProcessHandle.current().pid(); + VirtualMachine vm = VirtualMachine.attach(Long.toString(pid)); + vm.loadAgent("EventEmitterAgent.jar"); + vm.detach(); + EventEmitterAgent.validateRecording(); + } +} diff --git a/test/jdk/jdk/jfr/javaagent/TestPremainAgent.java b/test/jdk/jdk/jfr/javaagent/TestPremainAgent.java new file mode 100644 index 00000000000..19a39ff7ef0 --- /dev/null +++ b/test/jdk/jdk/jfr/javaagent/TestPremainAgent.java @@ -0,0 +1,48 @@ +/* + * 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 + * @key jfr + * @summary Tests emitting event before main using a Java agent + * @requires vm.hasJFR + * + * @library /test/lib + * @modules java.instrument + * + * @build jdk.jfr.javaagent.EventEmitterAgent + * + * @run driver jdk.test.lib.util.JavaAgentBuilder + * jdk.jfr.javaagent.EventEmitterAgent EventEmitterAgent.jar + * + * @run main/othervm -javaagent:EventEmitterAgent.jar jdk.jfr.javaagent.TestPremainAgent + */ + +package jdk.jfr.javaagent; + + +public class TestPremainAgent { + public static void main(String... arg) throws Exception { + EventEmitterAgent.validateRecording(); + } +} From a0cc4bffe3c5ff4d36986f966e351161dc132057 Mon Sep 17 00:00:00 2001 From: clanger Date: Fri, 20 Sep 2019 12:11:18 +0200 Subject: [PATCH 053/131] 8231247: (zipfs) Test failure in jdk/nio/zipfs/InvalidZipHeaderTests.java after backport of JDK-8222807 Reviewed-by: goetz --- test/jdk/jdk/nio/zipfs/InvalidZipHeaderTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jdk/jdk/nio/zipfs/InvalidZipHeaderTests.java b/test/jdk/jdk/nio/zipfs/InvalidZipHeaderTests.java index d89494e3125..7d9419a05f0 100644 --- a/test/jdk/jdk/nio/zipfs/InvalidZipHeaderTests.java +++ b/test/jdk/jdk/nio/zipfs/InvalidZipHeaderTests.java @@ -80,7 +80,7 @@ public void tearDown() throws Exception { public void walkInvalidHeaderTest(String startPath, List expectedPaths) throws IOException { try (FileSystem zipfs = - FileSystems.newFileSystem(Path.of(INVALID_JAR_FILE))) { + FileSystems.newFileSystem(Path.of(INVALID_JAR_FILE), null)) { List result = walk(zipfs.getPath(startPath)) .map(f -> f.toString()).collect(Collectors.toList()); assertTrue(result.equals(expectedPaths), From 978b19bbd6e02322d508fcc3cf28156f1580a26c Mon Sep 17 00:00:00 2001 From: mbalao Date: Thu, 12 Sep 2019 13:30:40 -0300 Subject: [PATCH 054/131] 8230923: SunJSSE is not properly initialized in FIPS mode from a configuration file Reviewed-by: andrew --- .../sun/security/jca/ProviderConfig.java | 6 +- .../security/pkcs11/fips/SunJSSEFIPSInit.java | 131 ++++++++++++++++++ .../pkcs11/fips/SunJSSEFIPSInitClient.java | 42 ++++++ 3 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 test/jdk/sun/security/pkcs11/fips/SunJSSEFIPSInit.java create mode 100644 test/jdk/sun/security/pkcs11/fips/SunJSSEFIPSInitClient.java diff --git a/src/java.base/share/classes/sun/security/jca/ProviderConfig.java b/src/java.base/share/classes/sun/security/jca/ProviderConfig.java index ffa06f51fb5..a07d6fea8b8 100644 --- a/src/java.base/share/classes/sun/security/jca/ProviderConfig.java +++ b/src/java.base/share/classes/sun/security/jca/ProviderConfig.java @@ -179,7 +179,11 @@ synchronized Provider getProvider() { } else if (provName.equals("SunJCE") || provName.equals("com.sun.crypto.provider.SunJCE")) { p = new com.sun.crypto.provider.SunJCE(); } else if (provName.equals("SunJSSE") || provName.equals("com.sun.net.ssl.internal.ssl.Provider")) { - p = new com.sun.net.ssl.internal.ssl.Provider(); + if (hasArgument()) { + p = new com.sun.net.ssl.internal.ssl.Provider(argument); + } else { + p = new com.sun.net.ssl.internal.ssl.Provider(); + } } else if (provName.equals("Apple") || provName.equals("apple.security.AppleProvider")) { // need to use reflection since this class only exists on MacOsx p = AccessController.doPrivileged(new PrivilegedAction() { diff --git a/test/jdk/sun/security/pkcs11/fips/SunJSSEFIPSInit.java b/test/jdk/sun/security/pkcs11/fips/SunJSSEFIPSInit.java new file mode 100644 index 00000000000..eda705a0857 --- /dev/null +++ b/test/jdk/sun/security/pkcs11/fips/SunJSSEFIPSInit.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2019, Red Hat, Inc. + * + * 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 8230923 + * @requires (jdk.version.major == 11) & (os.family == "linux") & (os.arch == "amd64" | os.arch == "x86_64") + * @modules java.base/com.sun.net.ssl.internal.ssl + * @library /test/lib + * @run main/othervm/timeout=30 SunJSSEFIPSInit + * @author Martin Balao (mbalao@redhat.com) + */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.security.Security; +import java.util.ArrayList; +import java.util.List; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class SunJSSEFIPSInit { + private static String lineSep = System.lineSeparator(); + private static String javaBinPath = System.getProperty("java.home", ".") + + File.separator + "bin" + File.separator + "java"; + private static String nssConfigFileName = "nss.cfg"; + private static String javaSecConfigFileName = "java.security"; + private static Path tmpDirPath; + public static void main(String[] args) throws Throwable { + tmpDirPath = Files.createTempDirectory("tmpdir"); + try { + deployConfigFiles(); + List cmds = new ArrayList<>(); + cmds.add(javaBinPath); + cmds.add("-cp"); + cmds.add(System.getProperty("test.classes", ".")); + cmds.add("-Djava.security.properties=" + tmpDirPath + + File.separator + javaSecConfigFileName); + cmds.add(SunJSSEFIPSInitClient.class.getName()); + OutputAnalyzer out = ProcessTools.executeCommand( + cmds.toArray(new String[cmds.size()])); + out.stdoutShouldContain("SunJSSE.isFIPS(): true"); + System.out.println("TEST PASS - OK"); + } finally { + deleteDir(tmpDirPath); + } + } + + private static void deployConfigFiles() throws IOException { + deployJavaSecurityFile(); + deployNssConfigFile(); + } + + private static void deployJavaSecurityFile() throws IOException { + int numberOfProviders = Security.getProviders().length; + StringBuilder sb = new StringBuilder(); + sb.append("security.provider.1=SunPKCS11 " + tmpDirPath + + File.separator + nssConfigFileName + lineSep); + sb.append("security.provider.2=com.sun.net.ssl.internal.ssl.Provider" + + " SunPKCS11-NSS" + lineSep); + for (int i = 3; i <= numberOfProviders; i++) { + sb.append("security.provider." + i + "=\"\"" + lineSep); + } + writeFile(javaSecConfigFileName, sb.toString()); + } + + private static void deployNssConfigFile() throws IOException { + StringBuilder sb = new StringBuilder(); + sb.append("name = NSS" + lineSep); + sb.append("nssLibraryDirectory = /usr/lib64" + lineSep); + sb.append("nssDbMode = noDb" + lineSep); + sb.append("nssModule = crypto" + lineSep); + writeFile(nssConfigFileName, sb.toString()); + } + + private static void writeFile(String fileName, String fileContent) + throws IOException { + try (FileOutputStream fos = new FileOutputStream(new File(tmpDirPath + + File.separator + fileName))) { + fos.write(fileContent.getBytes()); + } + } + + private static void deleteDir(Path directory) throws IOException { + Files.walkFileTree(directory, new SimpleFileVisitor() { + + @Override + public FileVisitResult visitFile(Path file, + BasicFileAttributes attrs) throws IOException { + Files.delete(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) + throws IOException { + Files.delete(dir); + return FileVisitResult.CONTINUE; + } + }); + } +} + diff --git a/test/jdk/sun/security/pkcs11/fips/SunJSSEFIPSInitClient.java b/test/jdk/sun/security/pkcs11/fips/SunJSSEFIPSInitClient.java new file mode 100644 index 00000000000..4bb8efe8c01 --- /dev/null +++ b/test/jdk/sun/security/pkcs11/fips/SunJSSEFIPSInitClient.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019, Red Hat, Inc. + * + * 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. + */ + +import java.security.Provider; +import java.security.Security; + +public class SunJSSEFIPSInitClient { + public static void main(String[] args) throws Exception { + boolean isSunJSSEFIPS = false; + Provider[] provs = Security.getProviders(); + for (Provider p : provs) { + if (p.getName().equals("SunJSSE") && + p instanceof com.sun.net.ssl.internal.ssl.Provider) { + isSunJSSEFIPS = ((com.sun.net.ssl.internal.ssl.Provider)p).isFIPS(); + break; + } + } + System.out.println("SunJSSE.isFIPS(): " + isSunJSSEFIPS); + } +} + From 1ca0267760fcbfb21a1d7eff9e9e6a3100533806 Mon Sep 17 00:00:00 2001 From: egahlin Date: Sun, 9 Jun 2019 11:28:13 +0200 Subject: [PATCH 055/131] 8216064: -XX:StartFlightRecording:settings= doesn't work properly Reviewed-by: mgronlun --- .../jdk/jfr/internal/dcmd/DCmdStart.java | 9 ++- .../classes/jdk/jfr/internal/jfc/JFC.java | 6 +- .../jfr/startupargs/TestStartNoSettings.java | 69 +++++++++++++++++++ 3 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 test/jdk/jdk/jfr/startupargs/TestStartNoSettings.java diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java index 0be1165b8af..7618e403026 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java @@ -24,6 +24,7 @@ */ package jdk.jfr.internal.dcmd; +import java.io.FileNotFoundException; import java.io.IOException; import java.nio.file.Files; import java.nio.file.InvalidPathException; @@ -105,13 +106,17 @@ public String execute(String name, String[] settings, Long delay, Long duration, if (duration == null && Boolean.FALSE.equals(dumpOnExit) && path != null) { throw new DCmdException("Filename can only be set for a time bound recording or if dumponexit=true. Set duration/dumponexit or omit filename."); } - + if (settings.length == 1 && settings[0].length() == 0) { + throw new DCmdException("No settings specified. Use settings=none to start without any settings"); + } Map s = new HashMap<>(); for (String configName : settings) { try { s.putAll(JFC.createKnown(configName).getSettings()); + } catch(FileNotFoundException e) { + throw new DCmdException("Could not find settings file'" + configName + "'", e); } catch (IOException | ParseException e) { - throw new DCmdException("Could not parse setting " + settings[0], e); + throw new DCmdException("Could not parse settings file '" + settings[0] + "'", e); } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/JFC.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/JFC.java index 3ca5465734b..83cb63097cb 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/JFC.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/JFC.java @@ -127,7 +127,11 @@ private static String nullSafeFileName(Path file) throws IOException { public static String nameFromPath(Path file) throws IOException { String f = nullSafeFileName(file); - return f.substring(0, f.length() - JFCParser.FILE_EXTENSION.length()); + if (f.endsWith(JFCParser.FILE_EXTENSION)) { + return f.substring(0, f.length() - JFCParser.FILE_EXTENSION.length()); + } else { + return f; + } } // Invoked by DCmdStart diff --git a/test/jdk/jdk/jfr/startupargs/TestStartNoSettings.java b/test/jdk/jdk/jfr/startupargs/TestStartNoSettings.java new file mode 100644 index 00000000000..0a65d5eed75 --- /dev/null +++ b/test/jdk/jdk/jfr/startupargs/TestStartNoSettings.java @@ -0,0 +1,69 @@ +/* + * 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. 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. + */ + +package jdk.jfr.startupargs; + +import jdk.jfr.Event; +import jdk.jfr.EventType; +import jdk.jfr.FlightRecorder; +import jdk.jfr.Name; +import jdk.jfr.Recording; + +/** + * @test + * @summary Start a FlightRecording without any settings (not even default). + * @key jfr + * @requires vm.hasJFR + * @library /test/lib + * @run main/othervm jdk.jfr.startupargs.TestStartNoSettings + * -XX:StartFlightRecording=settings=none + */ +public class TestStartNoSettings { + + @Name("UserEvent") + static class UserEvent extends Event { + } + + public static void main(String[] a) throws Exception { + boolean userEnabled = false; + try (Recording r = new Recording()) { + r.start(); + UserEvent e = new UserEvent(); + e.commit(); + for (EventType et : FlightRecorder.getFlightRecorder().getEventTypes()) { + if (et.isEnabled()) { + if (!et.getName().equals("UserEvent")) { + throw new Exception("Only 'UserEvent' should be enabled"); + } + userEnabled = true; + } + } + } + + if (!userEnabled) { + throw new Exception("Expected 'UserEvent' to be enabled with -XX:StartFlightRecording=settings=none"); + } + } +} From 7c1cbc1fbbe5d530cde88951e691149c1ffeb15c Mon Sep 17 00:00:00 2001 From: azeller Date: Tue, 24 Sep 2019 14:46:38 +0200 Subject: [PATCH 056/131] 8230110: TestLinkageErrorInGenerateOopMap times out Reviewed-by: stuefe, clanger, thartmann --- .../compiler/linkage/TestLinkageErrorInGenerateOopMap.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/hotspot/jtreg/compiler/linkage/TestLinkageErrorInGenerateOopMap.java b/test/hotspot/jtreg/compiler/linkage/TestLinkageErrorInGenerateOopMap.java index 52b523b612a..0a352517427 100644 --- a/test/hotspot/jtreg/compiler/linkage/TestLinkageErrorInGenerateOopMap.java +++ b/test/hotspot/jtreg/compiler/linkage/TestLinkageErrorInGenerateOopMap.java @@ -44,6 +44,8 @@ public static void main(String args[]) throws Exception { // Spawn new VM instance to execute test String[] flags = {"-noverify", "-XX:-TieredCompilation", "-XX:CompileCommand=dontinline,compiler/linkage/OSRWithBadOperandStack.m*", + "-XX:-CreateCoredumpOnCrash", + "-Xmx64m", "compiler.linkage.TestLinkageErrorInGenerateOopMap", "run"}; ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(flags); OutputAnalyzer out = new OutputAnalyzer(pb.start()); From 18fed25af4a1eb44c4c3a04dd5cf624f8c34bcc7 Mon Sep 17 00:00:00 2001 From: jiefu Date: Tue, 17 Sep 2019 20:38:23 +0800 Subject: [PATCH 057/131] 8230943: False deadlock detection with -XX:+CIPrintCompileQueue after JDK-8163511 Reviewed-by: dholmes, thartmann --- .../compiler/print/PrintCompileQueue.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/print/PrintCompileQueue.java diff --git a/test/hotspot/jtreg/compiler/print/PrintCompileQueue.java b/test/hotspot/jtreg/compiler/print/PrintCompileQueue.java new file mode 100644 index 00000000000..ee368b54bea --- /dev/null +++ b/test/hotspot/jtreg/compiler/print/PrintCompileQueue.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019, Loongson Technology Co. Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8230943 + * @summary possible deadlock was detected when ran with -XX:+CIPrintCompileQueue + * @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+CIPrintCompileQueue + * compiler.print.PrintCompileQueue + * + */ + +package compiler.print; + +public class PrintCompileQueue { + public static void main(String[] args) { + System.out.println("Passed"); + } +} From 33c980c7d8192cb0808f93719981ff25a14af814 Mon Sep 17 00:00:00 2001 From: mbaesken Date: Fri, 13 Sep 2019 11:04:46 +0200 Subject: [PATCH 058/131] 8230901: missing ReleaseStringUTFChars in serviceability native code Reviewed-by: stuefe, sspitsyn --- src/java.instrument/share/native/libinstrument/JPLISAgent.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/java.instrument/share/native/libinstrument/JPLISAgent.c b/src/java.instrument/share/native/libinstrument/JPLISAgent.c index 3ca1d32cf0b..da73cca25d1 100644 --- a/src/java.instrument/share/native/libinstrument/JPLISAgent.c +++ b/src/java.instrument/share/native/libinstrument/JPLISAgent.c @@ -1486,6 +1486,7 @@ appendToClassLoaderSearch(JNIEnv * jnienv, JPLISAgent * agent, jstring jarFile, platformLen = convertUft8ToPlatformString((char*)utf8Chars, utf8Len, platformChars, MAXPATHLEN); if (platformLen < 0) { createAndThrowInternalError(jnienv); + (*jnienv)->ReleaseStringUTFChars(jnienv, jarFile, utf8Chars); return; } From 1dd390131a636d36d871bfec6778dce5a55a6911 Mon Sep 17 00:00:00 2001 From: mbaesken Date: Fri, 13 Sep 2019 07:43:59 +0200 Subject: [PATCH 059/131] 8230900: missing ReleaseStringUTFChars in java.desktop native code Reviewed-by: clanger, prr --- .../unix/native/common/awt/fontpath.c | 31 ++++++++++++++----- .../native/libawt/windows/ShellFolder2.cpp | 5 ++- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/java.desktop/unix/native/common/awt/fontpath.c b/src/java.desktop/unix/native/common/awt/fontpath.c index 66ac6dff304..ab287555964 100644 --- a/src/java.desktop/unix/native/common/awt/fontpath.c +++ b/src/java.desktop/unix/native/common/awt/fontpath.c @@ -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 @@ -887,9 +887,9 @@ Java_sun_font_FontConfigManager_getFontConfigAASettings locale = (*env)->GetStringUTFChars(env, localeStr, 0); if ((libfontconfig = openFontConfig()) == NULL) { - (*env)->ReleaseStringUTFChars (env, fcNameStr, (const char*)fcName); + (*env)->ReleaseStringUTFChars(env, fcNameStr, (const char*)fcName); if (locale) { - (*env)->ReleaseStringUTFChars (env, localeStr,(const char*)locale); + (*env)->ReleaseStringUTFChars(env, localeStr,(const char*)locale); } return -1; } @@ -918,9 +918,9 @@ Java_sun_font_FontConfigManager_getFontConfigAASettings FcPatternGetInteger == NULL || FcPatternDestroy == NULL) { /* problem with the library: return. */ - (*env)->ReleaseStringUTFChars (env, fcNameStr, (const char*)fcName); + (*env)->ReleaseStringUTFChars(env, fcNameStr, (const char*)fcName); if (locale) { - (*env)->ReleaseStringUTFChars (env, localeStr,(const char*)locale); + (*env)->ReleaseStringUTFChars(env, localeStr,(const char*)locale); } closeFontConfig(libfontconfig, JNI_FALSE); return -1; @@ -945,9 +945,9 @@ Java_sun_font_FontConfigManager_getFontConfigAASettings } (*FcPatternDestroy)(pattern); - (*env)->ReleaseStringUTFChars (env, fcNameStr, (const char*)fcName); + (*env)->ReleaseStringUTFChars(env, fcNameStr, (const char*)fcName); if (locale) { - (*env)->ReleaseStringUTFChars (env, localeStr, (const char*)locale); + (*env)->ReleaseStringUTFChars(env, localeStr, (const char*)locale); } closeFontConfig(libfontconfig, JNI_TRUE); @@ -1179,6 +1179,9 @@ Java_sun_font_FontConfigManager_getFontConfig (*env)->DeleteLocalRef(env, fcNameStr); if (pattern == NULL) { closeFontConfig(libfontconfig, JNI_FALSE); + if (locale) { + (*env)->ReleaseStringUTFChars(env, localeStr, (const char*)locale); + } return; } @@ -1196,6 +1199,9 @@ Java_sun_font_FontConfigManager_getFontConfig if (fontset == NULL) { (*FcPatternDestroy)(pattern); closeFontConfig(libfontconfig, JNI_FALSE); + if (locale) { + (*env)->ReleaseStringUTFChars(env, localeStr, (const char*)locale); + } return; } @@ -1227,6 +1233,9 @@ Java_sun_font_FontConfigManager_getFontConfig (*FcPatternDestroy)(pattern); (*FcFontSetDestroy)(fontset); closeFontConfig(libfontconfig, JNI_FALSE); + if (locale) { + (*env)->ReleaseStringUTFChars(env, localeStr, (const char*)locale); + } return; } fontCount = 0; @@ -1269,6 +1278,9 @@ Java_sun_font_FontConfigManager_getFontConfig (*FcPatternDestroy)(pattern); (*FcFontSetDestroy)(fontset); closeFontConfig(libfontconfig, JNI_FALSE); + if (locale) { + (*env)->ReleaseStringUTFChars(env, localeStr, (const char*)locale); + } return; } @@ -1323,6 +1335,9 @@ Java_sun_font_FontConfigManager_getFontConfig (*FcPatternDestroy)(pattern); (*FcFontSetDestroy)(fontset); closeFontConfig(libfontconfig, JNI_FALSE); + if (locale) { + (*env)->ReleaseStringUTFChars(env, localeStr, (const char*)locale); + } return; } (*env)->SetObjectField(env,fcCompFontObj, fcAllFontsID, fcFontArr); @@ -1384,7 +1399,7 @@ Java_sun_font_FontConfigManager_getFontConfig /* release resources and close the ".so" */ if (locale) { - (*env)->ReleaseStringUTFChars (env, localeStr, (const char*)locale); + (*env)->ReleaseStringUTFChars(env, localeStr, (const char*)locale); } closeFontConfig(libfontconfig, JNI_TRUE); } diff --git a/src/java.desktop/windows/native/libawt/windows/ShellFolder2.cpp b/src/java.desktop/windows/native/libawt/windows/ShellFolder2.cpp index 6315fdf56cb..6e6d5bd0210 100644 --- a/src/java.desktop/windows/native/libawt/windows/ShellFolder2.cpp +++ b/src/java.desktop/windows/native/libawt/windows/ShellFolder2.cpp @@ -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 @@ -1130,6 +1130,9 @@ JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconResource const char *pLibName = env->GetStringUTFChars(libName, NULL); JNU_CHECK_EXCEPTION_RETURN(env, 0); HINSTANCE libHandle = (HINSTANCE)JDK_LoadSystemLibrary(pLibName); + if (pLibName != NULL) { + env->ReleaseStringUTFChars(libName, pLibName); + } if (libHandle != NULL) { UINT fuLoad = (useVGAColors && !IS_WINXP) ? LR_VGACOLOR : 0; return ptr_to_jlong(LoadImage(libHandle, MAKEINTRESOURCE(iconID), From a0ed36b17a148eb5e86e1084e908659f58a4afab Mon Sep 17 00:00:00 2001 From: mbaesken Date: Wed, 11 Sep 2019 16:13:05 +0200 Subject: [PATCH 060/131] 8230856: Java_java_net_NetworkInterface_getByName0 on unix misses ReleaseStringUTFChars in early return Reviewed-by: dfuchs, stuefe, vtewari --- src/java.base/unix/native/libnet/NetworkInterface.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/java.base/unix/native/libnet/NetworkInterface.c b/src/java.base/unix/native/libnet/NetworkInterface.c index ed93bd1ff11..cfa3864ba73 100644 --- a/src/java.base/unix/native/libnet/NetworkInterface.c +++ b/src/java.base/unix/native/libnet/NetworkInterface.c @@ -238,6 +238,7 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0 ifs = enumInterfaces(env); if (ifs == NULL) { + (*env)->ReleaseStringUTFChars(env, name, name_utf); return NULL; } From 01eed8078704ce2010f6d399a2123121128714e0 Mon Sep 17 00:00:00 2001 From: mbaesken Date: Wed, 11 Sep 2019 16:54:53 +0200 Subject: [PATCH 061/131] 8230861: missing ReleaseStringUTFChars in Java_sun_security_pkcs11_wrapper_PKCS11_connect Reviewed-by: alanb, stuefe --- src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.c b/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.c index fe05a1d23cc..cfcd1394dfc 100644 --- a/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.c +++ b/src/jdk.crypto.cryptoki/unix/native/libj2pkcs11/p11_md.c @@ -109,6 +109,7 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect exceptionMessage = (char *) malloc(sizeof(char) * (strlen(systemErrorMessage) + strlen(libraryNameStr) + 1)); if (exceptionMessage == NULL) { throwOutOfMemoryError(env, 0); + (*env)->ReleaseStringUTFChars(env, jPkcs11ModulePath, libraryNameStr); return; } strcpy(exceptionMessage, systemErrorMessage); From e9c25eabace16ab549c50b13d087ab7f3fe24783 Mon Sep 17 00:00:00 2001 From: shurailine Date: Mon, 6 Aug 2018 15:35:44 -0700 Subject: [PATCH 062/131] 8208364: java/lang/reflect/callerCache/ReflectionCallerCacheTest.java missing module dependencies declaration Reviewed-by: mchung --- .../lang/reflect/callerCache/ReflectionCallerCacheTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/jdk/java/lang/reflect/callerCache/ReflectionCallerCacheTest.java b/test/jdk/java/lang/reflect/callerCache/ReflectionCallerCacheTest.java index c69637f0493..a6e9da08806 100644 --- a/test/jdk/java/lang/reflect/callerCache/ReflectionCallerCacheTest.java +++ b/test/jdk/java/lang/reflect/callerCache/ReflectionCallerCacheTest.java @@ -25,8 +25,9 @@ * @test * @bug 8202113 * @summary Test the caller class loader is not kept strongly reachable - * by reflection API + * by reflection API * @library /test/lib/ + * @modules jdk.compiler * @build ReflectionCallerCacheTest Members jdk.test.lib.compiler.CompilerUtils * @run testng/othervm ReflectionCallerCacheTest */ From f94c155e84912eede1b7331674cedf316188378d Mon Sep 17 00:00:00 2001 From: vromero Date: Thu, 4 Oct 2018 10:19:01 -0700 Subject: [PATCH 063/131] 8210789: langtools/tools/javac/T8152616.java missing @modules Reviewed-by: jjg --- test/langtools/tools/javac/T8152616.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/langtools/tools/javac/T8152616.java b/test/langtools/tools/javac/T8152616.java index 9b49f283152..e2c6d38eaf6 100644 --- a/test/langtools/tools/javac/T8152616.java +++ b/test/langtools/tools/javac/T8152616.java @@ -25,8 +25,8 @@ * @test * @bug 8152616 * @summary Unit test for corner case of PrettyPrinting when SourceOutput is false - * @run compile --add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED T8152616.java - * @run main T8152616 + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.tree */ import java.io.File; From cb63cbc054393e3b16048b74cbf8494f614c45ff Mon Sep 17 00:00:00 2001 From: mseledtsov Date: Fri, 2 Aug 2019 13:51:34 -0700 Subject: [PATCH 064/131] 8228687: [TESTBUG] exclude Container tests from hotspot_misc group Summary: Excluded hotspot_containers from hotspot_misc Reviewed-by: dcubed, adinn --- test/hotspot/jtreg/TEST.groups | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index 72953ed2928..4748333ce0e 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -59,7 +59,8 @@ hotspot_misc = \ -:hotspot_compiler \ -:hotspot_gc \ -:hotspot_runtime \ - -:hotspot_serviceability + -:hotspot_serviceability \ + -:hotspot_containers hotspot_native_sanity = \ native_sanity From a260cfd4f392383270708fef1f02f6dfbb3b191d Mon Sep 17 00:00:00 2001 From: alanb Date: Tue, 18 Dec 2018 10:26:15 +0000 Subject: [PATCH 065/131] 8215449: Several tests failing when jtreg run with -vmoption:--illegal-access=deny Reviewed-by: redestad, mchung, jjg, adinn, clanger --- .../lang/reflect/callerCache/ReflectionCallerCacheTest.java | 1 + test/jdk/java/net/URL/RacyHandler.java | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/test/jdk/java/lang/reflect/callerCache/ReflectionCallerCacheTest.java b/test/jdk/java/lang/reflect/callerCache/ReflectionCallerCacheTest.java index a6e9da08806..5ccffa2020d 100644 --- a/test/jdk/java/lang/reflect/callerCache/ReflectionCallerCacheTest.java +++ b/test/jdk/java/lang/reflect/callerCache/ReflectionCallerCacheTest.java @@ -28,6 +28,7 @@ * by reflection API * @library /test/lib/ * @modules jdk.compiler + * java.base/java.lang.reflect:+open * @build ReflectionCallerCacheTest Members jdk.test.lib.compiler.CompilerUtils * @run testng/othervm ReflectionCallerCacheTest */ diff --git a/test/jdk/java/net/URL/RacyHandler.java b/test/jdk/java/net/URL/RacyHandler.java index 1255465d68b..6067e1e8bf8 100644 --- a/test/jdk/java/net/URL/RacyHandler.java +++ b/test/jdk/java/net/URL/RacyHandler.java @@ -32,6 +32,7 @@ * @test * @bug 8213942 * @summary URLStreamHandler initialization race + * @modules java.base/java.net:open * @run main/othervm RacyHandler * @run main/othervm RacyHandler * @run main/othervm RacyHandler @@ -110,4 +111,4 @@ protected URLConnection openConnection(URL u) throws IOException { return null; } } -} \ No newline at end of file +} From 33b05d41ef55c5c8e0d4735bbe61647197a59c7c Mon Sep 17 00:00:00 2001 From: mgronlun Date: Mon, 25 Mar 2019 15:37:06 +0100 Subject: [PATCH 066/131] 8217362: Emergency dump does not work when disk=false is set Reviewed-by: egahlin, ysuenaga Contributed-by: yasuenag@gmail.com --- test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java b/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java index 79c27b29a3d..77667547f35 100644 --- a/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java +++ b/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java @@ -77,23 +77,26 @@ public static void main(String[] args) throws Exception { } 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:-TransmitErrorReport", "-XX:-CreateCoredumpOnCrash", "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", - "-XX:StartFlightRecording", + "-XX:StartFlightRecording=" + flightRecordingOptions, crasher, signal) .start(); From 084ce903240947fc1f98d8dc428420eac6283e19 Mon Sep 17 00:00:00 2001 From: lbourges Date: Mon, 30 Sep 2019 15:30:12 +0200 Subject: [PATCH 067/131] 8230728: Thin stroked shapes are not rendered if affine transform has flip bit Summary: use abs(at.getDeterminant()) in userSpaceLineWidth() to ensure positive value Reviewed-by: prr, jdv --- .../java2d/marlin/DMarlinRenderingEngine.java | 3 +- .../java2d/marlin/MarlinRenderingEngine.java | 3 +- .../classes/sun/java2d/marlin/Version.java | 2 +- test/jdk/sun/java2d/marlin/FlipBitTest.java | 104 ++++++++++++++++++ 4 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 test/jdk/sun/java2d/marlin/FlipBitTest.java diff --git a/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java b/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java index f3d44e3ba92..66858dfdd5a 100644 --- a/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java +++ b/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java @@ -246,7 +246,8 @@ private double userSpaceLineWidth(AffineTransform at, double lw) { widthScale = 1.0d; } else if ((at.getType() & (AffineTransform.TYPE_GENERAL_TRANSFORM | AffineTransform.TYPE_GENERAL_SCALE)) != 0) { - widthScale = Math.sqrt(at.getDeterminant()); + // Determinant may be negative (flip), use its absolute value: + widthScale = Math.sqrt(Math.abs(at.getDeterminant())); } else { // First calculate the "maximum scale" of this transform. double A = at.getScaleX(); // m00 diff --git a/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java b/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java index a3baed14378..3bba4c194b2 100644 --- a/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java +++ b/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java @@ -245,7 +245,8 @@ private float userSpaceLineWidth(AffineTransform at, float lw) { widthScale = 1.0f; } else if ((at.getType() & (AffineTransform.TYPE_GENERAL_TRANSFORM | AffineTransform.TYPE_GENERAL_SCALE)) != 0) { - widthScale = (float)Math.sqrt(at.getDeterminant()); + // Determinant may be negative (flip), use its absolute value: + widthScale = (float)Math.sqrt(Math.abs(at.getDeterminant())); } else { // First calculate the "maximum scale" of this transform. double A = at.getScaleX(); // m00 diff --git a/src/java.desktop/share/classes/sun/java2d/marlin/Version.java b/src/java.desktop/share/classes/sun/java2d/marlin/Version.java index e7e94ffe397..0155b049fab 100644 --- a/src/java.desktop/share/classes/sun/java2d/marlin/Version.java +++ b/src/java.desktop/share/classes/sun/java2d/marlin/Version.java @@ -27,7 +27,7 @@ public final class Version { - private static final String VERSION = "marlin-0.9.1.2-Unsafe-OpenJDK"; + private static final String VERSION = "marlin-0.9.1.3-Unsafe-OpenJDK"; public static String getVersion() { return VERSION; diff --git a/test/jdk/sun/java2d/marlin/FlipBitTest.java b/test/jdk/sun/java2d/marlin/FlipBitTest.java new file mode 100644 index 00000000000..d966f701f6f --- /dev/null +++ b/test/jdk/sun/java2d/marlin/FlipBitTest.java @@ -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. + */ + + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import javax.imageio.ImageIO; + + +/** + * Tests calculating user space line with a negative determinant (flip). + * + * @test + * @summary verify that flipped transformed lines are properly rasterized + * @bug 8230728 + */ +public class FlipBitTest { + + static final boolean SAVE_IMAGE = false; + + public static void main(final String[] args) { + + final int size = 100; + + // First display which renderer is tested: + // JDK9 only: + System.setProperty("sun.java2d.renderer.verbose", "true"); + + System.out.println("FlipBitTest: size = " + size); + + final BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); + + final Graphics2D g2d = (Graphics2D) image.getGraphics(); + try { + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); + + final AffineTransform at = new AffineTransform(); + at.setToScale(1, -1.01); + g2d.setTransform(at); + + g2d.translate(0, -image.getHeight()); + g2d.setPaint(Color.WHITE); + g2d.fill(new Rectangle(image.getWidth(), image.getHeight())); + + g2d.setPaint(Color.BLACK); + g2d.setStroke(new BasicStroke(0.1f)); + g2d.draw(new Ellipse2D.Double(25, 25, 50, 50)); + + if (SAVE_IMAGE) { + try { + final File file = new File("FlipBitTest.png"); + + System.out.println("Writing file: " + file.getAbsolutePath()); + ImageIO.write(image, "PNG", file); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + + boolean nonWhitePixelFound = false; + for (int x = 0; x < image.getWidth(); ++x) { + if (image.getRGB(x, 50) != Color.WHITE.getRGB()) { + nonWhitePixelFound = true; + break; + } + } + if (!nonWhitePixelFound) { + throw new IllegalStateException("The ellipse was not drawn"); + } + } finally { + g2d.dispose(); + } + } +} From 9c5bc88bf8a3486756cf6a151da33d0587cc6783 Mon Sep 17 00:00:00 2001 From: simonis Date: Wed, 27 Mar 2019 19:47:47 +0100 Subject: [PATCH 068/131] 8220528: [AIX] Fix basic Xinerama and Xrender functionality Reviewed-by: clanger, stuefe, serb --- .../native/libawt_xawt/awt/awt_GraphicsEnv.c | 75 ++++++++++++------- 1 file changed, 49 insertions(+), 26 deletions(-) diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c index ecd592e2848..b3fea02b2a1 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c @@ -123,7 +123,15 @@ static char *x11GraphicsConfigClassName = "sun/awt/X11GraphicsConfig"; */ #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); +typedef Status XineramaGetCenterHintFunc(Display* display, int screen_number, + int* x, int* y); + +XineramaGetCenterHintFunc* XineramaSolarisCenterFunc = NULL; +#else /* Linux, Mac, AIX */ typedef struct { int screen_number; short x_org; @@ -133,15 +141,6 @@ typedef struct { } 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); -typedef Status XineramaGetCenterHintFunc(Display* display, int screen_number, - int* x, int* y); - -XineramaGetCenterHintFunc* XineramaSolarisCenterFunc = NULL; #endif Bool usingXinerama = False; @@ -442,6 +441,7 @@ getAllConfigs (JNIEnv *env, int screen, AwtScreenDataPtr screenDataPtr) { 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 @@ -455,18 +455,30 @@ getAllConfigs (JNIEnv *env, int screen, AwtScreenDataPtr screenDataPtr) { 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++) { @@ -482,18 +494,23 @@ getAllConfigs (JNIEnv *env, int screen, AwtScreenDataPtr screenDataPtr) { 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) { @@ -599,7 +616,7 @@ getAllConfigs (JNIEnv *env, int screen, AwtScreenDataPtr screenDataPtr) { } #ifndef HEADLESS -#if defined(__linux__) || defined(MACOSX) +#if defined(__linux__) || defined(MACOSX) || defined(_AIX) static void xinerama_init_linux() { void* libHandle = NULL; @@ -612,14 +629,18 @@ static void xinerama_init_linux() 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; @@ -639,7 +660,10 @@ static void xinerama_init_linux() 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"); @@ -649,8 +673,7 @@ static void xinerama_init_linux() 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; @@ -710,11 +733,11 @@ static void xineramaInit(void) { } DTRACE_PRINTLN("Xinerama extension is available"); -#if defined(__linux__) || defined(MACOSX) - xinerama_init_linux(); -#else /* Solaris */ +#if defined(__solaris__) xinerama_init_solaris(); -#endif /* __linux__ || MACOSX */ +#else /* Linux, Mac, AIX */ + xinerama_init_linux(); +#endif } #endif /* HEADLESS */ @@ -1615,7 +1638,7 @@ Java_sun_awt_X11GraphicsEnvironment_getXineramaCenterPoint(JNIEnv *env, { jobject point = NULL; #ifndef HEADLESS /* return NULL in HEADLESS, Linux */ -#if !defined(__linux__) && !defined(MACOSX) +#if defined(__solaris__) int x,y; AWT_LOCK(); @@ -1628,7 +1651,7 @@ Java_sun_awt_X11GraphicsEnvironment_getXineramaCenterPoint(JNIEnv *env, DTRACE_PRINTLN("unable to call XineramaSolarisCenterFunc: symbol is null"); } AWT_FLUSH_UNLOCK(); -#endif /* __linux __ || MACOSX */ +#endif /* __solaris__ */ #endif /* HEADLESS */ return point; } From cfbd9d4886c2ff1de1c3735cdec5fd991b673821 Mon Sep 17 00:00:00 2001 From: bobv Date: Mon, 24 Jun 2019 11:49:59 -0400 Subject: [PATCH 069/131] 8224502: [TESTBUG] JDK docker test TestSystemMetrics.java fails with access issues and OOM Reviewed-by: sgehwolf, mseledtsov --- test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java | 3 ++- test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java b/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java index c0e7884171f..46df8826648 100644 --- a/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java +++ b/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java @@ -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,6 +51,7 @@ public static void main(String[] args) throws Exception { DockerRunOptions opts = new DockerRunOptions(imageName, "/jdk/bin/java", "jdk.test.lib.containers.cgroup.MetricsTester"); opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/"); + opts.addDockerOpts("--memory=256m"); opts.addJavaOpts("-cp", "/test-classes/"); opts.addJavaOpts("--add-exports", "java.base/jdk.internal.platform=ALL-UNNAMED"); DockerTestUtils.dockerRunJava(opts).shouldHaveExitValue(0).shouldContain("TEST PASSED!!!"); diff --git a/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java b/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java index cbd3e83a0af..13f4693f8e5 100644 --- a/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java +++ b/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java @@ -579,7 +579,7 @@ public void testMemoryUsage() throws Exception { long memoryMaxUsage = metrics.getMemoryMaxUsage(); long memoryUsage = metrics.getMemoryUsage(); - long[] ll = new long[64*1024*1024]; // 64M + byte[] bb = new byte[64*1024*1024]; // 64M long newMemoryMaxUsage = metrics.getMemoryMaxUsage(); long newMemoryUsage = metrics.getMemoryUsage(); From d0db37349d4828342ed901544fe8fec664dedf75 Mon Sep 17 00:00:00 2001 From: sgehwolf Date: Fri, 12 Jul 2019 19:37:25 +0200 Subject: [PATCH 070/131] 8227642: [TESTBUG] Make docker tests podman compatible Reviewed-by: mseledtsov, iignatyev --- test/jtreg-ext/requires/VMProps.java | 2 +- test/lib/jdk/test/lib/Platform.java | 6 ++++++ .../lib/containers/cgroup/MetricsTester.java | 10 +++++++--- .../lib/containers/docker/DockerTestUtils.java | 17 ++++++----------- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java index bd1f85f1efd..db83704f3a6 100644 --- a/test/jtreg-ext/requires/VMProps.java +++ b/test/jtreg-ext/requires/VMProps.java @@ -449,7 +449,7 @@ else if (arch.equals("ppc64le")) { } private boolean checkDockerSupport() throws IOException, InterruptedException { - ProcessBuilder pb = new ProcessBuilder("docker", "ps"); + ProcessBuilder pb = new ProcessBuilder(Platform.DOCKER_COMMAND, "ps"); Process p = pb.start(); p.waitFor(10, TimeUnit.SECONDS); diff --git a/test/lib/jdk/test/lib/Platform.java b/test/lib/jdk/test/lib/Platform.java index 36ba37d420c..bf69e7414bd 100644 --- a/test/lib/jdk/test/lib/Platform.java +++ b/test/lib/jdk/test/lib/Platform.java @@ -33,6 +33,12 @@ import java.util.stream.Collectors; public class Platform { + // Use this property to specify docker location on your system. + // E.g.: "/usr/local/bin/docker". We define this constant here so + // that it can be used in VMProps as well which checks docker support + // via this command + public static final String DOCKER_COMMAND = + System.getProperty("jdk.test.docker.command", "docker"); public static final String vmName = System.getProperty("java.vm.name"); public static final String vmInfo = System.getProperty("java.vm.info"); private static final String osVersion = System.getProperty("os.version"); diff --git a/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java b/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java index 13f4693f8e5..115dcf9f1cf 100644 --- a/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java +++ b/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java @@ -550,16 +550,20 @@ public void testCpuConsumption() throws IOException, InterruptedException { long newUsage = metrics.getCpuUsage(); long[] newPerCpu = metrics.getPerCpuUsage(); - if (newSysVal <= startSysVal) { + // system/user CPU usage counters may be slowly increasing. + // allow for equal values for a pass + if (newSysVal < startSysVal) { fail(SubSystem.CPU, "getCpuSystemUsage", newSysVal, startSysVal); } - if (newUserVal <= startUserVal) { + // system/user CPU usage counters may be slowly increasing. + // allow for equal values for a pass + if (newUserVal < startUserVal) { fail(SubSystem.CPU, "getCpuUserUsage", newUserVal, startUserVal); } if (newUsage <= startUsage) { - fail(SubSystem.CPU, "getCpuUserUsage", newUsage, startUsage); + fail(SubSystem.CPU, "getCpuUsage", newUsage, startUsage); } boolean success = false; diff --git a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java index bb040826aa3..416b09cf317 100644 --- a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java +++ b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java @@ -37,6 +37,7 @@ 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 jtreg.SkippedException; @@ -52,11 +53,6 @@ public class DockerTestUtils { // diagnostic information. private static final int MAX_LINES_TO_COPY_FOR_CHILD_STDOUT = 100; - // Use this property to specify docker location on your system. - // E.g.: "/usr/local/bin/docker". - private static final String DOCKER_COMMAND = - System.getProperty("jdk.test.docker.command", "docker"); - // Set this property to true to retain image after test. By default // images are removed after test execution completes. // Retaining the image can be useful for diagnostics and image inspection. @@ -114,7 +110,7 @@ public static boolean canTestDocker() throws Exception { */ private static boolean isDockerEngineAvailableCheck() throws Exception { try { - execute(DOCKER_COMMAND, "ps") + execute(Platform.DOCKER_COMMAND, "ps") .shouldHaveExitValue(0) .shouldContain("CONTAINER") .shouldContain("IMAGE"); @@ -177,9 +173,8 @@ private static boolean isDockerEngineAvailableCheck() throws Exception { DockerfileConfig.getBaseImageVersion()); try { // Build the docker - execute(DOCKER_COMMAND, "build", "--no-cache", "--tag", imageName, buildDir.toString()) - .shouldHaveExitValue(0) - .shouldContain("Successfully built"); + execute(Platform.DOCKER_COMMAND, "build", "--no-cache", "--tag", imageName, buildDir.toString()) + .shouldHaveExitValue(0); } catch (Exception e) { // If docker image building fails there is a good chance it happens due to environment and/or // configuration other than product failure. Throw jtreg skipped exception in such case @@ -200,7 +195,7 @@ private static boolean isDockerEngineAvailableCheck() throws Exception { public static List buildJavaCommand(DockerRunOptions opts) throws Exception { List cmd = new ArrayList<>(); - cmd.add(DOCKER_COMMAND); + cmd.add(Platform.DOCKER_COMMAND); cmd.add("run"); if (opts.tty) cmd.add("--tty=true"); @@ -243,7 +238,7 @@ public static OutputAnalyzer dockerRunJava(DockerRunOptions opts) throws Excepti * @throws Exception */ public static void removeDockerImage(String imageNameAndTag) throws Exception { - execute(DOCKER_COMMAND, "rmi", "--force", imageNameAndTag); + execute(Platform.DOCKER_COMMAND, "rmi", "--force", imageNameAndTag); } From c9c0c937a6be70fbef77cbbc3f11805e70cfa94d Mon Sep 17 00:00:00 2001 From: sgehwolf Date: Mon, 22 Jul 2019 10:48:14 +0200 Subject: [PATCH 071/131] 8228434: jdk/net/Sockets/Test.java fails after JDK-8227642 Summary: Move container constant to separate test lib class Reviewed-by: alanb --- test/hotspot/jtreg/TEST.ROOT | 4 ++- test/jdk/TEST.ROOT | 4 ++- test/jtreg-ext/requires/VMProps.java | 3 +- test/lib/jdk/test/lib/Container.java | 32 +++++++++++++++++++ test/lib/jdk/test/lib/Platform.java | 6 ---- .../containers/docker/DockerTestUtils.java | 10 +++--- 6 files changed, 45 insertions(+), 14 deletions(-) create mode 100644 test/lib/jdk/test/lib/Container.java diff --git a/test/hotspot/jtreg/TEST.ROOT b/test/hotspot/jtreg/TEST.ROOT index 3b5e1b9b1f3..6ec1c0aeec8 100644 --- a/test/hotspot/jtreg/TEST.ROOT +++ b/test/hotspot/jtreg/TEST.ROOT @@ -35,7 +35,9 @@ groups=TEST.groups TEST.quick-groups # to determine additional characteristics of the system for use with the @requires tag. # Note: compiled bootlibs code will be located in the folder 'bootClasses' requires.extraPropDefns = ../../jtreg-ext/requires/VMProps.java -requires.extraPropDefns.bootlibs = ../../lib/sun ../../lib/jdk/test/lib/Platform.java +requires.extraPropDefns.bootlibs = ../../lib/sun \ + ../../lib/jdk/test/lib/Platform.java \ + ../../lib/jdk/test/lib/Container.java requires.extraPropDefns.vmOpts = -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:bootClasses requires.properties= \ sun.arch.data.model \ diff --git a/test/jdk/TEST.ROOT b/test/jdk/TEST.ROOT index 468417d8cba..854f7df2a62 100644 --- a/test/jdk/TEST.ROOT +++ b/test/jdk/TEST.ROOT @@ -32,7 +32,9 @@ groups=TEST.groups # to determine additional characteristics of the system for use with the @requires tag. # Note: compiled bootlibs code will be located in the folder 'bootClasses' requires.extraPropDefns = ../../test/jtreg-ext/requires/VMProps.java [../../closed/test/jtreg-ext/requires/VMPropsExt.java] -requires.extraPropDefns.bootlibs = ../../test/lib/sun ../../test/lib/jdk/test/lib/Platform.java +requires.extraPropDefns.bootlibs = ../../test/lib/sun \ + ../../test/lib/jdk/test/lib/Platform.java \ + ../../test/lib/jdk/test/lib/Container.java requires.extraPropDefns.vmOpts = -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:bootClasses requires.properties= \ sun.arch.data.model \ diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java index db83704f3a6..bc7dd35a83c 100644 --- a/test/jtreg-ext/requires/VMProps.java +++ b/test/jtreg-ext/requires/VMProps.java @@ -45,6 +45,7 @@ import sun.hotspot.gc.GC; import sun.hotspot.WhiteBox; import jdk.test.lib.Platform; +import jdk.test.lib.Container; /** * The Class to be invoked by jtreg prior Test Suite execution to @@ -449,7 +450,7 @@ else if (arch.equals("ppc64le")) { } private boolean checkDockerSupport() throws IOException, InterruptedException { - ProcessBuilder pb = new ProcessBuilder(Platform.DOCKER_COMMAND, "ps"); + ProcessBuilder pb = new ProcessBuilder(Container.ENGINE_COMMAND, "ps"); Process p = pb.start(); p.waitFor(10, TimeUnit.SECONDS); diff --git a/test/lib/jdk/test/lib/Container.java b/test/lib/jdk/test/lib/Container.java new file mode 100644 index 00000000000..e0ca4851e14 --- /dev/null +++ b/test/lib/jdk/test/lib/Container.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2019, Red Hat Inc. + * 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; + +public class Container { + // Use this property to specify docker location on your system. + // E.g.: "/usr/local/bin/docker". We define this constant here so + // that it can be used in VMProps as well which checks docker support + // via this command + public static final String ENGINE_COMMAND = + System.getProperty("jdk.test.container.command", "docker"); +} diff --git a/test/lib/jdk/test/lib/Platform.java b/test/lib/jdk/test/lib/Platform.java index bf69e7414bd..36ba37d420c 100644 --- a/test/lib/jdk/test/lib/Platform.java +++ b/test/lib/jdk/test/lib/Platform.java @@ -33,12 +33,6 @@ import java.util.stream.Collectors; public class Platform { - // Use this property to specify docker location on your system. - // E.g.: "/usr/local/bin/docker". We define this constant here so - // that it can be used in VMProps as well which checks docker support - // via this command - public static final String DOCKER_COMMAND = - System.getProperty("jdk.test.docker.command", "docker"); public static final String vmName = System.getProperty("java.vm.name"); public static final String vmInfo = System.getProperty("java.vm.info"); private static final String osVersion = System.getProperty("os.version"); diff --git a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java index 416b09cf317..05cf84d4c21 100644 --- a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java +++ b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java @@ -37,7 +37,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import jdk.test.lib.Platform; +import jdk.test.lib.Container; import jdk.test.lib.Utils; import jdk.test.lib.process.OutputAnalyzer; import jtreg.SkippedException; @@ -110,7 +110,7 @@ public static boolean canTestDocker() throws Exception { */ private static boolean isDockerEngineAvailableCheck() throws Exception { try { - execute(Platform.DOCKER_COMMAND, "ps") + execute(Container.ENGINE_COMMAND, "ps") .shouldHaveExitValue(0) .shouldContain("CONTAINER") .shouldContain("IMAGE"); @@ -173,7 +173,7 @@ private static boolean isDockerEngineAvailableCheck() throws Exception { DockerfileConfig.getBaseImageVersion()); try { // Build the docker - execute(Platform.DOCKER_COMMAND, "build", "--no-cache", "--tag", imageName, buildDir.toString()) + execute(Container.ENGINE_COMMAND, "build", "--no-cache", "--tag", imageName, buildDir.toString()) .shouldHaveExitValue(0); } catch (Exception e) { // If docker image building fails there is a good chance it happens due to environment and/or @@ -195,7 +195,7 @@ private static boolean isDockerEngineAvailableCheck() throws Exception { public static List buildJavaCommand(DockerRunOptions opts) throws Exception { List cmd = new ArrayList<>(); - cmd.add(Platform.DOCKER_COMMAND); + cmd.add(Container.ENGINE_COMMAND); cmd.add("run"); if (opts.tty) cmd.add("--tty=true"); @@ -238,7 +238,7 @@ public static OutputAnalyzer dockerRunJava(DockerRunOptions opts) throws Excepti * @throws Exception */ public static void removeDockerImage(String imageNameAndTag) throws Exception { - execute(Platform.DOCKER_COMMAND, "rmi", "--force", imageNameAndTag); + execute(Container.ENGINE_COMMAND, "rmi", "--force", imageNameAndTag); } From 71bbe05eab6188f4757246b5e59268b15133cbe2 Mon Sep 17 00:00:00 2001 From: mbaesken Date: Wed, 28 Aug 2019 14:22:56 +0200 Subject: [PATCH 072/131] 8229284: jdk/internal/platform/cgroup/TestCgroupMetrics.java fails for - memory:getMemoryUsage Reviewed-by: mseledtsov, sgehwolf --- .../lib/containers/cgroup/MetricsTester.java | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java b/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java index 115dcf9f1cf..5450a551d87 100644 --- a/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java +++ b/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java @@ -582,19 +582,28 @@ public void testMemoryUsage() throws Exception { Metrics metrics = Metrics.systemMetrics(); long memoryMaxUsage = metrics.getMemoryMaxUsage(); long memoryUsage = metrics.getMemoryUsage(); + long newMemoryMaxUsage = 0, newMemoryUsage = 0; + + // allocate memory in a loop and check more than once for new values + // otherwise we might see seldom the effect of decreasing new memory values + // e.g. because the system could free up memory + byte[][] bytes = new byte[32][]; + for (int i = 0; i < 32; i++) { + bytes[i] = new byte[8*1024*1024]; + newMemoryUsage = metrics.getMemoryUsage(); + if (newMemoryUsage > memoryUsage) { + break; + } + } + newMemoryMaxUsage = metrics.getMemoryMaxUsage(); - byte[] bb = new byte[64*1024*1024]; // 64M - - long newMemoryMaxUsage = metrics.getMemoryMaxUsage(); - long newMemoryUsage = metrics.getMemoryUsage(); - - if(newMemoryMaxUsage < memoryMaxUsage) { - fail(SubSystem.MEMORY, "getMemoryMaxUsage", newMemoryMaxUsage, - memoryMaxUsage); + if (newMemoryMaxUsage < memoryMaxUsage) { + fail(SubSystem.MEMORY, "getMemoryMaxUsage", memoryMaxUsage, + newMemoryMaxUsage); } - if(newMemoryUsage < memoryUsage) { - fail(SubSystem.MEMORY, "getMemoryUsage", newMemoryUsage, memoryUsage); + if (newMemoryUsage < memoryUsage) { + fail(SubSystem.MEMORY, "getMemoryUsage", memoryUsage, newMemoryUsage); } } From ec568cd7e26bed82c38d9b68a0022a92267eb105 Mon Sep 17 00:00:00 2001 From: roland Date: Mon, 23 Sep 2019 16:49:09 +0200 Subject: [PATCH 073/131] 8229483: Sinking load out of loop may trigger: assert(found_sfpt) failed: no node in loop that's not input to safepoint Reviewed-by: thartmann, neliasso --- ...ntiDependentLoadInOuterStripMinedLoop.java | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/loopstripmining/AntiDependentLoadInOuterStripMinedLoop.java diff --git a/test/hotspot/jtreg/compiler/loopstripmining/AntiDependentLoadInOuterStripMinedLoop.java b/test/hotspot/jtreg/compiler/loopstripmining/AntiDependentLoadInOuterStripMinedLoop.java new file mode 100644 index 00000000000..16b992ef282 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopstripmining/AntiDependentLoadInOuterStripMinedLoop.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2019, Red Hat, 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. + * + * 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 8229483 + * @summary Sinking load out of loop may trigger: assert(found_sfpt) failed: no node in loop that's not input to safepoint + * + * @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:LoopMaxUnroll=0 AntiDependentLoadInOuterStripMinedLoop + * + */ + +public class AntiDependentLoadInOuterStripMinedLoop { + private static int field; + private static volatile int barrier; + + public static void main(String[] args) { + int[] array = new int[1]; + A a = new A(); + for (int i = 0; i < 20_000; i++) { + test1(array); + test2(a, array); + test2_helper(array, 0, 0); + } + } + + private static int test1(int[] array) { + int res = 1; + + for (int i = 0; i < 10; i++) { + barrier = 1; + // field load doesn't float higher than here + + for (int j = 0; j < 2000; j++) { + array[0] = j; // seen as anti dependence by C2 during loop opts, sunk out of loop + res *= j; + } + } + + return field + res + field * 2; + } + + private static int test2(A a, int[] array) { + int ignore = a.field; + int res = 1; + + int k = 0; + for (k = 0; k < 2; k++) { + } + + for (int i = 0; i < 10; i++) { + barrier = 1; + + for (int j = 0; j < 2000; j++) { + test2_helper(array, k, j); + res *= j; + } + } + + return a.field + res + a.field * 2; + } + + private static void test2_helper(int[] array, int k, int j) { + if (k == 2) { + array[0] = j; + } + } + + private static class A { + public int field; + } +} From 590a3c5125304001230b2958712f6b01a70e777a Mon Sep 17 00:00:00 2001 From: clanger Date: Tue, 1 Oct 2019 14:51:04 +0200 Subject: [PATCH 074/131] 8223869: Problem list java/awt/FontMetrics/MaxAdvanceIsMax.java on more platforms Reviewed-by: goetz --- test/jdk/ProblemList.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index d09f9cf8e38..5b99a0feed8 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -221,7 +221,7 @@ java/awt/font/TextLayout/CombiningPerf.java 8192931 generic-all java/awt/font/TextLayout/TextLayoutBounds.java 8169188 generic-all java/awt/font/StyledMetrics/BoldSpace.java 8198422 linux-all java/awt/FontMetrics/FontCrash.java 8198336 windows-all -java/awt/FontMetrics/MaxAdvanceIsMax.java 8221305 solaris-all,macosx-all +java/awt/FontMetrics/MaxAdvanceIsMax.java 8221305,8231495 solaris-all,macosx-all,linux-all java/awt/image/DrawImage/IncorrectAlphaSurface2SW.java 8056077 generic-all java/awt/image/DrawImage/IncorrectClipXorModeSW2Surface.java 8196025 windows-all java/awt/image/DrawImage/IncorrectClipXorModeSurface2Surface.java 8196025 windows-all From efe96d86fb99e154388ab7bf1787e777f3bda6f3 Mon Sep 17 00:00:00 2001 From: roland Date: Tue, 17 Sep 2019 15:58:54 +0200 Subject: [PATCH 075/131] 8231055: C2: arraycopy with same non escaping src and dest but different positions causes wrong execution Reviewed-by: thartmann, vlivanov --- .../escapeAnalysis/TestSelfArrayCopy.java | 38 ++++++++++++++++--- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/test/hotspot/jtreg/compiler/escapeAnalysis/TestSelfArrayCopy.java b/test/hotspot/jtreg/compiler/escapeAnalysis/TestSelfArrayCopy.java index cf08a59bcea..3731f959d5b 100644 --- a/test/hotspot/jtreg/compiler/escapeAnalysis/TestSelfArrayCopy.java +++ b/test/hotspot/jtreg/compiler/escapeAnalysis/TestSelfArrayCopy.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8229016 + * @bug 8229016 8231055 * @summary Test correct elimination of array allocation with arraycopy to itself. * @library /test/lib * @run main/othervm -Xbatch -XX:CompileCommand=compileonly,compiler.escapeAnalysis.TestSelfArrayCopy::test @@ -39,7 +39,7 @@ public class TestSelfArrayCopy { private static final int rI1 = Utils.getRandomInstance().nextInt(); private static final int rI2 = Utils.getRandomInstance().nextInt(); - private static int test() { + private static int test1() { // Non-escaping allocation Integer[] array = {rI1, rI2}; // Arraycopy with src == dst @@ -51,14 +51,40 @@ private static int test() { return array[0] + array[1]; } + private static int test2() { + // Non-escaping allocation + Integer[] array = {rI1, rI2}; + // Arraycopy with src == dst + System.arraycopy(array, 0, array, 1, 1); + if (b) { + // Uncommon trap + System.out.println(array[0]); + } + return array[0] + array[1]; + } + public static void main(String[] args) { - int expected = rI1 + rI2; + int expected1 = rI1 + rI2; + int expected2 = rI1 + rI1; // Trigger compilation for (int i = 0; i < 20_000; ++i) { - int result = test(); - if (result != expected) { - throw new RuntimeException("Incorrect result: " + result + " != " + expected); + int result = test1(); + if (result != expected1) { + throw new RuntimeException("Incorrect result: " + result + " != " + expected1); } + result = test2(); + if (result != expected2) { + throw new RuntimeException("Incorrect result: " + result + " != " + expected2); + } + } + b = true; + int result = test1(); + if (result != expected1) { + throw new RuntimeException("Incorrect result: " + result + " != " + expected1); + } + result = test2(); + if (result != expected2) { + throw new RuntimeException("Incorrect result: " + result + " != " + expected2); } } } From 371fc21d6d69c0d6038be43fa2c5770cd0a7e6c8 Mon Sep 17 00:00:00 2001 From: roland Date: Mon, 30 Sep 2019 17:58:05 +0200 Subject: [PATCH 076/131] 8231665: 8231055 broke escapeAnalysis/TestSelfArrayCopy.java Reviewed-by: thartmann --- .../jtreg/compiler/escapeAnalysis/TestSelfArrayCopy.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/compiler/escapeAnalysis/TestSelfArrayCopy.java b/test/hotspot/jtreg/compiler/escapeAnalysis/TestSelfArrayCopy.java index 3731f959d5b..434498c2928 100644 --- a/test/hotspot/jtreg/compiler/escapeAnalysis/TestSelfArrayCopy.java +++ b/test/hotspot/jtreg/compiler/escapeAnalysis/TestSelfArrayCopy.java @@ -26,7 +26,7 @@ * @bug 8229016 8231055 * @summary Test correct elimination of array allocation with arraycopy to itself. * @library /test/lib - * @run main/othervm -Xbatch -XX:CompileCommand=compileonly,compiler.escapeAnalysis.TestSelfArrayCopy::test + * @run main/othervm -Xbatch -XX:CompileCommand=compileonly,compiler.escapeAnalysis.TestSelfArrayCopy::test* * compiler.escapeAnalysis.TestSelfArrayCopy */ From c932921b713a34108b5e46791702cde593871ad4 Mon Sep 17 00:00:00 2001 From: thartmann Date: Thu, 5 Sep 2019 13:56:17 +0200 Subject: [PATCH 077/131] 8229496: SIGFPE (division by zero) in C2 OSR compiled method Summary: Adding a CastNode to keep the dependency between the div/mod operation and the zero check. Reviewed-by: roland, mdoerr --- .../loopopts/TestDivZeroCheckControl.java | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestDivZeroCheckControl.java diff --git a/test/hotspot/jtreg/compiler/loopopts/TestDivZeroCheckControl.java b/test/hotspot/jtreg/compiler/loopopts/TestDivZeroCheckControl.java new file mode 100644 index 00000000000..e54fa346b88 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestDivZeroCheckControl.java @@ -0,0 +1,106 @@ +/* + * 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 8229496 + * @summary Verify that zero check is executed before division/modulo operation. + * @run main/othervm -Xbatch -XX:LoopUnrollLimit=0 + * -XX:CompileCommand=dontinline,compiler.loopopts.TestDivZeroCheckControl::test* + * compiler.loopopts.TestDivZeroCheckControl + */ + +package compiler.loopopts; + +public class TestDivZeroCheckControl { + + public static int test1(int div, int array[]) { + int res = 0; + for (int i = 0; i < 256; i++) { + int j = 0; + do { + array[i] = i; + try { + res = 1 % div; + } catch (ArithmeticException ex) { } + } while (++j < 9); + } + return res; + } + + // Same as test1 but with division instead of modulo + public static int test2(int div, int array[]) { + int res = 0; + for (int i = 0; i < 256; i++) { + int j = 0; + do { + array[i] = i; + try { + res = 1 / div; + } catch (ArithmeticException ex) { } + } while (++j < 9); + } + return res; + } + + // Same as test1 but with long + public static long test3(long div, int array[]) { + long res = 0; + for (int i = 0; i < 256; i++) { + int j = 0; + do { + array[i] = i; + try { + res = 1L % div; + } catch (ArithmeticException ex) { } + } while (++j < 9); + } + return res; + } + + // Same as test2 but with long + public static long test4(long div, int array[]) { + long res = 0; + for (int i = 0; i < 256; i++) { + int j = 0; + do { + array[i] = i; + try { + res = 1L / div; + } catch (ArithmeticException ex) { } + } while (++j < 9); + } + return res; + } + + public static void main(String[] args) { + int array[] = new int[256]; + for (int i = 0; i < 50_000; ++i) { + test1(0, array); + test2(0, array); + test3(0, array); + test4(0, array); + } + } +} From 5f4d49f81ca53bc6afa65ec2ece3c009c966702a Mon Sep 17 00:00:00 2001 From: roland Date: Wed, 28 Aug 2019 15:51:03 +0200 Subject: [PATCH 078/131] 8230061: # assert(mode == ControlAroundStripMined && use == sfpt) failed: missed a node Reviewed-by: thartmann, neliasso --- .../DeadNodesInOuterLoopAtLoopCloning.java | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/loopstripmining/DeadNodesInOuterLoopAtLoopCloning.java diff --git a/test/hotspot/jtreg/compiler/loopstripmining/DeadNodesInOuterLoopAtLoopCloning.java b/test/hotspot/jtreg/compiler/loopstripmining/DeadNodesInOuterLoopAtLoopCloning.java new file mode 100644 index 00000000000..3d722fc9ba3 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopstripmining/DeadNodesInOuterLoopAtLoopCloning.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2019, Red Hat, 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. + * + * 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 8230061 + * @summary loop unrolling breaks when outer strip mined loop contains dead node + * + * @run main/othervm -Xmx1G DeadNodesInOuterLoopAtLoopCloning + * + */ + +public class DeadNodesInOuterLoopAtLoopCloning { + + public static final int N = 400; + + public static long instanceCount=-2288355609708559532L; + + public static double checkSum(double[] a) { + double sum = 0; + for (int j = 0; j < a.length; j++) { + sum += (a[j] / (j + 1) + a[j] % (j + 1)); + } + return sum; + } + + public static int iMeth(double d1) { + + int i4=6022, i5=-211, i6=-15841, iArr[]=new int[N]; + double d2=-8.78129, dArr[]=new double[N]; + + i5 = 1; + do { + i6 = 1; + while (++i6 < 5) { + i4 = -933; + i4 *= i4; + dArr[i5 + 1] = i4; + i4 -= i4; + d2 = 1; + do { + iArr[(int)(d2 + 1)] += (int)instanceCount; + try { + i4 = (i4 % -51430); + i4 = (iArr[i6] % 31311); + iArr[i6 + 1] = (24197 / i5); + } catch (ArithmeticException a_e) {} + i4 -= (int)instanceCount; + i4 <<= i5; + i4 &= 12; + } while (++d2 < 1); + } + } while (++i5 < 320); + long meth_res = Double.doubleToLongBits(checkSum(dArr)); + return (int)meth_res; + } + + public static void main(String[] strArr) { + DeadNodesInOuterLoopAtLoopCloning _instance = new DeadNodesInOuterLoopAtLoopCloning(); + for (int i = 0; i < 10 * 320; i++ ) { + _instance.iMeth(0.8522); + } + } +} From e93ccbbc460e63dfbb2ba7f31cb7efba75d77de2 Mon Sep 17 00:00:00 2001 From: thartmann Date: Thu, 26 Sep 2019 09:16:08 +0200 Subject: [PATCH 079/131] 8231223: C2's conditional move optimization fails with assert(bol->Opcode() == Op_Bool) failed Summary: Bail out if the range check If has an Opaque4Node input instead of a BoolNode. Reviewed-by: roland, kvn --- .../compiler/loopopts/TestCMovWithOpaque.java | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestCMovWithOpaque.java diff --git a/test/hotspot/jtreg/compiler/loopopts/TestCMovWithOpaque.java b/test/hotspot/jtreg/compiler/loopopts/TestCMovWithOpaque.java new file mode 100644 index 00000000000..f463702b0f4 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestCMovWithOpaque.java @@ -0,0 +1,62 @@ +/* + * 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 8231223 + * @summary Test conditional move optimization encountering an Opaque4Node. + * @run main/othervm -Xbatch -XX:-TieredCompilation + * -XX:CompileCommand=inline,compiler.loopopts.TestCMovWithOpaque::test + * compiler.loopopts.TestCMovWithOpaque + */ + +package compiler.loopopts; + +public class TestCMovWithOpaque { + + public static void test(int array[]) { + for (int i = 1; i < 8; i += 3) { + for (int j = 0; j < 4; ++j) { + switch (i % 4) { + case 0: + break; + case 1: + break; + case 2: + break; + case 3: + array[j] += 42; + break; + } + } + } + } + + public static void main(String[] args) { + int[] array = new int[4]; + for (int i = 0; i < 20_000; ++i) { + test(array); + } + } +} From a8f1e8f10a0f7693cb96a21c6e4f8b5d2681bd79 Mon Sep 17 00:00:00 2001 From: aeubanks Date: Mon, 19 Aug 2019 16:08:28 -0700 Subject: [PATCH 080/131] 8229899: Make java.io.File.isInvalid() less racy Reviewed-by: alanb, martin, shade --- src/java.base/share/classes/java/io/File.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/java.base/share/classes/java/io/File.java b/src/java.base/share/classes/java/io/File.java index 6bf3fe708aa..617082896d6 100644 --- a/src/java.base/share/classes/java/io/File.java +++ b/src/java.base/share/classes/java/io/File.java @@ -182,11 +182,13 @@ private static enum PathStatus { INVALID, CHECKED }; * @return true if the file path is invalid. */ final boolean isInvalid() { - if (status == null) { - status = (this.path.indexOf('\u0000') < 0) ? PathStatus.CHECKED - : PathStatus.INVALID; + PathStatus s = status; + if (s == null) { + s = (this.path.indexOf('\u0000') < 0) ? PathStatus.CHECKED + : PathStatus.INVALID; + status = s; } - return status == PathStatus.INVALID; + return s == PathStatus.INVALID; } /** From a67c9a8a8549bc3a0d37acaeef1c0cb3570faf2d Mon Sep 17 00:00:00 2001 From: bpb Date: Wed, 2 Oct 2019 07:50:06 -0700 Subject: [PATCH 081/131] 8229022: BufferedReader performance can be improved by using StringBuilder Reviewed-by: igerasim, vtewari, dfuchs --- src/java.base/share/classes/java/io/BufferedReader.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/io/BufferedReader.java b/src/java.base/share/classes/java/io/BufferedReader.java index 8cb4f73e597..9e909734d16 100644 --- a/src/java.base/share/classes/java/io/BufferedReader.java +++ b/src/java.base/share/classes/java/io/BufferedReader.java @@ -312,7 +312,7 @@ public int read(char cbuf[], int off, int len) throws IOException { * @exception IOException If an I/O error occurs */ String readLine(boolean ignoreLF) throws IOException { - StringBuffer s = null; + StringBuilder s = null; int startChar; synchronized (lock) { @@ -368,7 +368,7 @@ String readLine(boolean ignoreLF) throws IOException { } if (s == null) - s = new StringBuffer(defaultExpectedLineLength); + s = new StringBuilder(defaultExpectedLineLength); s.append(cb, startChar, i - startChar); } } From 2d31283394610e4a995f43934b91df3914a9d5c7 Mon Sep 17 00:00:00 2001 From: pliden Date: Tue, 1 Oct 2019 12:27:14 +0200 Subject: [PATCH 082/131] 8231296: ZGC: vmTestbase/nsk/jvmti/Allocate/alloc001/ fails Reviewed-by: sspitsyn, dcubed, iignatyev --- .../vmTestbase/nsk/jvmti/Allocate/alloc001/TestDescription.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/Allocate/alloc001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/Allocate/alloc001/TestDescription.java index c7bf3df62fb..386dd36cbe8 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/Allocate/alloc001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/Allocate/alloc001/TestDescription.java @@ -42,6 +42,8 @@ * @library /vmTestbase * /test/lib * @requires os.family != "aix" + * @comment Test is incompatible with ZGC, due to ZGC's address space requirements. + * @requires vm.gc != "Z" * @run driver jdk.test.lib.FileInstaller . . * @build nsk.jvmti.Allocate.alloc001 * @run shell alloc001.sh From 697428ab2e1582ff3ebaf86deda6b9e66b28203c Mon Sep 17 00:00:00 2001 From: pliden Date: Thu, 26 Sep 2019 13:56:58 +0200 Subject: [PATCH 083/131] 8231294: ZGC: vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted002 fails Reviewed-by: shade, dholmes --- .../ResourceExhausted/resexhausted002/TestDescription.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted002/TestDescription.java index 4bd9c7c9ea1..aa62fb7f580 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted002/TestDescription.java @@ -39,8 +39,8 @@ * @run driver jdk.test.lib.FileInstaller . . * @run main/othervm/native * -agentlib:resexhausted=-waittime=5 - * -Xms8m - * -Xmx8m + * -Xms128m + * -Xmx128m * -XX:-UseGCOverheadLimit * nsk.jvmti.ResourceExhausted.resexhausted002 */ From 6bbd2711b85d68e19be231cc00948a9fa5c22b81 Mon Sep 17 00:00:00 2001 From: dzhou Date: Mon, 7 Jan 2019 18:48:39 -0800 Subject: [PATCH 084/131] 8215913: [Test_bug]java/util/Locale/LocaleProvidersRun.java failed on de_DE and ja_JP locale. Reviewed-by: naoto, rgoel, rriggs --- test/jdk/java/util/Locale/LocaleProviders.java | 16 ++++++++++------ test/jdk/java/util/Locale/LocaleProviders.sh | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/test/jdk/java/util/Locale/LocaleProviders.java b/test/jdk/java/util/Locale/LocaleProviders.java index c1558930b4d..342ea91fd1d 100644 --- a/test/jdk/java/util/Locale/LocaleProviders.java +++ b/test/jdk/java/util/Locale/LocaleProviders.java @@ -241,12 +241,16 @@ static void bug8013903Test() { } static void bug8027289Test(String expectedCodePoint) { - char[] expectedSymbol = Character.toChars(Integer.valueOf(expectedCodePoint, 16)); - NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.CHINA); - char formatted = nf.format(7000).charAt(0); - System.out.println("returned: " + formatted + ", expected: " + expectedSymbol[0]); - if (formatted != expectedSymbol[0]) { - throw new RuntimeException("Unexpected Chinese currency symbol. returned: " + formatted + ", expected: " + expectedSymbol[0]); + if (System.getProperty("os.name").startsWith("Windows")) { + char[] expectedSymbol = Character.toChars(Integer.valueOf(expectedCodePoint, 16)); + NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.CHINA); + char formatted = nf.format(7000).charAt(0); + System.out.println("returned: " + formatted + ", expected: " + expectedSymbol[0]); + if (formatted != expectedSymbol[0]) { + throw new RuntimeException( + "Unexpected Chinese currency symbol. returned: " + + formatted + ", expected: " + expectedSymbol[0]); + } } } diff --git a/test/jdk/java/util/Locale/LocaleProviders.sh b/test/jdk/java/util/Locale/LocaleProviders.sh index 652dadf0d81..bf56968ef6c 100644 --- a/test/jdk/java/util/Locale/LocaleProviders.sh +++ b/test/jdk/java/util/Locale/LocaleProviders.sh @@ -25,7 +25,7 @@ # @test # @bug 6336885 7196799 7197573 7198834 8000245 8000615 8001440 8008577 # 8010666 8013086 8013233 8013903 8015960 8028771 8054482 8062006 -# 8150432 8220227 +# 8150432 8220227 8215913 # @summary tests for "java.locale.providers" system property # @modules java.base/sun.util.locale # java.base/sun.util.locale.provider From b637cd1f17ba4c1ff71a26d6dd5972bdd2f543e2 Mon Sep 17 00:00:00 2001 From: mbaesken Date: Thu, 18 Jul 2019 14:01:54 +0200 Subject: [PATCH 085/131] 8228368: avoid incompatible pointer to integer conversion initializing gint in gtk2_interface Reviewed-by: prr --- .../unix/native/libawt_xawt/awt/gtk2_interface.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c b/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c index 800af14d67a..41ee56fcd4f 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2017, 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 @@ -2451,14 +2451,14 @@ static jobject get_string_property(JNIEnv *env, GtkSettings* settings, const gch static jobject get_integer_property(JNIEnv *env, GtkSettings* settings, const gchar* key) { - gint intval = NULL; + gint intval = 0; (*fp_g_object_get)(settings, key, &intval, NULL); return create_Integer(env, intval); } static jobject get_boolean_property(JNIEnv *env, GtkSettings* settings, const gchar* key) { - gint intval = NULL; + gint intval = 0; (*fp_g_object_get)(settings, key, &intval, NULL); return create_Boolean(env, intval); } From a4499e17afe5286c879c1202ecce03ac2f74be24 Mon Sep 17 00:00:00 2001 From: prr Date: Wed, 28 Aug 2019 09:13:01 -0700 Subject: [PATCH 086/131] 8229800: WindowsServerCore 1809 does not provide d2d1.dll library required by awt.dll Reviewed-by: jdv, serb, aaivanov --- .../common/awt/systemscale/systemScale.cpp | 31 ++++++++++++++----- .../windows/awt_Win32GraphicsDevice.cpp | 2 -- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/java.desktop/windows/native/common/awt/systemscale/systemScale.cpp b/src/java.desktop/windows/native/common/awt/systemscale/systemScale.cpp index f8ea087883c..ceca5d9ed4b 100644 --- a/src/java.desktop/windows/native/common/awt/systemscale/systemScale.cpp +++ b/src/java.desktop/windows/native/common/awt/systemscale/systemScale.cpp @@ -24,7 +24,6 @@ */ #include "systemScale.h" #include -#pragma comment(lib, "d2d1") #include #ifndef MDT_EFFECTIVE_DPI #define MDT_EFFECTIVE_DPI 0 @@ -53,6 +52,9 @@ void GetScreenDpi(HMONITOR hmon, float *dpiX, float *dpiY) return; } + typedef HRESULT(WINAPI D2D1CreateFactoryFunc) + (D2D1_FACTORY_TYPE, REFIID, + CONST D2D1_FACTORY_OPTIONS*, ID2D1Factory**); typedef HRESULT(WINAPI GetDpiForMonitorFunc)(HMONITOR, int, UINT*, UINT*); static HMODULE hLibSHCoreDll = NULL; static GetDpiForMonitorFunc *lpGetDpiForMonitor = NULL; @@ -73,12 +75,27 @@ void GetScreenDpi(HMONITOR hmon, float *dpiX, float *dpiY) *dpiY = static_cast(y); } } else { - ID2D1Factory* m_pDirect2dFactory; - HRESULT res = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, - &m_pDirect2dFactory); - if (res == S_OK) { - m_pDirect2dFactory->GetDesktopDpi(dpiX, dpiY); - m_pDirect2dFactory->Release(); + static HMODULE d2dDll = NULL; + static BOOL loadAttempted = FALSE; + static D2D1CreateFactoryFunc *lpD2D1CreateFactory = NULL; + if (!loadAttempted && d2dDll == NULL) { + loadAttempted = TRUE; + d2dDll = JDK_LoadSystemLibrary("d2d1.dll"); + } + if (d2dDll != NULL && lpD2D1CreateFactory == NULL) { + lpD2D1CreateFactory = (D2D1CreateFactoryFunc*)GetProcAddress( + d2dDll, "D2D1CreateFactory"); + } + if (lpD2D1CreateFactory != NULL) { + ID2D1Factory* m_pDirect2dFactory; + HRESULT res = lpD2D1CreateFactory + (D2D1_FACTORY_TYPE_SINGLE_THREADED, + __uuidof(ID2D1Factory), NULL, + &m_pDirect2dFactory); + if (res == S_OK) { + m_pDirect2dFactory->GetDesktopDpi(dpiX, dpiY); + m_pDirect2dFactory->Release(); + } } } return; diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.cpp index dcc5ee99335..258b2906f92 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.cpp @@ -49,8 +49,6 @@ #include "dither.h" #include "img_util_md.h" #include "Devices.h" -#include -#pragma comment(lib, "d2d1") #include "systemScale.h" uns_ordered_dither_array img_oda_alpha; From 68dcebc915164853852e704ba8a5346ec690e7b1 Mon Sep 17 00:00:00 2001 From: egahlin Date: Thu, 6 Jun 2019 15:22:12 +0200 Subject: [PATCH 087/131] 8224217: RecordingInfo should use textual representation of path Reviewed-by: mgronlun --- .../jdk/jfr/internal/PlatformRecorder.java | 4 ++-- .../jdk/jfr/internal/PlatformRecording.java | 4 ++-- .../jdk/jfr/internal/WriteableUserPath.java | 22 ++++++++++++++----- .../jdk/jfr/internal/dcmd/DCmdDump.java | 2 +- .../management/ManagementSupport.java | 12 ++++++++++ .../jdk/management/jfr/RecordingInfo.java | 5 ++--- 6 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java index 7c48fc26624..5ec29d1015b 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java @@ -315,7 +315,7 @@ synchronized void stop(PlatformRecording recording) { private void dumpMemoryToDestination(PlatformRecording recording) { WriteableUserPath dest = recording.getDestination(); if (dest != null) { - MetadataRepository.getInstance().setOutput(dest.getText()); + MetadataRepository.getInstance().setOutput(dest.getRealPathText()); recording.clearDestination(); } } @@ -406,7 +406,7 @@ private void writeMetaEvents() { event.id = r.getId(); event.name = r.getName(); WriteableUserPath p = r.getDestination(); - event.destination = p == null ? null : p.getText(); + event.destination = p == null ? null : p.getRealPathText(); Duration d = r.getDuration(); event.recordingDuration = d == null ? Long.MAX_VALUE : d.toMillis(); Duration age = r.getMaxAge(); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java index e460430b459..5a3a67bbeeb 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java @@ -132,7 +132,7 @@ public void start() { options.add("duration=" + Utils.formatTimespan(duration, "")); } if (destination != null) { - options.add("filename=" + destination.getText()); + options.add("filename=" + destination.getRealPathText()); } String optionText = options.toString(); if (optionText.length() != 0) { @@ -165,7 +165,7 @@ public boolean stop(String reason) { if (dest != null) { try { dumpStopped(dest); - Logger.log(LogTag.JFR, LogLevel.INFO, "Wrote recording \"" + getName() + "\" (" + getId() + ") to " + dest.getText()); + Logger.log(LogTag.JFR, LogLevel.INFO, "Wrote recording \"" + getName() + "\" (" + getId() + ") to " + dest.getRealPathText()); notifyIfStateChanged(newState, oldState); close(); // remove if copied out } catch(IOException e) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/WriteableUserPath.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/WriteableUserPath.java index 37a5a5a8141..d802b3b8c37 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/WriteableUserPath.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/WriteableUserPath.java @@ -50,7 +50,8 @@ public final class WriteableUserPath { private final AccessControlContext controlContext; private final Path original; private final Path real; - private final String text; + private final String realPathText; + private final String originalText; // Not to ensure security, but to help // against programming errors @@ -68,8 +69,9 @@ public WriteableUserPath(Path path) throws IOException { BufferedWriter fw = Files.newBufferedWriter(path); fw.close(); this.original = path; + this.originalText = path.toString(); this.real = path.toRealPath(); - this.text = real.toString(); + this.realPathText = real.toString(); } /** @@ -85,14 +87,24 @@ public Path getPotentiallyMaliciousOriginal() { } /** - * Returns a string representation of the path. + * Returns a string representation of the real path. * * @return path as text */ - public String getText() { - return text; + public String getRealPathText() { + return realPathText; } + /** + * Returns a string representation of the original path. + * + * @return path as text + */ + public String getOriginalText() { + return originalText; + } + + /** * Returns a potentially malicious path where the user may have implemented * their own version of Path. This method should never be called in an diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdDump.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdDump.java index d3e83ca39db..15088b986e5 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdDump.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdDump.java @@ -158,7 +158,7 @@ public void dump(PlatformRecorder recorder, Recording recording, String name, St wup = new WriteableUserPath(safe.toPath()); } r.dumpStopped(wup); - reportOperationComplete("Dumped", name, new SafePath(wup.getText())); + reportOperationComplete("Dumped", name, new SafePath(wup.getRealPathText())); } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ManagementSupport.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ManagementSupport.java index ccbdd1a78d7..af660b4c9d9 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ManagementSupport.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ManagementSupport.java @@ -31,12 +31,16 @@ import java.util.List; import jdk.jfr.EventType; +import jdk.jfr.Recording; import jdk.jfr.internal.JVMSupport; import jdk.jfr.internal.LogLevel; import jdk.jfr.internal.LogTag; import jdk.jfr.internal.Logger; import jdk.jfr.internal.MetadataRepository; +import jdk.jfr.internal.PlatformRecording; +import jdk.jfr.internal.PrivateAccess; import jdk.jfr.internal.Utils; +import jdk.jfr.internal.WriteableUserPath; import jdk.jfr.internal.instrument.JDKEvents; /** @@ -86,4 +90,12 @@ public static final String formatTimespan(Duration dValue, String separation) { public static void logError(String message) { Logger.log(LogTag.JFR, LogLevel.ERROR, message); } + + // Get the textual representation when the destination was set, which + // requires access to jdk.jfr.internal.PlatformRecording + public static String getDestinationOriginalText(Recording recording) { + PlatformRecording pr = PrivateAccess.getInstance().getPlatformRecording(recording); + WriteableUserPath wup = pr.getDestination(); + return wup == null ? null : wup.getOriginalText(); + } } diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/RecordingInfo.java b/src/jdk.management.jfr/share/classes/jdk/management/jfr/RecordingInfo.java index 7cc51e97bb8..9fcc9acee28 100644 --- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/RecordingInfo.java +++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/RecordingInfo.java @@ -25,7 +25,6 @@ package jdk.management.jfr; -import java.nio.file.Path; import java.time.Duration; import java.time.Instant; import java.util.LinkedHashMap; @@ -37,6 +36,7 @@ import jdk.jfr.Recording; import jdk.jfr.RecordingState; +import jdk.jfr.internal.management.ManagementSupport; /** * Management representation of a {@code Recording}. @@ -80,8 +80,7 @@ public final class RecordingInfo { startTime = s == null ? 0L : s.toEpochMilli(); Instant st = recording.getStopTime(); stopTime = st == null ? 0L : st.toEpochMilli(); - Path p = recording.getDestination(); - destination = p == null ? null : p.toString(); + destination = ManagementSupport.getDestinationOriginalText(recording); Duration duration = recording.getDuration(); durationInSeconds = duration == null ? 0 : duration.getSeconds(); settings = recording.getSettings(); From b8f9f02c13a7fdf563b3aa4752f699c11e0c4167 Mon Sep 17 00:00:00 2001 From: kbarrett Date: Wed, 31 Jul 2019 14:28:51 -0400 Subject: [PATCH 088/131] 8048556: Unnecessary GCLocker-initiated young GCs Summary: Fixed recognition of unnecessary GCLocker collections. Reviewed-by: pliden, tschatzl --- .../TestExcessGCLockerCollections.java | 188 ++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 test/hotspot/jtreg/gc/stress/gclocker/TestExcessGCLockerCollections.java diff --git a/test/hotspot/jtreg/gc/stress/gclocker/TestExcessGCLockerCollections.java b/test/hotspot/jtreg/gc/stress/gclocker/TestExcessGCLockerCollections.java new file mode 100644 index 00000000000..08d6c5a86c7 --- /dev/null +++ b/test/hotspot/jtreg/gc/stress/gclocker/TestExcessGCLockerCollections.java @@ -0,0 +1,188 @@ +/* + * 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 gc.stress.gclocker; + +/* + * @test TestExcessGCLockerCollections + * @key gc + * @bug 8048556 + * @summary Check for GC Locker initiated GCs that immediately follow another + * GC and so have very little needing to be collected. + * @requires vm.gc != "Z" + * @requires vm.gc != "Epsilon" + * @requires vm.gc != "Shenandoah" + * @library /test/lib + * @modules java.base/jdk.internal.misc + * @run driver/timeout=1000 gc.stress.gclocker.TestExcessGCLockerCollections 300 4 2 + */ + +import java.util.HashMap; +import java.util.Map; + +import java.util.zip.Deflater; + +import java.util.ArrayList; +import java.util.Arrays; + +import jdk.test.lib.Asserts; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; + +class TestExcessGCLockerCollectionsAux { + static private final int LARGE_MAP_SIZE = 64 * 1024; + + static private final int MAP_ARRAY_LENGTH = 4; + static private final int MAP_SIZE = 1024; + + static private final int BYTE_ARRAY_LENGTH = 128 * 1024; + + static private void println(String str) { System.out.println(str); } + + static private volatile boolean keepRunning = true; + + static Map populateMap(int size) { + Map map = new HashMap(); + for (int i = 0; i < size; i += 1) { + Integer keyInt = Integer.valueOf(i); + String valStr = "value is [" + i + "]"; + map.put(keyInt,valStr); + } + return map; + } + + static private class AllocatingWorker implements Runnable { + private final Object[] array = new Object[MAP_ARRAY_LENGTH]; + private int arrayIndex = 0; + + private void doStep() { + Map map = populateMap(MAP_SIZE); + array[arrayIndex] = map; + arrayIndex = (arrayIndex + 1) % MAP_ARRAY_LENGTH; + } + + public void run() { + while (keepRunning) { + doStep(); + } + } + } + + static private class JNICriticalWorker implements Runnable { + private int count; + + private void doStep() { + byte[] inputArray = new byte[BYTE_ARRAY_LENGTH]; + for (int i = 0; i < inputArray.length; i += 1) { + inputArray[i] = (byte) (count + i); + } + + Deflater deflater = new Deflater(); + deflater.setInput(inputArray); + deflater.finish(); + + byte[] outputArray = new byte[2 * inputArray.length]; + deflater.deflate(outputArray); + + count += 1; + } + + public void run() { + while (keepRunning) { + doStep(); + } + } + } + + static public Map largeMap; + + static public void main(String args[]) { + long durationSec = Long.parseLong(args[0]); + int allocThreadNum = Integer.parseInt(args[1]); + int jniCriticalThreadNum = Integer.parseInt(args[2]); + + println("Running for " + durationSec + " secs"); + + largeMap = populateMap(LARGE_MAP_SIZE); + + println("Starting " + allocThreadNum + " allocating threads"); + for (int i = 0; i < allocThreadNum; i += 1) { + new Thread(new AllocatingWorker()).start(); + } + + println("Starting " + jniCriticalThreadNum + " jni critical threads"); + for (int i = 0; i < jniCriticalThreadNum; i += 1) { + new Thread(new JNICriticalWorker()).start(); + } + + long durationMS = (long) (1000 * durationSec); + long start = System.currentTimeMillis(); + long now = start; + long soFar = now - start; + while (soFar < durationMS) { + try { + Thread.sleep(durationMS - soFar); + } catch (Exception e) { + } + now = System.currentTimeMillis(); + soFar = now - start; + } + println("Done."); + keepRunning = false; + } +} + +public class TestExcessGCLockerCollections { + private static final String locker = + "\\[gc\\s*\\] .* \\(GCLocker Initiated GC\\)"; + private static final String ANY_LOCKER = locker + " [1-9][0-9]*M"; + private static final String BAD_LOCKER = locker + " [1-9][0-9]?M"; + + private static final String[] COMMON_OPTIONS = new String[] { + "-Xmx1G", "-Xms1G", "-Xmn256M", "-Xlog:gc" }; + + public static void main(String args[]) throws Exception { + if (args.length < 3) { + System.out.println("usage: TestExcessGCLockerCollectionsAux" + + " " + + " "); + throw new RuntimeException("Invalid arguments"); + } + + ArrayList finalArgs = new ArrayList(); + finalArgs.addAll(Arrays.asList(COMMON_OPTIONS)); + finalArgs.add(TestExcessGCLockerCollectionsAux.class.getName()); + finalArgs.addAll(Arrays.asList(args)); + + // GC and other options obtained from test framework. + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + true, finalArgs.toArray(new String[0])); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + //System.out.println("------------- begin stdout ----------------"); + //System.out.println(output.getStdout()); + //System.out.println("------------- end stdout ----------------"); + output.stdoutShouldMatch(ANY_LOCKER); + output.stdoutShouldNotMatch(BAD_LOCKER); + } +} From 8fb399eaf047360a2a9d4bc10d8ac8f19a4dd4b3 Mon Sep 17 00:00:00 2001 From: serb Date: Sat, 9 Mar 2019 14:48:17 -0800 Subject: [PATCH 089/131] 8219504: Test for JDK-8211435 can be run on all platforms Reviewed-by: kaddepalli, dmarkov, sveerabhadra --- .../NullActiveWindowOnFocusLost.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/jdk/java/awt/Focus/NullActiveWindowOnFocusLost/NullActiveWindowOnFocusLost.java b/test/jdk/java/awt/Focus/NullActiveWindowOnFocusLost/NullActiveWindowOnFocusLost.java index 880e6345022..0924413bec4 100644 --- a/test/jdk/java/awt/Focus/NullActiveWindowOnFocusLost/NullActiveWindowOnFocusLost.java +++ b/test/jdk/java/awt/Focus/NullActiveWindowOnFocusLost/NullActiveWindowOnFocusLost.java @@ -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 @@ -31,7 +31,6 @@ * @test * @key headful * @bug 8211435 - * @requires (os.family == "mac") * @modules java.desktop/sun.awt */ public final class NullActiveWindowOnFocusLost { From 5ad46ad14b8293ebfc4b0a8b5b17213a6d1d5107 Mon Sep 17 00:00:00 2001 From: serb Date: Fri, 9 Nov 2018 22:25:40 -0800 Subject: [PATCH 090/131] 8213568: Typo in java/awt/GraphicsEnvironment/LoadLock/GE_init5.java Reviewed-by: prr --- test/jdk/java/awt/GraphicsEnvironment/LoadLock/GE_init5.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/jdk/java/awt/GraphicsEnvironment/LoadLock/GE_init5.java b/test/jdk/java/awt/GraphicsEnvironment/LoadLock/GE_init5.java index d0b40315ef0..d30e571c282 100644 --- a/test/jdk/java/awt/GraphicsEnvironment/LoadLock/GE_init5.java +++ b/test/jdk/java/awt/GraphicsEnvironment/LoadLock/GE_init5.java @@ -25,10 +25,10 @@ * @test * @bug 7002839 * @summary Static init deadlock Win32GraphicsEnvironment and WToolkit - * @run main/othervm -Djava.awt.headless=true GE_init4 + * @run main/othervm -Djava.awt.headless=true GE_init5 */ -import java.awt.Toolkit; +import java.awt.GraphicsEnvironment; public class GE_init5 { public static void main(String[] args) { From b9eeb71a23898a999fe1bcaa18c76f663d5047ec Mon Sep 17 00:00:00 2001 From: coffeys Date: Wed, 9 Oct 2019 10:14:03 +0000 Subject: [PATCH 091/131] 8231770: Test java/util/zip/FlaterTest.java fails with -Xcheck:jni Reviewed-by: alanb, coffeys, chegar Contributed-by: kiran.sidhartha.ravikumar@oracle.com --- src/java.base/share/native/libzip/Deflater.c | 2 +- test/jdk/java/util/zip/FlaterTest.java | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/java.base/share/native/libzip/Deflater.c b/src/java.base/share/native/libzip/Deflater.c index 2a5791ec62d..78de361cba3 100644 --- a/src/java.base/share/native/libzip/Deflater.c +++ b/src/java.base/share/native/libzip/Deflater.c @@ -257,7 +257,7 @@ Java_java_util_zip_Deflater_deflateBufferBytes(JNIEnv *env, jobject this, jlong res = doDeflate(env, addr, input, inputLen, output + outputOff, outputLen, flush, params); - (*env)->ReleasePrimitiveArrayCritical(env, outputArray, input, 0); + (*env)->ReleasePrimitiveArrayCritical(env, outputArray, output, 0); retVal = checkDeflateStatus(env, addr, inputLen, outputLen, params, res); return retVal; diff --git a/test/jdk/java/util/zip/FlaterTest.java b/test/jdk/java/util/zip/FlaterTest.java index 2d7124de42d..1545a2b91f3 100644 --- a/test/jdk/java/util/zip/FlaterTest.java +++ b/test/jdk/java/util/zip/FlaterTest.java @@ -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 @@ -23,10 +23,11 @@ /** * @test - * @bug 6348045 6341887 + * @bug 6348045 6341887 8231770 * @summary GZipOutputStream/InputStream goes critical(calls JNI_Get*Critical) - * and causes slowness. This test uses Deflater and Inflater directly. + * and causes slowness. This test uses Deflater and Inflater directly. * @key randomness + * @run main/othervm -Xcheck:jni FlaterTest */ import java.nio.*; From 329f66985a4a5a283c325b57532b8dd8a48fa709 Mon Sep 17 00:00:00 2001 From: joehw Date: Mon, 30 Sep 2019 17:54:11 +0000 Subject: [PATCH 092/131] 8016914: CoreDocumentImpl.setXmlVersion NPE Reviewed-by: lancea --- .../xerces/internal/dom/CoreDocumentImpl.java | 7 +- .../jaxp/unittest/transform/StAX2DOMTest.java | 82 ++++++++++++ .../jaxp/unittest/transform/StAX2DOMTest.xml | 119 +++++++++++++++++ .../jaxp/unittest/transform/StAX2DOMTest1.xml | 120 ++++++++++++++++++ 4 files changed, 326 insertions(+), 2 deletions(-) create mode 100644 test/jaxp/javax/xml/jaxp/unittest/transform/StAX2DOMTest.java create mode 100644 test/jaxp/javax/xml/jaxp/unittest/transform/StAX2DOMTest.xml create mode 100644 test/jaxp/javax/xml/jaxp/unittest/transform/StAX2DOMTest1.xml diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/CoreDocumentImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/CoreDocumentImpl.java index 94a83e5e2bd..05de2aff9b4 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/CoreDocumentImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/CoreDocumentImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -83,7 +83,7 @@ * @author Andy Clark, IBM * @author Ralf Pfeiffer, IBM * @since PR-DOM-Level-1-19980818. - * @LastModified: Nov 2018 + * @LastModified: Sept 2019 */ public class CoreDocumentImpl extends ParentNode implements Document { @@ -862,6 +862,9 @@ public String getEncoding() { * the version number of this document. */ public void setXmlVersion(String value) { + if (value == null) { + return; + } if(value.equals("1.0") || value.equals("1.1")){ //we need to change the flag value only -- // when the version set is different than already set. diff --git a/test/jaxp/javax/xml/jaxp/unittest/transform/StAX2DOMTest.java b/test/jaxp/javax/xml/jaxp/unittest/transform/StAX2DOMTest.java new file mode 100644 index 00000000000..a751402f885 --- /dev/null +++ b/test/jaxp/javax/xml/jaxp/unittest/transform/StAX2DOMTest.java @@ -0,0 +1,82 @@ +/* + * 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 transform; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamReader; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.stax.StAXSource; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import org.w3c.dom.Node; + +/* + * @test + * @bug 8016914 + * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest + * @run testng transform.StAX2DOMTest + * @summary Verifies transforming a StAXSource to a DOMResult. + */ +public class StAX2DOMTest { + /** + * Data files for test. + * Column(s): xml file + * + * @return data for test + */ + @DataProvider(name = "datafiles") + public Object[][] getData() { + return new Object[][] { + { "StAX2DOMTest.xml"}, //without declaration + { "StAX2DOMTest1.xml"}, //with declaration + }; + } + + /** + * Verifies that transforming a StAX source to a DOM result passes with + * or without the XML declaration. + * + * @param file the XML file + * @throws Exception if the test fails + */ + @Test(dataProvider = "datafiles") + public void test(String file) throws Exception { + final XMLInputFactory xif = XMLInputFactory.newInstance(); + final XMLStreamReader xsr = xif.createXMLStreamReader( + this.getClass().getResourceAsStream(file)); + xsr.nextTag(); // Advance to statements element + + final TransformerFactory tf = TransformerFactory.newInstance(); + final Transformer t = tf.newTransformer(); + while(xsr.nextTag() == XMLStreamConstants.START_ELEMENT) { + final DOMResult result = new DOMResult(); + t.transform(new StAXSource(xsr), result); + final Node domNode = result.getNode(); + System.out.println(domNode); + } + } +} diff --git a/test/jaxp/javax/xml/jaxp/unittest/transform/StAX2DOMTest.xml b/test/jaxp/javax/xml/jaxp/unittest/transform/StAX2DOMTest.xml new file mode 100644 index 00000000000..e09845566fa --- /dev/null +++ b/test/jaxp/javax/xml/jaxp/unittest/transform/StAX2DOMTest.xml @@ -0,0 +1,119 @@ + + + Gambardella, Matthew + XML Developer's Guide + Computer + 44.95 + 2000-10-01 + An in-depth look at creating applications + with XML. + + + Ralls, Kim + Midnight Rain + Fantasy + 5.95 + 2000-12-16 + A former architect battles corporate zombies, + an evil sorceress, and her own childhood to become queen + of the world. + + + Corets, Eva + Maeve Ascendant + Fantasy + 5.95 + 2000-11-17 + After the collapse of a nanotechnology + society in England, the young survivors lay the + foundation for a new society. + + + Corets, Eva + Oberon's Legacy + Fantasy + 5.95 + 2001-03-10 + In post-apocalypse England, the mysterious + agent known only as Oberon helps to create a new life + for the inhabitants of London. Sequel to Maeve + Ascendant. + + + Corets, Eva + The Sundered Grail + Fantasy + 5.95 + 2001-09-10 + The two daughters of Maeve, half-sisters, + battle one another for control of England. Sequel to + Oberon's Legacy. + + + Randall, Cynthia + Lover Birds + Romance + 4.95 + 2000-09-02 + When Carla meets Paul at an ornithology + conference, tempers fly as feathers get ruffled. + + + Thurman, Paula + Splish Splash + Romance + 4.95 + 2000-11-02 + A deep sea diver finds true love twenty + thousand leagues beneath the sea. + + + Knorr, Stefan + Creepy Crawlies + Horror + 4.95 + 2000-12-06 + An anthology of horror stories about roaches, + centipedes, scorpions and other insects. + + + Kress, Peter + Paradox Lost + Science Fiction + 6.95 + 2000-11-02 + After an inadvertant trip through a Heisenberg + Uncertainty Device, James Salway discovers the problems + of being quantum. + + + O'Brien, Tim + Microsoft .NET: The Programming Bible + Computer + 36.95 + 2000-12-09 + Microsoft's .NET initiative is explored in + detail in this deep programmer's reference. + + + O'Brien, Tim + MSXML3: A Comprehensive Guide + Computer + 36.95 + 2000-12-01 + The Microsoft MSXML3 parser is covered in + detail, with attention to XML DOM interfaces, XSLT processing, + SAX and more. + + + Galos, Mike + Visual Studio 7: A Comprehensive Guide + Computer + 49.95 + 2001-04-16 + Microsoft Visual Studio 7 is explored in depth, + looking at how Visual Basic, Visual C++, C#, and ASP+ are + integrated into a comprehensive development + environment. + + diff --git a/test/jaxp/javax/xml/jaxp/unittest/transform/StAX2DOMTest1.xml b/test/jaxp/javax/xml/jaxp/unittest/transform/StAX2DOMTest1.xml new file mode 100644 index 00000000000..c703274f7ae --- /dev/null +++ b/test/jaxp/javax/xml/jaxp/unittest/transform/StAX2DOMTest1.xml @@ -0,0 +1,120 @@ + + + + Gambardella, Matthew + XML Developer's Guide + Computer + 44.95 + 2000-10-01 + An in-depth look at creating applications + with XML. + + + Ralls, Kim + Midnight Rain + Fantasy + 5.95 + 2000-12-16 + A former architect battles corporate zombies, + an evil sorceress, and her own childhood to become queen + of the world. + + + Corets, Eva + Maeve Ascendant + Fantasy + 5.95 + 2000-11-17 + After the collapse of a nanotechnology + society in England, the young survivors lay the + foundation for a new society. + + + Corets, Eva + Oberon's Legacy + Fantasy + 5.95 + 2001-03-10 + In post-apocalypse England, the mysterious + agent known only as Oberon helps to create a new life + for the inhabitants of London. Sequel to Maeve + Ascendant. + + + Corets, Eva + The Sundered Grail + Fantasy + 5.95 + 2001-09-10 + The two daughters of Maeve, half-sisters, + battle one another for control of England. Sequel to + Oberon's Legacy. + + + Randall, Cynthia + Lover Birds + Romance + 4.95 + 2000-09-02 + When Carla meets Paul at an ornithology + conference, tempers fly as feathers get ruffled. + + + Thurman, Paula + Splish Splash + Romance + 4.95 + 2000-11-02 + A deep sea diver finds true love twenty + thousand leagues beneath the sea. + + + Knorr, Stefan + Creepy Crawlies + Horror + 4.95 + 2000-12-06 + An anthology of horror stories about roaches, + centipedes, scorpions and other insects. + + + Kress, Peter + Paradox Lost + Science Fiction + 6.95 + 2000-11-02 + After an inadvertant trip through a Heisenberg + Uncertainty Device, James Salway discovers the problems + of being quantum. + + + O'Brien, Tim + Microsoft .NET: The Programming Bible + Computer + 36.95 + 2000-12-09 + Microsoft's .NET initiative is explored in + detail in this deep programmer's reference. + + + O'Brien, Tim + MSXML3: A Comprehensive Guide + Computer + 36.95 + 2000-12-01 + The Microsoft MSXML3 parser is covered in + detail, with attention to XML DOM interfaces, XSLT processing, + SAX and more. + + + Galos, Mike + Visual Studio 7: A Comprehensive Guide + Computer + 49.95 + 2001-04-16 + Microsoft Visual Studio 7 is explored in depth, + looking at how Visual Basic, Visual C++, C#, and ASP+ are + integrated into a comprehensive development + environment. + + From 798a5869df6fe7f49142837f624afcea3cbb663e Mon Sep 17 00:00:00 2001 From: stefank Date: Wed, 10 Apr 2019 15:41:03 +0200 Subject: [PATCH 093/131] 8221913: Add GC.selected() jtreg-ext function Reviewed-by: kbarrett, pliden --- test/lib/sun/hotspot/gc/GC.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/lib/sun/hotspot/gc/GC.java b/test/lib/sun/hotspot/gc/GC.java index bfc872097a4..2cd83b69fe1 100644 --- a/test/lib/sun/hotspot/gc/GC.java +++ b/test/lib/sun/hotspot/gc/GC.java @@ -69,4 +69,16 @@ public boolean isSelected() { public static boolean isSelectedErgonomically() { return WB.isGCSelectedErgonomically(); } + + /** + * @return the selected GC. + */ + public static GC selected() { + for (GC gc : values()) { + if (gc.isSelected()) { + return gc; + } + } + throw new IllegalStateException("No selected GC found"); + } } From e413a7089cd8eadff20a4bd52b428ab5dc6873a9 Mon Sep 17 00:00:00 2001 From: shade Date: Tue, 1 Oct 2019 15:38:26 +0200 Subject: [PATCH 094/131] 8231503: [TESTBUG] compiler/{jvmci,aot} tests should not run with GCs that do not support JVMCI/AOT Reviewed-by: kvn, dlong, stefank --- test/jtreg-ext/requires/VMProps.java | 36 ++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java index bc7dd35a83c..103444e0165 100644 --- a/test/jtreg-ext/requires/VMProps.java +++ b/test/jtreg-ext/requires/VMProps.java @@ -216,7 +216,22 @@ protected String vmDebug() { */ protected String vmJvmci() { // builds with jvmci have this flag - return "" + (WB.getBooleanVMFlag("EnableJVMCI") != null); + if (WB.getBooleanVMFlag("EnableJVMCI") == null) { + return "false"; + } + + switch (GC.selected()) { + case Serial: + case Parallel: + case G1: + // These GCs are supported with JVMCI + return "true"; + default: + break; + } + + // Every other GC is not supported + return "false"; } /** @@ -342,7 +357,24 @@ protected String vmAOT() { } else { jaotc = bin.resolve("jaotc"); } - return "" + Files.exists(jaotc); + + if (!Files.exists(jaotc)) { + // No jaotc => no AOT + return "false"; + } + + switch (GC.selected()) { + case Serial: + case Parallel: + case G1: + // These GCs are supported with AOT + return "true"; + default: + break; + } + + // Every other GC is not supported + return "false"; } /** From 4094d4a3617d74283110bb17723740da80d938c2 Mon Sep 17 00:00:00 2001 From: igerasim Date: Tue, 10 Sep 2019 09:08:52 -0700 Subject: [PATCH 095/131] 8230303: JDB hangs when running monitor command Reviewed-by: sspitsyn --- .../com/sun/tools/example/debug/tty/TTY.java | 3 +- .../jdb/monitor/monitor002/monitor002.java | 136 ++++++++++++++++++ .../jdb/monitor/monitor002/monitor002a.java | 52 +++++++ 3 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdb/monitor/monitor002/monitor002.java create mode 100644 test/hotspot/jtreg/vmTestbase/nsk/jdb/monitor/monitor002/monitor002a.java diff --git a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java index 5fb37e25b04..e6163b0a074 100644 --- a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java +++ b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java @@ -40,6 +40,7 @@ import com.sun.jdi.connect.*; import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; import java.io.*; public class TTY implements EventNotifier { @@ -48,7 +49,7 @@ public class TTY implements EventNotifier { /** * List of Strings to execute at each stop. */ - private List monitorCommands = new ArrayList(); + private List monitorCommands = new CopyOnWriteArrayList<>(); private int monitorCount = 0; /** diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/monitor/monitor002/monitor002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/monitor/monitor002/monitor002.java new file mode 100644 index 00000000000..757ae8b061c --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/monitor/monitor002/monitor002.java @@ -0,0 +1,136 @@ +/* + * 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 + * + * @summary JDB problem running monitor command + * VM Testbase keywords: [jpda, jdb] + * VM Testbase readme: + * DESCRIPTION + * Make sure 'monitor unmonitor 1' does not cause ConcurrentModificationException + * in the debugger. + * The jdb sets up line breakpoint at the debugged application. Then one command + * 'monitor unmonitor 1' is set. After resuming the debuggee stops at the breakpoint. + * The test passes if correct reply for "unmonitor 1" commanda is found in jdb stdout + * stream. + * The test consists of two program: + * monitor002.java - launches jdb and debuggee, writes commands to jdb, reads the jdb output, + * monitor002a.java - the debugged application. + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @build nsk.jdb.monitor.monitor002.monitor002 + * nsk.jdb.monitor.monitor002.monitor002a + * @run main/othervm PropertyResolvingWrapper nsk.jdb.monitor.monitor002.monitor002 + * -arch=${os.family}-${os.simpleArch} + * -waittime=5 + * -debugee.vmkind=java + * -transport.address=dynamic + * -jdb=${test.jdk}/bin/jdb + * -java.options="${test.vm.opts} ${test.java.opts}" + * -workdir=. + * -debugee.vmkeys="${test.vm.opts} ${test.java.opts}" + */ + +package nsk.jdb.monitor.monitor002; + +import nsk.share.*; +import nsk.share.jdb.*; + +import java.io.*; +import java.util.*; + +public class monitor002 extends JdbTest { + + public static void main (String argv[]) { + System.exit(run(argv, System.out) + JCK_STATUS_BASE); + } + + public static int run(String argv[], PrintStream out) { + debuggeeClass = DEBUGGEE_CLASS; + firstBreak = FIRST_BREAK; + lastBreak = LAST_BREAK; + return new monitor002().runTest(argv, out); + } + + static final String PACKAGE_NAME = "nsk.jdb.monitor.monitor002"; + static final String TEST_CLASS = PACKAGE_NAME + ".monitor002"; + static final String DEBUGGEE_CLASS = TEST_CLASS + "a"; + static final String FIRST_BREAK = DEBUGGEE_CLASS + ".main"; + static final String LAST_BREAK = DEBUGGEE_CLASS + ".lastBreak"; + static final int LINE_NUMBER = 47; + + static final String[] CHECKED_COMMANDS = { + JdbCommand.unmonitor + "1" + }; + + protected void runCases() { + String[] reply; + Paragrep grep; + int count; + Vector v; + String found; + + reply = jdb.receiveReplyFor(JdbCommand.stop_at + DEBUGGEE_CLASS + ":" + LINE_NUMBER); + + for (int i = 0; i < CHECKED_COMMANDS.length; i++) { + reply = jdb.receiveReplyFor(JdbCommand.monitor + CHECKED_COMMANDS[i]); + } + + int repliesCount = CHECKED_COMMANDS.length + 1; + reply = jdb.receiveReplyFor(JdbCommand.cont, true, repliesCount); + + reply = jdb.receiveReplyFor(JdbCommand.monitor); + if (reply.length != 1) { + log.complain("Expected no active monitors after exectuting monitored command: " + CHECKED_COMMANDS[0]); + success = false; + } + + jdb.contToExit(1); + + reply = jdb.getTotalReply(); + + if (!checkCommands(reply)) { + success = false; + } + } + + private boolean checkCommands(String[] reply) { + Paragrep grep; + boolean result = true; + int count; + + grep = new Paragrep(reply); + + if ((count = grep.find("Unmonitoring 1: unmonitor 1")) != 1) { + log.complain("Wrong number of execution of monitored command: " + CHECKED_COMMANDS[0]); + log.complain(" Expected: 1; found: " + count); + result = false; + } + + return result; + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/monitor/monitor002/monitor002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/monitor/monitor002/monitor002a.java new file mode 100644 index 00000000000..cad54b701f7 --- /dev/null +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/monitor/monitor002/monitor002a.java @@ -0,0 +1,52 @@ +/* + * 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 nsk.jdb.monitor.monitor002; + +import nsk.share.*; +import nsk.share.jpda.*; +import nsk.share.jdb.*; + +import java.io.*; + +// THIS TEST IS LINE NUMBER SENSITIVE + +/* This is debuggee aplication */ +public class monitor002a { + static monitor002a _monitor002a = new monitor002a(); + + public static void main(String args[]) { + System.exit(monitor002.JCK_STATUS_BASE + _monitor002a.runIt(args, System.out)); + } + + static void lastBreak () {} + + public int runIt(String args[], PrintStream out) { + JdbArgumentHandler argumentHandler = new JdbArgumentHandler(args); + Log log = new Log(out, argumentHandler); + int localInt = 0; // monitor002.LINE_NUMBER + localInt++; // dummy breakpoint + log.display("Debuggee PASSED"); + return monitor002.PASSED; + } +} From bada99cd26d4dd71e2e1a573bd663e6a0efcaaa5 Mon Sep 17 00:00:00 2001 From: lbourges Date: Mon, 30 Sep 2019 15:30:12 +0200 Subject: [PATCH 096/131] 8230728: Thin stroked shapes are not rendered if affine transform has flip bit Summary: use abs(at.getDeterminant()) in userSpaceLineWidth() to ensure positive value Reviewed-by: prr, jdv --- .../java2d/marlin/DMarlinRenderingEngine.java | 3 +- .../java2d/marlin/MarlinRenderingEngine.java | 3 +- .../classes/sun/java2d/marlin/Version.java | 2 +- test/jdk/sun/java2d/marlin/FlipBitTest.java | 104 ++++++++++++++++++ 4 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 test/jdk/sun/java2d/marlin/FlipBitTest.java diff --git a/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java b/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java index f3d44e3ba92..66858dfdd5a 100644 --- a/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java +++ b/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java @@ -246,7 +246,8 @@ private double userSpaceLineWidth(AffineTransform at, double lw) { widthScale = 1.0d; } else if ((at.getType() & (AffineTransform.TYPE_GENERAL_TRANSFORM | AffineTransform.TYPE_GENERAL_SCALE)) != 0) { - widthScale = Math.sqrt(at.getDeterminant()); + // Determinant may be negative (flip), use its absolute value: + widthScale = Math.sqrt(Math.abs(at.getDeterminant())); } else { // First calculate the "maximum scale" of this transform. double A = at.getScaleX(); // m00 diff --git a/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java b/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java index a3baed14378..3bba4c194b2 100644 --- a/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java +++ b/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java @@ -245,7 +245,8 @@ private float userSpaceLineWidth(AffineTransform at, float lw) { widthScale = 1.0f; } else if ((at.getType() & (AffineTransform.TYPE_GENERAL_TRANSFORM | AffineTransform.TYPE_GENERAL_SCALE)) != 0) { - widthScale = (float)Math.sqrt(at.getDeterminant()); + // Determinant may be negative (flip), use its absolute value: + widthScale = (float)Math.sqrt(Math.abs(at.getDeterminant())); } else { // First calculate the "maximum scale" of this transform. double A = at.getScaleX(); // m00 diff --git a/src/java.desktop/share/classes/sun/java2d/marlin/Version.java b/src/java.desktop/share/classes/sun/java2d/marlin/Version.java index e7e94ffe397..0155b049fab 100644 --- a/src/java.desktop/share/classes/sun/java2d/marlin/Version.java +++ b/src/java.desktop/share/classes/sun/java2d/marlin/Version.java @@ -27,7 +27,7 @@ public final class Version { - private static final String VERSION = "marlin-0.9.1.2-Unsafe-OpenJDK"; + private static final String VERSION = "marlin-0.9.1.3-Unsafe-OpenJDK"; public static String getVersion() { return VERSION; diff --git a/test/jdk/sun/java2d/marlin/FlipBitTest.java b/test/jdk/sun/java2d/marlin/FlipBitTest.java new file mode 100644 index 00000000000..d966f701f6f --- /dev/null +++ b/test/jdk/sun/java2d/marlin/FlipBitTest.java @@ -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. + */ + + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import javax.imageio.ImageIO; + + +/** + * Tests calculating user space line with a negative determinant (flip). + * + * @test + * @summary verify that flipped transformed lines are properly rasterized + * @bug 8230728 + */ +public class FlipBitTest { + + static final boolean SAVE_IMAGE = false; + + public static void main(final String[] args) { + + final int size = 100; + + // First display which renderer is tested: + // JDK9 only: + System.setProperty("sun.java2d.renderer.verbose", "true"); + + System.out.println("FlipBitTest: size = " + size); + + final BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); + + final Graphics2D g2d = (Graphics2D) image.getGraphics(); + try { + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); + + final AffineTransform at = new AffineTransform(); + at.setToScale(1, -1.01); + g2d.setTransform(at); + + g2d.translate(0, -image.getHeight()); + g2d.setPaint(Color.WHITE); + g2d.fill(new Rectangle(image.getWidth(), image.getHeight())); + + g2d.setPaint(Color.BLACK); + g2d.setStroke(new BasicStroke(0.1f)); + g2d.draw(new Ellipse2D.Double(25, 25, 50, 50)); + + if (SAVE_IMAGE) { + try { + final File file = new File("FlipBitTest.png"); + + System.out.println("Writing file: " + file.getAbsolutePath()); + ImageIO.write(image, "PNG", file); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + + boolean nonWhitePixelFound = false; + for (int x = 0; x < image.getWidth(); ++x) { + if (image.getRGB(x, 50) != Color.WHITE.getRGB()) { + nonWhitePixelFound = true; + break; + } + } + if (!nonWhitePixelFound) { + throw new IllegalStateException("The ellipse was not drawn"); + } + } finally { + g2d.dispose(); + } + } +} From efddca339978d26e83b3f55619272b863d99ee24 Mon Sep 17 00:00:00 2001 From: lbourges Date: Tue, 1 Oct 2019 14:41:48 +0200 Subject: [PATCH 097/131] 8231693: Backout "8230728: Thin stroked shapes are not rendered if affine transform has flip bit" from jdk11u Summary: revert push to jdk11u Reviewed-by: sgehwolf --- .../java2d/marlin/DMarlinRenderingEngine.java | 3 +- .../java2d/marlin/MarlinRenderingEngine.java | 3 +- .../classes/sun/java2d/marlin/Version.java | 2 +- test/jdk/sun/java2d/marlin/FlipBitTest.java | 104 ------------------ 4 files changed, 3 insertions(+), 109 deletions(-) delete mode 100644 test/jdk/sun/java2d/marlin/FlipBitTest.java diff --git a/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java b/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java index 66858dfdd5a..f3d44e3ba92 100644 --- a/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java +++ b/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java @@ -246,8 +246,7 @@ private double userSpaceLineWidth(AffineTransform at, double lw) { widthScale = 1.0d; } else if ((at.getType() & (AffineTransform.TYPE_GENERAL_TRANSFORM | AffineTransform.TYPE_GENERAL_SCALE)) != 0) { - // Determinant may be negative (flip), use its absolute value: - widthScale = Math.sqrt(Math.abs(at.getDeterminant())); + widthScale = Math.sqrt(at.getDeterminant()); } else { // First calculate the "maximum scale" of this transform. double A = at.getScaleX(); // m00 diff --git a/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java b/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java index 3bba4c194b2..a3baed14378 100644 --- a/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java +++ b/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java @@ -245,8 +245,7 @@ private float userSpaceLineWidth(AffineTransform at, float lw) { widthScale = 1.0f; } else if ((at.getType() & (AffineTransform.TYPE_GENERAL_TRANSFORM | AffineTransform.TYPE_GENERAL_SCALE)) != 0) { - // Determinant may be negative (flip), use its absolute value: - widthScale = (float)Math.sqrt(Math.abs(at.getDeterminant())); + widthScale = (float)Math.sqrt(at.getDeterminant()); } else { // First calculate the "maximum scale" of this transform. double A = at.getScaleX(); // m00 diff --git a/src/java.desktop/share/classes/sun/java2d/marlin/Version.java b/src/java.desktop/share/classes/sun/java2d/marlin/Version.java index 0155b049fab..e7e94ffe397 100644 --- a/src/java.desktop/share/classes/sun/java2d/marlin/Version.java +++ b/src/java.desktop/share/classes/sun/java2d/marlin/Version.java @@ -27,7 +27,7 @@ public final class Version { - private static final String VERSION = "marlin-0.9.1.3-Unsafe-OpenJDK"; + private static final String VERSION = "marlin-0.9.1.2-Unsafe-OpenJDK"; public static String getVersion() { return VERSION; diff --git a/test/jdk/sun/java2d/marlin/FlipBitTest.java b/test/jdk/sun/java2d/marlin/FlipBitTest.java deleted file mode 100644 index d966f701f6f..00000000000 --- a/test/jdk/sun/java2d/marlin/FlipBitTest.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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. - */ - - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.geom.AffineTransform; -import java.awt.geom.Ellipse2D; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import javax.imageio.ImageIO; - - -/** - * Tests calculating user space line with a negative determinant (flip). - * - * @test - * @summary verify that flipped transformed lines are properly rasterized - * @bug 8230728 - */ -public class FlipBitTest { - - static final boolean SAVE_IMAGE = false; - - public static void main(final String[] args) { - - final int size = 100; - - // First display which renderer is tested: - // JDK9 only: - System.setProperty("sun.java2d.renderer.verbose", "true"); - - System.out.println("FlipBitTest: size = " + size); - - final BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); - - final Graphics2D g2d = (Graphics2D) image.getGraphics(); - try { - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); - g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); - - final AffineTransform at = new AffineTransform(); - at.setToScale(1, -1.01); - g2d.setTransform(at); - - g2d.translate(0, -image.getHeight()); - g2d.setPaint(Color.WHITE); - g2d.fill(new Rectangle(image.getWidth(), image.getHeight())); - - g2d.setPaint(Color.BLACK); - g2d.setStroke(new BasicStroke(0.1f)); - g2d.draw(new Ellipse2D.Double(25, 25, 50, 50)); - - if (SAVE_IMAGE) { - try { - final File file = new File("FlipBitTest.png"); - - System.out.println("Writing file: " + file.getAbsolutePath()); - ImageIO.write(image, "PNG", file); - } catch (IOException ex) { - ex.printStackTrace(); - } - } - - boolean nonWhitePixelFound = false; - for (int x = 0; x < image.getWidth(); ++x) { - if (image.getRGB(x, 50) != Color.WHITE.getRGB()) { - nonWhitePixelFound = true; - break; - } - } - if (!nonWhitePixelFound) { - throw new IllegalStateException("The ellipse was not drawn"); - } - } finally { - g2d.dispose(); - } - } -} From b40a46f19d7839baa531f576a681015e90ee7386 Mon Sep 17 00:00:00 2001 From: ccheung Date: Fri, 14 Sep 2018 11:17:25 -0700 Subject: [PATCH 098/131] 8190737: use unicode version of the canonicalize() function to handle long path on windows Summary: also calling CreateFileW in zip_util.c to handle long path Reviewed-by: sherman, iklam --- src/hotspot/os/windows/include/jvm_md.h | 2 +- src/java.base/share/native/libzip/zip_util.c | 42 ++++++++-- .../windows/native/libjava/canonicalize_md.c | 80 +++++++++++++------ .../windows/native/libjava/io_util_md.h | 2 +- .../jtreg/runtime/LoadClass/LongBCP.java | 19 +++++ 5 files changed, 112 insertions(+), 33 deletions(-) diff --git a/src/hotspot/os/windows/include/jvm_md.h b/src/hotspot/os/windows/include/jvm_md.h index e047137c783..4baba320855 100644 --- a/src/hotspot/os/windows/include/jvm_md.h +++ b/src/hotspot/os/windows/include/jvm_md.h @@ -63,7 +63,7 @@ typedef struct { #include /* For uintptr_t */ #include -#define JVM_MAXPATHLEN _MAX_PATH +#define JVM_MAXPATHLEN 1024 #define JVM_R_OK 4 #define JVM_W_OK 2 diff --git a/src/java.base/share/native/libzip/zip_util.c b/src/java.base/share/native/libzip/zip_util.c index 76c40747bb2..f129e4548e5 100644 --- a/src/java.base/share/native/libzip/zip_util.c +++ b/src/java.base/share/native/libzip/zip_util.c @@ -100,6 +100,9 @@ DEF_STATIC_JNI_OnLoad static ZFILE ZFILE_Open(const char *fname, int flags) { #ifdef WIN32 + WCHAR *wfname, *wprefixed_fname; + size_t converted_chars, fname_length; + jlong fhandle; const DWORD access = (flags & O_RDWR) ? (GENERIC_WRITE | GENERIC_READ) : (flags & O_WRONLY) ? GENERIC_WRITE : @@ -121,14 +124,37 @@ ZFILE_Open(const char *fname, int flags) { FILE_ATTRIBUTE_NORMAL; const DWORD flagsAndAttributes = maybeWriteThrough | maybeDeleteOnClose; - return (jlong) CreateFile( - fname, /* Wide char path name */ - access, /* Read and/or write permission */ - sharing, /* File sharing flags */ - NULL, /* Security attributes */ - disposition, /* creation disposition */ - flagsAndAttributes, /* flags and attributes */ - NULL); + fname_length = strlen(fname); + if (fname_length < MAX_PATH) { + return (jlong)CreateFile( + fname, /* path name in multibyte char */ + access, /* Read and/or write permission */ + sharing, /* File sharing flags */ + NULL, /* Security attributes */ + disposition, /* creation disposition */ + flagsAndAttributes, /* flags and attributes */ + NULL); + } else { + if ((wfname = (WCHAR*)malloc((fname_length + 1) * sizeof(WCHAR))) == NULL) + return (jlong)INVALID_HANDLE_VALUE; + + if (mbstowcs_s(&converted_chars, wfname, fname_length + 1, fname, fname_length) != 0) { + free(wfname); + return (jlong)INVALID_HANDLE_VALUE; + } + wprefixed_fname = getPrefixed(wfname, (int)fname_length); + fhandle = (jlong)CreateFileW( + wprefixed_fname, /* Wide char path name */ + access, /* Read and/or write permission */ + sharing, /* File sharing flags */ + NULL, /* Security attributes */ + disposition, /* creation disposition */ + flagsAndAttributes, /* flags and attributes */ + NULL); + free(wfname); + free(wprefixed_fname); + return fhandle; + } #else return open(fname, flags, 0); #endif diff --git a/src/java.base/windows/native/libjava/canonicalize_md.c b/src/java.base/windows/native/libjava/canonicalize_md.c index ba0d08624e3..b51919e77e4 100644 --- a/src/java.base/windows/native/libjava/canonicalize_md.c +++ b/src/java.base/windows/native/libjava/canonicalize_md.c @@ -225,6 +225,8 @@ lastErrorReportable() return 1; } +int wcanonicalize(WCHAR *orig_path, WCHAR *result, int size); + /* Convert a pathname to canonical form. The input orig_path is assumed to have been converted to native form already, via JVM_NativePath(). This is necessary because _fullpath() rejects duplicate separator characters on @@ -237,6 +239,38 @@ canonicalize(char *orig_path, char *result, int size) HANDLE h; char path[1024]; /* Working copy of path */ char *src, *dst, *dend; + wchar_t *worig_path, *wresult; + size_t converted_chars = 0; + + /* handle long path with length >= MAX_PATH */ + if (strlen(orig_path) >= MAX_PATH) { + if ((worig_path = (WCHAR*)malloc(size * sizeof(WCHAR))) == NULL) + return -1; + + if (mbstowcs_s(&converted_chars, worig_path, (size_t)size, orig_path, (size_t)(size - 1)) != 0) { + free(worig_path); + return -1; + } + + if ((wresult = (WCHAR*)malloc(size * sizeof(WCHAR))) == NULL) + return -1; + + if (wcanonicalize(worig_path, wresult, size) != 0) { + free(worig_path); + free(wresult); + return -1; + } + + if (wcstombs_s(&converted_chars, result, (size_t)size, wresult, (size_t)(size - 1)) != 0) { + free(worig_path); + free(wresult); + return -1; + } + + free(worig_path); + free(wresult); + return 0; + } /* Reject paths that contain wildcards */ if (wild(orig_path)) { @@ -245,15 +279,15 @@ canonicalize(char *orig_path, char *result, int size) } /* Collapse instances of "foo\.." and ensure absoluteness. Note that - contrary to the documentation, the _fullpath procedure does not require - the drive to be available. It also does not reliably change all - occurrences of '/' to '\\' on Win95, so now JVM_NativePath does that. */ - if(!_fullpath(path, orig_path, sizeof(path))) { + contrary to the documentation, the _fullpath procedure does not require + the drive to be available. It also does not reliably change all + occurrences of '/' to '\\' on Win95, so now JVM_NativePath does that. */ + if (!_fullpath(path, orig_path, sizeof(path))) { return -1; } /* Correction for Win95: _fullpath may leave a trailing "\\" - on a UNC pathname */ + on a UNC pathname */ if ((path[0] == '\\') && (path[1] == '\\')) { char *p = path + strlen(path); if ((p[-1] == '\\') && !islb(p[-2])) { @@ -281,16 +315,16 @@ canonicalize(char *orig_path, char *result, int size) char *p; p = nextsep(src + 2); /* Skip past host name */ if (!*p) { - /* A UNC pathname must begin with "\\\\host\\share", - so reject this path as invalid if there is no share name */ + /* A UNC pathname must begin with "\\\\host\\share", + so reject this path as invalid if there is no share name */ errno = EINVAL; return -1; - } - p = nextsep(p + 1); /* Skip past share name */ - if (!(dst = cp(dst, dend, '\0', src, p))) { - return -1; - } - src = p; + } + p = nextsep(p + 1); /* Skip past share name */ + if (!(dst = cp(dst, dend, '\0', src, p))) { + return -1; + } + src = p; } else { /* Invalid path */ errno = EINVAL; @@ -309,11 +343,11 @@ canonicalize(char *orig_path, char *result, int size) } /* At this point we have copied either a drive specifier ("z:") or a UNC - prefix ("\\\\host\\share") to the result buffer, and src points to the - first byte of the remainder of the path. We now scan through the rest - of the path, looking up each prefix in order to find the true name of - the last element of each prefix, thereby computing the full true name of - the original path. */ + prefix ("\\\\host\\share") to the result buffer, and src points to the + first byte of the remainder of the path. We now scan through the rest + of the path, looking up each prefix in order to find the true name of + the last element of each prefix, thereby computing the full true name of + the original path. */ while (*src) { char *p = nextsep(src + 1); /* Find next separator */ char c = *p; @@ -325,8 +359,8 @@ canonicalize(char *orig_path, char *result, int size) /* Lookup succeeded; append true name to result and continue */ FindClose(h); if (!(dst = cp(dst, dend, '\\', - fd.cFileName, - fd.cFileName + strlen(fd.cFileName)))) { + fd.cFileName, + fd.cFileName + strlen(fd.cFileName)))) { return -1; } src = p; @@ -344,8 +378,8 @@ canonicalize(char *orig_path, char *result, int size) } if (dst >= dend) { - errno = ENAMETOOLONG; - return -1; + errno = ENAMETOOLONG; + return -1; } *dst = '\0'; return 0; @@ -587,7 +621,7 @@ wcanonicalizeWithPrefix(WCHAR *canonicalPrefix, WCHAR *pathWithCanonicalPrefix, */ /* copy \\?\ or \\?\UNC\ to the front of path*/ -WCHAR* +__declspec(dllexport) WCHAR* getPrefixed(const WCHAR* path, int pathlen) { WCHAR* pathbuf = (WCHAR*)malloc((pathlen + 10) * sizeof (WCHAR)); if (pathbuf != 0) { diff --git a/src/java.base/windows/native/libjava/io_util_md.h b/src/java.base/windows/native/libjava/io_util_md.h index 66f9ab5b214..b1a272ac0fd 100644 --- a/src/java.base/windows/native/libjava/io_util_md.h +++ b/src/java.base/windows/native/libjava/io_util_md.h @@ -38,7 +38,7 @@ */ WCHAR* pathToNTPath(JNIEnv *env, jstring path, jboolean throwFNFE); WCHAR* fileToNTPath(JNIEnv *env, jobject file, jfieldID id); -WCHAR* getPrefixed(const WCHAR* path, int pathlen); +__declspec(dllexport) WCHAR* getPrefixed(const WCHAR* path, int pathlen); WCHAR* currentDir(int di); int currentDirLength(const WCHAR* path, int pathlen); int handleAvailable(FD fd, jlong *pbytes); diff --git a/test/hotspot/jtreg/runtime/LoadClass/LongBCP.java b/test/hotspot/jtreg/runtime/LoadClass/LongBCP.java index e1404c032d2..f6cdf4b40c7 100644 --- a/test/hotspot/jtreg/runtime/LoadClass/LongBCP.java +++ b/test/hotspot/jtreg/runtime/LoadClass/LongBCP.java @@ -29,9 +29,11 @@ * @library /test/lib * @modules java.base/jdk.internal.misc * java.management + * jdk.jartool/sun.tools.jar * @run main LongBCP */ +import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; @@ -81,6 +83,23 @@ public static void main(String args[]) throws Exception { output.shouldContain("Hello World") .shouldHaveExitValue(0); + // create a hello.jar + sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar"); + String helloJar = destDir.toString() + File.separator + "hello.jar"; + if (!jarTool.run(new String[] + {"-cf", helloJar, "-C", destDir.toString(), "Hello.class"})) { + throw new RuntimeException("Could not write the Hello jar file"); + } + + // run with long bootclasspath to hello.jar + bootCP = "-Xbootclasspath/a:" + helloJar; + pb = ProcessTools.createJavaProcessBuilder( + bootCP, "Hello"); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Hello World") + .shouldHaveExitValue(0); + // relative path tests // We currently cannot handle relative path specified in the // -Xbootclasspath/a on windows. From 84e885223b329166ffe4a265a1b6562562d4e27c Mon Sep 17 00:00:00 2001 From: erikj Date: Mon, 24 Sep 2018 13:51:22 -0700 Subject: [PATCH 099/131] 8211037: Load jib jars dynamically from JibArtifactManager Reviewed-by: ihse --- make/RunTests.gmk | 4 +- make/autoconf/spec.gmk.in | 2 +- make/autoconf/toolchain.m4 | 2 +- make/conf/jib-profiles.js | 4 +- test/TestCommon.gmk | 4 +- .../test/lib/artifacts/ArtifactResolver.java | 3 +- .../lib/artifacts/JibArtifactManager.java | 70 ++++++++++++++++--- 7 files changed, 69 insertions(+), 20 deletions(-) diff --git a/make/RunTests.gmk b/make/RunTests.gmk index af958831be7..c78ee7acf6c 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -562,8 +562,8 @@ define SetupRunJtregTestBody $1_JTREG_BASIC_OPTIONS += $$(addprefix -exclude:, $$($1_JTREG_PROBLEM_LIST)) endif - ifneq ($$(JIB_JAR), ) - $1_JTREG_BASIC_OPTIONS += -cpa:$$(JIB_JAR) + ifneq ($$(JIB_HOME), ) + $1_JTREG_BASIC_OPTIONS += -e:JIB_HOME=$$(JIB_HOME) endif $1_JTREG_BASIC_OPTIONS += -e:TEST_IMAGE_GRAAL_DIR=${TEST_IMAGE_DIR}/hotspot/jtreg/graal diff --git a/make/autoconf/spec.gmk.in b/make/autoconf/spec.gmk.in index c6523d7bd71..a458e99a020 100644 --- a/make/autoconf/spec.gmk.in +++ b/make/autoconf/spec.gmk.in @@ -732,7 +732,7 @@ SETFILE:=@SETFILE@ XATTR:=@XATTR@ JT_HOME:=@JT_HOME@ JTREGEXE:=@JTREGEXE@ -JIB_JAR:=@JIB_JAR@ +JIB_HOME:=@JIB_HOME@ XCODEBUILD=@XCODEBUILD@ DTRACE := @DTRACE@ FIXPATH:=@FIXPATH@ diff --git a/make/autoconf/toolchain.m4 b/make/autoconf/toolchain.m4 index 91fabcd4f49..a0b49a48057 100644 --- a/make/autoconf/toolchain.m4 +++ b/make/autoconf/toolchain.m4 @@ -1144,5 +1144,5 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_JIB], fi fi - AC_SUBST(JIB_JAR) + AC_SUBST(JIB_HOME) ]) diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 20a92a1b923..e3af3b41a0c 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -941,9 +941,9 @@ var getJibProfilesDependencies = function (input, common) { ext: "zip", classifier: "distribution", revision: "3.0-SNAPSHOT", - environment_name: "JIB_JAR", + environment_name: "JIB_HOME", environment_value: input.get("jib", "install_path") - + "/jib-3.0-SNAPSHOT-distribution/lib/jib-3.0-SNAPSHOT.jar" + + "/jib-3.0-SNAPSHOT-distribution" }, ant: { diff --git a/test/TestCommon.gmk b/test/TestCommon.gmk index 2d9b8288d7d..a51ce82c7b5 100644 --- a/test/TestCommon.gmk +++ b/test/TestCommon.gmk @@ -429,8 +429,8 @@ JTREG_BASIC_OPTIONS += -e:TEST_IMAGE_GRAAL_DIR=${TEST_IMAGE_DIR}/hotspot/jtreg/g # Set other vm and test options JTREG_TEST_OPTIONS += $(JAVA_ARGS:%=-javaoptions:%) $(JAVA_VM_ARGS:%=-vmoption:%) -ifneq ($(JIB_JAR), ) - JTREG_BASIC_OPTIONS += -cpa:$(shell $(GETMIXEDPATH) "$(JIB_JAR)") +ifneq ($(JIB_HOME), ) + JTREG_BASIC_OPTIONS += -e:JIB_HOME=$(shell $(GETMIXEDPATH) "$(JIB_HOME)") endif ifeq ($(IGNORE_MARKED_TESTS), true) # Option to tell jtreg to not run tests marked with "ignore" diff --git a/test/lib/jdk/test/lib/artifacts/ArtifactResolver.java b/test/lib/jdk/test/lib/artifacts/ArtifactResolver.java index 0c8c4b118fb..d4c2ccbcad6 100644 --- a/test/lib/jdk/test/lib/artifacts/ArtifactResolver.java +++ b/test/lib/jdk/test/lib/artifacts/ArtifactResolver.java @@ -23,7 +23,6 @@ package jdk.test.lib.artifacts; -import java.io.FileNotFoundException; import java.nio.file.Path; import java.util.HashMap; import java.util.Map; @@ -35,7 +34,7 @@ public static Map resolve(Class klass) throws ArtifactResolverE String managerName = System.getProperty("jdk.test.lib.artifacts.artifactmanager"); if (managerName != null) { manager = (ArtifactManager) Class.forName(managerName).newInstance(); - } else { + } else if (System.getenv().containsKey(JibArtifactManager.JIB_HOME_ENV_NAME)) { manager = JibArtifactManager.newInstance(); } } catch (Exception e) { diff --git a/test/lib/jdk/test/lib/artifacts/JibArtifactManager.java b/test/lib/jdk/test/lib/artifacts/JibArtifactManager.java index 964c324684b..0f08e087807 100644 --- a/test/lib/jdk/test/lib/artifacts/JibArtifactManager.java +++ b/test/lib/jdk/test/lib/artifacts/JibArtifactManager.java @@ -23,26 +23,66 @@ package jdk.test.lib.artifacts; -import java.io.FileNotFoundException; +import java.io.UncheckedIOException; import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; +import java.util.stream.Stream; public class JibArtifactManager implements ArtifactManager { private static final String JIB_SERVICE_FACTORY = "com.oracle.jib.api.JibServiceFactory"; + public static final String JIB_HOME_ENV_NAME = "JIB_HOME"; private static String jibVersion = "1.0"; + private Object installerObject; + private ClassLoader classLoader; - private JibArtifactManager(Object o) { - installerObject = o; + private JibArtifactManager(Object installerObject, ClassLoader classLoader) { + this.installerObject = installerObject; + this.classLoader = classLoader; } public static JibArtifactManager newInstance() throws ClassNotFoundException { + Path jibInstallDir = Paths.get(System.getenv(JIB_HOME_ENV_NAME)); + Path libDir = jibInstallDir.resolve("lib"); + if (!Files.isDirectory(libDir)) { + throw new ClassNotFoundException(JIB_SERVICE_FACTORY); + } try { - Class jibServiceFactory = Class.forName(JIB_SERVICE_FACTORY); - Object jibArtifactInstaller = jibServiceFactory.getMethod("createJibArtifactInstaller").invoke(null); - return new JibArtifactManager(jibArtifactInstaller); + URL[] jarUrls; + try (Stream files = Files.list(libDir)) { + jarUrls = files.filter(path -> path.toString().endsWith(".jar")) + .map(path -> { + try { + return path.toUri().toURL(); + } catch (MalformedURLException e) { + throw new UncheckedIOException(e); + } + }).toArray(URL[]::new); + } + // Create a class loader using all those jars and set the parent to the + // current class loader's parent. + ClassLoader classLoader = new URLClassLoader(jarUrls, JibArtifactManager.class.getClassLoader().getParent()); + + // Temporarily replace the context classLoader + Thread currentThread = Thread.currentThread(); + ClassLoader oldContextLoader = currentThread.getContextClassLoader(); + currentThread.setContextClassLoader(classLoader); + + Class jibServiceFactory = classLoader.loadClass(JIB_SERVICE_FACTORY); + try { + Object jibArtifactInstaller = jibServiceFactory.getMethod("createJibArtifactInstaller").invoke(null); + return new JibArtifactManager(jibArtifactInstaller, classLoader); + } finally { + currentThread.setContextClassLoader(oldContextLoader); + } + } catch (Exception e) { throw new ClassNotFoundException(JIB_SERVICE_FACTORY, e); } @@ -56,9 +96,19 @@ private Path install(String jibVersion, HashMap artifactDescript return invokeInstallerMethod("install", jibVersion, artifactDescription); } - private Path invokeInstallerMethod(String methodName, String jibVersion, HashMap artifactDescription) throws Exception { - Method m = Class.forName("com.oracle.jib.api.JibArtifactInstaller").getMethod(methodName, String.class, Map.class); - return (Path)m.invoke(installerObject, jibVersion, artifactDescription); + private Path invokeInstallerMethod(String methodName, String jibVersion, + HashMap artifactDescription) throws Exception { + // Temporarily replace the context classLoader + Thread currentThread = Thread.currentThread(); + ClassLoader oldContextLoader = currentThread.getContextClassLoader(); + currentThread.setContextClassLoader(classLoader); + try { + Method m = classLoader.loadClass("com.oracle.jib.api.JibArtifactInstaller") + .getMethod(methodName, String.class, Map.class); + return (Path) m.invoke(installerObject, jibVersion, artifactDescription); + } finally { + currentThread.setContextClassLoader(oldContextLoader); + } } @Override @@ -89,5 +139,5 @@ public Path resolve(Artifact artifact) throws ArtifactResolverException { } } return path; - } + } } From 2ae9dbabd039adebbced8baf6048f4d0c6e98699 Mon Sep 17 00:00:00 2001 From: erikj Date: Mon, 15 Oct 2018 11:36:20 -0700 Subject: [PATCH 100/131] 8212028: Use run-test makefile framework for testing in Oracle's Mach5 Reviewed-by: ihse --- make/Help.gmk | 2 +- make/RunTests.gmk | 98 ++++++++++++++----- make/RunTestsPrebuilt.gmk | 62 +++++++----- make/RunTestsPrebuiltSpec.gmk | 12 ++- make/common/MakeBase.gmk | 8 +- make/conf/jib-profiles.js | 38 +++++-- .../escapeAnalysis/TestArrayCopy.java | 2 +- .../compiler/graalunit/JttLangMathALTest.java | 3 +- .../compiler/graalunit/JttLangMathMZTest.java | 3 +- .../ContinuousCallSiteTargetChange.java | 2 +- .../appcds/jvmti/InstrumentationApp.java | 8 +- .../appcds/jvmti/InstrumentationTest.java | 4 +- .../correctBootstrap/TestDescription.java | 2 +- .../incorrectBootstrap/TestDescription.java | 2 +- .../stress/classfmt/mh/TestDescription.java | 2 +- .../stress/classfmt/mt/TestDescription.java | 2 +- .../stress/gc/createLotsOfMHConsts/Test.java | 2 +- test/jdk/tools/jimage/JImageExtractTest.java | 2 +- 18 files changed, 173 insertions(+), 81 deletions(-) diff --git a/make/Help.gmk b/make/Help.gmk index 461d3431a62..e58f54862af 100644 --- a/make/Help.gmk +++ b/make/Help.gmk @@ -119,7 +119,7 @@ print-configurations: run-test-prebuilt: @( cd $(topdir) && \ $(MAKE) --no-print-directory -r -R -I make/common/ -f make/RunTestsPrebuilt.gmk \ - run-test-prebuilt TEST="$(TEST)" ) + run-test-prebuilt CUSTOM_MAKE_DIR=$(CUSTOM_MAKE_DIR) TEST="$(TEST)" ) ALL_GLOBAL_TARGETS := help print-configurations run-test-prebuilt diff --git a/make/RunTests.gmk b/make/RunTests.gmk index c78ee7acf6c..be138562296 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -82,8 +82,8 @@ ifneq ($(TEST_VM_OPTS), ) endif $(eval $(call ParseKeywordVariable, TEST_OPTS, \ - KEYWORDS := JOBS TIMEOUT, \ - STRING_KEYWORDS := VM_OPTIONS, \ + SINGLE_KEYWORDS := JOBS TIMEOUT_FACTOR, \ + STRING_KEYWORDS := VM_OPTIONS JAVA_OPTIONS, \ )) # Helper function to propagate TEST_OPTS values. @@ -140,6 +140,31 @@ endif GTEST_LAUNCHER_DIRS := $(patsubst %/gtestLauncher, %, $(wildcard $(TEST_IMAGE_DIR)/hotspot/gtest/*/gtestLauncher)) GTEST_VARIANTS := $(strip $(patsubst $(TEST_IMAGE_DIR)/hotspot/gtest/%, %, $(GTEST_LAUNCHER_DIRS))) +################################################################################ +# Setup global test running parameters +################################################################################ + +# Each factor variable comes in 3 variants. The first one is reserved for users +# to use on command line. The other two are for predifined configurations in JDL +# and for machine specific configurations respectively. +TEST_JOBS_FACTOR ?= 1 +TEST_JOBS_FACTOR_JDL ?= 1 +TEST_JOBS_FACTOR_MACHINE ?= 1 + +ifeq ($(TEST_JOBS), 0) + # Concurrency based on min(cores / 2, 12) * TEST_JOBS_FACTOR + TEST_JOBS := $(shell $(AWK) \ + 'BEGIN { \ + c = $(NUM_CORES) / 2; \ + if (c > 12) c = 12; \ + c = c * $(TEST_JOBS_FACTOR); \ + c = c * $(TEST_JOBS_FACTOR_JDL); \ + c = c * $(TEST_JOBS_FACTOR_MACHINE); \ + if (c < 1) c = 1; \ + printf "%.0f", c; \ + }') +endif + ################################################################################ # Parse control variables ################################################################################ @@ -147,16 +172,19 @@ GTEST_VARIANTS := $(strip $(patsubst $(TEST_IMAGE_DIR)/hotspot/gtest/%, %, $(GTE ifneq ($(TEST_OPTS), ) # Inform the user $(info Running tests using TEST_OPTS control variable '$(TEST_OPTS)') +endif - $(eval $(call SetTestOpt,VM_OPTIONS,JTREG)) - $(eval $(call SetTestOpt,VM_OPTIONS,GTEST)) +$(eval $(call SetTestOpt,VM_OPTIONS,JTREG)) +$(eval $(call SetTestOpt,JAVA_OPTIONS,JTREG)) +$(eval $(call SetTestOpt,VM_OPTIONS,GTEST)) +$(eval $(call SetTestOpt,JAVA_OPTIONS,GTEST)) - $(eval $(call SetTestOpt,JOBS,JTREG)) - $(eval $(call SetTestOpt,TIMEOUT,JTREG)) -endif +$(eval $(call SetTestOpt,JOBS,JTREG)) +$(eval $(call SetTestOpt,TIMEOUT_FACTOR,JTREG)) $(eval $(call ParseKeywordVariable, JTREG, \ - KEYWORDS := JOBS TIMEOUT TEST_MODE ASSERT VERBOSE RETAIN MAX_MEM, \ + SINGLE_KEYWORDS := JOBS TIMEOUT_FACTOR TEST_MODE ASSERT VERBOSE RETAIN MAX_MEM \ + EXTRA_PROBLEM_LISTS KEYWORDS, \ STRING_KEYWORDS := OPTIONS JAVA_OPTIONS VM_OPTIONS, \ )) @@ -166,8 +194,8 @@ ifneq ($(JTREG), ) endif $(eval $(call ParseKeywordVariable, GTEST, \ - KEYWORDS := REPEAT, \ - STRING_KEYWORDS := OPTIONS VM_OPTIONS, \ + SINGLE_KEYWORDS := REPEAT, \ + STRING_KEYWORDS := OPTIONS VM_OPTIONS JAVA_OPTIONS, \ )) ifneq ($(GTEST), ) @@ -396,15 +424,16 @@ define SetupRunGtestTestBody $1_GTEST_REPEAT :=--gtest_repeat=$$(GTEST_REPEAT) endif - run-test-$1: + run-test-$1: $(TEST_PREREQS) $$(call LogWarn) $$(call LogWarn, Running test '$$($1_TEST)') $$(call MakeDir, $$($1_TEST_RESULTS_DIR) $$($1_TEST_SUPPORT_DIR)) $$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/gtest, \ $$(FIXPATH) $$(TEST_IMAGE_DIR)/hotspot/gtest/$$($1_VARIANT)/gtestLauncher \ - -jdk $(JDK_IMAGE_DIR) $$($1_GTEST_FILTER) \ - --gtest_output=xml:$$($1_TEST_RESULTS_DIR)/gtest.xml \ - $$($1_GTEST_REPEAT) $$(GTEST_OPTIONS) $$(GTEST_VM_OPTIONS) \ + -jdk $(JDK_IMAGE_DIR) $$($1_GTEST_FILTER) \ + --gtest_output=xml:$$($1_TEST_RESULTS_DIR)/gtest.xml \ + $$($1_GTEST_REPEAT) $$(GTEST_OPTIONS) $$(GTEST_VM_OPTIONS) \ + $$($1_GTEST_JAVA_OPTIONS) \ > >($(TEE) $$($1_TEST_RESULTS_DIR)/gtest.txt) \ && $$(ECHO) $$$$? > $$($1_EXITCODE) \ || $$(ECHO) $$$$? > $$($1_EXITCODE) \ @@ -475,12 +504,11 @@ define SetupRunJtregTestBody $1_TEST_NAME := $$(strip $$(patsubst jtreg:%, %, $$($1_TEST))) - $1_COMPONENT := \ + $1_TEST_ROOT := \ $$(strip $$(foreach root, $$(JTREG_TESTROOTS), \ - $$(if $$(filter $$(root)%, $$(JTREG_TOPDIR)/$$($1_TEST_NAME)), \ - $$(lastword $$(subst /, $$(SPACE), $$(root))) \ - ) \ + $$(if $$(filter $$(root)%, $$(JTREG_TOPDIR)/$$($1_TEST_NAME)), $$(root)) \ )) + $1_COMPONENT := $$(lastword $$(subst /, $$(SPACE), $$($1_TEST_ROOT))) # This will work only as long as just hotspot has the additional "jtreg" directory ifeq ($$($1_COMPONENT), jtreg) $1_COMPONENT := hotspot @@ -503,6 +531,9 @@ define SetupRunJtregTestBody $$(eval $$(call SetJtregValue,$1,JTREG_BASIC_OPTIONS)) $$(eval $$(call SetJtregValue,$1,JTREG_PROBLEM_LIST)) + # Only the problem list for the current test root should be used. + $1_JTREG_PROBLEM_LIST := $$(filter $$($1_TEST_ROOT)%, $$($1_JTREG_PROBLEM_LIST)) + ifneq ($(TEST_JOBS), 0) $$(eval $$(call SetJtregValue,$1,JTREG_JOBS,$$(TEST_JOBS))) else @@ -515,9 +546,9 @@ define SetupRunJtregTestBody # SPARC is in general slower per core so need to scale up timeouts a bit. ifeq ($(OPENJDK_TARGET_CPU_ARCH), sparc) - JTREG_TIMEOUT ?= 8 + JTREG_TIMEOUT_FACTOR ?= 8 else - JTREG_TIMEOUT ?= 4 + JTREG_TIMEOUT_FACTOR ?= 4 endif JTREG_VERBOSE ?= fail,error,summary JTREG_RETAIN ?= fail,error @@ -529,10 +560,10 @@ define SetupRunJtregTestBody $1_JTREG_BASIC_OPTIONS += -$$($1_JTREG_TEST_MODE) \ -verbose:$$(JTREG_VERBOSE) -retain:$$(JTREG_RETAIN) \ - -concurrency:$$($1_JTREG_JOBS) -timeoutFactor:$$(JTREG_TIMEOUT) \ + -concurrency:$$($1_JTREG_JOBS) -timeoutFactor:$$(JTREG_TIMEOUT_FACTOR) \ -vmoption:-XX:MaxRAMPercentage=$$($1_JTREG_MAX_RAM_PERCENTAGE) - $1_JTREG_BASIC_OPTIONS += -automatic -keywords:\!ignore -ignore:quiet + $1_JTREG_BASIC_OPTIONS += -automatic -ignore:quiet # Make it possible to specify the JIB_DATA_DIR for tests using the # JIB Artifact resolver @@ -562,6 +593,14 @@ define SetupRunJtregTestBody $1_JTREG_BASIC_OPTIONS += $$(addprefix -exclude:, $$($1_JTREG_PROBLEM_LIST)) endif + ifneq ($$(JTREG_EXTRA_PROBLEM_LISTS), ) + # Accept both absolute paths as well as relative to the current test root. + $1_JTREG_BASIC_OPTIONS += $$(addprefix -exclude:, $$(wildcard \ + $$(JTREG_EXTRA_PROBLEM_LISTS) \ + $$(addprefix $$($1_TEST_ROOT)/, $$(JTREG_EXTRA_PROBLEM_LISTS)) \ + )) + endif + ifneq ($$(JIB_HOME), ) $1_JTREG_BASIC_OPTIONS += -e:JIB_HOME=$$(JIB_HOME) endif @@ -572,10 +611,21 @@ define SetupRunJtregTestBody $1_JTREG_LAUNCHER_OPTIONS += -Djava.library.path="$(JTREG_FAILURE_HANDLER_DIR)" endif + ifneq ($$(JTREG_KEYWORDS), ) + # The keywords string may contain problematic characters and may be quoted + # already when it arrives here. Remove any existing quotes and replace them + # with one set of single quotes. + $1_JTREG_KEYWORDS := \ + $$(strip $$(subst $$(SQUOTE),,$$(subst $$(DQUOTE),,$$(JTREG_KEYWORDS)))) + ifneq ($$($1_JTREG_KEYWORDS), ) + $1_JTREG_BASIC_OPTIONS += -k:'$$($1_JTREG_KEYWORDS)' + endif + endif + clean-workdir-$1: $$(RM) -r $$($1_TEST_SUPPORT_DIR) - run-test-$1: clean-workdir-$1 + run-test-$1: clean-workdir-$1 $(TEST_PREREQS) $$(call LogWarn) $$(call LogWarn, Running test '$$($1_TEST)') $$(call MakeDir, $$($1_TEST_RESULTS_DIR) $$($1_TEST_SUPPORT_DIR)) @@ -662,7 +712,7 @@ define SetupRunSpecialTestBody $$(error Invalid special test specification: $$($1_TEST_NAME)) endif - run-test-$1: + run-test-$1: $(TEST_PREREQS) $$(call LogWarn) $$(call LogWarn, Running test '$$($1_TEST)') $$(call MakeDir, $$($1_TEST_RESULTS_DIR) $$($1_TEST_SUPPORT_DIR)) diff --git a/make/RunTestsPrebuilt.gmk b/make/RunTestsPrebuilt.gmk index 888393a141b..b781832fad2 100644 --- a/make/RunTestsPrebuilt.gmk +++ b/make/RunTestsPrebuilt.gmk @@ -49,10 +49,11 @@ TOPDIR := $(strip $(patsubst %/make/, %, $(dir $(makefile_path)))) # given. # Note: No spaces are allowed around the arguments. # -# $1: The name of the argument +# $1: The name of the variable # $2: The default value, if any, or OPTIONAL (do not provide a default but # do not exit if it is missing) # $3: If NO_CHECK, disable checking for target file/directory existence +# If MKDIR, create the default directory define SetupVariable ifeq ($$($1), ) ifeq ($2, ) @@ -75,10 +76,17 @@ define SetupVariable endif # If $1 has a value (is not optional), and $3 is not set (to NO_CHECK), # and if wildcard is empty, then complain that the file is missing. - ifeq ($$(strip $$(if $$($1), , OPTIONAL) $$(wildcard $$($1)) $3), ) - $$(info Error: Prebuilt variable $1 points to missing file/directory:) - $$(info '$$($1)') - $$(error Cannot continue.) + ifeq ($3, MKDIR) + ifneq ($$(findstring $$(LOG), info debug trace), ) + $$(info Creating directory for $1) + endif + $$(shell mkdir -p $$($1)) + else ifneq ($3, NO_CHECK) + ifeq ($$(strip $$(if $$($1), , OPTIONAL) $$(wildcard $$($1))), ) + $$(info Error: Prebuilt variable $1 points to missing file/directory:) + $$(info '$$($1)') + $$(error Cannot continue.) + endif endif endef @@ -106,14 +114,14 @@ endef # Verify that user has given correct additional input. # These variables are absolutely necessary -$(eval $(call SetupVariable,OUTPUTDIR)) +$(eval $(call SetupVariable,OUTPUTDIR,$(TOPDIR)/build/run-test-prebuilt,MKDIR)) $(eval $(call SetupVariable,BOOT_JDK)) $(eval $(call SetupVariable,JT_HOME)) # These can have default values based on the ones above $(eval $(call SetupVariable,JDK_IMAGE_DIR,$(OUTPUTDIR)/images/jdk)) $(eval $(call SetupVariable,TEST_IMAGE_DIR,$(OUTPUTDIR)/images/test)) -$(eval $(call SetupVariable,SYMBOLS_IMAGE_DIR,$(OUTPUTDIR)/images/symbols)) +$(eval $(call SetupVariable,SYMBOLS_IMAGE_DIR,$(OUTPUTDIR)/images/symbols,NO_CHECK)) # Provide default values for tools that we need $(eval $(call SetupVariable,MAKE,make,NO_CHECK)) @@ -202,8 +210,8 @@ endif ifeq ($(OPENJDK_TARGET_OS), windows) ifeq ($(wildcard $(TEST_IMAGE_DIR)/bin/fixpath.exe), ) - $$(info Error: fixpath is missing from test image '$(TEST_IMAGE_DIR)') - $$(error Cannot continue.) + $(info Error: fixpath is missing from test image '$(TEST_IMAGE_DIR)') + $(error Cannot continue.) endif FIXPATH := $(TEST_IMAGE_DIR)/bin/fixpath.exe -c PATH_SEP:=; @@ -214,27 +222,32 @@ endif # Check number of cores and memory in MB ifeq ($(OPENJDK_TARGET_OS), linux) - NUM_CORES := $(shell $(CAT) /proc/cpuinfo | $(GREP) -c processor) - MEMORY_SIZE := $(shell \ + NUM_CORES := $(shell $(CAT) /proc/cpuinfo | $(GREP) -c processor) + MEMORY_SIZE := $(shell \ $(EXPR) `$(CAT) /proc/meminfo | $(GREP) MemTotal | $(AWK) '{print $$2}'` / 1024 \ - ) + ) else ifeq ($(OPENJDK_TARGET_OS), macosx) - NUM_CORES := $(shell /usr/sbin/sysctl -n hw.ncpu) - MEMORY_SIZE := $(shell $(EXPR) `/usr/sbin/sysctl -n hw.memsize` / 1024 / 1024) + NUM_CORES := $(shell /usr/sbin/sysctl -n hw.ncpu) + MEMORY_SIZE := $(shell $(EXPR) `/usr/sbin/sysctl -n hw.memsize` / 1024 / 1024) else ifeq ($(OPENJDK_TARGET_OS), solaris) - NUM_CORES := $(shell LC_MESSAGES=C /usr/sbin/psrinfo -v | $(GREP) -c on-line) - MEMORY_SIZE := $(shell \ + NUM_CORES := $(shell LC_MESSAGES=C /usr/sbin/psrinfo -v | $(GREP) -c on-line) + MEMORY_SIZE := $(shell \ /usr/sbin/prtconf 2> /dev/null | $(GREP) "^Memory [Ss]ize" | $(AWK) '{print $$3}' \ - ) + ) else ifeq ($(OPENJDK_TARGET_OS), windows) - NUM_CORES := $(NUMBER_OF_PROCESSORS) - MEMORY_SIZE := $(shell \ + NUM_CORES := $(NUMBER_OF_PROCESSORS) + MEMORY_SIZE := $(shell \ $(EXPR) `wmic computersystem get totalphysicalmemory -value | $(GREP) = \ | $(CUT) -d "=" -f 2-` / 1024 / 1024 \ - ) -else - NUM_CORES := 1 - MEMORY_SIZE := 1024 + ) +endif +ifeq ($(NUM_CORES), ) + $(warn Could not find number of CPUs, assuming 1) + NUM_CORES := 1 +endif +ifeq ($(MEMORY_SIZE), ) + $(warn Could not find memory size, assuming 1024 MB) + MEMORY_SIZE := 1024 endif ################################################################################ @@ -289,9 +302,6 @@ run-test-prebuilt: @$(RM) -f $(MAKESUPPORT_OUTPUTDIR)/exit-with-error @cd $(TOPDIR) && $(MAKE) $(MAKE_ARGS) -f make/RunTests.gmk run-test \ TEST="$(TEST)" - @if test -f $(MAKESUPPORT_OUTPUTDIR)/exit-with-error ; then \ - exit 1 ; \ - fi all: run-test-prebuilt diff --git a/make/RunTestsPrebuiltSpec.gmk b/make/RunTestsPrebuiltSpec.gmk index fd76562e7e1..200ab32c144 100644 --- a/make/RunTestsPrebuiltSpec.gmk +++ b/make/RunTestsPrebuiltSpec.gmk @@ -124,7 +124,7 @@ JLINK := $(FIXPATH) $(JLINK_CMD) JMOD := $(FIXPATH) $(JMOD_CMD) JARSIGNER := $(FIXPATH) $(JARSIGNER_CMD) -BUILD_JAVA := $(JAVA) +BUILD_JAVA := $(JDK_IMAGE_DIR)/bin/JAVA ################################################################################ # Some common tools. Assume most common name and no path. AWK := awk @@ -172,3 +172,13 @@ UNZIP := unzip EXPR := expr FILE := file HG := hg + +# On Solaris gnu versions of some tools are required. +ifeq ($(OPENJDK_BUILD_OS), solaris) + AWK := gawk + GREP := ggrep + EGREP := ggrep -E + FGREP := grep -F + SED := gsed + TAR := gtar +endif diff --git a/make/common/MakeBase.gmk b/make/common/MakeBase.gmk index d511836f097..170c3ed0da0 100644 --- a/make/common/MakeBase.gmk +++ b/make/common/MakeBase.gmk @@ -842,7 +842,7 @@ endef # Parameter 1 is the name of the rule, and is also the name of the variable. # # Remaining parameters are named arguments. These include: -# KEYWORDS A list of valid keywords +# SINGLE_KEYWORDS A list of valid keywords with single string values # STRING_KEYWORDS A list of valid keywords, processed as string. This means # that '%20' will be replaced by ' ' to allow for multi-word strings. # @@ -856,7 +856,7 @@ define ParseKeywordVariableBody $$(eval mangled_part_eval := $$(call DoubleDollar, $$(mangled_part))) \ $$(eval part := $$$$(subst ||||,$$$$(SPACE),$$$$(mangled_part_eval))) \ $$(eval $1_NO_MATCH := true) \ - $$(foreach keyword, $$($1_KEYWORDS), \ + $$(foreach keyword, $$($1_SINGLE_KEYWORDS), \ $$(eval keyword_eval := $$(call DoubleDollar, $$(keyword))) \ $$(if $$(filter $$(keyword)=%, $$(part)), \ $$(eval $(strip $1)_$$$$(keyword_eval) := $$$$(strip $$$$(patsubst $$$$(keyword_eval)=%, %, $$$$(part)))) \ @@ -871,11 +871,11 @@ define ParseKeywordVariableBody ) \ ) \ $$(if $$($1_NO_MATCH), \ - $$(if $$(filter $$(part), $$($1_KEYWORDS) $$($1_STRING_KEYWORDS)), \ + $$(if $$(filter $$(part), $$($1_SINGLE_KEYWORDS) $$($1_STRING_KEYWORDS)), \ $$(info Keyword $$(part) for $1 needs to be assigned a value.) \ , \ $$(info $$(part) is not a valid keyword for $1.) \ - $$(info Valid keywords: $$($1_KEYWORDS) $$($1_STRING_KEYWORDS).) \ + $$(info Valid keywords: $$($1_SINGLE_KEYWORDS) $$($1_STRING_KEYWORDS).) \ ) \ $$(error Cannot continue) \ ) \ diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index e3af3b41a0c..04d5d70df87 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -747,16 +747,15 @@ var getJibProfilesProfiles = function (input, common, data) { "run-test-prebuilt": { target_os: input.build_os, target_cpu: input.build_cpu, - src: "src.conf", dependencies: [ "jtreg", "gnumake", "boot_jdk", "jib", testedProfile + ".jdk", - testedProfile + ".test", "src.full" + testedProfile + ".test" ], - work_dir: input.get("src.full", "install_path") + "/test", + src: "src.conf", + make_args: [ "run-test-prebuilt", "LOG_CMDLINES=true" ], environment: { - "JT_JAVA": common.boot_jdk_home, - "PRODUCT_HOME": input.get(testedProfile + ".jdk", "home_path"), - "TEST_IMAGE_DIR": input.get(testedProfile + ".test", "home_path"), - "TEST_OUTPUT_DIR": input.src_top_dir + "BOOT_JDK": common.boot_jdk_home, + "JDK_IMAGE_DIR": input.get(testedProfile + ".jdk", "home_path"), + "TEST_IMAGE_DIR": input.get(testedProfile + ".test", "home_path") }, labels: "test" } @@ -794,13 +793,34 @@ var getJibProfilesProfiles = function (input, common, data) { windowsRunTestPrebuiltExtra = { dependencies: [ testedProfile + ".jdk_symbols" ], environment: { - "PRODUCT_SYMBOLS_HOME": input.get(testedProfile + ".jdk_symbols", "home_path"), + "SYMBOLS_IMAGE_DIR": input.get(testedProfile + ".jdk_symbols", "home_path"), } }; profiles["run-test-prebuilt"] = concatObjects(profiles["run-test-prebuilt"], windowsRunTestPrebuiltExtra); } + // The profile run-test-prebuilt defines src.conf as the src bundle. When + // running in Mach 5, this reduces the time it takes to populate the + // considerably. But with just src.conf, we cannot actually run any tests, + // so if running from a workspace with just src.conf in it, we need to also + // get src.full as a dependency, and define the work_dir (where make gets + // run) to be in the src.full install path. By running in the install path, + // the same cached installation of the full src can be reused for multiple + // test tasks. Care must however be taken not to polute that work dir by + // setting the appropriate make variables to control output directories. + // + // Use the existance of the top level README as indication of if this is + // the full source or just src.conf. + if (!new java.io.File(__DIR__, "../../README").exists()) { + var runTestPrebuiltSrcFullExtra = { + dependencies: "src.full", + work_dir: input.get("src.full", "install_path"), + } + profiles["run-test-prebuilt"] = concatObjects(profiles["run-test-prebuilt"], + runTestPrebuiltSrcFullExtra); + } + // Generate the missing platform attributes profiles = generatePlatformAttributes(profiles); profiles = generateDefaultMakeTargetsConfigureArg(common, profiles); @@ -827,7 +847,7 @@ var getJibProfilesDependencies = function (input, common) { : "gcc7.3.0-Fedora27+1.0"), linux_arm: (input.profile != null && input.profile.indexOf("hflt") >= 0 ? "gcc-linaro-arm-linux-gnueabihf-raspbian-2012.09-20120921_linux+1.0" - : (input.profile.indexOf("arm32") >= 0 + : (input.profile != null && input.profile.indexOf("arm32") >= 0 ? "gcc7.3.0-Fedora27+1.0" : "arm-linaro-4.7+1.0" ) diff --git a/test/hotspot/jtreg/compiler/escapeAnalysis/TestArrayCopy.java b/test/hotspot/jtreg/compiler/escapeAnalysis/TestArrayCopy.java index 91c09a05acb..4ad0ff80c80 100644 --- a/test/hotspot/jtreg/compiler/escapeAnalysis/TestArrayCopy.java +++ b/test/hotspot/jtreg/compiler/escapeAnalysis/TestArrayCopy.java @@ -33,7 +33,7 @@ * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * - * @run main/othervm + * @run main/othervm/timeout=300 * -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI diff --git a/test/hotspot/jtreg/compiler/graalunit/JttLangMathALTest.java b/test/hotspot/jtreg/compiler/graalunit/JttLangMathALTest.java index 3ba1127bb4d..e17fa343021 100644 --- a/test/hotspot/jtreg/compiler/graalunit/JttLangMathALTest.java +++ b/test/hotspot/jtreg/compiler/graalunit/JttLangMathALTest.java @@ -34,5 +34,6 @@ * * @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt * - * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.lang.Math_[a-lA-L] -exclude ExcludeList.txt + * @run main/othervm/timeout=300 compiler.graalunit.common.GraalUnitTestLauncher + * -prefix org.graalvm.compiler.jtt.lang.Math_[a-lA-L] -exclude ExcludeList.txt */ diff --git a/test/hotspot/jtreg/compiler/graalunit/JttLangMathMZTest.java b/test/hotspot/jtreg/compiler/graalunit/JttLangMathMZTest.java index 874e697d047..86e09fe10e0 100644 --- a/test/hotspot/jtreg/compiler/graalunit/JttLangMathMZTest.java +++ b/test/hotspot/jtreg/compiler/graalunit/JttLangMathMZTest.java @@ -34,5 +34,6 @@ * * @run driver jdk.test.lib.FileInstaller ../../ProblemList-graal.txt ExcludeList.txt * - * @run main/othervm compiler.graalunit.common.GraalUnitTestLauncher -prefix org.graalvm.compiler.jtt.lang.Math_[m-zM-Z] -exclude ExcludeList.txt + * @run main/othervm/timeout=300 compiler.graalunit.common.GraalUnitTestLauncher + * -prefix org.graalvm.compiler.jtt.lang.Math_[m-zM-Z] -exclude ExcludeList.txt */ diff --git a/test/hotspot/jtreg/compiler/jsr292/ContinuousCallSiteTargetChange.java b/test/hotspot/jtreg/compiler/jsr292/ContinuousCallSiteTargetChange.java index 7fdd282033d..f41f883597f 100644 --- a/test/hotspot/jtreg/compiler/jsr292/ContinuousCallSiteTargetChange.java +++ b/test/hotspot/jtreg/compiler/jsr292/ContinuousCallSiteTargetChange.java @@ -25,7 +25,7 @@ * @test * @library /test/lib / * - * @run driver compiler.jsr292.ContinuousCallSiteTargetChange + * @run driver/timeout=300 compiler.jsr292.ContinuousCallSiteTargetChange */ package compiler.jsr292; diff --git a/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationApp.java b/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationApp.java index 1328f583031..ecb4da0b137 100644 --- a/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationApp.java +++ b/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationApp.java @@ -116,10 +116,10 @@ public static void main(String args[]) throws Throwable { System.out.println("INFO: AppCDSv1 " + (wb.isSharedClass(InstrumentationApp.class) ? "enabled" :"disabled")); System.out.println("INFO: AppCDSv2 " + (isAppCDSV2Enabled() ? "enabled" : "disabled")); - File bootJar = new File(args[0]); - File appJar = new File(args[1]); - File custJar = new File(args[2]); - String flagFile = args[3]; + String flagFile = args[0]; + File bootJar = new File(args[1]); + File appJar = new File(args[2]); + File custJar = new File(args[3]); waitAttach(flagFile); instrumentation = InstrumentationRegisterClassFileTransformer.getInstrumentation(); diff --git a/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationTest.java b/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationTest.java index 8ee5803fd4c..b1ce6dabbd5 100644 --- a/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationTest.java +++ b/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationTest.java @@ -120,7 +120,7 @@ public static void runTest(boolean attachAgent) throws Throwable { "-XX:+WhiteBoxAPI", "-Xshare:off", agentCmdArg, - "InstrumentationApp", bootJar, appJar, custJar, flagFile); + "InstrumentationApp", flagFile, bootJar, appJar, custJar); TestCommon.executeAndLog(pb, "no-sharing").shouldHaveExitValue(0); checkAttach(t); @@ -155,7 +155,7 @@ public static void runTest(boolean attachAgent) throws Throwable { "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", agentCmdArg, - "InstrumentationApp", bootJar, appJar, custJar, flagFile); + "InstrumentationApp", flagFile, bootJar, appJar, custJar); CDSOptions opts = (new CDSOptions()).setXShareMode("auto"); TestCommon.checkExec(out, opts); diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/cp/stress/classfmt/correctBootstrap/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/cp/stress/classfmt/correctBootstrap/TestDescription.java index 1d1d23c7ad9..f5fcea91fd9 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/cp/stress/classfmt/correctBootstrap/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/cp/stress/classfmt/correctBootstrap/TestDescription.java @@ -50,7 +50,7 @@ * @build vm.mlvm.share.ClassfileGeneratorTest * @run driver vm.mlvm.share.IndifiedClassesBuilder * - * @run main/othervm + * @run main/othervm/timeout=300 * vm.mlvm.share.ClassfileGeneratorTest * -generator vm.mlvm.cp.share.GenManyIndyCorrectBootstrap */ diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/cp/stress/classfmt/incorrectBootstrap/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/cp/stress/classfmt/incorrectBootstrap/TestDescription.java index e82f7881fff..df8f5f83b53 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/cp/stress/classfmt/incorrectBootstrap/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/cp/stress/classfmt/incorrectBootstrap/TestDescription.java @@ -51,7 +51,7 @@ * @build vm.mlvm.share.ClassfileGeneratorTest * @run driver vm.mlvm.share.IndifiedClassesBuilder * - * @run main/othervm + * @run main/othervm/timeout=300 * vm.mlvm.share.ClassfileGeneratorTest * -generator vm.mlvm.cp.share.GenManyIndyIncorrectBootstrap */ diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/cp/stress/classfmt/mh/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/cp/stress/classfmt/mh/TestDescription.java index 132267c067f..afbcea913e3 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/cp/stress/classfmt/mh/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/cp/stress/classfmt/mh/TestDescription.java @@ -50,6 +50,6 @@ * @build vm.mlvm.share.ClassfileGeneratorTest * @run driver vm.mlvm.share.IndifiedClassesBuilder * - * @run main/othervm vm.mlvm.share.ClassfileGeneratorTest -generator vm.mlvm.cp.share.GenCPFullOfMH + * @run main/othervm/timeout=300 vm.mlvm.share.ClassfileGeneratorTest -generator vm.mlvm.cp.share.GenCPFullOfMH */ diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/cp/stress/classfmt/mt/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/cp/stress/classfmt/mt/TestDescription.java index 18155a3ffd1..b50296fcdea 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/cp/stress/classfmt/mt/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/cp/stress/classfmt/mt/TestDescription.java @@ -50,6 +50,6 @@ * @build vm.mlvm.share.ClassfileGeneratorTest * @run driver vm.mlvm.share.IndifiedClassesBuilder * - * @run main/othervm vm.mlvm.share.ClassfileGeneratorTest -generator vm.mlvm.cp.share.GenCPFullOfMT + * @run main/othervm/timeout=300 vm.mlvm.share.ClassfileGeneratorTest -generator vm.mlvm.cp.share.GenCPFullOfMT */ diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/gc/createLotsOfMHConsts/Test.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/gc/createLotsOfMHConsts/Test.java index 5d0a916af0d..0630b3b896e 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/gc/createLotsOfMHConsts/Test.java +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/gc/createLotsOfMHConsts/Test.java @@ -50,7 +50,7 @@ * @build vm.mlvm.meth.stress.gc.createLotsOfMHConsts.Test * @run driver vm.mlvm.share.IndifiedClassesBuilder * - * @run main/othervm + * @run main/othervm/timeout=300 * vm.mlvm.meth.stress.gc.createLotsOfMHConsts.Test * -stressIterationsFactor 100000 * -generator vm.mlvm.cp.share.GenCPFullOfMH diff --git a/test/jdk/tools/jimage/JImageExtractTest.java b/test/jdk/tools/jimage/JImageExtractTest.java index 3b636e698fa..4895fdf218e 100644 --- a/test/jdk/tools/jimage/JImageExtractTest.java +++ b/test/jdk/tools/jimage/JImageExtractTest.java @@ -27,7 +27,7 @@ * @library /test/lib * @modules jdk.jlink/jdk.tools.jimage * @build jdk.test.lib.Asserts - * @run main/othervm JImageExtractTest + * @run main/othervm/timeout=300 JImageExtractTest */ import java.io.IOException; From e4229eda79c502f3bc91e47ab0de8475c959f479 Mon Sep 17 00:00:00 2001 From: erikj Date: Thu, 25 Oct 2018 16:47:14 -0700 Subject: [PATCH 101/131] 8213005: Missing symbols in hs_err files on Windows after JDK-8212028 Reviewed-by: ctornqvi --- make/RunTests.gmk | 10 +++++++--- make/RunTestsPrebuiltSpec.gmk | 4 ++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/make/RunTests.gmk b/make/RunTests.gmk index be138562296..782d8fed564 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -102,10 +102,14 @@ ifeq ($(OPENJDK_TARGET_OS), windows) ifndef _NT_SYMBOL_PATH # Can't use PathList here as it adds quotes around the value. _NT_SYMBOL_PATH := \ - $(subst $(SPACE),;, $(foreach p, $(sort $(dir $(wildcard \ - $(addprefix $(SYMBOLS_IMAGE_DIR)/bin/, *.pdb */*.pdb)))), $(call FixPath, $p))) + $(subst $(SPACE),;,$(strip \ + $(foreach p, $(sort $(dir $(wildcard \ + $(addprefix $(SYMBOLS_IMAGE_DIR)/bin/, *.pdb */*.pdb)))), \ + $(call FixPath, $p) \ + ) \ + )) export _NT_SYMBOL_PATH - $(info _NT_SYMBOL_PATH $(_NT_SYMBOL_PATH)) + $(info _NT_SYMBOL_PATH=$(_NT_SYMBOL_PATH)) endif endif diff --git a/make/RunTestsPrebuiltSpec.gmk b/make/RunTestsPrebuiltSpec.gmk index 200ab32c144..8564a1f7ddd 100644 --- a/make/RunTestsPrebuiltSpec.gmk +++ b/make/RunTestsPrebuiltSpec.gmk @@ -182,3 +182,7 @@ ifeq ($(OPENJDK_BUILD_OS), solaris) SED := gsed TAR := gtar endif + +ifeq ($(OPENJDK_BUILD_OS), windows) + CYGPATH := cygpath +endif From 183c4e7523c418e7a0feaace7458209ce51c30a9 Mon Sep 17 00:00:00 2001 From: dfuchs Date: Fri, 18 Jan 2019 17:06:29 +0000 Subject: [PATCH 102/131] 8216561: HttpClient: The logic of retry on connect exception is inverted Summary: Allows retry on connect exception by default, ensuring that the second attempt takes into account the time spent in the first attempt in order to honor the connect timeout value (if present). Reviewed-by: chegar --- .../jdk/internal/net/http/Exchange.java | 6 ++ .../jdk/internal/net/http/HttpClientImpl.java | 10 ++-- .../jdk/internal/net/http/MultiExchange.java | 55 +++++++++++++++++-- .../net/http/PlainHttpConnection.java | 4 +- 4 files changed, 63 insertions(+), 12 deletions(-) diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java b/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java index 743cfc5afdb..6a07e584c14 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java @@ -33,8 +33,10 @@ import java.net.URISyntaxException; import java.net.URLPermission; import java.security.AccessControlContext; +import java.time.Duration; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.function.Function; @@ -125,6 +127,10 @@ public HttpRequestImpl request() { return request; } + public Optional remainingConnectTimeout() { + return multi.remainingConnectTimeout(); + } + HttpClientImpl client() { return client; } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java index 109dd8c4ebf..942502d806f 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java @@ -158,7 +158,7 @@ public void execute(Runnable command) { private final CookieHandler cookieHandler; private final Duration connectTimeout; private final Redirect followRedirects; - private final Optional userProxySelector; + private final ProxySelector userProxySelector; private final ProxySelector proxySelector; private final Authenticator authenticator; private final Version version; @@ -284,12 +284,12 @@ private HttpClientImpl(HttpClientBuilderImpl builder, connectTimeout = builder.connectTimeout; followRedirects = builder.followRedirects == null ? Redirect.NEVER : builder.followRedirects; - this.userProxySelector = Optional.ofNullable(builder.proxy); - this.proxySelector = userProxySelector + this.userProxySelector = builder.proxy; + this.proxySelector = Optional.ofNullable(userProxySelector) .orElseGet(HttpClientImpl::getDefaultProxySelector); if (debug.on()) debug.log("proxySelector is %s (user-supplied=%s)", - this.proxySelector, userProxySelector.isPresent()); + this.proxySelector, userProxySelector != null); authenticator = builder.authenticator; if (builder.version == null) { version = HttpClient.Version.HTTP_2; @@ -1138,7 +1138,7 @@ public Optional connectTimeout() { @Override public Optional proxy() { - return this.userProxySelector; + return Optional.ofNullable(userProxySelector); } // Return the effective proxy that this client uses. diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java b/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java index 4dcf3be0c88..0b92f112cd9 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java @@ -26,12 +26,14 @@ package jdk.internal.net.http; import java.io.IOException; -import java.io.UncheckedIOException; import java.net.ConnectException; import java.net.http.HttpConnectTimeoutException; +import java.time.Duration; import java.util.Iterator; import java.util.LinkedList; import java.security.AccessControlContext; +import java.util.Objects; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.CompletionException; @@ -39,6 +41,7 @@ import java.util.concurrent.Executor; import java.util.concurrent.Flow; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; import java.util.function.Function; import java.net.http.HttpClient; @@ -71,6 +74,7 @@ class MultiExchange { private final HttpRequest userRequest; // the user request private final HttpRequestImpl request; // a copy of the user request + private final ConnectTimeoutTracker connectTimeout; // null if no timeout final AccessControlContext acc; final HttpClientImpl client; final HttpResponse.BodyHandler responseHandler; @@ -107,6 +111,38 @@ class MultiExchange { // RedirectHandler volatile int numberOfRedirects = 0; + // This class is used to keep track of the connection timeout + // across retries, when a ConnectException causes a retry. + // In that case - we will retry the connect, but we don't + // want to double the timeout by starting a new timer with + // the full connectTimeout again. + // Instead we use the ConnectTimeoutTracker to return a new + // duration that takes into account the time spent in the + // first connect attempt. + // If however, the connection gets connected, but we later + // retry the whole operation, then we reset the timer before + // retrying (since the connection used for the second request + // will not necessarily be the same: it could be a new + // unconnected connection) - see getExceptionalCF(). + private static final class ConnectTimeoutTracker { + final Duration max; + final AtomicLong startTime = new AtomicLong(); + ConnectTimeoutTracker(Duration connectTimeout) { + this.max = Objects.requireNonNull(connectTimeout); + } + + Duration getRemaining() { + long now = System.nanoTime(); + long previous = startTime.compareAndExchange(0, now); + if (previous == 0 || max.isZero()) return max; + Duration remaining = max.minus(Duration.ofNanos(now - previous)); + assert remaining.compareTo(max) <= 0; + return remaining.isNegative() ? Duration.ZERO : remaining; + } + + void reset() { startTime.set(0); } + } + /** * MultiExchange with one final response. */ @@ -135,7 +171,8 @@ class MultiExchange { } else { pushGroup = null; } - + this.connectTimeout = client.connectTimeout() + .map(ConnectTimeoutTracker::new).orElse(null); this.exchange = new Exchange<>(request, this); } @@ -161,6 +198,11 @@ private synchronized void setExchange(Exchange exchange) { this.exchange = exchange; } + public Optional remainingConnectTimeout() { + return Optional.ofNullable(connectTimeout) + .map(ConnectTimeoutTracker::getRemaining); + } + private void cancelTimer() { if (responseTimerEvent != null) { client.cancelTimer(responseTimerEvent); @@ -354,7 +396,7 @@ private static boolean retryPostValue() { return s.isEmpty() ? true : Boolean.parseBoolean(s); } - private static boolean retryConnect() { + private static boolean disableRetryConnect() { String s = Utils.getNetProperty("jdk.httpclient.disableRetryConnect"); if (s == null) return false; @@ -364,7 +406,7 @@ private static boolean retryConnect() { /** True if ALL ( even non-idempotent ) requests can be automatic retried. */ private static final boolean RETRY_ALWAYS = retryPostValue(); /** True if ConnectException should cause a retry. Enabled by default */ - private static final boolean RETRY_CONNECT = retryConnect(); + private static final boolean RETRY_CONNECT = !disableRetryConnect(); /** Returns true is given request has an idempotent method. */ private static boolean isIdempotentRequest(HttpRequest request) { @@ -415,10 +457,13 @@ private CompletableFuture getExceptionalCF(Throwable t) { Throwable cause = retryCause(t); if (!(t instanceof ConnectException)) { + // we may need to start a new connection, and if so + // we want to start with a fresh connect timeout again. + if (connectTimeout != null) connectTimeout.reset(); if (!canRetryRequest(currentreq)) { return failedFuture(cause); // fails with original cause } - } + } // ConnectException: retry, but don't reset the connectTimeout. // allow the retry mechanism to do its work retryCause = cause; diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java b/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java index d9db165bcea..3256e3c6d36 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java @@ -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 @@ -65,7 +65,7 @@ class PlainHttpConnection extends HttpConnection { */ private ConnectTimerEvent newConnectTimer(Exchange exchange, CompletableFuture cf) { - Duration duration = client().connectTimeout().orElse(null); + Duration duration = exchange.remainingConnectTimeout().orElse(null); if (duration != null) { ConnectTimerEvent cte = new ConnectTimerEvent(duration, exchange, cf); return cte; From 6a1881e77e83ca9e20141791b2653ccd1cfe4905 Mon Sep 17 00:00:00 2001 From: rhalade Date: Wed, 9 Oct 2019 12:21:28 -0700 Subject: [PATCH 103/131] 8231887: ComodoCA.java fails because certificate was revoked Reviewed-by: mullan, clanger --- .../certification/ComodoCA.java | 504 ++++++++++-------- 1 file changed, 286 insertions(+), 218 deletions(-) diff --git a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/ComodoCA.java b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/ComodoCA.java index e3edae41261..3b3466116ef 100644 --- a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/ComodoCA.java +++ b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/ComodoCA.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8189131 + * @bug 8189131 8231887 * @summary Interoperability tests with Comodo RSA, ECC, userTrust RSA, and * userTrust ECC CAs * @build ValidatePathWithParams @@ -110,6 +110,59 @@ class ComodoRSA { + "pLwltum95OmYdBbxN4SBB7SC\n" + "-----END CERTIFICATE-----"; + // Owner: CN=comodorsacertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, O=Sectigo Limited, + // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford, + // OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.3=GB, + // SERIALNUMBER=04058690 + // Issuer: CN=COMODO RSA Extended Validation Secure Server CA, O=COMODO CA Limited, L=Salford, + // ST=Greater Manchester, C=GB + // Serial number: a0c7cabcc25ed9358ded02cc1d485545 + // Valid from: Sun Sep 29 17:00:00 PDT 2019 until: Tue Dec 28 15:59:59 PST 2021 + private static final String VALID = "-----BEGIN CERTIFICATE-----\n" + + "MIIH0TCCBrmgAwIBAgIRAKDHyrzCXtk1je0CzB1IVUUwDQYJKoZIhvcNAQELBQAw\n" + + "gZIxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO\n" + + "BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTgwNgYD\n" + + "VQQDEy9DT01PRE8gUlNBIEV4dGVuZGVkIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZl\n" + + "ciBDQTAeFw0xOTA5MzAwMDAwMDBaFw0yMTEyMjgyMzU5NTlaMIIBPjERMA8GA1UE\n" + + "BRMIMDQwNTg2OTAxEzARBgsrBgEEAYI3PAIBAxMCR0IxHTAbBgNVBA8TFFByaXZh\n" + + "dGUgT3JnYW5pemF0aW9uMQswCQYDVQQGEwJHQjEPMA0GA1UEERMGTTUgM0VRMRAw\n" + + "DgYDVQQHEwdTYWxmb3JkMRYwFAYDVQQJEw1UcmFmZm9yZCBSb2FkMRYwFAYDVQQJ\n" + + "Ew1FeGNoYW5nZSBRdWF5MSUwIwYDVQQJExwzcmQgRmxvb3IsIDI2IE9mZmljZSBW\n" + + "aWxsYWdlMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxGjAYBgNVBAsTEUNPTU9E\n" + + "TyBFViBTR0MgU1NMMTgwNgYDVQQDEy9jb21vZG9yc2FjZXJ0aWZpY2F0aW9uYXV0\n" + + "aG9yaXR5LWV2LmNvbW9kb2NhLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\n" + + "AQoCggEBAND/eZQBTjpBDsuteKwl+zpTitF8tJzwHAhcQHC2AaLF/GJl1rnjx4Of\n" + + "elMhKhN1Od9KU6onHGOd2w4mD4EiYK9TpXwuwTyzfkCmnkqxZjYK3KAJN013o4L+\n" + + "8y1zsGVUulpN/GfMaxTb4XdmeSekTP91Phw3xezijBq3sa++1rO5RBaT1IHeHhHv\n" + + "iC9WNrG8CIg/j5MyC9i43LZHiRXLER1LzT/MCIRsiG5AEbiYXV5BNd5SiiHtBJ1q\n" + + "0ZJH+AxL2ERaT41VCppboZwThmJGGoky9FWjp6z8U6Enx0fAMJIZNEzW6LAJFKPE\n" + + "ynEU004jFFCEumPUqqCC4ogxulphY80CAwEAAaOCA3EwggNtMB8GA1UdIwQYMBaA\n" + + "FDna/8ooFIqodBMIueQOqdL6fp1pMB0GA1UdDgQWBBQ+S4ZhIrwOoeGs9BBT4uXq\n" + + "89Ux/jAOBgNVHQ8BAf8EBAMCBaAwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggr\n" + + "BgEFBQcDAQYIKwYBBQUHAwIwTwYDVR0gBEgwRjA7BgwrBgEEAbIxAQIBBQEwKzAp\n" + + "BggrBgEFBQcCARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLmNvbS9DUFMwBwYFZ4EM\n" + + "AQEwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5jb21vZG9jYS5jb20vQ09N\n" + + "T0RPUlNBRXh0ZW5kZWRWYWxpZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3JsMIGHBggr\n" + + "BgEFBQcBAQR7MHkwUQYIKwYBBQUHMAKGRWh0dHA6Ly9jcnQuY29tb2RvY2EuY29t\n" + + "L0NPTU9ET1JTQUV4dGVuZGVkVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNydDAk\n" + + "BggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29tMDoGA1UdEQQzMDGC\n" + + "L2NvbW9kb3JzYWNlcnRpZmljYXRpb25hdXRob3JpdHktZXYuY29tb2RvY2EuY29t\n" + + "MIIBfQYKKwYBBAHWeQIEAgSCAW0EggFpAWcAdQDuS723dc5guuFCaR+r4Z5mow9+\n" + + "X7By2IMAxHuJeqj9ywAAAW2DAXefAAAEAwBGMEQCIDqP1einOiPHnaG1fOZMDrEc\n" + + "RAxjq3vEl94fp4pkmke7AiBsJOvPE6irgcOO1/lnP7NRuln7iPJjU7T20PEK5/rm\n" + + "KwB2AFWB1MIWkDYBSuoLm1c8U/DA5Dh4cCUIFy+jqh0HE9MMAAABbYMBd0kAAAQD\n" + + "AEcwRQIhALgUI5XxM1NHbJDdr19h2pe3LhzK4tpuB/OQ9BgCyrGXAiBdr6mNCB/G\n" + + "rbdVx0u7iezwC7mq7iaWugR3rrWlSA8fWQB2ALvZ37wfinG1k5Qjl6qSe0c4V5UK\n" + + "q1LoGpCWZDaOHtGFAAABbYMBd1oAAAQDAEcwRQIgXbG32dagMeLhuZb+LSpJO1vI\n" + + "BmxmRnNdiz5FbG9cCbwCIQCr1X9f+ebT5fhlDUNBURUorTtM8QQciBiueBqvHk7+\n" + + "1DANBgkqhkiG9w0BAQsFAAOCAQEAM/A/1dgoc5NP1n+w3SX9qWcN7QT7ExdrnZSl\n" + + "Ygn0PF2fx4gz7cvNKucbpQJNA4C9awGydyYK8/o5KDUXt3K7eb1OAZ/NZBjygsJs\n" + + "ikXvxlBh8oEoqBOfOtr24l0NGUWnP8Qeu/VPcIMER4V8qX+in0pCXkSd67nkp6Bs\n" + + "EcqhDPgmzdSC1gQHsZuBdotG14OfdH1cG1bRK6GadISLG1h8BFukVem42B149v8F\n" + + "MCIUQAYprAVv2WlTZKBx9XzuK6IK3+klHZ07Jfvjvt7PPG5HKSMWBMnMaTHKcyQI\n" + + "G3t91yw7BnNNInZlBSsFtqjbHhDcr7uruZdbi0rerSsi2qDr0w==\n" + + "-----END CERTIFICATE-----"; + // Owner: CN=comodorsacertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, O=Sectigo Limited, // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford, // ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization, @@ -118,7 +171,7 @@ class ComodoRSA { // ST=Greater Manchester, C=GB // Serial number: d3df2597cbed1ab6e02ee82021771614 // Valid from: Wed Nov 28 16:00:00 PST 2018 until: Fri Feb 26 15:59:59 PST 2021 - private static final String VALID = "-----BEGIN CERTIFICATE-----\n" + + private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" + "MIIH7jCCBtagAwIBAgIRANPfJZfL7Rq24C7oICF3FhQwDQYJKoZIhvcNAQELBQAw\n" + "gZIxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO\n" + "BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTgwNgYD\n" + @@ -164,60 +217,6 @@ class ComodoRSA { "YrTYerPngjPbZB0bfLOja0vb\n" + "-----END CERTIFICATE-----"; - // Owner: CN=comodorsacertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, O=COMODO CA Limited, - // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford, - // ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization, - // OID.1.3.6.1.4.1.311.60.2.1.3=GB, SERIALNUMBER=04058690 - // Issuer: CN=COMODO RSA Extended Validation Secure Server CA, O=COMODO CA Limited, L=Salford, - // ST=Greater Manchester, C=GB - // Serial number: 720aa2cfa40094521224f901a984b167 - // Valid from: Thu Jun 29 17:00:00 PDT 2017 until: Sun Sep 29 16:59:59 PDT 2019 - private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" + - "MIIH8jCCBtqgAwIBAgIQcgqiz6QAlFISJPkBqYSxZzANBgkqhkiG9w0BAQsFADCB\n" + - "kjELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G\n" + - "A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxODA2BgNV\n" + - "BAMTL0NPTU9ETyBSU0EgRXh0ZW5kZWQgVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVy\n" + - "IENBMB4XDTE3MDYzMDAwMDAwMFoXDTE5MDkyOTIzNTk1OVowggFdMREwDwYDVQQF\n" + - "EwgwNDA1ODY5MDETMBEGCysGAQQBgjc8AgEDEwJHQjEdMBsGA1UEDxMUUHJpdmF0\n" + - "ZSBPcmdhbml6YXRpb24xCzAJBgNVBAYTAkdCMQ8wDQYDVQQREwZNNSAzRVExGzAZ\n" + - "BgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEWMBQG\n" + - "A1UECRMNVHJhZmZvcmQgUm9hZDEWMBQGA1UECRMNRXhjaGFuZ2UgUXVheTElMCMG\n" + - "A1UECRMcM3JkIEZsb29yLCAyNiBPZmZpY2UgVmlsbGFnZTEaMBgGA1UEChMRQ09N\n" + - "T0RPIENBIExpbWl0ZWQxGjAYBgNVBAsTEUNPTU9ETyBFViBTR0MgU1NMMTgwNgYD\n" + - "VQQDEy9jb21vZG9yc2FjZXJ0aWZpY2F0aW9uYXV0aG9yaXR5LWV2LmNvbW9kb2Nh\n" + - "LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAND/eZQBTjpBDsut\n" + - "eKwl+zpTitF8tJzwHAhcQHC2AaLF/GJl1rnjx4OfelMhKhN1Od9KU6onHGOd2w4m\n" + - "D4EiYK9TpXwuwTyzfkCmnkqxZjYK3KAJN013o4L+8y1zsGVUulpN/GfMaxTb4Xdm\n" + - "eSekTP91Phw3xezijBq3sa++1rO5RBaT1IHeHhHviC9WNrG8CIg/j5MyC9i43LZH\n" + - "iRXLER1LzT/MCIRsiG5AEbiYXV5BNd5SiiHtBJ1q0ZJH+AxL2ERaT41VCppboZwT\n" + - "hmJGGoky9FWjp6z8U6Enx0fAMJIZNEzW6LAJFKPEynEU004jFFCEumPUqqCC4ogx\n" + - "ulphY80CAwEAAaOCA3QwggNwMB8GA1UdIwQYMBaAFDna/8ooFIqodBMIueQOqdL6\n" + - "fp1pMB0GA1UdDgQWBBQ+S4ZhIrwOoeGs9BBT4uXq89Ux/jAOBgNVHQ8BAf8EBAMC\n" + - "BaAwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw\n" + - "TwYDVR0gBEgwRjA7BgwrBgEEAbIxAQIBBQEwKzApBggrBgEFBQcCARYdaHR0cHM6\n" + - "Ly9zZWN1cmUuY29tb2RvLmNvbS9DUFMwBwYFZ4EMAQEwVgYDVR0fBE8wTTBLoEmg\n" + - "R4ZFaHR0cDovL2NybC5jb21vZG9jYS5jb20vQ09NT0RPUlNBRXh0ZW5kZWRWYWxp\n" + - "ZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3JsMIGHBggrBgEFBQcBAQR7MHkwUQYIKwYB\n" + - "BQUHMAKGRWh0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9ET1JTQUV4dGVuZGVk\n" + - "VmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNydDAkBggrBgEFBQcwAYYYaHR0cDov\n" + - "L29jc3AuY29tb2RvY2EuY29tMDoGA1UdEQQzMDGCL2NvbW9kb3JzYWNlcnRpZmlj\n" + - "YXRpb25hdXRob3JpdHktZXYuY29tb2RvY2EuY29tMIIBgAYKKwYBBAHWeQIEAgSC\n" + - "AXAEggFsAWoAdgCkuQmQtBhYFIe7E6LMZ3AKPDWYBPkb37jjd80OyA3cEAAAAVz5\n" + - "cV7GAAAEAwBHMEUCIQCpgc0Eqw3g4pr+oX88h5xgL1VEAiDpqAhbRtilgYwBbgIg\n" + - "UaIm+n8AHi55nB//Sb4Nz18GYVcfELfpIzRh1vW9HbYAdwBWFAaaL9fC7NP14b1E\n" + - "sj7HRna5vJkRXMDvlJhV1onQ3QAAAVz5cVybAAAEAwBIMEYCIQDdsgC4KZ++OP44\n" + - "X7LbUcNaxe0kFzbctF2L3bnmhp9nXQIhAM0/g+PrZBIBpYlOtzidePi8bBHrLWn2\n" + - "uBiP3pYIntl4AHcA7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/csAAAFc\n" + - "+XFeoQAABAMASDBGAiEAoySTb/QKw7JwtZtPHnECEMzgENQSFy58Kl+Mvcd3SmcC\n" + - "IQD8cU66Ih3ejvt0OTX+lfxQPKyggQfm4Uk/lwn5LEJXbDANBgkqhkiG9w0BAQsF\n" + - "AAOCAQEAKEaSYWn3Hi8rfJS4cMTJoMkVp2vpPH2dGXySBEy67TEGRw9+f75w3q95\n" + - "r1m3P+xsR6dBoidTq/6wqUYI51lB4Fq9ylh1Stp5Gj54CuyT+S31l7lD7sl0KMsn\n" + - "HDUDQHId7hKeORYpiIZOcrKOglKdi1uiGwDgoiLKh98lUrZA6durrhH+sl69wqp2\n" + - "0XAu+3hurXzCoZFJfyngTO1kt9qcFUAxc5LofIa9QvC6VR7dI4aAh7dUpIRlnjG3\n" + - "jJ1mUMTqWO6TFTtddb+uQjDqNgkYYYNuSax1WMEIZWbIi13EjXK1GPQUXJe6gQin\n" + - "NUq9JH9NPK6m8A1YKT+wgzfTDeaV2Q==\n" + - "-----END CERTIFICATE-----"; - public void runTest(ValidatePathWithParams pathValidator) throws Exception { // Validate valid pathValidator.validate(new String[]{VALID, INT}, @@ -226,7 +225,7 @@ public void runTest(ValidatePathWithParams pathValidator) throws Exception { // Validate Revoked pathValidator.validate(new String[]{REVOKED, INT}, ValidatePathWithParams.Status.REVOKED, - "Thu Nov 29 08:41:09 PST 2018", System.out); + "Wed Oct 02 06:06:24 PDT 2019", System.out); } } @@ -261,6 +260,51 @@ class ComodoECC { + "lnxmeeOBnnCaDIxAcA3aCj2Gtdt3sA==\n" + "-----END CERTIFICATE-----"; + // Owner: CN=comodoecccertificationauthority-ev.comodoca.com, OU=COMODO EV SSL, O=Sectigo Limited, + // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford, + // OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.3=GB, + // SERIALNUMBER=04058690 + // Issuer: CN=COMODO ECC Extended Validation Secure Server CA, O=COMODO CA Limited, L=Salford, + // ST=Greater Manchester, C=GB + // Serial number: 7972d9d8472a2d52ad1ee6edfb16cbe1 + // Valid from: Sun Sep 29 17:00:00 PDT 2019 until: Tue Dec 28 15:59:59 PST 2021 + private static final String VALID = "-----BEGIN CERTIFICATE-----\n" + + "MIIGPzCCBeWgAwIBAgIQeXLZ2EcqLVKtHubt+xbL4TAKBggqhkjOPQQDAjCBkjEL\n" + + "MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE\n" + + "BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxODA2BgNVBAMT\n" + + "L0NPTU9ETyBFQ0MgRXh0ZW5kZWQgVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENB\n" + + "MB4XDTE5MDkzMDAwMDAwMFoXDTIxMTIyODIzNTk1OVowggE6MREwDwYDVQQFEwgw\n" + + "NDA1ODY5MDETMBEGCysGAQQBgjc8AgEDEwJHQjEdMBsGA1UEDxMUUHJpdmF0ZSBP\n" + + "cmdhbml6YXRpb24xCzAJBgNVBAYTAkdCMQ8wDQYDVQQREwZNNSAzRVExEDAOBgNV\n" + + "BAcTB1NhbGZvcmQxFjAUBgNVBAkTDVRyYWZmb3JkIFJvYWQxFjAUBgNVBAkTDUV4\n" + + "Y2hhbmdlIFF1YXkxJTAjBgNVBAkTHDNyZCBGbG9vciwgMjYgT2ZmaWNlIFZpbGxh\n" + + "Z2UxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDEWMBQGA1UECxMNQ09NT0RPIEVW\n" + + "IFNTTDE4MDYGA1UEAxMvY29tb2RvZWNjY2VydGlmaWNhdGlvbmF1dGhvcml0eS1l\n" + + "di5jb21vZG9jYS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS3bqoFLtNG\n" + + "7/J9H5GKosDNbYL5SykVmU5FzgSEt81gyAWShkqMSfAnO50fpr65E+o86E+BR3o8\n" + + "V9FAU5wuOaGBo4IDcDCCA2wwHwYDVR0jBBgwFoAU007DGbpYWdEcYLdhU0c7p3eP\n" + + "+IowHQYDVR0OBBYEFOlnS3MqxwXDpne8IQMXMZHlVKRXMA4GA1UdDwEB/wQEAwIF\n" + + "gDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBP\n" + + "BgNVHSAESDBGMDsGDCsGAQQBsjEBAgEFATArMCkGCCsGAQUFBwIBFh1odHRwczov\n" + + "L3NlY3VyZS5jb21vZG8uY29tL0NQUzAHBgVngQwBATBWBgNVHR8ETzBNMEugSaBH\n" + + "hkVodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9FQ0NFeHRlbmRlZFZhbGlk\n" + + "YXRpb25TZWN1cmVTZXJ2ZXJDQS5jcmwwgYcGCCsGAQUFBwEBBHsweTBRBggrBgEF\n" + + "BQcwAoZFaHR0cDovL2NydC5jb21vZG9jYS5jb20vQ09NT0RPRUNDRXh0ZW5kZWRW\n" + + "YWxpZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8v\n" + + "b2NzcC5jb21vZG9jYS5jb20wOgYDVR0RBDMwMYIvY29tb2RvZWNjY2VydGlmaWNh\n" + + "dGlvbmF1dGhvcml0eS1ldi5jb21vZG9jYS5jb20wggF8BgorBgEEAdZ5AgQCBIIB\n" + + "bASCAWgBZgB1AO5Lvbd1zmC64UJpH6vhnmajD35fsHLYgwDEe4l6qP3LAAABbYME\n" + + "EzgAAAQDAEYwRAIgbdo71lBleuJiq+D0ZLp51oVUyWD9EyrtgBSCNwIW4cMCIAqg\n" + + "0VFTWHEmAVjaV23fGj3Ybu3mpSiHr6viGlgA2lYaAHUAVYHUwhaQNgFK6gubVzxT\n" + + "8MDkOHhwJQgXL6OqHQcT0wwAAAFtgwQTKAAABAMARjBEAiBb/gW1RU7kgFBiNpHx\n" + + "LStujKIocyENUTXsMbsac+LktwIgXbEr8vOOCEdBdXQ2F/FKec8ft6gz57mHNmwl\n" + + "pp7phbQAdgC72d+8H4pxtZOUI5eqkntHOFeVCqtS6BqQlmQ2jh7RhQAAAW2DBBM6\n" + + "AAAEAwBHMEUCIQDjKN3h86ofR94+JxLFoYuoA+DRtxEY8XGg+NQXlZfUrgIgEoO2\n" + + "ZzKbGfohdwj/WtDwJDRX5pjXF4M0nECiwtYXDIwwCgYIKoZIzj0EAwIDSAAwRQIg\n" + + "AkIRVQBwrElFjrnqk5XPvnlnwkIm1A70ayqOf1FexoQCIQC8tBTn//RCfrhcgTjd\n" + + "ER4wRjFfFoc6lC68OHGVg9CZZg==\n" + + "-----END CERTIFICATE-----"; + // Owner: CN=comodoecccertificationauthority-ev.comodoca.com, OU=COMODO EV SSL, O=Sectigo Limited, // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford, // ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization, @@ -269,7 +313,7 @@ class ComodoECC { // ST=Greater Manchester, C=GB // Serial number: 603a5c2f85b63e00ba46ce8c3f6000b0 // Valid from: Wed Nov 28 16:00:00 PST 2018 until: Fri Feb 26 15:59:59 PST 2021 - private static final String VALID = "-----BEGIN CERTIFICATE-----\n" + + private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" + "MIIGXzCCBgWgAwIBAgIQYDpcL4W2PgC6Rs6MP2AAsDAKBggqhkjOPQQDAjCBkjEL\n" + "MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE\n" + "BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxODA2BgNVBAMT\n" + @@ -307,52 +351,6 @@ class ComodoECC { "KOC7\n" + "-----END CERTIFICATE-----"; - // Owner: CN=comodoecccertificationauthority-ev.comodoca.com, OU=COMODO EV SSL, O=COMODO CA Limited, - // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford, - // ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization, - // OID.1.3.6.1.4.1.311.60.2.1.3=GB, SERIALNUMBER=04058690 - // Issuer: CN=COMODO ECC Extended Validation Secure Server CA, O=COMODO CA Limited, L=Salford, - // ST=Greater Manchester, C=GB - // Serial number: 414e5d66ec7d15ca504213f2811d57af - // Valid from: Mon Jul 03 17:00:00 PDT 2017 until: Thu Oct 03 16:59:59 PDT 2019 - private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" + - "MIIGYDCCBgWgAwIBAgIQQU5dZux9FcpQQhPygR1XrzAKBggqhkjOPQQDAjCBkjEL\n" + - "MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE\n" + - "BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxODA2BgNVBAMT\n" + - "L0NPTU9ETyBFQ0MgRXh0ZW5kZWQgVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENB\n" + - "MB4XDTE3MDcwNDAwMDAwMFoXDTE5MTAwMzIzNTk1OVowggFZMREwDwYDVQQFEwgw\n" + - "NDA1ODY5MDETMBEGCysGAQQBgjc8AgEDEwJHQjEdMBsGA1UEDxMUUHJpdmF0ZSBP\n" + - "cmdhbml6YXRpb24xCzAJBgNVBAYTAkdCMQ8wDQYDVQQREwZNNSAzRVExGzAZBgNV\n" + - "BAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEWMBQGA1UE\n" + - "CRMNVHJhZmZvcmQgUm9hZDEWMBQGA1UECRMNRXhjaGFuZ2UgUXVheTElMCMGA1UE\n" + - "CRMcM3JkIEZsb29yLCAyNiBPZmZpY2UgVmlsbGFnZTEaMBgGA1UEChMRQ09NT0RP\n" + - "IENBIExpbWl0ZWQxFjAUBgNVBAsTDUNPTU9ETyBFViBTU0wxODA2BgNVBAMTL2Nv\n" + - "bW9kb2VjY2NlcnRpZmljYXRpb25hdXRob3JpdHktZXYuY29tb2RvY2EuY29tMFkw\n" + - "EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEt26qBS7TRu/yfR+RiqLAzW2C+UspFZlO\n" + - "Rc4EhLfNYMgFkoZKjEnwJzudH6a+uRPqPOhPgUd6PFfRQFOcLjmhgaOCA3EwggNt\n" + - "MB8GA1UdIwQYMBaAFNNOwxm6WFnRHGC3YVNHO6d3j/iKMB0GA1UdDgQWBBTpZ0tz\n" + - "KscFw6Z3vCEDFzGR5VSkVzAOBgNVHQ8BAf8EBAMCBYAwDAYDVR0TAQH/BAIwADAd\n" + - "BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwTwYDVR0gBEgwRjA7BgwrBgEE\n" + - "AbIxAQIBBQEwKzApBggrBgEFBQcCARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLmNv\n" + - "bS9DUFMwBwYFZ4EMAQEwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5jb21v\n" + - "ZG9jYS5jb20vQ09NT0RPRUNDRXh0ZW5kZWRWYWxpZGF0aW9uU2VjdXJlU2VydmVy\n" + - "Q0EuY3JsMIGHBggrBgEFBQcBAQR7MHkwUQYIKwYBBQUHMAKGRWh0dHA6Ly9jcnQu\n" + - "Y29tb2RvY2EuY29tL0NPTU9ET0VDQ0V4dGVuZGVkVmFsaWRhdGlvblNlY3VyZVNl\n" + - "cnZlckNBLmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29t\n" + - "MDoGA1UdEQQzMDGCL2NvbW9kb2VjY2NlcnRpZmljYXRpb25hdXRob3JpdHktZXYu\n" + - "Y29tb2RvY2EuY29tMIIBfQYKKwYBBAHWeQIEAgSCAW0EggFpAWcAdgCkuQmQtBhY\n" + - "FIe7E6LMZ3AKPDWYBPkb37jjd80OyA3cEAAAAV0NLqsqAAAEAwBHMEUCIAz9Jjq3\n" + - "qLUd/a2PYZnLGsEG/MrL7vab5rmGBg8RGAJxAiEA7JJnar07NIjCLLO77xJ3UFcu\n" + - "UMM3M8JgGC8wbuRwxbUAdgBWFAaaL9fC7NP14b1Esj7HRna5vJkRXMDvlJhV1onQ\n" + - "3QAAAV0NLqjmAAAEAwBHMEUCIHRvPWKr7vPMBWx1gLPkt8inPINWPNSoax178e5A\n" + - "D0cPAiEAvRL/VP4DLiyHvcU9AOqTzQXGuWCzswWKG59hSm7gS4kAdQDuS723dc5g\n" + - "uuFCaR+r4Z5mow9+X7By2IMAxHuJeqj9ywAAAV0NLqsDAAAEAwBGMEQCIFALT043\n" + - "X5IffLsxIAGXTrWgkZHf12QKgrYKXVB629eOAiAIeci2xi3fUW6mU8tT4LwyjowV\n" + - "DkrSCw1ZMo0JApsfzTAKBggqhkjOPQQDAgNJADBGAiEA7HUxjwx0MBC+4PuPx4Z1\n" + - "WpKz7jdHOMTh1sdaoVV5hNoCIQDrnjBFUopXHTvm/rj+aMFIeYejggPqv14KJOqT\n" + - "gym+uA==\n" + - "-----END CERTIFICATE-----"; - public void runTest(ValidatePathWithParams pathValidator) throws Exception { // Validate valid pathValidator.validate(new String[]{VALID, INT}, @@ -361,19 +359,61 @@ public void runTest(ValidatePathWithParams pathValidator) throws Exception { // Validate Revoked pathValidator.validate(new String[]{REVOKED, INT}, ValidatePathWithParams.Status.REVOKED, - "Thu Nov 29 08:12:02 PST 2018", System.out); + "Wed Oct 02 06:05:57 PDT 2019", System.out); } } class ComodoUserTrustRSA { + // Owner: CN=Sectigo RSA Extended Validation Secure Server CA, O=Sectigo Limited, L=Salford, + // ST=Greater Manchester, C=GB + // Issuer: CN=USERTrust RSA Certification Authority, O=The USERTRUST Network, L=Jersey City, ST=New Jersey, C=US + // Serial number: 284e39c14b386d889c7299e58cd05a57 + // Valid from: Thu Nov 01 17:00:00 PDT 2018 until: Tue Dec 31 15:59:59 PST 2030 + private static final String INT_VALID = "-----BEGIN CERTIFICATE-----\n" + + "MIIGNDCCBBygAwIBAgIQKE45wUs4bYiccpnljNBaVzANBgkqhkiG9w0BAQwFADCB\n" + + "iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl\n" + + "cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV\n" + + "BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTgx\n" + + "MTAyMDAwMDAwWhcNMzAxMjMxMjM1OTU5WjCBkTELMAkGA1UEBhMCR0IxGzAZBgNV\n" + + "BAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEYMBYGA1UE\n" + + "ChMPU2VjdGlnbyBMaW1pdGVkMTkwNwYDVQQDEzBTZWN0aWdvIFJTQSBFeHRlbmRl\n" + + "ZCBWYWxpZGF0aW9uIFNlY3VyZSBTZXJ2ZXIgQ0EwggEiMA0GCSqGSIb3DQEBAQUA\n" + + "A4IBDwAwggEKAoIBAQCaoslYBiqFev0Yc4TXPa0s9oliMcn9VaENfTUK4GVT7niB\n" + + "QXxC6Mt8kTtvyr5lU92hDQDh2WDPQsZ7oibh75t2kowT3z1S+Sy1GsUDM4NbdOde\n" + + "orcmzFm/b4bwD4G/G+pB4EX1HSfjN9eT0Hje+AGvCrd2MmnxJ+Yymv9BH9OB65jK\n" + + "rUO9Na4iHr48XWBDFvzsPCJ11Uioof6dRBVp+Lauj88Z7k2X8d606HeXn43h6acp\n" + + "LLURWyqXM0CrzedVWBzuXKuBEaqD6w/1VpLJvSU+wl3ScvXSLFp82DSRJVJONXWl\n" + + "dp9gjJioPGRByeZw11k3galbbF5gFK9xSnbDx29LAgMBAAGjggGNMIIBiTAfBgNV\n" + + "HSMEGDAWgBRTeb9aqitKz1SA4dibwJ3ysgNmyzAdBgNVHQ4EFgQULGn/gMmHkK40\n" + + "4bTnTJOFmUDpp7IwDgYDVR0PAQH/BAQDAgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAw\n" + + "HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMDoGA1UdIAQzMDEwLwYEVR0g\n" + + "ADAnMCUGCCsGAQUFBwIBFhlodHRwczovL2Nwcy51c2VydHJ1c3QuY29tMFAGA1Ud\n" + + "HwRJMEcwRaBDoEGGP2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VU0VSVHJ1c3RS\n" + + "U0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDB2BggrBgEFBQcBAQRqMGgwPwYI\n" + + "KwYBBQUHMAKGM2h0dHA6Ly9jcnQudXNlcnRydXN0LmNvbS9VU0VSVHJ1c3RSU0FB\n" + + "ZGRUcnVzdENBLmNydDAlBggrBgEFBQcwAYYZaHR0cDovL29jc3AudXNlcnRydXN0\n" + + "LmNvbTANBgkqhkiG9w0BAQwFAAOCAgEAQ4AzPxVypLyy3IjUUmVl7FaxrHsXQq2z\n" + + "Zt2gKnHQShuA+5xpRPNndjvhHk4D08PZXUe6Im7E5knqxtyl5aYdldb+HI/7f+zd\n" + + "W/1ub2N4Vq4ZYUjcZ1ECOFK7Z2zoNicDmU+Fe/TreXPuPsDicTG/tMcWEVM558OQ\n" + + "TJkB2LK3ZhGukWM/RTMRcRdXaXOX8Lh0ylzRO1O0ObXytvOFpkkkD92HGsfS06i7\n" + + "NLDPJEeZXqzHE5Tqj7VSAj+2luwfaXaPLD8lQEVci8xmsPGOn0mXE1ZzsChEPhVq\n" + + "FYQUsbiRJRhidKauhd+G2CkRTcR5fpsuz+iStB9s5Fks9lKoXnn0hv78VYjvR78C\n" + + "Cvj5FW/ounHjWTWMb3il9S5ngbFGcelB1l/MQkR63+1ybdi2OpjNWJCftxOWUpkC\n" + + "xaRdnOnSj7GQY0NLn8Gtq9FcSZydtkVgXpouSFZkXNS/MYwbcCCcRKBbrk8ss0SI\n" + + "Xg1gTURjh9VP1OHm0OktYcUw9e90wHIDn7h0qA+bWOsZquSRzT4s2crF3ZSA3tuV\n" + + "/UJ33mjdVO8wBD8aI5y10QreSPJvZHHNDyCmoyjXvNhR+u3arXUoHWxO+MZBeXbi\n" + + "iF7Nwn/IEmQvWBW8l6D26CXIavcY1kAJcfyzHkrPbLo+fAOa/KFl3lIU+0biEVNk\n" + + "Q9zXE6hC6X4=\n" + + "-----END CERTIFICATE-----"; + // Owner: CN=USERTrust RSA Extended Validation Secure Server CA, // O=The USERTRUST Network, L=Jersey City, ST=New Jersey, C=US // Issuer: CN=USERTrust RSA Certification Authority, O=The USERTRUST Network, // L=Jersey City, ST=New Jersey, C=US // Serial number: f6bb751efa7d2e8368e606407334f83 // Valid from: Sat Feb 11 16:00:00 PST 2012 until: Thu Feb 11 15:59:59 PST 2027 - private static final String INT = "-----BEGIN CERTIFICATE-----\n" + private static final String INT_REVOKED = "-----BEGIN CERTIFICATE-----\n" + "MIIGGTCCBAGgAwIBAgIQD2u3Ue+n0ug2jmBkBzNPgzANBgkqhkiG9w0BAQwFADCB\n" + "iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl\n" + "cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV\n" @@ -409,15 +449,69 @@ class ComodoUserTrustRSA { + "4fokbdNREXoShKClNIPbB5iY+WdSzb9CKLyb96g=\n" + "-----END CERTIFICATE-----"; - // Owner: CN=usertrustrsacertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, - // O=Sectigo Limited, STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, - // L=Salford, ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization, + // Owner: CN=usertrustrsacertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, O=Sectigo Limited, + // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford, ST=Manchester, + // OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.3=GB, + // SERIALNUMBER=04058690 + // Issuer: CN=Sectigo RSA Extended Validation Secure Server CA, O=Sectigo Limited, L=Salford, + // ST=Greater Manchester, C=GB + // Serial number: b07fd164b5790c9d5d1fddff5819cdb2 + // Valid from: Sun Sep 29 17:00:00 PDT 2019 until: Tue Dec 28 15:59:59 PST 2021 + private static final String VALID = "-----BEGIN CERTIFICATE-----\n" + + "MIIH5TCCBs2gAwIBAgIRALB/0WS1eQydXR/d/1gZzbIwDQYJKoZIhvcNAQELBQAw\n" + + "gZExCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO\n" + + "BgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDE5MDcGA1UE\n" + + "AxMwU2VjdGlnbyBSU0EgRXh0ZW5kZWQgVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVy\n" + + "IENBMB4XDTE5MDkzMDAwMDAwMFoXDTIxMTIyODIzNTk1OVowggFWMREwDwYDVQQF\n" + + "EwgwNDA1ODY5MDETMBEGCysGAQQBgjc8AgEDEwJHQjEdMBsGA1UEDxMUUHJpdmF0\n" + + "ZSBPcmdhbml6YXRpb24xCzAJBgNVBAYTAkdCMQ8wDQYDVQQREwZNNSAzRVExEzAR\n" + + "BgNVBAgTCk1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxFjAUBgNVBAkTDVRy\n" + + "YWZmb3JkIFJvYWQxFjAUBgNVBAkTDUV4Y2hhbmdlIFF1YXkxJTAjBgNVBAkTHDNy\n" + + "ZCBGbG9vciwgMjYgT2ZmaWNlIFZpbGxhZ2UxGDAWBgNVBAoTD1NlY3RpZ28gTGlt\n" + + "aXRlZDEaMBgGA1UECxMRQ09NT0RPIEVWIFNHQyBTU0wxOzA5BgNVBAMTMnVzZXJ0\n" + + "cnVzdHJzYWNlcnRpZmljYXRpb25hdXRob3JpdHktZXYuY29tb2RvY2EuY29tMIIB\n" + + "IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnh/rxeiYwpLa651eLvGnR+RE\n" + + "rhDWkTZtqZcHw9Oy7JL2uELyEPbM+v0az40cBHS0bQZJZbWmXNukMUMSwIb4z7t8\n" + + "OXlxz9uvxEufvlqBl4qeC/z3LpFBRRHEero3yGKVwkoe1aP2Pq7Udi+7i7eVZZdA\n" + + "1ticxZWo/UBU9mwbIOYqf/4xzZ6G891hKb+NAuuEfxG52vXZl8odMThfHuDlkfS7\n" + + "nZMQBaO40KJeSEBhr+5TIS7d7tWWye/F6oEQ0+dHBiF9PyZ1dXoO8aue/80mP+0F\n" + + "MYTmRFsKHge6ZjojfH9cLlR5kTqtP5Tqh5GBQ4zp3uyIBBU6ylKp9PNHkewGUQID\n" + + "AQABo4IDbjCCA2owHwYDVR0jBBgwFoAULGn/gMmHkK404bTnTJOFmUDpp7IwHQYD\n" + + "VR0OBBYEFHz7cvDn1LYe2M+z4plwQn7rt938MA4GA1UdDwEB/wQEAwIFoDAMBgNV\n" + + "HRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBJBgNVHSAE\n" + + "QjBAMDUGDCsGAQQBsjEBAgEFATAlMCMGCCsGAQUFBwIBFhdodHRwczovL3NlY3Rp\n" + + "Z28uY29tL0NQUzAHBgVngQwBATBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3Js\n" + + "LnNlY3RpZ28uY29tL1NlY3RpZ29SU0FFeHRlbmRlZFZhbGlkYXRpb25TZWN1cmVT\n" + + "ZXJ2ZXJDQS5jcmwwgYYGCCsGAQUFBwEBBHoweDBRBggrBgEFBQcwAoZFaHR0cDov\n" + + "L2NydC5zZWN0aWdvLmNvbS9TZWN0aWdvUlNBRXh0ZW5kZWRWYWxpZGF0aW9uU2Vj\n" + + "dXJlU2VydmVyQ0EuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdv\n" + + "LmNvbTA9BgNVHREENjA0gjJ1c2VydHJ1c3Ryc2FjZXJ0aWZpY2F0aW9uYXV0aG9y\n" + + "aXR5LWV2LmNvbW9kb2NhLmNvbTCCAX4GCisGAQQB1nkCBAIEggFuBIIBagFoAHYA\n" + + "7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/csAAAFtgzv54wAABAMARzBF\n" + + "AiB5PmhsK3zU3XdKvyxw/wWHMmLI7apHLa1yKdjkA8H+ggIhALdUx7Tl8aeWhK6z\n" + + "lh+PHvMAdCcAJK6w9qBJGQtSrYO5AHUAVYHUwhaQNgFK6gubVzxT8MDkOHhwJQgX\n" + + "L6OqHQcT0wwAAAFtgzv5zgAABAMARjBEAiBumSwAUamibqJXTN2cf/H3mjd0T35/\n" + + "UK9w2hu9gFobxgIgSXTLndHyqFUmcmquu3It0WC1yl6YMceGixbQL1e8BQcAdwC7\n" + + "2d+8H4pxtZOUI5eqkntHOFeVCqtS6BqQlmQ2jh7RhQAAAW2DO/nXAAAEAwBIMEYC\n" + + "IQDHRs10oYoXE5yq6WsiksjdQsUWZNpbSsrmz0u+KlxTVQIhAJ4rvHItKSeJLkaN\n" + + "S3YpVZnkN8tOwuxPsYeyVx/BtaNpMA0GCSqGSIb3DQEBCwUAA4IBAQAPFIsUFymo\n" + + "VTp0vntHrZpBApBQzDeriQv7Bi7tmou/Ng47RtXW3DjGdrePGSfOdl7h62k8qprU\n" + + "JeLyloDqhvmT/CG/hdwrfZ3Sv3N2xpetGcnW5S3oEi3m+/M1ls9eD+x1vybqV9Kd\n" + + "lcjuV7SYDlbvAS9w7TcygudhdW0cI8XTCvesGKohBkAlqaQ/MWYpt4WvsxHjbWgn\n" + + "5ZlIYR6A1ZFEjADifViH/5AA79lgGhAskkIWPjvRFalEVKTKtjhRK76eCfZs4Frr\n" + + "CEOpon+BeNKk+x/K/r10dSoWe0SV2uGVxTD83zkP++eREwo1hTgn8bXn7ftlnA3j\n" + + "7ml+Usz6udaD\n" + + "-----END CERTIFICATE-----"; + + // Owner: CN=usertrustrsacertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, O=Sectigo Limited, + // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford, + // ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization, // OID.1.3.6.1.4.1.311.60.2.1.3=GB, SERIALNUMBER=04058690 // Issuer: CN=USERTrust RSA Extended Validation Secure Server CA, O=The USERTRUST Network, L=Jersey City, // ST=New Jersey, C=US // Serial number: d3c204e8df6a1539568cf15e97e57b1d // Valid from: Wed Nov 28 16:00:00 PST 2018 until: Fri Feb 26 15:59:59 PST 2021 - private static final String VALID = "-----BEGIN CERTIFICATE-----\n" + + private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" + "MIIIADCCBuigAwIBAgIRANPCBOjfahU5VozxXpflex0wDQYJKoZIhvcNAQELBQAw\n" + "gZUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5MRQwEgYDVQQHEwtK\n" + "ZXJzZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMTswOQYD\n" + @@ -463,81 +557,56 @@ class ComodoUserTrustRSA { "3Ld31zbQaywKdpCsT74/hEBMfcDiP02mmtyrlqHD4R3tdYne\n" + "-----END CERTIFICATE-----"; - // Owner: CN=usertrustrsacertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, O=COMODO CA Limited, - // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford, - // ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization, - // OID.1.3.6.1.4.1.311.60.2.1.3=GB, SERIALNUMBER=04058690 - // Issuer: CN=USERTrust RSA Extended Validation Secure Server CA, O=The USERTRUST Network, L=Jersey City, - // ST=New Jersey, C=US - // Serial number: ffcada019c9fb1155a32300083cb99c9 - // Valid from: Mon Jul 03 17:00:00 PDT 2017 until: Thu Oct 03 16:59:59 PDT 2019 - private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" + - "MIIIATCCBumgAwIBAgIRAP/K2gGcn7EVWjIwAIPLmckwDQYJKoZIhvcNAQELBQAw\n" + - "gZUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5MRQwEgYDVQQHEwtK\n" + - "ZXJzZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMTswOQYD\n" + - "VQQDEzJVU0VSVHJ1c3QgUlNBIEV4dGVuZGVkIFZhbGlkYXRpb24gU2VjdXJlIFNl\n" + - "cnZlciBDQTAeFw0xNzA3MDQwMDAwMDBaFw0xOTEwMDMyMzU5NTlaMIIBYDERMA8G\n" + - "A1UEBRMIMDQwNTg2OTAxEzARBgsrBgEEAYI3PAIBAxMCR0IxHTAbBgNVBA8TFFBy\n" + - "aXZhdGUgT3JnYW5pemF0aW9uMQswCQYDVQQGEwJHQjEPMA0GA1UEERMGTTUgM0VR\n" + - "MRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQx\n" + - "FjAUBgNVBAkTDVRyYWZmb3JkIFJvYWQxFjAUBgNVBAkTDUV4Y2hhbmdlIFF1YXkx\n" + - "JTAjBgNVBAkTHDNyZCBGbG9vciwgMjYgT2ZmaWNlIFZpbGxhZ2UxGjAYBgNVBAoT\n" + - "EUNPTU9ETyBDQSBMaW1pdGVkMRowGAYDVQQLExFDT01PRE8gRVYgU0dDIFNTTDE7\n" + - "MDkGA1UEAxMydXNlcnRydXN0cnNhY2VydGlmaWNhdGlvbmF1dGhvcml0eS1ldi5j\n" + - "b21vZG9jYS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCeH+vF\n" + - "6JjCktrrnV4u8adH5ESuENaRNm2plwfD07Lskva4QvIQ9sz6/RrPjRwEdLRtBkll\n" + - "taZc26QxQxLAhvjPu3w5eXHP26/ES5++WoGXip4L/PcukUFFEcR6ujfIYpXCSh7V\n" + - "o/Y+rtR2L7uLt5Vll0DW2JzFlaj9QFT2bBsg5ip//jHNnobz3WEpv40C64R/Ebna\n" + - "9dmXyh0xOF8e4OWR9LudkxAFo7jQol5IQGGv7lMhLt3u1ZbJ78XqgRDT50cGIX0/\n" + - "JnV1eg7xq57/zSY/7QUxhOZEWwoeB7pmOiN8f1wuVHmROq0/lOqHkYFDjOne7IgE\n" + - "FTrKUqn080eR7AZRAgMBAAGjggN8MIIDeDAfBgNVHSMEGDAWgBQvgU/iZvq8aL+Z\n" + - "Q4RSiSA6gvOkpTAdBgNVHQ4EFgQUfPty8OfUth7Yz7PimXBCfuu33fwwDgYDVR0P\n" + - "AQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG\n" + - "AQUFBwMCMEsGA1UdIAREMEIwNwYMKwYBBAGyMQECAQUBMCcwJQYIKwYBBQUHAgEW\n" + - "GWh0dHBzOi8vY3BzLnVzZXJ0cnVzdC5jb20wBwYFZ4EMAQEwWgYDVR0fBFMwUTBP\n" + - "oE2gS4ZJaHR0cDovL2NybC51c2VydHJ1c3QuY29tL1VTRVJUcnVzdFJTQUV4dGVu\n" + - "ZGVkVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNybDCBjQYIKwYBBQUHAQEEgYAw\n" + - "fjBVBggrBgEFBQcwAoZJaHR0cDovL2NydC51c2VydHJ1c3QuY29tL1VTRVJUcnVz\n" + - "dFJTQUV4dGVuZGVkVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNydDAlBggrBgEF\n" + - "BQcwAYYZaHR0cDovL29jc3AudXNlcnRydXN0LmNvbTA9BgNVHREENjA0gjJ1c2Vy\n" + - "dHJ1c3Ryc2FjZXJ0aWZpY2F0aW9uYXV0aG9yaXR5LWV2LmNvbW9kb2NhLmNvbTCC\n" + - "AX8GCisGAQQB1nkCBAIEggFvBIIBawFpAHYApLkJkLQYWBSHuxOizGdwCjw1mAT5\n" + - "G9+443fNDsgN3BAAAAFdDU2iYQAABAMARzBFAiB0o4GnVHD8MeVQ32D0XYu+EQQW\n" + - "jvN78rmCfk0OEBxyFAIhAKgyctIn0IaDJiZzsrtAiqEnkcMtuh8o+R0Rqw1ygAjk\n" + - "AHcAVhQGmi/XwuzT9eG9RLI+x0Z2ubyZEVzA75SYVdaJ0N0AAAFdDU2gFgAABAMA\n" + - "SDBGAiEA7mcmZ8H5uHuNCdI0CVxsqDZQcZX/gVk94KckePkzQoACIQCHwm5hcvNC\n" + - "M8vNmFkboQN79DglRctHrlh143A6mUTk8QB2AO5Lvbd1zmC64UJpH6vhnmajD35f\n" + - "sHLYgwDEe4l6qP3LAAABXQ1NojoAAAQDAEcwRQIhAPqwijgE0Fr6uJ+yF+TvyXco\n" + - "Hduv9h7R5WWwJfghXiMyAiBB4+fJm4rIcOnJBZmOqFnRpIjPN0jwDqJT0nDHxaXA\n" + - "nDANBgkqhkiG9w0BAQsFAAOCAQEACXitF1bTEvV1HX11WrT/XuoMhsoPK4TS16rs\n" + - "FqztV4iXKlA1/h5qbsjYY1gVrM+/6kQkmEs5qrxsek2WNxY80NO3WAzroRJ3H9Sd\n" + - "mPn0No2P8LZ5Fs5hvaD/PfWO5xxey80c3kGyvWOej90P3IrL/1RiULyh95TrXBjI\n" + - "ddCBsZ28904wsQUrPBPMpiu0DKl1HR/em9WkcipMi+onJxxFWjucssz5PW/BzGYF\n" + - "jfWLDEI0tN5L4CWV3iVXFXOURY1Mwhtsey9jvlEyxSsys55QdKF40yGgtV9VC+os\n" + - "7hJP33+qA0cvCTaRytiPP6z/l2G/KSIXTyv6SxzGhsTFfzLAOg==\n" + - "-----END CERTIFICATE-----"; - public void runTest(ValidatePathWithParams pathValidator) throws Exception { // Validate valid - pathValidator.validate(new String[]{VALID, INT}, + pathValidator.validate(new String[]{VALID, INT_VALID}, ValidatePathWithParams.Status.GOOD, null, System.out); // Validate Revoked - pathValidator.validate(new String[]{REVOKED, INT}, + pathValidator.validate(new String[]{REVOKED, INT_REVOKED}, ValidatePathWithParams.Status.REVOKED, - "Thu Nov 29 10:58:13 PST 2018", System.out); + "Wed Oct 02 06:07:12 PDT 2019", System.out); } } class ComodoUserTrustECC { + // Owner: CN=Sectigo ECC Extended Validation Secure Server CA, O=Sectigo Limited, L=Salford, + // ST=Greater Manchester, C=GB + // Issuer: CN=USERTrust ECC Certification Authority, O=The USERTRUST Network, L=Jersey City, ST=New Jersey, C=US + // Serial number: 80f5606d3a162b143adc12fbe8c2066f + // Valid from: Thu Nov 01 17:00:00 PDT 2018 until: Tue Dec 31 15:59:59 PST 2030 + private static final String INT_VALID = "-----BEGIN CERTIFICATE-----\n" + + "MIIDyTCCA0+gAwIBAgIRAID1YG06FisUOtwS++jCBm8wCgYIKoZIzj0EAwMwgYgx\n" + + "CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5MRQwEgYDVQQHEwtKZXJz\n" + + "ZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMS4wLAYDVQQD\n" + + "EyVVU0VSVHJ1c3QgRUNDIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTE4MTEw\n" + + "MjAwMDAwMFoXDTMwMTIzMTIzNTk1OVowgZExCzAJBgNVBAYTAkdCMRswGQYDVQQI\n" + + "ExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoT\n" + + "D1NlY3RpZ28gTGltaXRlZDE5MDcGA1UEAxMwU2VjdGlnbyBFQ0MgRXh0ZW5kZWQg\n" + + "VmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENBMFkwEwYHKoZIzj0CAQYIKoZIzj0D\n" + + "AQcDQgAEAyJ5Ca9JyXq8bO+krLVWysbtm7fdMSJ54uFD23t0x6JAC4IjxevfQJzW\n" + + "z4T6yY+FybTBqtOa++ijJFnkB5wKy6OCAY0wggGJMB8GA1UdIwQYMBaAFDrhCYbU\n" + + "zxnClnZ0SXbc4DXGY2OaMB0GA1UdDgQWBBTvwSqVDDLa+3Mw3IoT2BVL9xPo+DAO\n" + + "BgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHSUEFjAUBggr\n" + + "BgEFBQcDAQYIKwYBBQUHAwIwOgYDVR0gBDMwMTAvBgRVHSAAMCcwJQYIKwYBBQUH\n" + + "AgEWGWh0dHBzOi8vY3BzLnVzZXJ0cnVzdC5jb20wUAYDVR0fBEkwRzBFoEOgQYY/\n" + + "aHR0cDovL2NybC51c2VydHJ1c3QuY29tL1VTRVJUcnVzdEVDQ0NlcnRpZmljYXRp\n" + + "b25BdXRob3JpdHkuY3JsMHYGCCsGAQUFBwEBBGowaDA/BggrBgEFBQcwAoYzaHR0\n" + + "cDovL2NydC51c2VydHJ1c3QuY29tL1VTRVJUcnVzdEVDQ0FkZFRydXN0Q0EuY3J0\n" + + "MCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcC51c2VydHJ1c3QuY29tMAoGCCqGSM49\n" + + "BAMDA2gAMGUCMQCjHztBDL90GCRXHlGqm0H7kzP04hd0MxwakKjWzOmstXNFLONj\n" + + "RFa0JqI/iKUJMFcCMCbLgyzcFW7DihtY5XE0XCLCw+git0NjxiFB6FaOFIlyDdqT\n" + + "j+Th+DJ92JLvICVD/g==\n" + + "-----END CERTIFICATE-----"; + // Owner: CN=USERTrust ECC Extended Validation Secure Server CA, O=The USERTRUST Network, // L=Jersey City, ST=New Jersey, C=US // Issuer: CN=USERTrust ECC Certification Authority, O=The USERTRUST Network, // L=Jersey City, ST=New Jersey, C=US // Serial number: 3d09b24f5c08a7ce8eb85a51d3c1aa52 // Valid from: Sun Apr 14 17:00:00 PDT 2013 until: Fri Apr 14 16:59:59 PDT 2028 - private static final String INT = "-----BEGIN CERTIFICATE-----\n" + private static final String INT_REVOKED = "-----BEGIN CERTIFICATE-----\n" + "MIIDwTCCA0igAwIBAgIQPQmyT1wIp86OuFpR08GqUjAKBggqhkjOPQQDAzCBiDEL\n" + "MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl\n" + "eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT\n" @@ -561,6 +630,51 @@ class ComodoUserTrustECC { + "s1rWGRU=\n" + "-----END CERTIFICATE-----"; + // Owner: CN=usertrustecccertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, O=Sectigo Limited, + // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford, + // OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.3=GB, + // SERIALNUMBER=04058690 + // Issuer: CN=Sectigo ECC Extended Validation Secure Server CA, O=Sectigo Limited, L=Salford, + // ST=Greater Manchester, C=GB + // Serial number: 8b72489b7f505a55e2a22659c90ed2ab + // Valid from: Sun Sep 29 17:00:00 PDT 2019 until: Tue Dec 28 15:59:59 PST 2021 + private static final String VALID = "-----BEGIN CERTIFICATE-----\n" + + "MIIGRTCCBeugAwIBAgIRAItySJt/UFpV4qImWckO0qswCgYIKoZIzj0EAwIwgZEx\n" + + "CzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNV\n" + + "BAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDE5MDcGA1UEAxMw\n" + + "U2VjdGlnbyBFQ0MgRXh0ZW5kZWQgVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENB\n" + + "MB4XDTE5MDkzMDAwMDAwMFoXDTIxMTIyODIzNTk1OVowggFBMREwDwYDVQQFEwgw\n" + + "NDA1ODY5MDETMBEGCysGAQQBgjc8AgEDEwJHQjEdMBsGA1UEDxMUUHJpdmF0ZSBP\n" + + "cmdhbml6YXRpb24xCzAJBgNVBAYTAkdCMQ8wDQYDVQQREwZNNSAzRVExEDAOBgNV\n" + + "BAcTB1NhbGZvcmQxFjAUBgNVBAkTDVRyYWZmb3JkIFJvYWQxFjAUBgNVBAkTDUV4\n" + + "Y2hhbmdlIFF1YXkxJTAjBgNVBAkTHDNyZCBGbG9vciwgMjYgT2ZmaWNlIFZpbGxh\n" + + "Z2UxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDEaMBgGA1UECxMRQ09NT0RPIEVW\n" + + "IFNHQyBTU0wxOzA5BgNVBAMTMnVzZXJ0cnVzdGVjY2NlcnRpZmljYXRpb25hdXRo\n" + + "b3JpdHktZXYuY29tb2RvY2EuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE\n" + + "LTJfEd92Wlg+h/AVtPsMmwX9Puvi+WGCv3sgFRpur8Iy2kGVpXHRQTCn2j9aky4t\n" + + "FQGm7OG2klJA/MEeevKVaaOCA28wggNrMB8GA1UdIwQYMBaAFO/BKpUMMtr7czDc\n" + + "ihPYFUv3E+j4MB0GA1UdDgQWBBSzrWHzmiHwx2Rrm7SjRC0UegNrKzAOBgNVHQ8B\n" + + "Af8EBAMCB4AwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB\n" + + "BQUHAwIwSQYDVR0gBEIwQDA1BgwrBgEEAbIxAQIBBQEwJTAjBggrBgEFBQcCARYX\n" + + "aHR0cHM6Ly9zZWN0aWdvLmNvbS9DUFMwBwYFZ4EMAQEwVgYDVR0fBE8wTTBLoEmg\n" + + "R4ZFaHR0cDovL2NybC5zZWN0aWdvLmNvbS9TZWN0aWdvRUNDRXh0ZW5kZWRWYWxp\n" + + "ZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3JsMIGGBggrBgEFBQcBAQR6MHgwUQYIKwYB\n" + + "BQUHMAKGRWh0dHA6Ly9jcnQuc2VjdGlnby5jb20vU2VjdGlnb0VDQ0V4dGVuZGVk\n" + + "VmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNydDAjBggrBgEFBQcwAYYXaHR0cDov\n" + + "L29jc3Auc2VjdGlnby5jb20wPQYDVR0RBDYwNIIydXNlcnRydXN0ZWNjY2VydGlm\n" + + "aWNhdGlvbmF1dGhvcml0eS1ldi5jb21vZG9jYS5jb20wggF/BgorBgEEAdZ5AgQC\n" + + "BIIBbwSCAWsBaQB2AO5Lvbd1zmC64UJpH6vhnmajD35fsHLYgwDEe4l6qP3LAAAB\n" + + "bYL/SJoAAAQDAEcwRQIhAL7EJt/Rgz6NBnx2v8Hevux3Gpcxy64kaeyLVgFeNqFk\n" + + "AiBRf+OWLOtZzEav/oERljrk8hgZB4CR1nj/Tn98cmRrwwB2AFWB1MIWkDYBSuoL\n" + + "m1c8U/DA5Dh4cCUIFy+jqh0HE9MMAAABbYL/SIgAAAQDAEcwRQIgVtZZaiBMC2lu\n" + + "atBzUHQmOq4qrUQP7nS83cd3VzPhToECIQDnlpOCdaxJwr8C0MtkvYpKSabwBPFL\n" + + "ASEkwmOpjuQErAB3ALvZ37wfinG1k5Qjl6qSe0c4V5UKq1LoGpCWZDaOHtGFAAAB\n" + + "bYL/SJoAAAQDAEgwRgIhAI8OgzP/kzF1bOJRHU2S/ewij/6HpGPy7Mbm7Hyuv3IU\n" + + "AiEAxDmX2FmORlgeerQmQ+ar3D9/TwA9RQckVDu5IrgweREwCgYIKoZIzj0EAwID\n" + + "SAAwRQIhAPwQWGWd3oR7YJ7ngCDQ9TAbdPgND51SiR34WfEgaTQtAiAxD4umKm02\n" + + "59GEMj5NpyF2ZQEq5mEGcjJNojrn+PC4zg==\n" + + "-----END CERTIFICATE-----"; + // Owner: CN=usertrustecccertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, O=Sectigo Limited, // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford, // ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization, @@ -569,7 +683,7 @@ class ComodoUserTrustECC { // ST=New Jersey, C=US // Serial number: ab1455f9833ae7783f95de8744181f6a // Valid from: Wed Nov 28 16:00:00 PST 2018 until: Fri Feb 26 15:59:59 PST 2021 - private static final String VALID = "-----BEGIN CERTIFICATE-----\n" + + private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" + "MIIGhjCCBiygAwIBAgIRAKsUVfmDOud4P5Xeh0QYH2owCgYIKoZIzj0EAwIwgZUx\n" + "CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5MRQwEgYDVQQHEwtKZXJz\n" + "ZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMTswOQYDVQQD\n" + @@ -607,60 +721,14 @@ class ComodoUserTrustECC { "11EPtBSCEhUCIBcyI0yl5dRff6+4x8IeCrLiAOYsfzM7Y/a5uRKFnbYz\n" + "-----END CERTIFICATE-----"; - // Owner: CN=usertrustecccertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, O=COMODO CA Limited, - // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford, - // ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization, - // OID.1.3.6.1.4.1.311.60.2.1.3=GB, SERIALNUMBER=04058690 - // Issuer: CN=USERTrust ECC Extended Validation Secure Server CA, O=The USERTRUST Network, L=Jersey City, - // ST=New Jersey, C=US - // Serial number: 9bd0c93cac9ca2edc1a7dd923316b3c6 - // Valid from: Mon Jul 03 17:00:00 PDT 2017 until: Thu Oct 03 16:59:59 PDT 2019 - private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" + - "MIIGhzCCBi2gAwIBAgIRAJvQyTysnKLtwafdkjMWs8YwCgYIKoZIzj0EAwIwgZUx\n" + - "CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5MRQwEgYDVQQHEwtKZXJz\n" + - "ZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMTswOQYDVQQD\n" + - "EzJVU0VSVHJ1c3QgRUNDIEV4dGVuZGVkIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZl\n" + - "ciBDQTAeFw0xNzA3MDQwMDAwMDBaFw0xOTEwMDMyMzU5NTlaMIIBYDERMA8GA1UE\n" + - "BRMIMDQwNTg2OTAxEzARBgsrBgEEAYI3PAIBAxMCR0IxHTAbBgNVBA8TFFByaXZh\n" + - "dGUgT3JnYW5pemF0aW9uMQswCQYDVQQGEwJHQjEPMA0GA1UEERMGTTUgM0VRMRsw\n" + - "GQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxFjAU\n" + - "BgNVBAkTDVRyYWZmb3JkIFJvYWQxFjAUBgNVBAkTDUV4Y2hhbmdlIFF1YXkxJTAj\n" + - "BgNVBAkTHDNyZCBGbG9vciwgMjYgT2ZmaWNlIFZpbGxhZ2UxGjAYBgNVBAoTEUNP\n" + - "TU9ETyBDQSBMaW1pdGVkMRowGAYDVQQLExFDT01PRE8gRVYgU0dDIFNTTDE7MDkG\n" + - "A1UEAxMydXNlcnRydXN0ZWNjY2VydGlmaWNhdGlvbmF1dGhvcml0eS1ldi5jb21v\n" + - "ZG9jYS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQtMl8R33ZaWD6H8BW0\n" + - "+wybBf0+6+L5YYK/eyAVGm6vwjLaQZWlcdFBMKfaP1qTLi0VAabs4baSUkD8wR56\n" + - "8pVpo4IDjjCCA4owHwYDVR0jBBgwFoAUKpxa+U6hMNpASyvpS/H1nNwC+S4wHQYD\n" + - "VR0OBBYEFLOtYfOaIfDHZGubtKNELRR6A2srMA4GA1UdDwEB/wQEAwIFgDAMBgNV\n" + - "HRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBQBgNVHSAE\n" + - "STBHMDwGDCsGAQQBsjEBAgEFATAsMCoGCCsGAQUFBwIBFh5odHRwczovL2Nwcy50\n" + - "cnVzdC1wcm92aWRlci5jb20wBwYFZ4EMAQEwXwYDVR0fBFgwVjBUoFKgUIZOaHR0\n" + - "cDovL2NybC50cnVzdC1wcm92aWRlci5jb20vVVNFUlRydXN0RUNDRXh0ZW5kZWRW\n" + - "YWxpZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3JsMIGYBggrBgEFBQcBAQSBizCBiDBa\n" + - "BggrBgEFBQcwAoZOaHR0cDovL2NydC50cnVzdC1wcm92aWRlci5jb20vVVNFUlRy\n" + - "dXN0RUNDRXh0ZW5kZWRWYWxpZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3J0MCoGCCsG\n" + - "AQUFBzABhh5odHRwOi8vb2NzcC50cnVzdC1wcm92aWRlci5jb20wPQYDVR0RBDYw\n" + - "NIIydXNlcnRydXN0ZWNjY2VydGlmaWNhdGlvbmF1dGhvcml0eS1ldi5jb21vZG9j\n" + - "YS5jb20wggF8BgorBgEEAdZ5AgQCBIIBbASCAWgBZgB1AKS5CZC0GFgUh7sTosxn\n" + - "cAo8NZgE+RvfuON3zQ7IDdwQAAABXQ0/jQ0AAAQDAEYwRAIgPbaNWgoi6OfyNwL2\n" + - "+jiySsoLrkx+0d4NJE1WnZQcfzwCICW4yvsXaMxoOXpQp3EPgrYk5Ajfvy/dY3Ui\n" + - "0/dbQtHxAHYAVhQGmi/XwuzT9eG9RLI+x0Z2ubyZEVzA75SYVdaJ0N0AAAFdDT+K\n" + - "xwAABAMARzBFAiB3GQasrX+akoHX02ZvXCcvhWCqv6qQOhLCUqflPoRbuAIhALwe\n" + - "hrQo8S1Tm5vbMcxGiViq5ZcawxENWhxZ9hS0BZweAHUA7ku9t3XOYLrhQmkfq+Ge\n" + - "ZqMPfl+wctiDAMR7iXqo/csAAAFdDT+M4AAABAMARjBEAiAjvp8w/fdTVW1VGE0T\n" + - "I0YcCIXTYFDgzUMsEUiKHANAgwIgETQUcac7Hiis2fgQ+GdGF9yuh+xMo2Z8QXNu\n" + - "1Cknf+8wCgYIKoZIzj0EAwIDSAAwRQIgQ5UiUI7xodmmMYNs3CmqlZHw/04BQRAR\n" + - "4gRm7blZSIMCIQDHvIWTaPzSO6vwVzs6wSD6FqebLiFxoddC6aZG8Nm0wQ==\n" + - "-----END CERTIFICATE-----"; - public void runTest(ValidatePathWithParams pathValidator) throws Exception { // Validate valid - pathValidator.validate(new String[]{VALID, INT}, + pathValidator.validate(new String[]{VALID, INT_VALID}, ValidatePathWithParams.Status.GOOD, null, System.out); // Validate Revoked - pathValidator.validate(new String[]{REVOKED, INT}, + pathValidator.validate(new String[]{REVOKED, INT_REVOKED}, ValidatePathWithParams.Status.REVOKED, - "Thu Nov 29 10:06:00 PST 2018", System.out); + "Wed Oct 02 06:06:50 PDT 2019", System.out); } } From 4887cfb2a8e59c8349c556e4419afa28cd28ce9c Mon Sep 17 00:00:00 2001 From: vkempik Date: Tue, 24 Sep 2019 14:54:57 +0300 Subject: [PATCH 104/131] 8229872: (fs) Increase buffer size used with getmntent Summary: Dynamically allocate memory for getmntent Reviewed-by: alanb --- .../classes/sun/nio/fs/LinuxFileSystem.java | 20 +++++++- .../sun/nio/fs/LinuxNativeDispatcher.java | 14 +++++- .../native/libnio/fs/LinuxNativeDispatcher.c | 11 ++--- .../sun/nio/fs/UnixNativeDispatcher.java | 12 ++++- .../native/libnio/fs/UnixNativeDispatcher.c | 47 ++++++++++++++++++- 5 files changed, 92 insertions(+), 12 deletions(-) diff --git a/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystem.java b/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystem.java index c154ff56476..cfd83963b2b 100644 --- a/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystem.java +++ b/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -79,10 +79,26 @@ List getMountEntries(String fstab) { ArrayList entries = new ArrayList<>(); try { long fp = setmntent(Util.toBytes(fstab), Util.toBytes("r")); + int maxLineSize = 1024; + try { + for (;;) { + int lineSize = getlinelen(fp); + if (lineSize == -1) + break; + if (lineSize > maxLineSize) + maxLineSize = lineSize; + } + } catch (UnixException x) { + // nothing we need to do + } finally { + rewind(fp); + } + try { for (;;) { UnixMountEntry entry = new UnixMountEntry(); - int res = getmntent(fp, entry); + // count in NUL character at the end + int res = getmntent(fp, entry, maxLineSize + 1); if (res < 0) break; entries.add(entry); diff --git a/src/java.base/linux/classes/sun/nio/fs/LinuxNativeDispatcher.java b/src/java.base/linux/classes/sun/nio/fs/LinuxNativeDispatcher.java index 5dbb331631f..1fa359b3f06 100644 --- a/src/java.base/linux/classes/sun/nio/fs/LinuxNativeDispatcher.java +++ b/src/java.base/linux/classes/sun/nio/fs/LinuxNativeDispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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,7 +54,17 @@ private static native long setmntent0(long pathAddress, long typeAddress) /** * int getmntent(FILE *fp, struct mnttab *mp, int len); */ - static native int getmntent(long fp, UnixMountEntry entry) + + static int getmntent(long fp, UnixMountEntry entry, int buflen) throws UnixException { + NativeBuffer buffer = NativeBuffers.getNativeBuffer(buflen); + try { + return getmntent0(fp, entry, buffer.address(), buflen); + } finally { + buffer.release(); + } + } + + static native int getmntent0(long fp, UnixMountEntry entry, long buffer, int bufLen) throws UnixException; /** diff --git a/src/java.base/linux/native/libnio/fs/LinuxNativeDispatcher.c b/src/java.base/linux/native/libnio/fs/LinuxNativeDispatcher.c index c8500db5c87..48df9b7c197 100644 --- a/src/java.base/linux/native/libnio/fs/LinuxNativeDispatcher.c +++ b/src/java.base/linux/native/libnio/fs/LinuxNativeDispatcher.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -169,12 +169,11 @@ Java_sun_nio_fs_LinuxNativeDispatcher_setmntent0(JNIEnv* env, jclass this, jlong } JNIEXPORT jint JNICALL -Java_sun_nio_fs_LinuxNativeDispatcher_getmntent(JNIEnv* env, jclass this, - jlong value, jobject entry) +Java_sun_nio_fs_LinuxNativeDispatcher_getmntent0(JNIEnv* env, jclass this, + jlong value, jobject entry, jlong buffer, jint bufLen) { struct mntent ent; - char buf[1024]; - int buflen = sizeof(buf); + char * buf = (char*)jlong_to_ptr(buffer); struct mntent* m; FILE* fp = jlong_to_ptr(value); jsize len; @@ -184,7 +183,7 @@ Java_sun_nio_fs_LinuxNativeDispatcher_getmntent(JNIEnv* env, jclass this, char* fstype; char* options; - m = getmntent_r(fp, &ent, (char*)&buf, buflen); + m = getmntent_r(fp, &ent, buf, (int)bufLen); if (m == NULL) return -1; name = m->mnt_fsname; diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java b/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java index fe2d0f3f1a5..9f59063d357 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -121,6 +121,16 @@ private static native long fopen0(long pathAddress, long modeAddress) */ static native void fclose(long stream) throws UnixException; + /** + * void rewind(FILE* stream); + */ + static native void rewind(long stream) throws UnixException; + + /** + * ssize_t getline(char **lineptr, size_t *n, FILE *stream); + */ + static native int getlinelen(long stream) throws UnixException; + /** * link(const char* existing, const char* new) */ diff --git a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c index 472de82490b..aa6ff9b1061 100644 --- a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c +++ b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -390,6 +390,51 @@ Java_sun_nio_fs_UnixNativeDispatcher_fclose(JNIEnv* env, jclass this, jlong stre } } +JNIEXPORT void JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_rewind(JNIEnv* env, jclass this, jlong stream) +{ + FILE* fp = jlong_to_ptr(stream); + int saved_errno; + + errno = 0; + rewind(fp); + saved_errno = errno; + if (ferror(fp)) { + throwUnixException(env, saved_errno); + } +} + +/** + * This function returns line length without NUL terminator or -1 on EOF. + */ +JNIEXPORT jint JNICALL +Java_sun_nio_fs_UnixNativeDispatcher_getlinelen(JNIEnv* env, jclass this, jlong stream) +{ + FILE* fp = jlong_to_ptr(stream); + size_t lineSize = 0; + char * lineBuffer = NULL; + int saved_errno; + + ssize_t res = getline(&lineBuffer, &lineSize, fp); + saved_errno = errno; + + /* Should free lineBuffer no matter result, according to man page */ + if (lineBuffer != NULL) + free(lineBuffer); + + if (feof(fp)) + return -1; + + /* On successfull return res >= 0, otherwise res is -1 */ + if (res == -1) + throwUnixException(env, saved_errno); + + if (res > INT_MAX) + throwUnixException(env, EOVERFLOW); + + return (jint)res; +} + JNIEXPORT jint JNICALL Java_sun_nio_fs_UnixNativeDispatcher_open0(JNIEnv* env, jclass this, jlong pathAddress, jint oflags, jint mode) From f0dc55310a679623bfc104f05137420a7f1eff12 Mon Sep 17 00:00:00 2001 From: serb Date: Thu, 12 Sep 2019 22:20:35 -0700 Subject: [PATCH 105/131] 8225101: Crash at sun.awt.X11.XlibWrapper.XkbGetUpdatedMap when change keybord map Reviewed-by: prr, pbansal --- .../unix/classes/sun/awt/X11/XToolkit.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java b/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java index 2b8f26da5c9..65cb46ccfdf 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java @@ -2554,14 +2554,16 @@ private void processXkbChanges(XEvent ev) { //System.out.println("XkbNewKeyboard:"+(xke.get_new_kbd())); break; case XConstants.XkbMapNotify : - //TODO: provide a simple unit test. - XlibWrapper.XkbGetUpdatedMap(getDisplay(), - XConstants.XkbKeyTypesMask | - XConstants.XkbKeySymsMask | - XConstants.XkbModifierMapMask | - XConstants.XkbVirtualModsMask, - awt_XKBDescPtr); - //System.out.println("XkbMap:"+(xke.get_map())); + if (awt_XKBDescPtr != 0) { + //TODO: provide a simple unit test. + XlibWrapper.XkbGetUpdatedMap(getDisplay(), + XConstants.XkbKeyTypesMask | + XConstants.XkbKeySymsMask | + XConstants.XkbModifierMapMask | + XConstants.XkbVirtualModsMask, + awt_XKBDescPtr); + } + //System.out.println("XkbMap:"+(xke.get_map())); break; case XConstants.XkbStateNotify : // May use it later e.g. to obtain an effective group etc. From a7860696cfd8d68f85211d4c2153953b075930e7 Mon Sep 17 00:00:00 2001 From: serb Date: Fri, 29 Mar 2019 16:09:47 -0700 Subject: [PATCH 106/131] 8215105: java/awt/Robot/HiDPIScreenCapture/ScreenCaptureTest.java: Wrong Pixel Color Reviewed-by: prr --- .../macosx/native/libawt_lwawt/awt/CRobot.m | 2 +- .../CheckCommonColors/CheckCommonColors.java | 86 +++++++++++++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 test/jdk/java/awt/Robot/CheckCommonColors/CheckCommonColors.java diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m index c394854a5c6..b06b8de6905 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m @@ -301,7 +301,7 @@ static void PostMouseEvent(const CGPoint point, CGMouseButton button, // create a graphics context around the Java int array CGColorSpaceRef picColorSpace = CGColorSpaceCreateWithName( - kCGColorSpaceGenericRGB); + kCGColorSpaceSRGB); CGContextRef jPicContextRef = CGBitmapContextCreate( jPixelData, picWidth, picHeight, diff --git a/test/jdk/java/awt/Robot/CheckCommonColors/CheckCommonColors.java b/test/jdk/java/awt/Robot/CheckCommonColors/CheckCommonColors.java new file mode 100644 index 00000000000..ddf4f7e7fdb --- /dev/null +++ b/test/jdk/java/awt/Robot/CheckCommonColors/CheckCommonColors.java @@ -0,0 +1,86 @@ +/* + * 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. + */ + +import java.awt.Color; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.util.List; + +/** + * @test + * @key headful + * @bug 8215105 + * @summary tests that Robot can capture the common colors without artifacts + */ +public final class CheckCommonColors { + + private static final Frame frame = new Frame(); + private static Robot robot; + + public static void main(final String[] args) throws Exception { + robot = new Robot(); + try { + test(); + } finally { + frame.dispose(); + } + } + + private static void test() { + frame.setSize(400, 400); + frame.setLocationRelativeTo(null); + frame.setUndecorated(true); + for (final Color color : List.of(Color.WHITE, Color.LIGHT_GRAY, + Color.GRAY, Color.DARK_GRAY, + Color.BLACK, Color.RED, Color.PINK, + Color.ORANGE, Color.YELLOW, + Color.GREEN, Color.MAGENTA, Color.CYAN, + Color.BLUE)) { + frame.dispose(); + frame.setBackground(color); + frame.setVisible(true); + checkPixels(color); + } + } + + private static void checkPixels(final Color color) { + int attempt = 0; + while (true) { + Point p = frame.getLocationOnScreen(); + Color pixel = robot.getPixelColor(p.x + frame.getWidth() / 2, + p.y + frame.getHeight() / 2); + if (color.equals(pixel)) { + return; + } + if (attempt > 10) { + System.err.println("Expected: " + color); + System.err.println("Actual: " + pixel); + throw new RuntimeException("Too many attempts: " + attempt); + } + // skip Robot.waitForIdle to speedup the common case, but also take + // care about slow systems + robot.delay((int) Math.pow(2.2, attempt++)); + } + } +} From 20f7b9cfc5d81edd4210a12cebba2ccd7609fdc6 Mon Sep 17 00:00:00 2001 From: psadhukhan Date: Mon, 19 Aug 2019 12:13:47 +0530 Subject: [PATCH 107/131] 8226513: JEditorPane is shown with incorrect size Reviewed-by: prr, psadhukhan Contributed-by: semyon.sadetsky@oracle.com --- .../javax/swing/plaf/basic/BasicTextUI.java | 11 +- .../8226513/JEditorPaneLayoutTest.java | 138 ++++++++++++++++++ 2 files changed, 145 insertions(+), 4 deletions(-) create mode 100644 test/jdk/javax/swing/JEditorPane/8226513/JEditorPaneLayoutTest.java diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java index 3bd0585c94a..ec05b6aced5 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java @@ -702,6 +702,7 @@ protected void modelChanged() { Document doc = editor.getDocument(); Element elem = doc.getDefaultRootElement(); setView(f.create(elem)); + rootViewNeedsLayout = false; } /** @@ -947,11 +948,10 @@ public Dimension getPreferredSize(JComponent c) { if ((d.width > (i.left + i.right + caretMargin)) && (d.height > (i.top + i.bottom))) { rootView.setSize(d.width - i.left - i.right - caretMargin, d.height - i.top - i.bottom); - } - else if (!rootViewInitialized && (d.width <= 0 || d.height <= 0)) { + } if (!rootViewNeedsLayout) { // Probably haven't been layed out yet, force some sort of // initial sizing. - rootViewInitialized = true; + rootViewNeedsLayout = true; rootView.setSize(Integer.MAX_VALUE, Integer.MAX_VALUE); } d.width = (int) Math.min((long) rootView.getPreferredSpan(View.X_AXIS) + @@ -1403,7 +1403,7 @@ static class BasicCursor extends Cursor implements UIResource { private static final Position.Bias[] discardBias = new Position.Bias[1]; private DefaultCaret dropCaret; private int caretMargin; - private boolean rootViewInitialized; + private boolean rootViewNeedsLayout; /** * Root view that acts as a gateway between the component @@ -1966,6 +1966,7 @@ public final void insertUpdate(DocumentEvent e) { // normal insert update Rectangle alloc = (painted) ? getVisibleEditorRect() : null; rootView.insertUpdate(e, alloc, rootView.getViewFactory()); + rootViewNeedsLayout = false; } /** @@ -1981,6 +1982,7 @@ public final void insertUpdate(DocumentEvent e) { public final void removeUpdate(DocumentEvent e) { Rectangle alloc = (painted) ? getVisibleEditorRect() : null; rootView.removeUpdate(e, alloc, rootView.getViewFactory()); + rootViewNeedsLayout = false; } /** @@ -1996,6 +1998,7 @@ public final void removeUpdate(DocumentEvent e) { public final void changedUpdate(DocumentEvent e) { Rectangle alloc = (painted) ? getVisibleEditorRect() : null; rootView.changedUpdate(e, alloc, rootView.getViewFactory()); + rootViewNeedsLayout = false; } // --- LayoutManager2 methods -------------------------------- diff --git a/test/jdk/javax/swing/JEditorPane/8226513/JEditorPaneLayoutTest.java b/test/jdk/javax/swing/JEditorPane/8226513/JEditorPaneLayoutTest.java new file mode 100644 index 00000000000..6f2bae353f5 --- /dev/null +++ b/test/jdk/javax/swing/JEditorPane/8226513/JEditorPaneLayoutTest.java @@ -0,0 +1,138 @@ +/* + * 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 + * @key headful + * @bug 8226513 + * @summary JEditorPane is shown with incorrect size + * @run main/othervm -Dsun.java2d.uiScale=1.0 JEditorPaneLayoutTest + */ + +import javax.swing.JFrame; +import javax.swing.JEditorPane; +import javax.swing.SwingUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.html.HTMLEditorKit; +import java.awt.Dimension; +import java.awt.Robot; + +public class JEditorPaneLayoutTest { + + public static final String TEXT = + "some text some text some text
some text"; + static JFrame frame; + static JEditorPane editorPane; + static Dimension size1; + static Dimension size2; + static Dimension size3; + static Dimension size4; + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame(); + editorPane = new JEditorPane("text/html", TEXT); + size1 = editorPane.getPreferredSize(); + editorPane.setText(TEXT); + frame.add(editorPane); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + + robot.waitForIdle(); + robot.delay(300); + + SwingUtilities.invokeAndWait(() -> { + size2 = editorPane.getSize(); + frame.dispose(); + + frame = new JFrame(); + editorPane = new JEditorPane("text/html", TEXT); + editorPane.getPreferredSize(); + editorPane.setText(TEXT); + frame.add(editorPane); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + + robot.waitForIdle(); + robot.delay(300); + + if (!size1.equals(size2)) { + SwingUtilities.invokeLater(frame::dispose); + throw new RuntimeException("Wrong size " + size2 + + " expected " + size1); + } + + SwingUtilities.invokeAndWait(() -> { + editorPane.setText(TEXT); + frame.pack(); + size3 = editorPane.getSize(); + frame.dispose(); + + frame = new JFrame(); + editorPane = new JEditorPane("text/html", TEXT); + editorPane.getPreferredSize(); + editorPane.setSize(1, 1); + Document doc = new HTMLEditorKit().createDefaultDocument(); + try { + doc.insertString(0, TEXT, null); + } catch (BadLocationException e) { + e.printStackTrace(); + } + editorPane.setDocument(doc); + editorPane.setText(TEXT); + frame.add(editorPane); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + + robot.waitForIdle(); + robot.delay(300); + + if (!size1.equals(size3)) { + SwingUtilities.invokeLater(frame::dispose); + throw new RuntimeException("Wrong size " + size3 + + " expected " + size1); + } + + SwingUtilities.invokeAndWait(() -> { + size4 = editorPane.getSize(); + frame.dispose(); + }); + + robot.waitForIdle(); + robot.delay(300); + + if (!size1.equals(size4)) { + SwingUtilities.invokeLater(frame::dispose); + throw new RuntimeException("Wrong size " + size4 + + " expected " + size1); + } + } +} From f6c65bef2439e05c6dd4681dba0176328f3390dd Mon Sep 17 00:00:00 2001 From: serb Date: Wed, 26 Jun 2019 15:34:13 -0700 Subject: [PATCH 108/131] 8134672: [TEST_BUG] Some tests should check isDisplayChangeSupported Reviewed-by: prr --- .../awt/GraphicsDevice/IncorrectDisplayModeExitFullscreen.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/jdk/java/awt/GraphicsDevice/IncorrectDisplayModeExitFullscreen.java b/test/jdk/java/awt/GraphicsDevice/IncorrectDisplayModeExitFullscreen.java index ce21bfb7a68..c2992c133d6 100644 --- a/test/jdk/java/awt/GraphicsDevice/IncorrectDisplayModeExitFullscreen.java +++ b/test/jdk/java/awt/GraphicsDevice/IncorrectDisplayModeExitFullscreen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, 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 @@ -46,6 +46,7 @@ public static void main(final String[] args) { GraphicsEnvironment.getLocalGraphicsEnvironment() .getScreenDevices(); if (devices.length < 2 || devices[0].getDisplayModes().length < 2 + || !devices[0].isDisplayChangeSupported() || !devices[0].isFullScreenSupported() || !devices[1].isFullScreenSupported()) { System.err.println("Testcase is not applicable"); From 2bce1432372efdb9cfc19a1685e06215c7c908f5 Mon Sep 17 00:00:00 2001 From: serb Date: Tue, 27 Aug 2019 04:43:01 -0700 Subject: [PATCH 109/131] 8146238: [macosx] Java2D Queue Flusher crash on OSX after switching between user accounts Reviewed-by: prr, avu --- .../sun/java2d/opengl/CGLSurfaceData.java | 11 ++-- .../java2d/opengl/CGLSurfaceData.m | 41 ++++++-------- .../sun/java2d/opengl/OGLSurfaceData.java | 9 ++-- .../common/java2d/opengl/OGLSurfaceData.c | 12 +++-- .../common/java2d/opengl/OGLSurfaceData.h | 6 ++- .../sun/java2d/opengl/GLXSurfaceData.java | 5 +- .../common/java2d/opengl/GLXSurfaceData.c | 54 ++++++------------- .../sun/java2d/opengl/WGLSurfaceData.java | 6 +-- .../libawt/java2d/opengl/WGLSurfaceData.c | 45 ++++++---------- 9 files changed, 75 insertions(+), 114 deletions(-) diff --git a/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLSurfaceData.java b/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLSurfaceData.java index 2eb9048e71e..bebc9b5fc2c 100644 --- a/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLSurfaceData.java +++ b/src/java.desktop/macosx/classes/sun/java2d/opengl/CGLSurfaceData.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -48,8 +48,9 @@ public abstract class CGLSurfaceData extends OGLSurfaceData { native void validate(int xoff, int yoff, int width, int height, boolean isOpaque); - private native void initOps(long pConfigInfo, long pPeerData, long layerPtr, - int xoff, int yoff, boolean isOpaque); + private native void initOps(OGLGraphicsConfig gc, long pConfigInfo, + long pPeerData, long layerPtr, int xoff, + int yoff, boolean isOpaque); protected CGLSurfaceData(CGLGraphicsConfig gc, ColorModel cm, int type, int width, int height) { @@ -74,7 +75,7 @@ protected CGLSurfaceData(CPlatformView pView, CGLGraphicsConfig gc, pPeerData = pView.getAWTView(); isOpaque = pView.isOpaque(); } - initOps(pConfigInfo, pPeerData, 0, 0, 0, isOpaque); + initOps(gc, pConfigInfo, pPeerData, 0, 0, 0, isOpaque); } protected CGLSurfaceData(CGLLayer layer, CGLGraphicsConfig gc, @@ -90,7 +91,7 @@ protected CGLSurfaceData(CGLLayer layer, CGLGraphicsConfig gc, layerPtr = layer.getPointer(); isOpaque = layer.isOpaque(); } - initOps(pConfigInfo, 0, layerPtr, 0, 0, isOpaque); + initOps(gc, pConfigInfo, 0, layerPtr, 0, 0, isOpaque); } @Override //SurfaceData diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLSurfaceData.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLSurfaceData.m index 328721843a3..981009176e6 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLSurfaceData.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLSurfaceData.m @@ -130,31 +130,6 @@ extern CGLError CGLTexImageIOSurface2D( JNF_COCOA_EXIT(env); } -/** - * Returns a pointer (as a jlong) to the native CGLGraphicsConfigInfo - * associated with the given OGLSDOps. This method can be called from - * shared code to retrieve the native GraphicsConfig data in a platform- - * independent manner. - */ -jlong -OGLSD_GetNativeConfigInfo(OGLSDOps *oglsdo) -{ - J2dTraceLn(J2D_TRACE_INFO, "OGLSD_GetNativeConfigInfo"); - - if (oglsdo == NULL) { - J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_GetNativeConfigInfo: ops are null"); - return 0L; - } - - CGLSDOps *cglsdo = (CGLSDOps *)oglsdo->privOps; - if (cglsdo == NULL) { - J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_GetNativeConfigInfo: cgl ops are null"); - return 0L; - } - - return ptr_to_jlong(cglsdo->configInfo); -} - /** * Makes the given GraphicsConfig's context current to its associated * "scratch" surface. If there is a problem making the context current, @@ -376,7 +351,7 @@ extern CGLError CGLTexImageIOSurface2D( JNIEXPORT void JNICALL Java_sun_java2d_opengl_CGLSurfaceData_initOps - (JNIEnv *env, jobject cglsd, + (JNIEnv *env, jobject cglsd, jobject gc, jlong pConfigInfo, jlong pPeerData, jlong layerPtr, jint xoff, jint yoff, jboolean isOpaque) { @@ -384,8 +359,22 @@ extern CGLError CGLTexImageIOSurface2D( J2dTraceLn1(J2D_TRACE_INFO, " pPeerData=%p", jlong_to_ptr(pPeerData)); J2dTraceLn2(J2D_TRACE_INFO, " xoff=%d, yoff=%d", (int)xoff, (int)yoff); + gc = (*env)->NewGlobalRef(env, gc); + if (gc == NULL) { + JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed."); + return; + } + OGLSDOps *oglsdo = (OGLSDOps *) SurfaceData_InitOps(env, cglsd, sizeof(OGLSDOps)); + if (oglsdo == NULL) { + (*env)->DeleteGlobalRef(env, gc); + JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed."); + return; + } + // later the graphicsConfig will be used for deallocation of oglsdo + oglsdo->graphicsConfig = gc; + CGLSDOps *cglsdo = (CGLSDOps *)malloc(sizeof(CGLSDOps)); if (cglsdo == NULL) { JNU_ThrowOutOfMemoryError(env, "creating native cgl ops"); diff --git a/src/java.desktop/share/classes/sun/java2d/opengl/OGLSurfaceData.java b/src/java.desktop/share/classes/sun/java2d/opengl/OGLSurfaceData.java index 5e6f802da14..02302ceb8f1 100644 --- a/src/java.desktop/share/classes/sun/java2d/opengl/OGLSurfaceData.java +++ b/src/java.desktop/share/classes/sun/java2d/opengl/OGLSurfaceData.java @@ -27,6 +27,7 @@ import java.awt.AlphaComposite; import java.awt.Composite; +import java.awt.GraphicsConfiguration; import java.awt.GraphicsEnvironment; import java.awt.Rectangle; import java.awt.Transparency; @@ -578,16 +579,16 @@ public void flush() { * (referenced by the pData parameter). This method is invoked from * the native Dispose() method from the Disposer thread when the * Java-level OGLSurfaceData object is about to go away. Note that we - * also pass a reference to the native GLX/WGLGraphicsConfigInfo - * (pConfigInfo) for the purposes of making a context current. + * also pass a reference to the OGLGraphicsConfig + * for the purposes of making a context current. */ - static void dispose(long pData, long pConfigInfo) { + static void dispose(long pData, OGLGraphicsConfig gc) { OGLRenderQueue rq = OGLRenderQueue.getInstance(); rq.lock(); try { // make sure we have a current context before // disposing the native resources (e.g. texture object) - OGLContext.setScratchSurface(pConfigInfo); + OGLContext.setScratchSurface(gc); RenderBuffer buf = rq.getBuffer(); rq.ensureCapacityAndAlignment(12, 4); diff --git a/src/java.desktop/share/native/common/java2d/opengl/OGLSurfaceData.c b/src/java.desktop/share/native/common/java2d/opengl/OGLSurfaceData.c index d12ab19d87d..59773ec666d 100644 --- a/src/java.desktop/share/native/common/java2d/opengl/OGLSurfaceData.c +++ b/src/java.desktop/share/native/common/java2d/opengl/OGLSurfaceData.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, 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 @@ -37,7 +37,6 @@ * The following methods are implemented in the windowing system (i.e. GLX * and WGL) source files. */ -extern jlong OGLSD_GetNativeConfigInfo(OGLSDOps *oglsdo); extern jboolean OGLSD_InitOGLWindow(JNIEnv *env, OGLSDOps *oglsdo); extern void OGLSD_DestroyOGLSurface(JNIEnv *env, OGLSDOps *oglsdo); @@ -593,11 +592,14 @@ void OGLSD_Dispose(JNIEnv *env, SurfaceDataOps *ops) { OGLSDOps *oglsdo = (OGLSDOps *)ops; - jlong pConfigInfo = OGLSD_GetNativeConfigInfo(oglsdo); + jobject graphicsConfig = oglsdo->graphicsConfig; JNU_CallStaticMethodByName(env, NULL, "sun/java2d/opengl/OGLSurfaceData", - "dispose", "(JJ)V", - ptr_to_jlong(ops), pConfigInfo); + "dispose", + "(JLsun/java2d/opengl/OGLGraphicsConfig;)V", + ptr_to_jlong(ops), graphicsConfig); + (*env)->DeleteGlobalRef(env, graphicsConfig); + oglsdo->graphicsConfig = NULL; } /** diff --git a/src/java.desktop/share/native/common/java2d/opengl/OGLSurfaceData.h b/src/java.desktop/share/native/common/java2d/opengl/OGLSurfaceData.h index e5ce1604fbe..353a2a2b649 100644 --- a/src/java.desktop/share/native/common/java2d/opengl/OGLSurfaceData.h +++ b/src/java.desktop/share/native/common/java2d/opengl/OGLSurfaceData.h @@ -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 @@ -85,6 +85,9 @@ typedef struct { * Pointer to native-specific (GLX, WGL, etc.) SurfaceData info, such as the * native Drawable handle and GraphicsConfig data. * + * jobject graphicsConfig;; + * Strong reference to the OGLGraphicsConfig used by this OGLSurfaceData. + * * jint drawableType; * The surface type; can be any one of the surface type constants defined * below (OGLSD_WINDOW, OGLSD_TEXTURE, etc). @@ -162,6 +165,7 @@ typedef struct { struct _OGLSDOps { SurfaceDataOps sdOps; void *privOps; + jobject graphicsConfig; jint drawableType; GLenum activeBuffer; jboolean isOpaque; diff --git a/src/java.desktop/unix/classes/sun/java2d/opengl/GLXSurfaceData.java b/src/java.desktop/unix/classes/sun/java2d/opengl/GLXSurfaceData.java index bfe9a26426e..790a0c38f0c 100644 --- a/src/java.desktop/unix/classes/sun/java2d/opengl/GLXSurfaceData.java +++ b/src/java.desktop/unix/classes/sun/java2d/opengl/GLXSurfaceData.java @@ -40,7 +40,8 @@ public abstract class GLXSurfaceData extends OGLSurfaceData { protected X11ComponentPeer peer; private GLXGraphicsConfig graphicsConfig; - private native void initOps(X11ComponentPeer peer, long aData); + private native void initOps(OGLGraphicsConfig gc, X11ComponentPeer peer, + long aData); protected GLXSurfaceData(X11ComponentPeer peer, GLXGraphicsConfig gc, ColorModel cm, int type) @@ -48,7 +49,7 @@ protected GLXSurfaceData(X11ComponentPeer peer, GLXGraphicsConfig gc, super(gc, cm, type); this.peer = peer; this.graphicsConfig = gc; - initOps(peer, graphicsConfig.getAData()); + initOps(gc, peer, graphicsConfig.getAData()); } public GraphicsConfiguration getDeviceConfiguration() { diff --git a/src/java.desktop/unix/native/common/java2d/opengl/GLXSurfaceData.c b/src/java.desktop/unix/native/common/java2d/opengl/GLXSurfaceData.c index 9ea366e46fd..c48b38fa1f3 100644 --- a/src/java.desktop/unix/native/common/java2d/opengl/GLXSurfaceData.c +++ b/src/java.desktop/unix/native/common/java2d/opengl/GLXSurfaceData.c @@ -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 @@ -54,23 +54,32 @@ jboolean surfaceCreationFailed = JNI_FALSE; JNIEXPORT void JNICALL Java_sun_java2d_opengl_GLXSurfaceData_initOps(JNIEnv *env, jobject glxsd, + jobject gc, jobject peer, jlong aData) { #ifndef HEADLESS - GLXSDOps *glxsdo = (GLXSDOps *)malloc(sizeof(GLXSDOps)); - - if (glxsdo == NULL) { - JNU_ThrowOutOfMemoryError(env, "creating native GLX ops"); + gc = (*env)->NewGlobalRef(env, gc); + if (gc == NULL) { + JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed."); return; } OGLSDOps *oglsdo = (OGLSDOps *)SurfaceData_InitOps(env, glxsd, sizeof(OGLSDOps)); if (oglsdo == NULL) { - free(glxsdo); + (*env)->DeleteGlobalRef(env, gc); JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed."); return; } + // later the graphicsConfig will be used for deallocation of oglsdo + oglsdo->graphicsConfig = gc; + + GLXSDOps *glxsdo = (GLXSDOps *)malloc(sizeof(GLXSDOps)); + + if (glxsdo == NULL) { + JNU_ThrowOutOfMemoryError(env, "creating native GLX ops"); + return; + } J2dTraceLn(J2D_TRACE_INFO, "GLXSurfaceData_initOps"); @@ -152,39 +161,6 @@ GLXSD_MakeCurrentToScratch(JNIEnv *env, OGLContext *oglc) return JNI_TRUE; } -/** - * Returns a pointer (as a jlong) to the native GLXGraphicsConfigInfo - * associated with the given OGLSDOps. This method can be called from - * shared code to retrieve the native GraphicsConfig data in a platform- - * independent manner. - */ -jlong -OGLSD_GetNativeConfigInfo(OGLSDOps *oglsdo) -{ - GLXSDOps *glxsdo; - - if (oglsdo == NULL) { - J2dRlsTraceLn(J2D_TRACE_ERROR, - "OGLSD_GetNativeConfigInfo: ops are null"); - return 0L; - } - - glxsdo = (GLXSDOps *)oglsdo->privOps; - if (glxsdo == NULL) { - J2dRlsTraceLn(J2D_TRACE_ERROR, - "OGLSD_GetNativeConfigInfo: glx ops are null"); - return 0L; - } - - if (glxsdo->configData == NULL) { - J2dRlsTraceLn(J2D_TRACE_ERROR, - "OGLSD_GetNativeConfigInfo: config data is null"); - return 0L; - } - - return ptr_to_jlong(glxsdo->configData->glxInfo); -} - /** * Makes the given GraphicsConfig's context current to its associated * "scratch" surface. If there is a problem making the context current, diff --git a/src/java.desktop/windows/classes/sun/java2d/opengl/WGLSurfaceData.java b/src/java.desktop/windows/classes/sun/java2d/opengl/WGLSurfaceData.java index 79eff60b2f8..fa4cb6a3cc2 100644 --- a/src/java.desktop/windows/classes/sun/java2d/opengl/WGLSurfaceData.java +++ b/src/java.desktop/windows/classes/sun/java2d/opengl/WGLSurfaceData.java @@ -46,8 +46,8 @@ public abstract class WGLSurfaceData extends OGLSurfaceData { protected double scaleX = 1; protected double scaleY = 1; - private native void initOps(long pConfigInfo, WComponentPeer peer, - long hwnd); + private native void initOps(OGLGraphicsConfig gc, long pConfigInfo, + WComponentPeer peer, long hwnd); protected WGLSurfaceData(WComponentPeer peer, WGLGraphicsConfig gc, ColorModel cm, int type) @@ -62,7 +62,7 @@ protected WGLSurfaceData(WComponentPeer peer, WGLGraphicsConfig gc, long pConfigInfo = gc.getNativeConfigInfo(); long hwnd = peer != null ? peer.getHWnd() : 0L; - initOps(pConfigInfo, peer, hwnd); + initOps(gc, pConfigInfo, peer, hwnd); } @Override diff --git a/src/java.desktop/windows/native/libawt/java2d/opengl/WGLSurfaceData.c b/src/java.desktop/windows/native/libawt/java2d/opengl/WGLSurfaceData.c index 3496252553b..76bbb89c526 100644 --- a/src/java.desktop/windows/native/libawt/java2d/opengl/WGLSurfaceData.c +++ b/src/java.desktop/windows/native/libawt/java2d/opengl/WGLSurfaceData.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2015, 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 @@ -58,11 +58,25 @@ extern void JNIEXPORT void JNICALL Java_sun_java2d_opengl_WGLSurfaceData_initOps(JNIEnv *env, jobject wglsd, - jlong pConfigInfo, + jobject gc, jlong pConfigInfo, jobject peer, jlong hwnd) { + gc = (*env)->NewGlobalRef(env, gc); + if (gc == NULL) { + JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed."); + return; + } + OGLSDOps *oglsdo = (OGLSDOps *)SurfaceData_InitOps(env, wglsd, sizeof(OGLSDOps)); + if (oglsdo == NULL) { + (*env)->DeleteGlobalRef(env, gc); + JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed."); + return; + } + // later the graphicsConfig will be used for deallocation of oglsdo + oglsdo->graphicsConfig = gc; + WGLSDOps *wglsdo = (WGLSDOps *)malloc(sizeof(WGLSDOps)); J2dTraceLn(J2D_TRACE_INFO, "WGLSurfaceData_initOps"); @@ -144,33 +158,6 @@ WGLSD_MakeCurrentToScratch(JNIEnv *env, OGLContext *oglc) return JNI_TRUE; } -/** - * Returns a pointer (as a jlong) to the native WGLGraphicsConfigInfo - * associated with the given OGLSDOps. This method can be called from - * shared code to retrieve the native GraphicsConfig data in a platform- - * independent manner. - */ -jlong -OGLSD_GetNativeConfigInfo(OGLSDOps *oglsdo) -{ - WGLSDOps *wglsdo; - - if (oglsdo == NULL) { - J2dRlsTraceLn(J2D_TRACE_ERROR, - "OGLSD_GetNativeConfigInfo: ops are null"); - return 0L; - } - - wglsdo = (WGLSDOps *)oglsdo->privOps; - if (wglsdo == NULL) { - J2dRlsTraceLn(J2D_TRACE_ERROR, - "OGLSD_GetNativeConfigInfo: wgl ops are null"); - return 0L; - } - - return ptr_to_jlong(wglsdo->configInfo); -} - /** * Makes the given GraphicsConfig's context current to its associated * "scratch" surface. If there is a problem making the context current, From 0cfd454c9facfae6b83d2c91f747258a24a91841 Mon Sep 17 00:00:00 2001 From: cito Date: Mon, 7 Oct 2019 16:44:12 +0200 Subject: [PATCH 110/131] 8225694: Destination option missing in FlightRecorderMXBeanImpl Reviewed-by: egahlin --- .../jdk/jfr/internal/PlatformRecording.java | 8 ++++++- .../management/ManagementSupport.java | 10 +++++++++ .../jfr/FlightRecorderMXBeanImpl.java | 21 ++++++++++++++++++- .../jdk/management/jfr/MBeanUtils.java | 13 ++++++++++++ .../jdk/jdk/jfr/jmx/TestRecordingOptions.java | 5 ++++- 5 files changed, 54 insertions(+), 3 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java index 5a3a67bbeeb..96a259b10fa 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java @@ -365,11 +365,17 @@ public void setMaxSize(long maxSize) { } public void setDestination(WriteableUserPath userSuppliedPath) throws IOException { + synchronized (recorder) { + checkSetDestination(userSuppliedPath); + this.destination = userSuppliedPath; + } + } + + public void checkSetDestination(WriteableUserPath userSuppliedPath) throws IOException { synchronized (recorder) { if (Utils.isState(getState(), RecordingState.STOPPED, RecordingState.CLOSED)) { throw new IllegalStateException("Destination can't be set on a recording that has been stopped/closed"); } - this.destination = userSuppliedPath; } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ManagementSupport.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ManagementSupport.java index af660b4c9d9..efe4accdcd1 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ManagementSupport.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ManagementSupport.java @@ -25,6 +25,8 @@ package jdk.jfr.internal.management; +import java.io.IOException; +import java.nio.file.Paths; import java.time.Duration; import java.util.ArrayList; import java.util.Collections; @@ -98,4 +100,12 @@ public static String getDestinationOriginalText(Recording recording) { WriteableUserPath wup = pr.getDestination(); return wup == null ? null : wup.getOriginalText(); } + + public static void checkSetDestination(Recording recording, String destination) throws IOException{ + PlatformRecording pr = PrivateAccess.getInstance().getPlatformRecording(recording); + if(destination != null){ + WriteableUserPath wup = new WriteableUserPath(Paths.get(destination)); + pr.checkSetDestination(wup); + } + } } diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBeanImpl.java b/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBeanImpl.java index 4a9206b7772..115ed8cd87f 100644 --- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBeanImpl.java +++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBeanImpl.java @@ -28,6 +28,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.StringReader; +import java.nio.file.Path; import java.nio.file.Paths; import java.security.AccessControlContext; import java.security.AccessController; @@ -105,7 +106,8 @@ public Void run() { private static final String OPTION_DISK = "disk"; private static final String OPTION_DUMP_ON_EXIT = "dumpOnExit"; private static final String OPTION_DURATION = "duration"; - private static final List OPTIONS = Arrays.asList(new String[] { OPTION_DUMP_ON_EXIT, OPTION_DURATION, OPTION_NAME, OPTION_MAX_AGE, OPTION_MAX_SIZE, OPTION_DISK, }); + private static final String OPTION_DESTINATION = "destination"; + private static final List OPTIONS = Arrays.asList(new String[] { OPTION_DUMP_ON_EXIT, OPTION_DURATION, OPTION_NAME, OPTION_MAX_AGE, OPTION_MAX_SIZE, OPTION_DISK, OPTION_DESTINATION, }); private final StreamManager streamHandler = new StreamManager(); private final Map changes = new ConcurrentHashMap<>(); private final AtomicLong sequenceNumber = new AtomicLong(); @@ -283,6 +285,7 @@ public void setRecordingOptions(long recording, Map options) thr validateOption(ops, OPTION_MAX_AGE, MBeanUtils::duration); validateOption(ops, OPTION_MAX_SIZE, MBeanUtils::size); validateOption(ops, OPTION_DURATION, MBeanUtils::duration); + validateOption(ops, OPTION_DESTINATION, x -> MBeanUtils.destination(r, x)); // All OK, now set them.atomically setOption(ops, OPTION_DUMP_ON_EXIT, "false", MBeanUtils::booleanValue, x -> r.setDumpOnExit(x)); @@ -291,6 +294,7 @@ public void setRecordingOptions(long recording, Map options) thr setOption(ops, OPTION_MAX_AGE, null, MBeanUtils::duration, x -> r.setMaxAge(x)); setOption(ops, OPTION_MAX_SIZE, "0", MBeanUtils::size, x -> r.setMaxSize(x)); setOption(ops, OPTION_DURATION, null, MBeanUtils::duration, x -> r.setDuration(x)); + setOption(ops, OPTION_DESTINATION, null, x -> MBeanUtils.destination(r, x), x -> setOptionDestination(r, x)); } @Override @@ -305,6 +309,7 @@ public Map getRecordingOptions(long recording) throws IllegalArg Long maxSize = r.getMaxSize(); options.put(OPTION_MAX_SIZE, String.valueOf(maxSize == null ? "0" : maxSize.toString())); options.put(OPTION_DURATION, ManagementSupport.formatTimespan(r.getDuration(), " ")); + options.put(OPTION_DESTINATION, ManagementSupport.getDestinationOriginalText(r)); return options; } @@ -349,6 +354,20 @@ private static void setOption(Map options, String name, S } } + private static void setOptionDestination(Recording recording, String destination){ + try { + Path pathDestination = null; + if(destination != null){ + pathDestination = Paths.get(destination); + } + recording.setDestination(pathDestination); + } catch (IOException e) { + IllegalArgumentException iae = new IllegalArgumentException("Not a valid destination " + destination); + iae.addSuppressed(e); + throw iae; + } + } + private static void validateOption(Map options, String name, Function validator) { try { String v = options.get(name); diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/MBeanUtils.java b/src/jdk.management.jfr/share/classes/jdk/management/jfr/MBeanUtils.java index 8a69641e2a3..9cb6424230e 100644 --- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/MBeanUtils.java +++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/MBeanUtils.java @@ -24,6 +24,7 @@ */ package jdk.management.jfr; +import java.io.IOException; import java.lang.management.ManagementPermission; import java.security.Permission; import java.time.DateTimeException; @@ -37,6 +38,7 @@ import javax.management.MalformedObjectNameException; import javax.management.ObjectName; +import jdk.jfr.Recording; import jdk.jfr.internal.management.ManagementSupport; final class MBeanUtils { @@ -126,5 +128,16 @@ public static int parseBlockSize(String string, int defaultSize) { } return size; } + + public static String destination(Recording recording, String destination) throws IllegalArgumentException{ + try { + ManagementSupport.checkSetDestination(recording, destination); + return destination; + }catch(IOException e){ + IllegalArgumentException iae = new IllegalArgumentException("Not a valid destination " + destination); + iae.addSuppressed(e); + throw iae; + } + } } diff --git a/test/jdk/jdk/jfr/jmx/TestRecordingOptions.java b/test/jdk/jdk/jfr/jmx/TestRecordingOptions.java index 6ba4a51fdf0..7192eec3411 100644 --- a/test/jdk/jdk/jfr/jmx/TestRecordingOptions.java +++ b/test/jdk/jdk/jfr/jmx/TestRecordingOptions.java @@ -25,6 +25,7 @@ package jdk.jfr.jmx; +import java.io.File; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; @@ -49,7 +50,7 @@ public static void main(String[] args) throws Exception { options.put("dumpOnExit", "false"); options.put("disk", "false"); options.put("duration", "1 h"); // don't want recording to stop - + options.put("destination", "." + File.separator + "dump.jfr"); FlightRecorderMXBean bean = JmxHelper.getFlighteRecorderMXBean(); long recId = bean.newRecording(); Map defaults = bean.getRecordingOptions(recId); @@ -72,6 +73,7 @@ public static void main(String[] args) throws Exception { Asserts.assertEquals(outOptions.get("dumpOnExit"), "false", "Wrong dumpOnExit"); Asserts.assertEquals(outOptions.get("disk"), "false", "Wrong disk"); Asserts.assertEquals(outOptions.get("duration"), "1 h", "Wrong duration"); + Asserts.assertEquals(outOptions.get("destination"), "." + File.separator + "dump.jfr", "Wrong destination"); // try empty map bean.setRecordingOptions(recId, new HashMap<>()); @@ -116,6 +118,7 @@ public static void main(String[] args) throws Exception { nullMap.put("dumpOnExit", null); nullMap.put("disk", null); nullMap.put("duration", null); + nullMap.put("destination", null); bean.setRecordingOptions(recId, nullMap); Asserts.assertEquals(bean.getRecordingOptions(recId), defaults); From 432988a234105b4f1554368d9370eaafe0d5066f Mon Sep 17 00:00:00 2001 From: rschmelter Date: Tue, 1 Oct 2019 14:09:44 +0200 Subject: [PATCH 111/131] 8191521: handle long relative path specified in -Xbootclasspath/a on windows 8231885: Fix/remove malformed assert in os_windows.cpp 8231930: Windows build fails after JDK-8191521 Reviewed-by: ccheung, clanger --- .../hotspot/gtest/runtime/test_os_windows.cpp | 608 ++++++++++++++++++ .../jtreg/runtime/LoadClass/LongBCP.java | 21 +- 2 files changed, 613 insertions(+), 16 deletions(-) create mode 100644 test/hotspot/gtest/runtime/test_os_windows.cpp diff --git a/test/hotspot/gtest/runtime/test_os_windows.cpp b/test/hotspot/gtest/runtime/test_os_windows.cpp new file mode 100644 index 00000000000..773f2304dfb --- /dev/null +++ b/test/hotspot/gtest/runtime/test_os_windows.cpp @@ -0,0 +1,608 @@ +/* + * 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 + * 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" + +#ifdef _WINDOWS + +#include "runtime/os.hpp" +#include "unittest.hpp" + +// The types of path modifications we randomly apply to a path. They should not change the file designated by the path. +enum ModsFilter { + Allow_None = 0, // No modifications + Allow_Sep_Mods = 1, // Replace '\\' by any sequence of '/' or '\\' or at least length 1. + Allow_Dot_Path = 2, // Add /. segments at random positions + Allow_Dot_Dot_Path = 4, // Add /../ segments at random positions. + Allow_All = Allow_Sep_Mods | Allow_Dot_Path | Allow_Dot_Dot_Path +}; + +// The mode in which to run. +enum Mode { + TEST, // Runs the test. This is the normal modus. + EXAMPLES, // Runs example which document the behaviour of the Windows system calls. + BENCH // Runs a small benchmark which tries to show the costs of using the *W variants/_wfullpath. +}; + +// Parameters of the test. +static ModsFilter mods_filter = Allow_All; +static int mods_per_path = 50; // The number of variants of a path we try. +static Mode mode = TEST; + + +// Utility methods +static void get_current_dir_w(wchar_t* path, size_t size) { + DWORD count = GetCurrentDirectoryW((DWORD) size, path); + EXPECT_GT((int) count, 0) << "Failed to get current directory: " << GetLastError(); + EXPECT_LT((size_t) count, size) << "Buffer too small for current directory: " << size; +} + +#define WITH_ABS_PATH(path) \ + wchar_t abs_path[JVM_MAXPATHLEN]; \ + wchar_t cwd[JVM_MAXPATHLEN]; \ + get_current_dir_w(cwd, JVM_MAXPATHLEN); \ + wsprintfW(abs_path, L"\\\\?\\%ls\\%ls", cwd, (path)) + +static bool file_exists_w(const wchar_t* path) { + WIN32_FILE_ATTRIBUTE_DATA file_data; + return ::GetFileAttributesExW(path, GetFileExInfoStandard, &file_data); +} + +static void create_rel_directory_w(const wchar_t* path) { + WITH_ABS_PATH(path); + EXPECT_FALSE(file_exists_w(abs_path)) << "Can't create directory: \"" << path << "\" already exists"; + BOOL result = CreateDirectoryW(abs_path, NULL); + EXPECT_TRUE(result) << "Failed to create directory \"" << path << "\" " << GetLastError(); +} + +static void delete_empty_rel_directory_w(const wchar_t* path) { + WITH_ABS_PATH(path); + EXPECT_TRUE(file_exists_w(abs_path)) << "Can't delete directory: \"" << path << "\" does not exists"; + BOOL result = RemoveDirectoryW(abs_path); + EXPECT_TRUE(result) << "Failed to delete directory \"" << path << "\": " << GetLastError(); +} + +static void create_rel_file_w(const wchar_t* path) { + WITH_ABS_PATH(path); + EXPECT_FALSE(file_exists_w(abs_path)) << "Can't create file: \"" << path << "\" already exists"; + HANDLE h = CreateFileW(abs_path, 0, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); + EXPECT_NE(h, INVALID_HANDLE_VALUE) << "Failed to create file \"" << path << "\": " << GetLastError(); + CloseHandle(h); +} + +static void delete_rel_file_w(const wchar_t* path) { + WITH_ABS_PATH(path); + EXPECT_TRUE(file_exists_w(abs_path)) << "Can't delete file: \"" << path << "\" does not exists"; + BOOL result = DeleteFileW(abs_path); + EXPECT_TRUE(result) << "Failed to delete file \"" << path << "\": " << GetLastError(); +} + +static bool convert_to_cstring(char* c_str, size_t size, wchar_t* w_str) { + size_t converted; + errno_t err = wcstombs_s(&converted, c_str, size, w_str, size - 1); + EXPECT_EQ(err, ERROR_SUCCESS) << "Could not convert \"" << w_str << "\" to c-string"; + + return err == ERROR_SUCCESS; +} + +static wchar_t* my_wcscpy_s(wchar_t* dest, size_t size, wchar_t* start, const wchar_t* to_copy) { + size_t already_used = dest - start; + size_t len = wcslen(to_copy); + + if (already_used + len < size) { + wcscpy_s(dest, size - already_used, to_copy); + } + + return dest + wcslen(to_copy); +} + +// The currently finite list of seperator sequences we might use instead of '\\'. +static const wchar_t* sep_replacements[] = { + L"\\", L"\\/", L"/", L"//", L"\\\\/\\", L"//\\/" +}; + +// Takes a path and modifies it in a way that it should still designate the same file. +static bool unnormalize_path(wchar_t* result, size_t size, bool is_dir, const wchar_t* path) { + wchar_t* dest = result; + const wchar_t* src = path; + const wchar_t* path_start; + + if (wcsncmp(src, L"\\\\?\\UNC\\", 8) == 0) { + path_start = src + 8; + } else if (wcsncmp(src, L"\\\\?\\", 4) == 0) { + if (src[5] == L':') { + path_start = src + 6; + } else { + path_start = wcschr(src + 4, L'\\'); + } + } else if (wcsncmp(src, L"\\\\", 2) == 0) { + path_start = wcschr(src + 2, L'?'); + + if (path_start == NULL) { + path_start = wcschr(src + 2, L'\\'); + } else { + path_start = wcschr(path_start, L'\\'); + } + } else { + path_start = wcschr(src + 1, L'\\'); + } + + bool allow_sep_change = (mods_filter & Allow_Sep_Mods) && (os::random() & 1) == 0; + bool allow_dot_change = (mods_filter & Allow_Dot_Path) && (os::random() & 1) == 0; + bool allow_dotdot_change = (mods_filter & Allow_Dot_Dot_Path) && (os::random() & 1) == 0; + + while ((*src != L'\0') && (result + size > dest)) { + wchar_t c = *src; + *dest = c; + ++src; + ++dest; + + if (c == L'\\') { + if (allow_sep_change && (os::random() & 3) == 3) { + int i = os::random() % (sizeof(sep_replacements) / sizeof(sep_replacements[0])); + + if (i >= 0) { + const wchar_t* replacement = sep_replacements[i]; + dest = my_wcscpy_s(dest - 1, size, result, replacement); + } + } else if (path_start != NULL) { + if (allow_dotdot_change && (src > path_start + 1) && ((os::random() & 7) == 7)) { + wchar_t const* last_sep = src - 2; + + while (last_sep[0] != L'\\') { + --last_sep; + } + + if (last_sep > path_start) { + dest = my_wcscpy_s(dest, size, result, L"../"); + src = last_sep + 1; + } + } else if (allow_dot_change && (src > path_start + 1) && ((os::random() & 7) == 7)) { + dest = my_wcscpy_s(dest, size, result, L"./"); + } + } + } + } + + while (is_dir && ((os::random() & 15) == 1)) { + dest = my_wcscpy_s(dest, size, result, L"/"); + } + + if (result + size > dest) { + *dest = L'\0'; + } + + // Use this modification only if not too close to the max size. + return result + size - 10 > dest; +} + +static void check_dir_impl(wchar_t* path, bool should_be_empty) { + char buf[JVM_MAXPATHLEN]; + + if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) { + struct stat st; + EXPECT_EQ(os::stat(buf, &st), 0) << "os::stat failed for \"" << path << "\""; + EXPECT_EQ(st.st_mode & S_IFMT, S_IFDIR) << "\"" << path << "\" is not a directory according to os::stat"; + errno = ERROR_SUCCESS; + bool is_empty = os::dir_is_empty(buf); + errno_t err = errno; + EXPECT_EQ(is_empty, should_be_empty) << "os::dir_is_empty assumed \"" << path << "\" is " + << (should_be_empty ? "not ": "") << "empty"; + EXPECT_EQ(err, ERROR_SUCCESS) << "os::dir_is_empty failed for \"" << path << "\"with errno " << err; + } +} + +static void check_file_impl(wchar_t* path) { + char buf[JVM_MAXPATHLEN]; + + if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) { + struct stat st; + EXPECT_EQ(os::stat(buf, &st), 0) << "os::stat failed for \"" << path << "\""; + EXPECT_EQ(st.st_mode & S_IFMT, S_IFREG) << "\"" << path << "\" is not a regular file according to os::stat"; + int fd = os::open(buf, O_RDONLY, 0); + EXPECT_NE(fd, -1) << "os::open failed for \"" << path << "\" with errno " << errno; + if (fd >= 0) { + ::close(fd); + } + } +} + +static void check_file_not_present_impl(wchar_t* path) { + char buf[JVM_MAXPATHLEN]; + + if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) { + struct stat st; + int stat_ret; + EXPECT_EQ(stat_ret = os::stat(buf, &st), -1) << "os::stat did not fail for \"" << path << "\""; + if (stat_ret != -1) { + // Only check open if stat not already failed. + int fd = os::open(buf, O_RDONLY, 0); + EXPECT_EQ(fd, -1) << "os::open did not fail for \"" << path << "\""; + if (fd >= 0) { + ::close(fd); + } + } + } +} + +static void check_dir(wchar_t* path, bool should_be_empty) { + check_dir_impl(path, should_be_empty); + + for (int i = 0; mods_filter != Allow_None && i < mods_per_path; ++i) { + wchar_t tmp[JVM_MAXPATHLEN]; + if (unnormalize_path(tmp, JVM_MAXPATHLEN, true, path)) { + check_dir_impl(tmp, should_be_empty); + } + } +} + +static void check_file(wchar_t* path) { + check_file_impl(path); + + for (int i = 0; mods_filter != Allow_None && i < mods_per_path; ++i) { + wchar_t tmp[JVM_MAXPATHLEN]; + if (unnormalize_path(tmp, JVM_MAXPATHLEN, false, path)) { + check_file_impl(tmp); + } + } +} + +static void check_file_not_present(wchar_t* path) { + check_file_not_present_impl(path); + + for (int i = 0; mods_filter != Allow_None && i < mods_per_path; ++i) { + wchar_t tmp[JVM_MAXPATHLEN]; + if (unnormalize_path(tmp, JVM_MAXPATHLEN, false, path)) { + check_file_not_present_impl(tmp); + } + } +} + +static void record_path(char const* name, char const* len_name, wchar_t* path) { + char buf[JVM_MAXPATHLEN]; + + if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) { + ::testing::Test::RecordProperty(name, buf); + os::snprintf(buf, JVM_MAXPATHLEN, "%d", (int) wcslen(path)); + ::testing::Test::RecordProperty(len_name, buf); + } +} + +static void bench_path(wchar_t* path) { + char buf[JVM_MAXPATHLEN]; + int reps = 100000; + + if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) { + jlong wtime[2]; + + for (int t = 0; t < 2; ++t) { + wtime[t] = os::javaTimeNanos(); + + for (int i = 0; i < reps; ++i) { + bool succ = false; + size_t buf_len = strlen(buf); + wchar_t* w_path = (wchar_t*) os::malloc(sizeof(wchar_t) * (buf_len + 1), mtInternal); + + if (w_path != NULL) { + size_t converted_chars; + if (::mbstowcs_s(&converted_chars, w_path, buf_len + 1, buf, buf_len) == ERROR_SUCCESS) { + if (t == 1) { + wchar_t* tmp = (wchar_t*) os::malloc(sizeof(wchar_t) * JVM_MAXPATHLEN, mtInternal); + + if (tmp) { + if (_wfullpath(tmp, w_path, JVM_MAXPATHLEN)) { + succ = true; + } + + // Note that we really don't use the full path name, but just add the cost of running _wfullpath. + os::free(tmp); + } + if (!succ) { + printf("Failed fullpathing \"%s\"\n", buf); + return; + } + succ = false; + } + HANDLE h = ::CreateFileW(w_path, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + + if (h != INVALID_HANDLE_VALUE) { + ::CloseHandle(h); + succ = true; + } + } + } + + os::free(w_path); + if (!succ) { + printf("Failed getting W*attr. \"%s\"\n", buf); + return; + } + } + + wtime[t] = os::javaTimeNanos() - wtime[t]; + } + + jlong ctime = os::javaTimeNanos(); + + for (int i = 0; i < reps; ++i) { + HANDLE h = ::CreateFileA(buf, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + + if (h == INVALID_HANDLE_VALUE) { + return; + } + + ::CloseHandle(h); + } + + ctime = os::javaTimeNanos() - ctime; + + printf("\"%s\" %f us for *A, %f us for *W, %f us for *W with fullpath\n", buf, + 0.001 * ctime / reps, 0.001 * wtime[0] / reps, 0.001 * wtime[1] / reps); + } +} + +static void print_attr_result_for_path(wchar_t* path) { + WIN32_FILE_ATTRIBUTE_DATA file_data; + struct stat st; + char buf[JVM_MAXPATHLEN]; + wchar_t abs[JVM_MAXPATHLEN]; + + _wfullpath(abs, path, JVM_MAXPATHLEN); + printf("Checking \"%ls\" (%d chars):\n", path, (int) wcslen(path)); + printf("_wfullpath %ls (%d chars)\n", abs, (int) wcslen(abs)); + BOOL bret = ::GetFileAttributesExW(path, GetFileExInfoStandard, &file_data); + printf("GetFileAttributesExW() %s\n", bret ? "success" : "failed"); + + if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) { + bret = ::GetFileAttributesExA(buf, GetFileExInfoStandard, &file_data); + printf("GetFileAttributesExA() %s\n", bret ? "success" : "failed"); + + bool succ = os::stat(buf, &st) != -1; + printf("os::stat() %s\n", succ ? "success" : "failed"); + } +} + +static void print_attr_result(wchar_t* format, ...) { + va_list argptr; + wchar_t buf[JVM_MAXPATHLEN]; + + va_start(argptr, format); + wvsprintfW(buf, format, argptr); + print_attr_result_for_path(buf); + va_end(argptr); +} + +#define RECORD_PATH(name) record_path(#name, #name "Len", name) +#define NAME_PART_50 L"01234567890123456789012345678901234567890123456789" +#define NAME_PART_250 NAME_PART_50 NAME_PART_50 NAME_PART_50 NAME_PART_50 NAME_PART_50 + +// Test which tries to find out if the os::stat, os::open and os::dir_is_empty methods +// can handle long path names correctly. +TEST_VM(os_windows, handle_long_paths) { + static wchar_t cwd[JVM_MAXPATHLEN]; + static wchar_t nearly_long_rel_path[JVM_MAXPATHLEN]; + static wchar_t long_rel_path[JVM_MAXPATHLEN]; + static wchar_t empty_dir_rel_path[JVM_MAXPATHLEN]; + static wchar_t not_empty_dir_rel_path[JVM_MAXPATHLEN]; + static wchar_t file_rel_path[JVM_MAXPATHLEN]; + static wchar_t nearly_long_file_rel_path[JVM_MAXPATHLEN]; + static wchar_t nearly_long_path[JVM_MAXPATHLEN]; + static wchar_t empty_dir_path[JVM_MAXPATHLEN]; + static wchar_t not_empty_dir_path[JVM_MAXPATHLEN]; + static wchar_t nearly_long_file_path[JVM_MAXPATHLEN]; + static wchar_t file_path[JVM_MAXPATHLEN]; + static wchar_t nearly_long_unc_path[JVM_MAXPATHLEN]; + static wchar_t empty_dir_unc_path[JVM_MAXPATHLEN]; + static wchar_t not_empty_dir_unc_path[JVM_MAXPATHLEN]; + static wchar_t nearly_long_file_unc_path[JVM_MAXPATHLEN]; + static wchar_t file_unc_path[JVM_MAXPATHLEN]; + static wchar_t root_dir_path[JVM_MAXPATHLEN]; + static wchar_t root_rel_dir_path[JVM_MAXPATHLEN]; + + wchar_t* dir_prefix = L"os_windows_long_paths_dir_"; + wchar_t* empty_dir_name = L"empty_directory_with_long_path"; + wchar_t* not_empty_dir_name = L"not_empty_directory_with_long_path"; + wchar_t* file_name = L"file"; + wchar_t dir_letter; + WIN32_FILE_ATTRIBUTE_DATA file_data; + bool can_test_unc = false; + + get_current_dir_w(cwd, sizeof(cwd) / sizeof(wchar_t)); + dir_letter = (cwd[1] == L':' ? cwd[0] : L'\0'); + int cwd_len = (int) wcslen(cwd); + int dir_prefix_len = (int) wcslen(dir_prefix); + int rel_path_len = MAX2(dir_prefix_len, 235 - cwd_len); + + memcpy(nearly_long_rel_path, dir_prefix, sizeof(wchar_t) * dir_prefix_len); + + for (int i = dir_prefix_len; i < rel_path_len; ++i) { + nearly_long_rel_path[i] = L'L'; + } + + nearly_long_rel_path[rel_path_len] = L'\0'; + + wsprintfW(long_rel_path, L"%ls\\%ls", nearly_long_rel_path, NAME_PART_250); + wsprintfW(empty_dir_rel_path, L"%ls\\%ls", nearly_long_rel_path, empty_dir_name); + wsprintfW(not_empty_dir_rel_path, L"%ls\\%ls", nearly_long_rel_path, not_empty_dir_name); + wsprintfW(nearly_long_file_rel_path, L"%ls\\%ls", nearly_long_rel_path, file_name); + wsprintfW(file_rel_path, L"%ls\\%ls\\%ls", nearly_long_rel_path, not_empty_dir_name, file_name); + wsprintfW(nearly_long_path, L"\\\\?\\%ls\\%ls", cwd, nearly_long_rel_path); + wsprintfW(empty_dir_path, L"%ls\\%ls", nearly_long_path, empty_dir_name); + wsprintfW(not_empty_dir_path, L"%ls\\%ls", nearly_long_path, not_empty_dir_name); + wsprintfW(nearly_long_file_path, L"%ls\\%ls", nearly_long_path, file_name); + wsprintfW(file_path, L"%ls\\%ls\\%ls", nearly_long_path, not_empty_dir_name, file_name); + wsprintfW(nearly_long_unc_path, L"\\\\localhost\\%lc$\\%s", dir_letter, nearly_long_path + 7); + wsprintfW(empty_dir_unc_path, L"%s\\%s", nearly_long_unc_path, empty_dir_name); + wsprintfW(not_empty_dir_unc_path, L"%s\\%s", nearly_long_unc_path, not_empty_dir_name); + wsprintfW(nearly_long_file_unc_path, L"%ls\\%ls", nearly_long_unc_path, file_name); + wsprintfW(file_unc_path, L"%s\\%s\\%s", nearly_long_unc_path, not_empty_dir_name, file_name); + wsprintfW(root_dir_path, L"%lc:\\", dir_letter); + wsprintfW(root_rel_dir_path, L"%lc:", dir_letter); + + RECORD_PATH(long_rel_path); + RECORD_PATH(nearly_long_rel_path); + RECORD_PATH(nearly_long_path); + RECORD_PATH(nearly_long_unc_path); + RECORD_PATH(empty_dir_rel_path); + RECORD_PATH(empty_dir_path); + RECORD_PATH(empty_dir_unc_path); + RECORD_PATH(not_empty_dir_rel_path); + RECORD_PATH(not_empty_dir_path); + RECORD_PATH(not_empty_dir_unc_path); + RECORD_PATH(nearly_long_file_rel_path); + RECORD_PATH(nearly_long_file_path); + RECORD_PATH(nearly_long_file_unc_path); + RECORD_PATH(file_rel_path); + RECORD_PATH(file_path); + RECORD_PATH(file_unc_path); + + create_rel_directory_w(nearly_long_rel_path); + create_rel_directory_w(long_rel_path); + create_rel_directory_w(empty_dir_rel_path); + create_rel_directory_w(not_empty_dir_rel_path); + create_rel_file_w(nearly_long_file_rel_path); + create_rel_file_w(file_rel_path); + + // For UNC path test we assume that the current DRIVE has a share + // called "$" (so for D: we expect \\localhost\D$ to be + // the same). Since this is only an assumption, we have to skip + // the UNC tests if the share is missing. + if (dir_letter && !::GetFileAttributesExW(nearly_long_unc_path, GetFileExInfoStandard, &file_data)) { + printf("Disabled UNC path test, since %lc: is not mapped as share %lc$.\n", dir_letter, dir_letter); + } else { + can_test_unc = true; + } + + if (mode == BENCH) { + bench_path(nearly_long_path + 4); + bench_path(nearly_long_rel_path); + bench_path(nearly_long_file_path + 4); + bench_path(nearly_long_file_rel_path); + } else if (mode == EXAMPLES) { + printf("Working directory: %ls", cwd); + + if (dir_letter) { + static wchar_t top_buf[JVM_MAXPATHLEN]; + wchar_t* top_path = wcschr(cwd + 3, L'\\'); + + if (top_path) { + size_t top_len = (top_path - cwd) - 3; + + memcpy(top_buf, cwd + 3, top_len * 2); + top_buf[top_len] = L'\0'; + top_path = top_buf; + } + + print_attr_result(L"%lc:\\", dir_letter); + print_attr_result(L"%lc:\\.\\", dir_letter); + + if (top_path) { + print_attr_result(L"%lc:\\%ls\\..\\%ls\\", dir_letter, top_path, top_path); + } + + print_attr_result(L"%lc:", dir_letter); + print_attr_result(L"%lc:.", dir_letter); + print_attr_result(L"%lc:\\COM1", dir_letter); + print_attr_result(L"%lc:\\PRN", dir_letter); + print_attr_result(L"%lc:\\PRN\\COM1", dir_letter); + print_attr_result(L"\\\\?\\UNC\\localhost\\%lc$\\", dir_letter); + print_attr_result(L"\\\\?\\UNC\\\\localhost\\%lc$\\", dir_letter); + print_attr_result(nearly_long_unc_path); + print_attr_result(L"%ls\\.\\", nearly_long_unc_path); + print_attr_result(L"%ls\\..\\%ls", nearly_long_unc_path, nearly_long_rel_path); + print_attr_result(L"\\\\?\\UNC\\%ls", nearly_long_unc_path + 2); + print_attr_result(file_unc_path); + print_attr_result(L"%ls\\%ls\\..\\%ls\\%ls", nearly_long_unc_path, not_empty_dir_name, not_empty_dir_name, file_name); + print_attr_result(L"%ls\\%ls\\.\\%ls", nearly_long_unc_path, not_empty_dir_name, file_name); + print_attr_result(L"\\\\?\\UNC\\%ls", file_unc_path + 2); + print_attr_result(L"\\\\?\\UNC\\%ls\\%ls\\.\\%ls", nearly_long_unc_path + 2, not_empty_dir_name, file_name); + print_attr_result(L"\\\\?\\UNC\\%ls\\%ls\\..\\%ls\\%ls", nearly_long_unc_path + 2, not_empty_dir_name, not_empty_dir_name, file_name); + } + + print_attr_result(nearly_long_rel_path); + print_attr_result(L"%ls\\.\\", nearly_long_rel_path); + print_attr_result(L"%ls\\..\\%ls", nearly_long_rel_path, nearly_long_rel_path); + print_attr_result(L"%\\\\?\\%ls", nearly_long_rel_path); + print_attr_result(L"\\\\?\\%ls\\.\\", nearly_long_rel_path); + print_attr_result(L"\\\\?\\%ls\\..\\%ls", nearly_long_rel_path, nearly_long_rel_path); + + print_attr_result(nearly_long_path + 4); + print_attr_result(L"%ls\\.\\", nearly_long_path + 4); + print_attr_result(L"%ls\\..\\%ls", nearly_long_path + 4, nearly_long_rel_path); + print_attr_result(nearly_long_path); + print_attr_result(L"%ls\\.\\", nearly_long_path); + print_attr_result(L"%ls\\..\\%ls", nearly_long_path, nearly_long_rel_path); + } else { + check_file_not_present(L""); + + // Check relative paths + check_dir(nearly_long_rel_path, false); + check_dir(long_rel_path, true); + check_dir(empty_dir_rel_path, true); + check_dir(not_empty_dir_rel_path, false); + check_file(nearly_long_file_rel_path); + check_file(file_rel_path); + + // Check absolute paths + if (dir_letter) { + check_dir(root_dir_path, false); + check_dir(root_rel_dir_path, false); + } + + check_dir(cwd, false); + check_dir(nearly_long_path + 4, false); + check_dir(empty_dir_path + 4, true); + check_dir(not_empty_dir_path + 4, false); + check_file(nearly_long_file_path + 4); + check_file(file_path + 4); + + // Check UNC paths + if (can_test_unc) { + check_dir(nearly_long_unc_path, false); + check_dir(empty_dir_unc_path, true); + check_dir(not_empty_dir_unc_path, false); + check_file(nearly_long_file_unc_path); + check_file(file_unc_path); + } + + // Check handling of :/../:/path/... + // The other drive letter should not overwrite the original one. + if (dir_letter) { + static wchar_t tmp[JVM_MAXPATHLEN]; + wchar_t* other_letter = dir_letter == L'D' ? L"C" : L"D"; + wsprintfW(tmp, L"%2ls\\..\\%ls:%ls", nearly_long_file_path, other_letter, nearly_long_file_path + 2); + check_file_not_present(tmp); + wsprintfW(tmp, L"%2ls\\..\\%ls:%ls", file_path, other_letter, file_path + 2); + check_file_not_present(tmp); + } + } + + delete_rel_file_w(file_rel_path); + delete_rel_file_w(nearly_long_file_rel_path); + delete_empty_rel_directory_w(not_empty_dir_rel_path); + delete_empty_rel_directory_w(empty_dir_rel_path); + delete_empty_rel_directory_w(long_rel_path); + delete_empty_rel_directory_w(nearly_long_rel_path); +} + +#endif diff --git a/test/hotspot/jtreg/runtime/LoadClass/LongBCP.java b/test/hotspot/jtreg/runtime/LoadClass/LongBCP.java index f6cdf4b40c7..98ca4495966 100644 --- a/test/hotspot/jtreg/runtime/LoadClass/LongBCP.java +++ b/test/hotspot/jtreg/runtime/LoadClass/LongBCP.java @@ -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 @@ -37,7 +37,6 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; -import jdk.test.lib.Platform; import jdk.test.lib.compiler.CompilerUtils; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; @@ -117,13 +116,8 @@ public static void main(String args[]) throws Exception { bootCP, "Hello"); output = new OutputAnalyzer(pb.start()); - if (!Platform.isWindows()) { - output.shouldContain("Hello World") - .shouldHaveExitValue(0); - } else { - output.shouldContain("Could not find or load main class Hello") - .shouldHaveExitValue(1); - } + output.shouldContain("Hello World") + .shouldHaveExitValue(0); // total relative path length exceeds MAX_PATH destDir = Paths.get(destDir.toString(), "yyyyyyyy"); @@ -135,12 +129,7 @@ public static void main(String args[]) throws Exception { bootCP, "Hello"); output = new OutputAnalyzer(pb.start()); - if (!Platform.isWindows()) { - output.shouldContain("Hello World") - .shouldHaveExitValue(0); - } else { - output.shouldContain("Could not find or load main class Hello") - .shouldHaveExitValue(1); - } + output.shouldContain("Hello World") + .shouldHaveExitValue(0); } } From da37efc95fd7b0a651b2328d99393c9c7607bff8 Mon Sep 17 00:00:00 2001 From: kbarrett Date: Tue, 6 Aug 2019 11:40:23 -0400 Subject: [PATCH 112/131] 8229156: ProblemList gc/stress/gclocker/TestExcessGCLockerCollections.java Reviewed-by: shade --- test/hotspot/jtreg/ProblemList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index f9197349194..404556e5859 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -69,6 +69,7 @@ gc/g1/humongousObjects/objectGraphTest/TestObjectGraphAfterGC.java 8156755 gener gc/survivorAlignment/TestPromotionToSurvivor.java 8129886 generic-all gc/g1/logging/TestG1LoggingFailure.java 8169634 generic-all gc/g1/humongousObjects/TestHeapCounters.java 8178918 generic-all +gc/stress/gclocker/TestExcessGCLockerCollections.java 8229120 generic-all gc/stress/gclocker/TestGCLockerWithParallel.java 8180622 generic-all gc/stress/gclocker/TestGCLockerWithG1.java 8180622 generic-all gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java 8177765 generic-all From d2c52ec706eb76b964105c7f7d2c622ba6ba243a Mon Sep 17 00:00:00 2001 From: mbaesken Date: Wed, 19 Dec 2018 10:30:43 +0100 Subject: [PATCH 113/131] 8215411: some GetByteArrayElements calls miss corresponding Release Reviewed-by: dholmes, jcbeyler --- src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m | 6 ++++-- .../windows/native/libattach/VirtualMachineImpl.c | 5 ++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m b/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m index c9ddeefe3e6..6c35dbf2b10 100644 --- a/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m +++ b/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m @@ -581,13 +581,15 @@ static void addCertificatesToKeystore(JNIEnv *env, jobject keyStore) cssmPerror("_addItemToKeychain: SecKeychainItemImport", err); } - (*env)->ReleaseByteArrayElements(env, rawDataObj, rawData, JNI_ABORT); - if (createdItems != NULL) { CFRelease(createdItems); } errOut: + if (rawData) { + (*env)->ReleaseByteArrayElements(env, rawDataObj, rawData, JNI_ABORT); + } + if (passwordStrRef) CFRelease(passwordStrRef); if (passwordChars) { // clear the password and release diff --git a/src/jdk.attach/windows/native/libattach/VirtualMachineImpl.c b/src/jdk.attach/windows/native/libattach/VirtualMachineImpl.c index bf0b21138f9..a21ce9fa73b 100644 --- a/src/jdk.attach/windows/native/libattach/VirtualMachineImpl.c +++ b/src/jdk.attach/windows/native/libattach/VirtualMachineImpl.c @@ -457,12 +457,11 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_enqueue if (pCode == NULL) { JNU_ThrowIOExceptionWithLastError(env, "VirtualAllocEx failed"); VirtualFreeEx(hProcess, pData, 0, MEM_RELEASE); + (*env)->ReleaseByteArrayElements(env, stub, stubCode, JNI_ABORT); return; } WriteProcessMemory( hProcess, (LPVOID)pCode, (LPCVOID)stubCode, (SIZE_T)stubLen, NULL ); - if (isCopy) { - (*env)->ReleaseByteArrayElements(env, stub, stubCode, JNI_ABORT); - } + (*env)->ReleaseByteArrayElements(env, stub, stubCode, JNI_ABORT); /* * Create thread in target process to execute code From 9d4dc16f94a8d120946b20a9477867ce1f402d29 Mon Sep 17 00:00:00 2001 From: dfuchs Date: Thu, 28 Mar 2019 12:16:36 +0000 Subject: [PATCH 114/131] 8221395: HttpClient leaving connections in CLOSE_WAIT state until Java process ends Summary: When a non WebSocket connection is not returned to the pool, it needs to be closed even if HttpConnection::isOpen yields false. Reviewed-by: chegar, michaelm --- .../jdk/internal/net/http/HttpConnection.java | 9 +- .../whitebox/ConnectionPoolTestDriver.java | 8 +- .../internal/net/http/ConnectionPoolTest.java | 233 +++++++++++++++++- 3 files changed, 232 insertions(+), 18 deletions(-) diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java b/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java index 9b8ab1d3ab8..76bb3c0a606 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java @@ -317,14 +317,13 @@ private static HttpConnection getPlainConnection(InetSocketAddress addr, void closeOrReturnToCache(HttpHeaders hdrs) { if (hdrs == null) { // the connection was closed by server, eof + Log.logTrace("Cannot return connection to pool: closing {0}", this); close(); return; } - if (!isOpen()) { - return; - } HttpClientImpl client = client(); if (client == null) { + Log.logTrace("Client released: closing {0}", this); close(); return; } @@ -333,10 +332,12 @@ void closeOrReturnToCache(HttpHeaders hdrs) { .map((s) -> !s.equalsIgnoreCase("close")) .orElse(true); - if (keepAlive) { + if (keepAlive && isOpen()) { Log.logTrace("Returning connection to the pool: {0}", this); pool.returnToPool(this); } else { + Log.logTrace("Closing connection (keepAlive={0}, isOpen={1}): {2}", + keepAlive, isOpen(), this); close(); } } diff --git a/test/jdk/java/net/httpclient/whitebox/ConnectionPoolTestDriver.java b/test/jdk/java/net/httpclient/whitebox/ConnectionPoolTestDriver.java index 91eb090f52d..23478be57bc 100644 --- a/test/jdk/java/net/httpclient/whitebox/ConnectionPoolTestDriver.java +++ b/test/jdk/java/net/httpclient/whitebox/ConnectionPoolTestDriver.java @@ -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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8187044 8187111 + * @bug 8187044 8187111 8221395 * @summary Verifies that the ConnectionPool correctly handle * connection deadlines and purges the right connections * from the cache. @@ -35,4 +35,8 @@ * @run main/othervm * --add-reads java.net.http=java.management * java.net.http/jdk.internal.net.http.ConnectionPoolTest testPoolSize + * @run main/othervm + * --add-reads java.net.http=java.management + * -Djdk.httpclient.HttpClient.log=errors,requests,headers,content,ssl,trace,channel + * java.net.http/jdk.internal.net.http.ConnectionPoolTest testCloseOrReturnToPool */ diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/ConnectionPoolTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/ConnectionPoolTest.java index 37144fcfe14..5d30b19562b 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/ConnectionPoolTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/ConnectionPoolTest.java @@ -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 @@ -25,17 +25,25 @@ import java.io.IOException; import java.lang.management.ManagementFactory; +import java.lang.ref.Reference; import java.net.Authenticator; import java.net.CookieHandler; import java.net.InetSocketAddress; import java.net.ProxySelector; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.SocketOption; +import java.net.http.HttpHeaders; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; +import java.nio.channels.spi.SelectorProvider; import java.time.Duration; -import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Random; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.concurrent.Flow; @@ -53,7 +61,7 @@ * @summary Verifies that the ConnectionPool correctly handle * connection deadlines and purges the right connections * from the cache. - * @bug 8187044 8187111 + * @bug 8187044 8187111 8221395 * @author danielfuchs */ public class ConnectionPoolTest { @@ -78,7 +86,10 @@ public static void main(String[] args) throws Exception { } else if ("testPoolSize".equals(arg)) { assert args.length == 1 : "testPoolSize should be run in its own VM"; testPoolSize(); - } + } else if ("testCloseOrReturnToPool".equals(arg)) { + assert args.length == 1 : "testCloseOrReturnToPool should be run in its own VM"; + testCloseOrReturnToPool(); + } else throw new RuntimeException("unknown test case: " + arg); } } @@ -226,6 +237,113 @@ public static void testPoolSize() throws Exception { } } + public static void testCloseOrReturnToPool() throws Exception { + HttpClientFacade facade = (HttpClientFacade)HttpClient.newHttpClient(); + HttpClientImpl client = facade.impl; + ConnectionPool pool = client.connectionPool(); + InetSocketAddress proxy = InetSocketAddress.createUnresolved("bar", 80); + + InetSocketAddress addr = InetSocketAddress.createUnresolved("foo1", 80); + HttpConnectionStub conn1 = new HttpConnectionStub(facade, client, addr, proxy, true); + HttpHeaders hdrs = HttpHeaders.of(new HashMap<>(), (s1,s2) -> true); + HttpConnection conn; + + conn1.reopen(); + if (!conn1.isOpen()) { + throw new RuntimeException("conn1 finished"); + } + + conn1.closeOrReturnToCache(hdrs); + + // Check we can find conn1 in the pool + if (conn1 != (conn = pool.getConnection(true, addr, proxy))) { + throw new RuntimeException("conn1 not returned, got: " + conn); + } + System.out.println("Found connection in the pool: " + conn ); + + // Try to return it with no headers: the connection should + // be closed and not returned to the pool (EOF). + conn.closeOrReturnToCache(null); + if ((conn = pool.getConnection(true, addr, proxy)) != null) { + throw new RuntimeException(conn + " found in the pool!"); + } + if (!conn1.closed) { + throw new RuntimeException("conn1 not closed!"); + } + System.out.println("EOF connection successfully closed when returned to pool"); + + // reopen the connection + conn1.reopen(); + if (!conn1.isOpen()) { + throw new RuntimeException("conn1 finished"); + } + + // Try to return it with empty headers: the connection should + // be returned to the pool. + conn1.closeOrReturnToCache(hdrs); + if (conn1 != (conn = pool.getConnection(true, addr, proxy))) { + throw new RuntimeException("conn1 not returned to pool, got: " + conn); + } + if (conn1.closed) { + throw new RuntimeException("conn1 closed"); + } + if (!conn1.isOpen()) { + throw new RuntimeException("conn1 finished"); + } + + System.out.println("Keep alive connection successfully returned to pool"); + + // Try to return it with connection: close headers: the connection should + // not be returned to the pool, and should be closed. + HttpHeaders hdrs2 = HttpHeaders.of(Map.of("connection", List.of("close")), (s1, s2) -> true); + conn1.closeOrReturnToCache(hdrs2); + if ((conn = pool.getConnection(true, addr, proxy)) != null) { + throw new RuntimeException(conn + " found in the pool!"); + } + if (!conn1.closed) { + throw new RuntimeException("conn1 not closed!"); + } + System.out.println("Close connection successfully closed when returned to pool"); + + // reopen and finish the connection. + conn1.reopen(); + conn1.finish(true); + if (conn1.closed) { + throw new RuntimeException("conn1 closed"); + } + if (conn1.isOpen()) { + throw new RuntimeException("conn1 is opened!"); + } + conn1.closeOrReturnToCache(hdrs2); + if ((conn = pool.getConnection(true, addr, proxy)) != null) { + throw new RuntimeException(conn + " found in the pool!"); + } + if (!conn1.closed) { + throw new RuntimeException("conn1 not closed!"); + } + System.out.println("Finished 'close' connection successfully closed when returned to pool"); + + // reopen and finish the connection. + conn1.reopen(); + conn1.finish(true); + if (conn1.closed) { + throw new RuntimeException("conn1 closed"); + } + if (conn1.isOpen()) { + throw new RuntimeException("conn1 is opened!"); + } + conn1.closeOrReturnToCache(hdrs); + if ((conn = pool.getConnection(true, addr, proxy)) != null) { + throw new RuntimeException(conn + " found in the pool!"); + } + if (!conn1.closed) { + throw new RuntimeException("conn1 not closed!"); + } + System.out.println("Finished keep-alive connection successfully closed when returned to pool"); + + Reference.reachabilityFence(facade); + } + static T error() { throw new InternalError("Should not reach here: wrong test assumptions!"); } @@ -241,22 +359,108 @@ public void onSubscribe(Flow.Subscription subscription) { } @Override public void subscribe(Flow.Subscriber> subscriber) { } - @Override public boolean isFinished() { return conn.closed; } + @Override public boolean isFinished() { return conn.finished; } + } + + static class SocketChannelStub extends SocketChannel { + + SocketChannelStub() { super(SelectorProvider.provider()); } + + @Override + public SocketChannel bind(SocketAddress local) throws IOException { + return error(); + } + @Override + public SocketChannel setOption(SocketOption name, T value) throws IOException { + return error(); + } + @Override + public SocketChannel shutdownInput() throws IOException { + return error(); + } + @Override + public SocketChannel shutdownOutput() throws IOException { + return error(); + } + @Override + public Socket socket() { return error(); } + @Override + public boolean isConnected() { return true; } + @Override + public boolean isConnectionPending() { return false; } + @Override + public boolean connect(SocketAddress remote) throws IOException { + return error(); + } + @Override + public boolean finishConnect() throws IOException { + return error(); + } + @Override + public SocketAddress getRemoteAddress() throws IOException { + return error(); + } + @Override + public int read(ByteBuffer dst) throws IOException { + return error(); + } + @Override + public long read(ByteBuffer[] dsts, int offset, int length) throws IOException { + return error(); + } + @Override + public int write(ByteBuffer src) throws IOException { + return error(); + } + @Override + public long write(ByteBuffer[] srcs, int offset, int length) throws IOException { + return 0; + } + @Override + public SocketAddress getLocalAddress() throws IOException { + return error(); + } + @Override + public T getOption(SocketOption name) throws IOException { + return error(); + } + @Override + public Set> supportedOptions() { + return error(); + } + @Override + protected void implCloseSelectableChannel() throws IOException { + error(); + } + @Override + protected void implConfigureBlocking(boolean block) throws IOException { + error(); + } } // Emulates an HttpConnection that has a strong reference to its HttpClient. static class HttpConnectionStub extends HttpConnection { - public HttpConnectionStub(HttpClient client, + public HttpConnectionStub( + HttpClient client, InetSocketAddress address, InetSocketAddress proxy, boolean secured) { - super(address, null); + this(client, null, address, proxy, secured); + } + public HttpConnectionStub( + HttpClient client, + HttpClientImpl impl, + InetSocketAddress address, + InetSocketAddress proxy, + boolean secured) { + super(address, impl); this.key = ConnectionPool.cacheKey(address, proxy); this.address = address; this.proxy = proxy; this.secured = secured; this.client = client; + this.channel = new SocketChannelStub(); this.flow = new FlowTubeStub(this); } @@ -266,16 +470,23 @@ public HttpConnectionStub(HttpClient client, final ConnectionPool.CacheKey key; final HttpClient client; final FlowTubeStub flow; - volatile boolean closed; + final SocketChannel channel; + volatile boolean closed, finished; + + // Used for testing closeOrReturnToPool. + void finish(boolean finished) { this.finished = finished; } + void reopen() { closed = finished = false;} // All these return something @Override boolean connected() {return !closed;} @Override boolean isSecure() {return secured;} @Override boolean isProxied() {return proxy!=null;} @Override ConnectionPool.CacheKey cacheKey() {return key;} + @Override FlowTube getConnectionFlow() {return flow;} + @Override SocketChannel channel() {return channel;} @Override public void close() { - closed=true; + closed=finished=true; System.out.println("closed: " + this); } @Override @@ -283,13 +494,11 @@ public String toString() { return "HttpConnectionStub: " + address + " proxy: " + proxy; } + // All these throw errors @Override public HttpPublisher publisher() {return error();} @Override public CompletableFuture connectAsync(Exchange e) {return error();} @Override public CompletableFuture finishConnect() {return error();} - @Override SocketChannel channel() {return error();} - @Override - FlowTube getConnectionFlow() {return flow;} } // Emulates an HttpClient that has a strong reference to its connection pool. static class HttpClientStub extends HttpClient { From 8f9d329a7d851e7e4fa2bb078f7ba3e00887a76f Mon Sep 17 00:00:00 2001 From: chagedorn Date: Wed, 23 Oct 2019 12:17:14 +0200 Subject: [PATCH 115/131] 8232874: Add missing test for 8230062 Summary: Adds a missing test which verifies the bug fix of 8230062. Reviewed-by: roland, thartmann --- .../superword/SuperWordIntermediateUse.java | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/loopopts/superword/SuperWordIntermediateUse.java diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/SuperWordIntermediateUse.java b/test/hotspot/jtreg/compiler/loopopts/superword/SuperWordIntermediateUse.java new file mode 100644 index 00000000000..1d8357fd32e --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/superword/SuperWordIntermediateUse.java @@ -0,0 +1,81 @@ +/* + * 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 8230062 + * @summary The IR of this test contains a reduction chain which corresponds to a pack in which the 2nd last element has a usage outside of the optimized loop. + * + * @run main/othervm -Xbatch -XX:CompileCommand=compileonly,compiler.loopopts.superword.SuperWordIntermediateUse::test + * compiler.loopopts.superword.SuperWordIntermediateUse + */ + +package compiler.loopopts.superword; + +public class SuperWordIntermediateUse { + + private int iFld; + private int[] iArr = new int[1024]; + + public void test() { + int local = 4; + + /** + * Before unrolling this loop: + * iFld: AddI 1 = -85 + Phi 1 + * local: MulI 2 = Phi 1 * LoadI 3 + * + * This loop is now unrolled. 'local' is a reduction. The loop is first copied: + * iFldCopy: AddI C1 = -85 + Phi C1 + * localCopy: MulI C2 = Phi C1 * LoadI C3 + * + * iFld: AddI 1 = -85 + Phi 1 + * local: MulI 2 = Phi 1 * LoadI 3 + * + * Then, the unnecessary nodes like phis are removed from the original loop by igvn: + * (iFldCopy: AddI C1 = -85 + Phi C1) field store optimized away + * localCopy: MulI C2 = Phi C1 * LoadI C3 + * + * iFld: AddI 1 = -85 + MulI C2 + * local: MulI 2 = MulI C2 * LoadI 3 -> Input into Phi C1 + * + * As a result AddI 1 has an input from MulI C2 which isn't the last operation in the reduction chain + * Phi C1 -> MulI C2 -> MulI 2 -> Phi C1 and therefore not the last element in a pack. + * Additionally, AddI 1 does not belong to the loop being optimized: The store node for iFld is put outside of the loop being optimized. + * This triggers the assertion bug when unrolled at least 4 times which creates packs of at least size 4. + */ + for (int i = 0; i < 1024; i++) { + iFld = -85; + iFld = iFld + local; + local = local * iArr[i]; + iArr[i] = 3; // Just used to trigger SuperWord optimization + } + } + + public static void main(String[] strArr) { + SuperWordIntermediateUse instance = new SuperWordIntermediateUse(); + for (int i = 0; i < 1000; i++) { + instance.test(); + } + } +} From fe7e5bbc8af8b98c07e9ee15c0b919ac9460283a Mon Sep 17 00:00:00 2001 From: shade Date: Tue, 15 Oct 2019 19:45:09 +0200 Subject: [PATCH 116/131] 8232051: Epsilon should warn about Xms/Xmx/AlwaysPreTouch configuration Reviewed-by: zgu --- test/hotspot/jtreg/gc/epsilon/TestAlwaysPretouch.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/gc/epsilon/TestAlwaysPretouch.java b/test/hotspot/jtreg/gc/epsilon/TestAlwaysPretouch.java index b15ef7c7993..094125c259d 100644 --- a/test/hotspot/jtreg/gc/epsilon/TestAlwaysPretouch.java +++ b/test/hotspot/jtreg/gc/epsilon/TestAlwaysPretouch.java @@ -26,7 +26,12 @@ * @key gc * @requires vm.gc.Epsilon & !vm.graal.enabled * @summary Basic sanity test for Epsilon - * @run main/othervm -Xmx1g -XX:+AlwaysPreTouch -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestAlwaysPretouch + * @run main/othervm -Xms128m -Xmx1g -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestAlwaysPretouch + * @run main/othervm -Xms128m -Xmx1g -XX:-AlwaysPreTouch -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestAlwaysPretouch + * @run main/othervm -Xms128m -Xmx1g -XX:+AlwaysPreTouch -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestAlwaysPretouch + * @run main/othervm -Xmx1g -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestAlwaysPretouch + * @run main/othervm -Xmx1g -XX:-AlwaysPreTouch -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestAlwaysPretouch + * @run main/othervm -Xmx1g -XX:+AlwaysPreTouch -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestAlwaysPretouch */ public class TestAlwaysPretouch { From 27fdfd61b1e64a28f51a5152ea98d9bc634af849 Mon Sep 17 00:00:00 2001 From: jwilhelm Date: Sat, 8 Dec 2018 05:04:19 +0100 Subject: [PATCH 117/131] 8214052: [testbug] vmTestbase/vm/compiler/CodeCacheInfoOnCompilation - wrong shell used Reviewed-by: jwilhelm Contributed-by: merkel05@gmail.com --- .../vmTestbase/vm/compiler/CodeCacheInfoOnCompilation/run.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/vmTestbase/vm/compiler/CodeCacheInfoOnCompilation/run.sh b/test/hotspot/jtreg/vmTestbase/vm/compiler/CodeCacheInfoOnCompilation/run.sh index 3c41316d891..3159eb22e1a 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/compiler/CodeCacheInfoOnCompilation/run.sh +++ b/test/hotspot/jtreg/vmTestbase/vm/compiler/CodeCacheInfoOnCompilation/run.sh @@ -27,7 +27,7 @@ TESTED_JAVA_HOME="$TESTJAVA" ver=$(${TESTED_JAVA_HOME}/bin/java ${JAVA_OPTS} -version 2>&1) isComp=$( echo ${ver} | grep -c "compiled mode") -if [[ $isComp != 1 ]]; then +if [ "$isComp" -ne 1 ]; then echo "skipped. This test works only with -Xcomp" exit fi @@ -40,7 +40,7 @@ pattern="(CodeCache|(CodeHeap.*)): size=${size_pattern} used=${size_pattern} max res=$(${TESTED_JAVA_HOME}/bin/java ${JAVA_OPTS} -XX:+PrintCodeCacheOnCompilation -XX:-Inline vm.compiler.CodeCacheInfoOnCompilation.PrintOnCall | egrep -ce "${pattern}") echo "res: " ${res} -if (( "${res}" != "0" )); then +if [ "$res" -ne 0 ]; then echo "passed" true else From 93a36363c7b56cb8466f768bd412df622218b18c Mon Sep 17 00:00:00 2001 From: egahlin Date: Fri, 4 Jan 2019 14:05:16 +0100 Subject: [PATCH 118/131] 8215771: The jfr tool should pretty print reference chains Reviewed-by: mgronlun --- .../jdk/jfr/internal/tool/PrettyWriter.java | 82 +++++++++++++++++-- 1 file changed, 77 insertions(+), 5 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/PrettyWriter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/PrettyWriter.java index 1575acea1b8..0a4e94325ba 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/PrettyWriter.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/PrettyWriter.java @@ -57,9 +57,11 @@ * This class is also used by {@link RecordedObject#toString()} */ public final class PrettyWriter extends EventPrintWriter { + private static final String TYPE_OLD_OBJECT = Type.TYPES_PREFIX + "OldObject"; private final static DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("HH:mm:ss.SSS"); private final static Long ZERO = 0L; private boolean showIds; + private RecordedEvent currentEvent; public PrettyWriter(PrintWriter destination) { super(destination); @@ -198,6 +200,7 @@ private String makeSimpleType(String typeName) { } public void print(RecordedEvent event) { + currentEvent = event; print(event.getEventType().getName(), " "); println("{"); indent(); @@ -308,7 +311,11 @@ private void printValue(Object value, ValueDescriptor field, String postFix) { println(formatMethod((RecordedMethod) value)); return; } - print((RecordedObject) value, postFix); + if (field.getTypeName().equals(TYPE_OLD_OBJECT)) { + printOldObject((RecordedObject) value); + return; + } + print((RecordedObject) value, postFix); return; } if (value.getClass().isArray()) { @@ -356,6 +363,70 @@ private void printValue(Object value, ValueDescriptor field, String postFix) { println(text); } + private void printOldObject(RecordedObject object) { + println(" ["); + indent(); + printIndent(); + try { + printReferenceChain(object); + } catch (IllegalArgumentException iae) { + // Could not find a field + // Not possible to validate fields beforehand using RecordedObject#hasField + // since nested objects, for example object.referrer.array.index, requires + // an actual array object (which may be null). + } + retract(); + printIndent(); + println("]"); + } + + private void printReferenceChain(RecordedObject object) { + printObject(object, currentEvent.getLong("arrayElements")); + for (RecordedObject ref = object.getValue("referrer"); ref != null; ref = object.getValue("referrer")) { + long skip = ref.getLong("skip"); + if (skip > 0) { + printIndent(); + println("..."); + } + String objectHolder = ""; + long size = Long.MIN_VALUE; + RecordedObject array = ref.getValue("array"); + if (array != null) { + long index = array.getLong("index"); + size = array.getLong("size"); + objectHolder = "[" + index + "]"; + } + RecordedObject field = ref.getValue("field"); + if (field != null) { + objectHolder = field.getString("name"); + } + printIndent(); + print(objectHolder); + print(" : "); + object = ref.getValue("object"); + if (object != null) { + printObject(object, size); + } + } + } + + void printObject(RecordedObject object, long arraySize) { + RecordedClass clazz = object.getClass("type"); + if (clazz != null) { + String className = clazz.getName(); + if (className!= null && className.startsWith("[")) { + className = decodeDescriptors(className, arraySize > 0 ? Long.toString(arraySize) : "").get(0); + } + print(className); + String description = object.getString("description"); + if (description != null) { + print(" "); + print(description); + } + } + println(); + } + private void printClassLoader(RecordedClassLoader cl, String postFix) { // Purposely not printing class loader name to avoid cluttered output RecordedClass clazz = cl.getType(); @@ -386,7 +457,7 @@ private String formatMethod(RecordedMethod m) { StringJoiner sj = new StringJoiner(", "); String md = m.getDescriptor().replace("/", "."); String parameter = md.substring(1, md.lastIndexOf(")")); - for (String qualifiedName : decodeDescriptors(parameter)) { + for (String qualifiedName : decodeDescriptors(parameter, "")) { String typeName = qualifiedName.substring(qualifiedName.lastIndexOf('.') + 1); sj.add(typeName); } @@ -407,17 +478,18 @@ private void printClass(RecordedClass clazz, String postFix) { } String className = clazz.getName(); if (className.startsWith("[")) { - className = decodeDescriptors(className).get(0); + className = decodeDescriptors(className, "").get(0); } println(className + " (classLoader = " + classLoaderName + ")" + postFix); } - List decodeDescriptors(String descriptor) { + List decodeDescriptors(String descriptor, String arraySize) { List descriptors = new ArrayList<>(); for (int index = 0; index < descriptor.length(); index++) { String arrayBrackets = ""; while (descriptor.charAt(index) == '[') { - arrayBrackets += "[]"; + arrayBrackets = arrayBrackets + "[" + arraySize + "]" ; + arraySize = ""; index++; } char c = descriptor.charAt(index); From 24c310e67635a2f025c515b6ab9e0db152638e5a Mon Sep 17 00:00:00 2001 From: fyang Date: Fri, 11 Oct 2019 16:52:18 +0800 Subject: [PATCH 119/131] 8231988: Unexpected test result caused by C2 IdealLoopTree::do_remove_empty_loop Summary: Duplicate cmp node in empty loop if it has other users Reviewed-by: neliasso, thartmann Contributed-by: wanghuang3@huawei.com, xietuo@huawei.com --- .../loopopts/TestRemoveEmptyLoop.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestRemoveEmptyLoop.java diff --git a/test/hotspot/jtreg/compiler/loopopts/TestRemoveEmptyLoop.java b/test/hotspot/jtreg/compiler/loopopts/TestRemoveEmptyLoop.java new file mode 100644 index 00000000000..94c79c9c214 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestRemoveEmptyLoop.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2019, Huawei Technologies Co. Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8231988 + * @summary Unexpected test result caused by C2 IdealLoopTree::do_remove_empty_loop + * + * @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation + * compiler.loopopts.TestRemoveEmptyLoop + */ + +package compiler.loopopts; + +public class TestRemoveEmptyLoop { + + public void test() { + int i = 34; + for (; i > 0; i -= 11); + if (i < 0) { + // do nothing + } else { + throw new RuntimeException("Test failed."); + } + } + + public static void main(String[] args) { + TestRemoveEmptyLoop _instance = new TestRemoveEmptyLoop(); + for (int i = 0; i < 50000; i++) { + _instance.test(); + } + System.out.println("Test passed."); + } + +} From e8a029993990a64d2973993aa7dd6392da94ad22 Mon Sep 17 00:00:00 2001 From: iignatyev Date: Wed, 30 Jan 2019 09:30:40 -0800 Subject: [PATCH 120/131] 8207922: ctw of jdk.security.auth failed with "Unexpected zero exit codebefore finishing all compilations" Reviewed-by: roland, thartmann --- .../testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java index 4b4a02a56ad..fabf95b61b0 100644 --- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java +++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java @@ -263,6 +263,8 @@ private String[] cmd(long classStart, long classStop) { "-XX:-UseCounterDecay", "-XX:-ShowMessageBoxOnError", "-XX:+UnlockDiagnosticVMOptions", + // redirect VM output to cerr so it won't collide w/ ctw output + "-XX:+DisplayVMOutputToStderr", // define phase start "-DCompileTheWorldStartAt=" + classStart, "-DCompileTheWorldStopAt=" + classStop, From fb6e65ca8f9bd74bca03bcea459e6129e81847ea Mon Sep 17 00:00:00 2001 From: xuelei Date: Fri, 8 Feb 2019 10:03:07 -0800 Subject: [PATCH 121/131] 8218580: endpoint identification algorithm should be case-insensitive Reviewed-by: jnimeh --- .../share/classes/sun/security/ssl/ClientHello.java | 6 +++--- .../classes/sun/security/ssl/PreSharedKeyExtension.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/java.base/share/classes/sun/security/ssl/ClientHello.java b/src/java.base/share/classes/sun/security/ssl/ClientHello.java index 6fbac3103e5..53b74223bfb 100644 --- a/src/java.base/share/classes/sun/security/ssl/ClientHello.java +++ b/src/java.base/share/classes/sun/security/ssl/ClientHello.java @@ -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 @@ -519,7 +519,7 @@ public byte[] produce(ConnectionContext context) throws IOException { if (session != null && identityAlg != null) { String sessionIdentityAlg = session.getIdentificationProtocol(); - if (!Objects.equals(identityAlg, sessionIdentityAlg)) { + if (!identityAlg.equalsIgnoreCase(sessionIdentityAlg)) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake,verbose")) { SSLLogger.finest("Can't resume, endpoint id" + @@ -1036,7 +1036,7 @@ public void consume(ConnectionContext context, if (resumingSession && identityAlg != null) { String sessionIdentityAlg = previous.getIdentificationProtocol(); - if (!Objects.equals(identityAlg, sessionIdentityAlg)) { + if (!identityAlg.equalsIgnoreCase(sessionIdentityAlg)) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake,verbose")) { SSLLogger.finest("Can't resume, endpoint id" + diff --git a/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java b/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java index de485e23d89..1f0a957e2f9 100644 --- a/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java +++ b/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java @@ -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 @@ -458,7 +458,7 @@ private static boolean canRejoin(ClientHelloMessage clientHello, String identityAlg = shc.sslConfig.identificationProtocol; if (result && identityAlg != null) { String sessionIdentityAlg = s.getIdentificationProtocol(); - if (!Objects.equals(identityAlg, sessionIdentityAlg)) { + if (!identityAlg.equalsIgnoreCase(sessionIdentityAlg)) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake,verbose")) { From 45e3c68cda3c2e56b9be85214fde94d7ce329246 Mon Sep 17 00:00:00 2001 From: cito Date: Tue, 22 Oct 2019 23:55:33 +0200 Subject: [PATCH 122/131] 8223697: jfr tool can't format duration values greater than 1 minute Reviewed-by: egahlin --- .../jdk/jfr/internal/tool/PrettyWriter.java | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/PrettyWriter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/PrettyWriter.java index 0a4e94325ba..dae86fefef8 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/PrettyWriter.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/PrettyWriter.java @@ -57,6 +57,9 @@ * This class is also used by {@link RecordedObject#toString()} */ public final class PrettyWriter extends EventPrintWriter { + private static final Duration MILLSECOND = Duration.ofMillis(1); + private static final Duration SECOND = Duration.ofSeconds(1); + private static final Duration MINUTE = Duration.ofMinutes(1); private static final String TYPE_OLD_OBJECT = Type.TYPES_PREFIX + "OldObject"; private final static DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("HH:mm:ss.SSS"); private final static Long ZERO = 0L; @@ -548,19 +551,14 @@ private boolean printFormatted(ValueDescriptor field, Object value) { println("N/A"); return true; } - double s = d.toNanosPart() / 1000_000_000.0 + d.toSecondsPart(); - if (s < 1.0) { - if (s < 0.001) { - println(String.format("%.3f", s * 1_000_000) + " us"); - } else { - println(String.format("%.3f", s * 1_000) + " ms"); - } + if(d.compareTo(MILLSECOND) < 0){ + println(String.format("%.3f us", (double)d.toNanos() / 1_000)); + } else if(d.compareTo(SECOND) < 0){ + println(String.format("%.3f ms", (double)d.toNanos() / 1_000_000)); + } else if(d.compareTo(MINUTE) < 0){ + println(String.format("%.3f s", (double)d.toMillis() / 1_000)); } else { - if (s < 1000.0) { - println(String.format("%.3f", s) + " s"); - } else { - println(String.format("%.0f", s) + " s"); - } + println(String.format("%d s", d.toSeconds())); } return true; } From 999ed5d5045a24329daa4c34e2d876559f2e7477 Mon Sep 17 00:00:00 2001 From: ihse Date: Mon, 3 Dec 2018 18:43:24 +0100 Subject: [PATCH 123/131] 8214311: dtrace gensrc has missing dependencies Reviewed-by: tbell, erikj, clanger --- make/Main.gmk | 1 + make/hotspot/gensrc/GensrcDtrace.gmk | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/make/Main.gmk b/make/Main.gmk index f4757f3a946..ce234ef382f 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -637,6 +637,7 @@ else # Declare dependencies between hotspot-* targets $(foreach v, $(JVM_VARIANTS), \ $(eval hotspot-$v: hotspot-$v-gensrc hotspot-$v-libs) \ + $(eval hotspot-$v-gensrc: java.base-copy) \ $(eval hotspot-$v-libs: hotspot-$v-gensrc java.base-copy) \ ) diff --git a/make/hotspot/gensrc/GensrcDtrace.gmk b/make/hotspot/gensrc/GensrcDtrace.gmk index 3a013c71808..9b279e8200c 100644 --- a/make/hotspot/gensrc/GensrcDtrace.gmk +++ b/make/hotspot/gensrc/GensrcDtrace.gmk @@ -64,8 +64,9 @@ ifeq ($(call check-jvm-feature, dtrace), true) include lib/JvmFeatures.gmk include lib/JvmFlags.gmk - # We cannot compile until the JVMTI gensrc has finished + # We cannot compile until the JVMTI and JFR gensrc has finished JVMTI_H := $(JVM_VARIANT_OUTPUTDIR)/gensrc/jvmtifiles/jvmti.h + JFR_FILES := $(JVM_VARIANT_OUTPUTDIR)/gensrc/jfrfiles/jfrEventClasses.hpp $(eval $(call SetupNativeCompilation, BUILD_DTRACE_GEN_OFFSETS, \ NAME := dtraceGenOffsets, \ @@ -74,7 +75,7 @@ ifeq ($(call check-jvm-feature, dtrace), true) TOOLCHAIN := $(TOOLCHAIN_BUILD), \ LDFLAGS := -m64, \ CFLAGS := -m64 $(JVM_CFLAGS), \ - EXTRA_DEPS := $(JVMTI_H), \ + EXTRA_DEPS := $(JVMTI_H) $(JFR_FILES), \ OBJECT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/dtrace-gen-offsets/objs, \ OUTPUT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/dtrace-gen-offsets, \ )) From 50c4e4c4c9fd9d463da85e9dd308f480e5b24ef4 Mon Sep 17 00:00:00 2001 From: gromero Date: Fri, 14 Sep 2018 15:32:22 -0400 Subject: [PATCH 124/131] 8209972: [GRAAL] Don't run RTM tests with Graal Reviewed-by: kvn, goetz --- test/hotspot/jtreg/TEST.ROOT | 2 +- ...kingStatisticsOptionOnSupportedConfig.java | 4 +-- ...ngStatisticsOptionOnUnsupportedConfig.java | 4 +-- .../rtm/cli/TestRTMAbortThresholdOption.java | 2 +- .../TestRTMLockingCalculationDelayOption.java | 2 +- .../cli/TestRTMLockingThresholdOption.java | 2 +- .../rtm/cli/TestRTMRetryCountOption.java | 2 +- .../rtm/cli/TestRTMSpinLoopCountOption.java | 2 +- ...lCountIncrRateOptionOnSupportedConfig.java | 4 +-- ...estUseRTMDeoptOptionOnSupportedConfig.java | 2 +- ...tUseRTMDeoptOptionOnUnsupportedConfig.java | 4 +-- ...MForStackLocksOptionOnSupportedConfig.java | 4 +-- ...orStackLocksOptionOnUnsupportedConfig.java | 4 +-- ...tUseRTMLockingOptionOnSupportedConfig.java | 6 ++-- ...stUseRTMLockingOptionOnUnsupportedCPU.java | 4 +-- ...tUseRTMLockingOptionWithBiasedLocking.java | 4 +-- .../cli/TestUseRTMXendForLockBusyOption.java | 2 +- .../rtm/locking/TestRTMAbortRatio.java | 2 +- .../rtm/locking/TestRTMAbortThreshold.java | 2 +- .../rtm/locking/TestRTMAfterNonRTMDeopt.java | 2 +- .../locking/TestRTMDeoptOnHighAbortRatio.java | 2 +- .../locking/TestRTMDeoptOnLowAbortRatio.java | 2 +- .../TestRTMLockingCalculationDelay.java | 2 +- .../rtm/locking/TestRTMLockingThreshold.java | 2 +- .../rtm/locking/TestRTMRetryCount.java | 2 +- .../rtm/locking/TestRTMSpinLoopCount.java | 2 +- .../locking/TestRTMTotalCountIncrRate.java | 2 +- .../locking/TestUseRTMAfterLockInflation.java | 2 +- .../compiler/rtm/locking/TestUseRTMDeopt.java | 4 +-- .../locking/TestUseRTMForInflatedLocks.java | 2 +- .../rtm/locking/TestUseRTMForStackLocks.java | 2 +- .../locking/TestUseRTMXendForLockBusy.java | 2 +- .../TestNoRTMLockElidingOption.java | 2 +- .../TestUseRTMLockElidingOption.java | 2 +- .../TestPrintPreciseRTMLockingStatistics.java | 2 +- test/jtreg-ext/requires/VMProps.java | 28 ++++++------------- 36 files changed, 55 insertions(+), 65 deletions(-) diff --git a/test/hotspot/jtreg/TEST.ROOT b/test/hotspot/jtreg/TEST.ROOT index 6ec1c0aeec8..d228ea4a221 100644 --- a/test/hotspot/jtreg/TEST.ROOT +++ b/test/hotspot/jtreg/TEST.ROOT @@ -58,7 +58,7 @@ requires.properties= \ vm.hasSAandCanAttach \ vm.hasJFR \ vm.rtm.cpu \ - vm.rtm.os \ + vm.rtm.compiler \ vm.aot \ vm.cds \ vm.cds.custom.loaders \ diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java b/test/hotspot/jtreg/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java index 5a05b5a6b0c..7800fd2ca22 100644 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java +++ b/test/hotspot/jtreg/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java @@ -24,12 +24,12 @@ /** * @test * @bug 8031320 - * @summary Verify PrintPreciseRTMLockingStatistics on CPUs with + * @summary Verify PrintPreciseRTMLockingStatistics on CPUs and OSs with * rtm support and on VM with rtm locking support, * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java b/test/hotspot/jtreg/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java index 76e380c3934..de289f2f108 100644 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java +++ b/test/hotspot/jtreg/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java @@ -24,12 +24,12 @@ /** * @test * @bug 8031320 - * @summary Verify PrintPreciseRTMLockingStatistics on CPUs without + * @summary Verify PrintPreciseRTMLockingStatistics on CPUs or OSs without * rtm support and/or unsupported VM. * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires !(vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os) + * @requires !vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @build compiler.rtm.cli.TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig * @run driver ClassFileInstaller sun.hotspot.WhiteBox diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMAbortThresholdOption.java b/test/hotspot/jtreg/compiler/rtm/cli/TestRTMAbortThresholdOption.java index c314e68dcd7..e6e4893065a 100644 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMAbortThresholdOption.java +++ b/test/hotspot/jtreg/compiler/rtm/cli/TestRTMAbortThresholdOption.java @@ -28,7 +28,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * + * @requires vm.rtm.compiler * @run main/othervm compiler.rtm.cli.TestRTMAbortThresholdOption */ diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMLockingCalculationDelayOption.java b/test/hotspot/jtreg/compiler/rtm/cli/TestRTMLockingCalculationDelayOption.java index d8823501397..119be8b985a 100644 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMLockingCalculationDelayOption.java +++ b/test/hotspot/jtreg/compiler/rtm/cli/TestRTMLockingCalculationDelayOption.java @@ -28,7 +28,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * + * @requires vm.rtm.compiler * @run main/othervm compiler.rtm.cli.TestRTMLockingCalculationDelayOption */ diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMLockingThresholdOption.java b/test/hotspot/jtreg/compiler/rtm/cli/TestRTMLockingThresholdOption.java index 532e61e69b5..a00c408565b 100644 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMLockingThresholdOption.java +++ b/test/hotspot/jtreg/compiler/rtm/cli/TestRTMLockingThresholdOption.java @@ -28,7 +28,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * + * @requires vm.rtm.compiler * @run main/othervm compiler.rtm.cli.TestRTMLockingThresholdOption */ diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMRetryCountOption.java b/test/hotspot/jtreg/compiler/rtm/cli/TestRTMRetryCountOption.java index 8a472ec1bcb..d87f6399f0c 100644 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMRetryCountOption.java +++ b/test/hotspot/jtreg/compiler/rtm/cli/TestRTMRetryCountOption.java @@ -28,7 +28,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * + * @requires vm.rtm.compiler * @run main/othervm compiler.rtm.cli.TestRTMRetryCountOption */ diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMSpinLoopCountOption.java b/test/hotspot/jtreg/compiler/rtm/cli/TestRTMSpinLoopCountOption.java index 15868ff12ed..ddfa4573088 100644 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMSpinLoopCountOption.java +++ b/test/hotspot/jtreg/compiler/rtm/cli/TestRTMSpinLoopCountOption.java @@ -28,7 +28,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * + * @requires vm.rtm.compiler * @run main/othervm compiler.rtm.cli.TestRTMSpinLoopCountOption */ diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnSupportedConfig.java b/test/hotspot/jtreg/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnSupportedConfig.java index 4ceae005539..3d7023f2680 100644 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnSupportedConfig.java +++ b/test/hotspot/jtreg/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnSupportedConfig.java @@ -24,12 +24,12 @@ /** * @test * @bug 8031320 - * @summary Verify RTMTotalCountIncrRate option processing on CPU with + * @summary Verify RTMTotalCountIncrRate option processing on CPU and OS with * rtm support and on VM with rtm locking support. * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java index 3f66ab39568..44467ceac56 100644 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java +++ b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java @@ -29,7 +29,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java index da1a207d16c..37035712e4e 100644 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java +++ b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java @@ -24,12 +24,12 @@ /** * @test * @bug 8031320 - * @summary Verify UseRTMDeopt option processing on CPUs without rtm support + * @summary Verify UseRTMDeopt option processing on CPUs or OSs without rtm support * or on VMs without rtm locking support. * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires !(vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os) + * @requires !vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java index f52d8561db5..2d232cb11ed 100644 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java +++ b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java @@ -24,12 +24,12 @@ /** * @test * @bug 8031320 - * @summary Verify UseRTMForStackLocks option processing on CPU with + * @summary Verify UseRTMForStackLocks option processing on CPU and OS with * rtm support when VM supports rtm locking. * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java index 49bfdb0ba7f..16c29d78e1d 100644 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java +++ b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java @@ -24,12 +24,12 @@ /** * @test * @bug 8031320 - * @summary Verify UseRTMForStackLocks option processing on CPUs without + * @summary Verify UseRTMForStackLocks option processing on CPUs or OSs without * rtm support and/or on VMs without rtm locking support. * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires !(vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os) + * @requires !vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java index 7ed1c3de26a..54fd18d938d 100644 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java +++ b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java @@ -24,12 +24,12 @@ /** * @test * @bug 8031320 - * @summary Verify UseRTMLocking option processing on CPU with rtm support and - * on VM with rtm-locking support. + * @summary Verify UseRTMLocking option processing on CPU and OS with rtm support and + * on VM with rtm locking support. * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java index f45c8cda89e..d6c45b6c42e 100644 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java +++ b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java @@ -24,12 +24,12 @@ /** * @test * @bug 8031320 - * @summary Verify UseRTMLocking option processing on CPU without + * @summary Verify UseRTMLocking option processing on CPUs without * rtm support. * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires (!vm.rtm.cpu) & (vm.flavor == "server" & !vm.emulatedClient) + * @requires !vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java index f133ccc405b..8fe96a19825 100644 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java +++ b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java @@ -25,11 +25,11 @@ * @test * @bug 8031320 * @summary Verify processing of UseRTMLocking and UseBiasedLocking - * options combination on CPU and VM with rtm support. + * options combination on CPU, OS, and VM with rtm support. * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMXendForLockBusyOption.java b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMXendForLockBusyOption.java index bf94689be6c..49a5ca169db 100644 --- a/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMXendForLockBusyOption.java +++ b/test/hotspot/jtreg/compiler/rtm/cli/TestUseRTMXendForLockBusyOption.java @@ -28,7 +28,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * + * @requires vm.rtm.compiler * @run main/othervm compiler.rtm.cli.TestUseRTMXendForLockBusyOption */ diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMAbortRatio.java b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMAbortRatio.java index 3613d5c4cf8..5ce08feb258 100644 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMAbortRatio.java +++ b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMAbortRatio.java @@ -29,7 +29,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMAbortThreshold.java b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMAbortThreshold.java index 98bc11256b5..b42abe13f20 100644 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMAbortThreshold.java +++ b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMAbortThreshold.java @@ -29,7 +29,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java index ba0a1ef6d44..8677e1b9277 100644 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java +++ b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java @@ -31,7 +31,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java index 677456fae08..494381e1046 100644 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java +++ b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java @@ -29,7 +29,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java index 402ead2a640..48ebead642e 100644 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java +++ b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java @@ -28,7 +28,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMLockingCalculationDelay.java b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMLockingCalculationDelay.java index 25cf21ff64d..8c81a4e0451 100644 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMLockingCalculationDelay.java +++ b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMLockingCalculationDelay.java @@ -29,7 +29,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMLockingThreshold.java b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMLockingThreshold.java index 65fc9eecea9..7bdb62eab9b 100644 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMLockingThreshold.java +++ b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMLockingThreshold.java @@ -29,7 +29,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMRetryCount.java b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMRetryCount.java index ae492d76c76..a1a80e13e3d 100644 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMRetryCount.java +++ b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMRetryCount.java @@ -28,7 +28,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMSpinLoopCount.java b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMSpinLoopCount.java index 3f641e0f7e9..13119a24c78 100644 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMSpinLoopCount.java +++ b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMSpinLoopCount.java @@ -29,7 +29,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMTotalCountIncrRate.java b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMTotalCountIncrRate.java index 2712bc4dd1e..fdb2933b749 100644 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestRTMTotalCountIncrRate.java +++ b/test/hotspot/jtreg/compiler/rtm/locking/TestRTMTotalCountIncrRate.java @@ -29,7 +29,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMAfterLockInflation.java b/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMAfterLockInflation.java index 0d92cfee490..2cdc91c1f99 100644 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMAfterLockInflation.java +++ b/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMAfterLockInflation.java @@ -29,7 +29,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMDeopt.java b/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMDeopt.java index 294def6b37a..0a4cd460a8a 100644 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMDeopt.java +++ b/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMDeopt.java @@ -25,11 +25,11 @@ * @test * @bug 8031320 * @summary Verify that UseRTMDeopt affects uncommon trap installation in - * copmpiled methods with synchronized block. + * compiled methods with synchronized block. * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMForInflatedLocks.java b/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMForInflatedLocks.java index d76c8cf820f..0acb6e9dcc7 100644 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMForInflatedLocks.java +++ b/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMForInflatedLocks.java @@ -28,7 +28,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMForStackLocks.java b/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMForStackLocks.java index 77c55d04b2c..be8c391f207 100644 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMForStackLocks.java +++ b/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMForStackLocks.java @@ -28,7 +28,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMXendForLockBusy.java b/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMXendForLockBusy.java index 0f2a1da6dc3..74265f96ebb 100644 --- a/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMXendForLockBusy.java +++ b/test/hotspot/jtreg/compiler/rtm/locking/TestUseRTMXendForLockBusy.java @@ -29,7 +29,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/method_options/TestNoRTMLockElidingOption.java b/test/hotspot/jtreg/compiler/rtm/method_options/TestNoRTMLockElidingOption.java index 2a3cdf97961..e6243fcedff 100644 --- a/test/hotspot/jtreg/compiler/rtm/method_options/TestNoRTMLockElidingOption.java +++ b/test/hotspot/jtreg/compiler/rtm/method_options/TestNoRTMLockElidingOption.java @@ -29,7 +29,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/method_options/TestUseRTMLockElidingOption.java b/test/hotspot/jtreg/compiler/rtm/method_options/TestUseRTMLockElidingOption.java index 71aae8d167c..2537b2082f5 100644 --- a/test/hotspot/jtreg/compiler/rtm/method_options/TestUseRTMLockElidingOption.java +++ b/test/hotspot/jtreg/compiler/rtm/method_options/TestUseRTMLockElidingOption.java @@ -30,7 +30,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/hotspot/jtreg/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java b/test/hotspot/jtreg/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java index 8c6a11b76f8..16663ac5116 100644 --- a/test/hotspot/jtreg/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java +++ b/test/hotspot/jtreg/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java @@ -31,7 +31,7 @@ * @library /test/lib / * @modules java.base/jdk.internal.misc * java.management - * @requires vm.flavor == "server" & !vm.emulatedClient & vm.rtm.cpu & vm.rtm.os + * @requires vm.rtm.cpu & vm.rtm.compiler * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java index 103444e0165..84d5a559ddb 100644 --- a/test/jtreg-ext/requires/VMProps.java +++ b/test/jtreg-ext/requires/VMProps.java @@ -85,7 +85,7 @@ public Map call() { map.put("vm.hasJFR", vmHasJFR()); map.put("vm.cpu.features", cpuFeatures()); map.put("vm.rtm.cpu", vmRTMCPU()); - map.put("vm.rtm.os", vmRTMOS()); + map.put("vm.rtm.compiler", vmRTMCompiler()); map.put("vm.aot", vmAOT()); // vm.cds is true if the VM is compiled with cds support. map.put("vm.cds", vmCDS()); @@ -132,8 +132,6 @@ else if (arch.contains("86")) { } } - - /** * @return VM type value extracted from the "java.vm.name" property. */ @@ -317,24 +315,16 @@ protected String vmHasJFR() { } /** - * @return true if VM runs RTM supported OS and false otherwise. + * @return true if compiler in use supports RTM and false otherwise. */ - protected String vmRTMOS() { - boolean isRTMOS = true; - - if (Platform.isAix()) { - // Actually, this works since AIX 7.1.3.30, but os.version property - // is set to 7.1. - isRTMOS = (Platform.getOsVersionMajor() > 7) || - (Platform.getOsVersionMajor() == 7 && Platform.getOsVersionMinor() > 1); - - } else if (Platform.isLinux()) { - if (Platform.isPPC()) { - isRTMOS = (Platform.getOsVersionMajor() > 4) || - (Platform.getOsVersionMajor() == 4 && Platform.getOsVersionMinor() > 1); - } + protected String vmRTMCompiler() { + boolean isRTMCompiler = false; + + if (Compiler.isC2Enabled() && + (Platform.isX86() || Platform.isX64() || Platform.isPPC())) { + isRTMCompiler = true; } - return "" + isRTMOS; + return "" + isRTMCompiler; } /** From d5871c94dd08732140645f309c1feae1ed1c173b Mon Sep 17 00:00:00 2001 From: prr Date: Wed, 30 Oct 2019 15:57:15 +0100 Subject: [PATCH 125/131] 8212071: Need to set the FreeType LCD Filter to reduce fringing. Reviewed-by: prr, lbourges Contributed-by: John Neffenger --- src/java.desktop/share/native/libfontmanager/freetypeScaler.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c index b94430e2d11..e61a4e7de0a 100644 --- a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c +++ b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c @@ -41,6 +41,7 @@ #include FT_SIZES_H #include FT_OUTLINE_H #include FT_SYNTHESIS_H +#include FT_LCD_FILTER_H #include FT_MODULE_H #include "fontscaler.h" @@ -490,6 +491,8 @@ static int setupFTContext(JNIEnv *env, if (errCode == 0) { errCode = FT_Activate_Size(scalerInfo->face->size); } + + FT_Library_SetLcdFilter(scalerInfo->library, FT_LCD_FILTER_DEFAULT); } return errCode; From df424ce532c3e1d95ad421a2a52da40deecc3c45 Mon Sep 17 00:00:00 2001 From: dtitov Date: Thu, 28 Mar 2019 04:30:52 +0000 Subject: [PATCH 126/131] 8221532: Incorrect copyright header in FileSystemSupport_md.c Reviewed-by: cjplummer, gadams --- .../unix/native/libinstrument/FileSystemSupport_md.c | 2 +- .../windows/native/libinstrument/FileSystemSupport_md.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.instrument/unix/native/libinstrument/FileSystemSupport_md.c b/src/java.instrument/unix/native/libinstrument/FileSystemSupport_md.c index 4740a7f7f0f..84ff5863333 100644 --- a/src/java.instrument/unix/native/libinstrument/FileSystemSupport_md.c +++ b/src/java.instrument/unix/native/libinstrument/FileSystemSupport_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 diff --git a/src/java.instrument/windows/native/libinstrument/FileSystemSupport_md.c b/src/java.instrument/windows/native/libinstrument/FileSystemSupport_md.c index f1900675ccf..c93b7b6342f 100644 --- a/src/java.instrument/windows/native/libinstrument/FileSystemSupport_md.c +++ b/src/java.instrument/windows/native/libinstrument/FileSystemSupport_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 From 4eebcd7ae1866ef226dc38e931b27882058f69f3 Mon Sep 17 00:00:00 2001 From: gadams Date: Tue, 12 Mar 2019 11:53:06 -0400 Subject: [PATCH 127/131] 8220474: Incorrect GPL header in src/java.instrument/share/classes/java/lang/instrument/package-info.java Reviewed-by: dholmes --- .../share/classes/java/lang/instrument/package-info.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.instrument/share/classes/java/lang/instrument/package-info.java b/src/java.instrument/share/classes/java/lang/instrument/package-info.java index 9519bf21948..550d3b7b64c 100644 --- a/src/java.instrument/share/classes/java/lang/instrument/package-info.java +++ b/src/java.instrument/share/classes/java/lang/instrument/package-info.java @@ -5,7 +5,7 @@ * 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 + * 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 From 09d55316f097da72ce78e5e9bb07ade782fcae7a Mon Sep 17 00:00:00 2001 From: bobv Date: Fri, 8 Mar 2019 16:21:16 -0500 Subject: [PATCH 128/131] 8220476: Incorrect GPL header in src/jdk.internal.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/protocol/local/PerfDataFile.java Reviewed-by: lancea --- .../jvmstat/perfdata/monitor/protocol/local/PerfDataFile.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jdk.internal.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/protocol/local/PerfDataFile.java b/src/jdk.internal.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/protocol/local/PerfDataFile.java index b40e67ee931..3f7b5917999 100644 --- a/src/jdk.internal.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/protocol/local/PerfDataFile.java +++ b/src/jdk.internal.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/protocol/local/PerfDataFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 From 4945c43473bfe8bdd9419e7776dee926dd7ce4bf Mon Sep 17 00:00:00 2001 From: mbalao Date: Wed, 5 Jun 2019 01:42:11 -0300 Subject: [PATCH 129/131] 8215032: Support Kerberos cross-realm referrals (RFC 6806) Reviewed-by: weijun --- .../share/conf/security/java.security | 25 ++ .../auth/kerberos/KerberosPrincipal.java | 7 +- .../classes/sun/security/krb5/Checksum.java | 4 +- .../classes/sun/security/krb5/Config.java | 38 ++- .../classes/sun/security/krb5/KrbAsRep.java | 6 +- .../classes/sun/security/krb5/KrbAsReq.java | 15 +- .../sun/security/krb5/KrbAsReqBuilder.java | 82 ++++++- .../classes/sun/security/krb5/KrbKdcRep.java | 66 +++++- .../classes/sun/security/krb5/KrbTgsRep.java | 4 +- .../classes/sun/security/krb5/KrbTgsReq.java | 90 +++---- .../sun/security/krb5/PrincipalName.java | 8 +- .../krb5/internal/CredentialsUtil.java | 219 +++++++++++++----- .../security/krb5/internal/EncASRepPart.java | 4 +- .../security/krb5/internal/EncKDCRepPart.java | 73 +++--- .../security/krb5/internal/EncTGSRepPart.java | 4 +- .../security/krb5/internal/KDCOptions.java | 4 +- .../sun/security/krb5/internal/KDCReq.java | 20 +- .../sun/security/krb5/internal/KRBError.java | 20 +- .../sun/security/krb5/internal/Krb5.java | 7 +- .../sun/security/krb5/internal/PAData.java | 39 +++- .../krb5/internal/ReferralsCache.java | 137 +++++++++++ .../security/krb5/internal/TicketFlags.java | 6 +- .../krb5/internal/crypto/KeyUsage.java | 3 +- test/jdk/sun/security/krb5/auto/KDC.java | 87 ++++++- .../sun/security/krb5/auto/ReferralsTest.java | 169 ++++++++++++++ 25 files changed, 933 insertions(+), 204 deletions(-) create mode 100644 src/java.security.jgss/share/classes/sun/security/krb5/internal/ReferralsCache.java create mode 100644 test/jdk/sun/security/krb5/auto/ReferralsTest.java diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security index e4afe9e3ceb..dd261418787 100644 --- a/src/java.base/share/conf/security/java.security +++ b/src/java.base/share/conf/security/java.security @@ -474,6 +474,31 @@ networkaddress.cache.negative.ttl=10 # krb5.kdc.bad.policy = tryLast +# +# Kerberos cross-realm referrals (RFC 6806) +# +# OpenJDK's Kerberos client supports cross-realm referrals as defined in +# RFC 6806. This allows to setup more dynamic environments in which clients +# do not need to know in advance how to reach the realm of a target principal +# (either a user or service). +# +# When a client issues an AS or a TGS request, the "canonicalize" option +# is set to announce support of this feature. A KDC server may fulfill the +# request or reply referring the client to a different one. If referred, +# the client will issue a new request and the cycle repeats. +# +# In addition to referrals, the "canonicalize" option allows the KDC server +# to change the client name in response to an AS request. For security reasons, +# RFC 6806 (section 11) FAST scheme is enforced. +# +# Disable Kerberos cross-realm referrals. Value may be overwritten with a +# System property (-Dsun.security.krb5.disableReferrals). +sun.security.krb5.disableReferrals=false + +# Maximum number of AS or TGS referrals to avoid infinite loops. Value may +# be overwritten with a System property (-Dsun.security.krb5.maxReferrals). +sun.security.krb5.maxReferrals=5 + # # Algorithm restrictions for certification path (CertPath) processing # diff --git a/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosPrincipal.java b/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosPrincipal.java index edfce9f13dc..dcdbce3c506 100644 --- a/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosPrincipal.java +++ b/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosPrincipal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -80,6 +80,11 @@ public final class KerberosPrincipal public static final int KRB_NT_UID = 5; + /** + * Enterprise name (alias) + */ + public static final int KRB_NT_ENTERPRISE = 10; + private transient String fullName; private transient String realm; diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/Checksum.java b/src/java.security.jgss/share/classes/sun/security/krb5/Checksum.java index 027b125d9fd..687ff3d79b4 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/Checksum.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/Checksum.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -218,7 +218,7 @@ boolean isEqual(Checksum cksum) throws KdcErrException { * @exception IOException if an I/O error occurs while reading encoded data. * */ - private Checksum(DerValue encoding) throws Asn1Exception, IOException { + public Checksum(DerValue encoding) throws Asn1Exception, IOException { DerValue der; if (encoding.getTag() != DerValue.tag_Sequence) { throw new Asn1Exception(Krb5.ASN1_BAD_ID); diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/Config.java b/src/java.security.jgss/share/classes/sun/security/krb5/Config.java index 05fcb63345a..f3fda25767b 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/Config.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/Config.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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,7 @@ import sun.net.dns.ResolverConfiguration; import sun.security.krb5.internal.crypto.EType; import sun.security.krb5.internal.Krb5; +import sun.security.util.SecurityProperties; /** * This class maintains key-value pairs of Kerberos configurable constants @@ -55,6 +56,41 @@ public class Config { + /** + * {@systemProperty sun.security.krb5.disableReferrals} property + * indicating whether or not cross-realm referrals (RFC 6806) are + * enabled. + */ + public static final boolean DISABLE_REFERRALS; + + /** + * {@systemProperty sun.security.krb5.maxReferrals} property + * indicating the maximum number of cross-realm referral + * hops allowed. + */ + public static final int MAX_REFERRALS; + + static { + String disableReferralsProp = + SecurityProperties.privilegedGetOverridable( + "sun.security.krb5.disableReferrals"); + if (disableReferralsProp != null) { + DISABLE_REFERRALS = "true".equalsIgnoreCase(disableReferralsProp); + } else { + DISABLE_REFERRALS = false; + } + + int maxReferralsValue = 5; + String maxReferralsProp = + SecurityProperties.privilegedGetOverridable( + "sun.security.krb5.maxReferrals"); + try { + maxReferralsValue = Integer.parseInt(maxReferralsProp); + } catch (NumberFormatException e) { + } + MAX_REFERRALS = maxReferralsValue; + } + /* * Only allow a single instance of Config. */ diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/KrbAsRep.java b/src/java.security.jgss/share/classes/sun/security/krb5/KrbAsRep.java index 1d5febdf41d..d647b82ab16 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/KrbAsRep.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/KrbAsRep.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -155,11 +155,11 @@ private void decrypt(EncryptionKey dkey, KrbAsReq asReq) rep.encKDCRepPart = enc_part; ASReq req = asReq.getMessage(); - check(true, req, rep); + check(true, req, rep, dkey); creds = new Credentials( rep.ticket, - req.reqBody.cname, + rep.cname, enc_part.sname, enc_part.key, enc_part.flags, diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/KrbAsReq.java b/src/java.security.jgss/share/classes/sun/security/krb5/KrbAsReq.java index 01fdb9bbb33..19e3ef61076 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/KrbAsReq.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/KrbAsReq.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ import sun.security.krb5.internal.crypto.KeyUsage; import java.io.IOException; import java.time.Instant; +import java.util.Arrays; /** * This class encapsulates the KRB-AS-REQ message that the client @@ -58,7 +59,8 @@ public KrbAsReq(EncryptionKey pakey, // ok KerberosTime till, // ok, will use KerberosTime rtime, // ok int[] eTypes, // NO - HostAddresses addresses // ok + HostAddresses addresses, // ok + PAData[] extraPAs // ok ) throws KrbException, IOException { @@ -93,6 +95,15 @@ public KrbAsReq(EncryptionKey pakey, // ok paData[0] = new PAData( Krb5.PA_ENC_TIMESTAMP, encTs.asn1Encode()); } + if (extraPAs != null && extraPAs.length > 0) { + if (paData == null) { + paData = new PAData[extraPAs.length]; + } else { + paData = Arrays.copyOf(paData, paData.length + extraPAs.length); + } + System.arraycopy(extraPAs, 0, paData, + paData.length - extraPAs.length, extraPAs.length); + } if (cname.getRealm() == null) { throw new RealmException(Krb5.REALM_NULL, diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/KrbAsReqBuilder.java b/src/java.security.jgss/share/classes/sun/security/krb5/KrbAsReqBuilder.java index 953bb557041..5c434b54efa 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/KrbAsReqBuilder.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/KrbAsReqBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -262,7 +262,9 @@ public void setAddresses(HostAddresses addresses) { * @throws KrbException * @throws IOException */ - private KrbAsReq build(EncryptionKey key) throws KrbException, IOException { + private KrbAsReq build(EncryptionKey key, ReferralsState referralsState) + throws KrbException, IOException { + PAData[] extraPAs = null; int[] eTypes; if (password != null) { eTypes = EType.getDefaults("default_tkt_enctypes"); @@ -272,6 +274,14 @@ private KrbAsReq build(EncryptionKey key) throws KrbException, IOException { ks); for (EncryptionKey k: ks) k.destroy(); } + options = (options == null) ? new KDCOptions() : options; + if (referralsState.isEnabled()) { + options.set(KDCOptions.CANONICALIZE, true); + extraPAs = new PAData[]{ new PAData(Krb5.PA_REQ_ENC_PA_REP, + new byte[]{}) }; + } else { + options.set(KDCOptions.CANONICALIZE, false); + } return new KrbAsReq(key, options, cname, @@ -280,7 +290,8 @@ private KrbAsReq build(EncryptionKey key) throws KrbException, IOException { till, rtime, eTypes, - addresses); + addresses, + extraPAs); } /** @@ -318,11 +329,15 @@ private KrbAsReqBuilder resolve() */ private KrbAsReqBuilder send() throws KrbException, IOException { boolean preAuthFailedOnce = false; - KdcComm comm = new KdcComm(cname.getRealmAsString()); + KdcComm comm = null; EncryptionKey pakey = null; + ReferralsState referralsState = new ReferralsState(); while (true) { + if (referralsState.refreshComm()) { + comm = new KdcComm(cname.getRealmAsString()); + } try { - req = build(pakey); + req = build(pakey, referralsState); rep = new KrbAsRep(comm.send(req.encoding())); return this; } catch (KrbException ke) { @@ -351,12 +366,69 @@ private KrbAsReqBuilder send() throws KrbException, IOException { } paList = kerr.getPA(); // Update current paList } else { + if (referralsState.handleError(ke)) { + continue; + } throw ke; } } } } + private final class ReferralsState { + private boolean enabled; + private int count; + private boolean refreshComm; + + ReferralsState() throws KrbException { + if (Config.DISABLE_REFERRALS) { + if (cname.getNameType() == PrincipalName.KRB_NT_ENTERPRISE) { + throw new KrbException("NT-ENTERPRISE principals only allowed" + + " when referrals are enabled."); + } + enabled = false; + } else { + enabled = true; + } + refreshComm = true; + } + + boolean handleError(KrbException ke) throws RealmException { + if (enabled) { + if (ke.returnCode() == Krb5.KRB_ERR_WRONG_REALM) { + Realm referredRealm = ke.getError().getClientRealm(); + if (req.getMessage().reqBody.kdcOptions.get(KDCOptions.CANONICALIZE) && + referredRealm != null && referredRealm.toString().length() > 0 && + count < Config.MAX_REFERRALS) { + cname = new PrincipalName(cname.getNameType(), + cname.getNameStrings(), referredRealm); + refreshComm = true; + count++; + return true; + } + } + if (count < Config.MAX_REFERRALS && + cname.getNameType() != PrincipalName.KRB_NT_ENTERPRISE) { + // Server may raise an error if CANONICALIZE is true. + // Try CANONICALIZE false. + enabled = false; + return true; + } + } + return false; + } + + boolean refreshComm() { + boolean retRefreshComm = refreshComm; + refreshComm = false; + return retRefreshComm; + } + + boolean isEnabled() { + return enabled; + } + } + /** * Performs AS-REQ send and AS-REP receive. * Maybe a state is needed here, to divide prepare process and getCreds. diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/KrbKdcRep.java b/src/java.security.jgss/share/classes/sun/security/krb5/KrbKdcRep.java index c4a04b1d86c..4f91c2ef3ef 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/KrbKdcRep.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/KrbKdcRep.java @@ -31,23 +31,41 @@ package sun.security.krb5; import sun.security.krb5.internal.*; +import sun.security.krb5.internal.crypto.KeyUsage; +import sun.security.util.DerInputStream; abstract class KrbKdcRep { static void check( boolean isAsReq, KDCReq req, - KDCRep rep + KDCRep rep, + EncryptionKey replyKey ) throws KrbApErrException { - if (isAsReq && !req.reqBody.cname.equals(rep.cname)) { + // cname change in AS-REP is allowed only if the client + // sent CANONICALIZE and the server supports RFC 6806 - Section 11 + // FAST scheme (ENC-PA-REP flag). + if (isAsReq && !req.reqBody.cname.equals(rep.cname) && + (!req.reqBody.kdcOptions.get(KDCOptions.CANONICALIZE) || + !rep.encKDCRepPart.flags.get(Krb5.TKT_OPTS_ENC_PA_REP))) { rep.encKDCRepPart.key.destroy(); throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED); } + // sname change in TGS-REP is allowed only if client + // sent CANONICALIZE and new sname is a referral of + // the form krbtgt/TO-REALM.COM@FROM-REALM.COM. if (!req.reqBody.sname.equals(rep.encKDCRepPart.sname)) { - rep.encKDCRepPart.key.destroy(); - throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED); + String[] snameStrings = rep.encKDCRepPart.sname.getNameStrings(); + if (isAsReq || !req.reqBody.kdcOptions.get(KDCOptions.CANONICALIZE) || + snameStrings == null || snameStrings.length != 2 || + !snameStrings[0].equals(PrincipalName.TGS_DEFAULT_SRV_NAME) || + !rep.encKDCRepPart.sname.getRealmString().equals( + req.reqBody.sname.getRealmString())) { + rep.encKDCRepPart.key.destroy(); + throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED); + } } if (req.reqBody.getNonce() != rep.encKDCRepPart.nonce) { @@ -118,5 +136,45 @@ static void check( } } } + + // RFC 6806 - Section 11 mechanism check + if (rep.encKDCRepPart.flags.get(Krb5.TKT_OPTS_ENC_PA_REP) && + req.reqBody.kdcOptions.get(KDCOptions.CANONICALIZE)) { + boolean reqPaReqEncPaRep = false; + boolean repPaReqEncPaRepValid = false; + + // PA_REQ_ENC_PA_REP only required for AS requests + for (PAData pa : req.pAData) { + if (pa.getType() == Krb5.PA_REQ_ENC_PA_REP) { + reqPaReqEncPaRep = true; + break; + } + } + + if (rep.encKDCRepPart.pAData != null) { + for (PAData pa : rep.encKDCRepPart.pAData) { + if (pa.getType() == Krb5.PA_REQ_ENC_PA_REP) { + try { + Checksum repCksum = new Checksum( + new DerInputStream( + pa.getValue()).getDerValue()); + repPaReqEncPaRepValid = + repCksum.verifyKeyedChecksum( + req.asn1Encode(), replyKey, + KeyUsage.KU_AS_REQ); + } catch (Exception e) { + if (Krb5.DEBUG) { + e.printStackTrace(); + } + } + break; + } + } + } + + if (reqPaReqEncPaRep && !repPaReqEncPaRepValid) { + throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED); + } + } } } diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/KrbTgsRep.java b/src/java.security.jgss/share/classes/sun/security/krb5/KrbTgsRep.java index c0e6ef8f0fe..d1f469d37ab 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/KrbTgsRep.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/KrbTgsRep.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -84,7 +84,7 @@ public class KrbTgsRep extends KrbKdcRep { EncTGSRepPart enc_part = new EncTGSRepPart(ref); rep.encKDCRepPart = enc_part; - check(false, req, rep); + check(false, req, rep, tgsReq.tgsReqKey); this.creds = new Credentials(rep.ticket, rep.cname, diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/KrbTgsReq.java b/src/java.security.jgss/share/classes/sun/security/krb5/KrbTgsReq.java index 191eb8cd592..02d14a9e39f 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/KrbTgsReq.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/KrbTgsReq.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ import java.io.IOException; import java.net.UnknownHostException; import java.time.Instant; +import java.util.Arrays; /** * This class encapsulates a Kerberos TGS-REQ that is sent from the @@ -57,59 +58,23 @@ public class KrbTgsReq { private byte[] ibuf; // Used in CredentialsUtil - public KrbTgsReq(Credentials asCreds, - PrincipalName sname) + public KrbTgsReq(KDCOptions options, Credentials asCreds, + PrincipalName cname, PrincipalName sname, + Ticket[] additionalTickets, PAData[] extraPAs) throws KrbException, IOException { - this(new KDCOptions(), - asCreds, - sname, - null, // KerberosTime from - null, // KerberosTime till - null, // KerberosTime rtime - null, // eTypes, // null, // int[] eTypes - null, // HostAddresses addresses - null, // AuthorizationData authorizationData - null, // Ticket[] additionalTickets - null); // EncryptionKey subSessionKey - } - - // S4U2proxy - public KrbTgsReq(Credentials asCreds, - Ticket second, - PrincipalName sname) - throws KrbException, IOException { - this(KDCOptions.with(KDCOptions.CNAME_IN_ADDL_TKT, - KDCOptions.FORWARDABLE), - asCreds, - sname, - null, - null, - null, - null, - null, - null, - new Ticket[] {second}, // the service ticket - null); - } - - // S4U2user - public KrbTgsReq(Credentials asCreds, - PrincipalName sname, - PAData extraPA) - throws KrbException, IOException { - this(KDCOptions.with(KDCOptions.FORWARDABLE), - asCreds, - asCreds.getClient(), - sname, - null, - null, - null, - null, - null, - null, - null, - null, - extraPA); // the PA-FOR-USER + this(options, + asCreds, + cname, + sname, + null, // KerberosTime from + null, // KerberosTime till + null, // KerberosTime rtime + null, // int[] eTypes + null, // HostAddresses addresses + null, // AuthorizationData authorizationData + additionalTickets, + null, // EncryptionKey subKey + extraPAs); } // Called by Credentials, KrbCred @@ -143,7 +108,7 @@ private KrbTgsReq( AuthorizationData authorizationData, Ticket[] additionalTickets, EncryptionKey subKey, - PAData extraPA) throws KrbException, IOException { + PAData[] extraPAs) throws KrbException, IOException { princName = cname; servName = sname; @@ -216,7 +181,7 @@ private KrbTgsReq( authorizationData, additionalTickets, subKey, - extraPA); + extraPAs); obuf = tgsReqMessg.asn1Encode(); // XXX We need to revisit this to see if can't move it @@ -282,7 +247,7 @@ private TGSReq createRequest( AuthorizationData authorizationData, Ticket[] additionalTickets, EncryptionKey subKey, - PAData extraPA) + PAData[] extraPAs) throws IOException, KrbException, UnknownHostException { KerberosTime req_till = null; if (till == null) { @@ -382,11 +347,14 @@ private TGSReq createRequest( null).getMessage(); PAData tgsPAData = new PAData(Krb5.PA_TGS_REQ, tgs_ap_req); - return new TGSReq( - extraPA != null ? - new PAData[] {extraPA, tgsPAData } : - new PAData[] {tgsPAData}, - reqBody); + PAData[] pa; + if (extraPAs != null) { + pa = Arrays.copyOf(extraPAs, extraPAs.length + 1); + pa[extraPAs.length] = tgsPAData; + } else { + pa = new PAData[] {tgsPAData}; + } + return new TGSReq(pa, reqBody); } TGSReq getMessage() { diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/PrincipalName.java b/src/java.security.jgss/share/classes/sun/security/krb5/PrincipalName.java index b3a0e8bea38..577c5e4633e 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/PrincipalName.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/PrincipalName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -90,6 +90,11 @@ public class PrincipalName implements Cloneable { */ public static final int KRB_NT_UID = 5; + /** + * Enterprise name (alias) + */ + public static final int KRB_NT_ENTERPRISE = 10; + /** * TGS Name */ @@ -454,6 +459,7 @@ public PrincipalName(String name, int type, String realm) case KRB_NT_SRV_INST: case KRB_NT_SRV_XHST: case KRB_NT_UID: + case KRB_NT_ENTERPRISE: nameStrings = nameParts; nameType = type; if (realm != null) { diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/CredentialsUtil.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/CredentialsUtil.java index 14620e94483..25e29387a2f 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/CredentialsUtil.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/CredentialsUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, 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 @@ -33,6 +33,8 @@ import sun.security.krb5.*; import java.io.IOException; +import java.util.LinkedList; +import java.util.List; /** * This class is a utility that contains much of the TGS-Exchange @@ -61,13 +63,11 @@ public static Credentials acquireS4U2selfCreds(PrincipalName client, if (!ccreds.isForwardable()) { throw new KrbException("S4U2self needs a FORWARDABLE ticket"); } - KrbTgsReq req = new KrbTgsReq( - ccreds, - ccreds.getClient(), - new PAData(Krb5.PA_FOR_USER, - new PAForUserEnc(client, - ccreds.getSessionKey()).asn1Encode())); - Credentials creds = req.sendAndGetCreds(); + Credentials creds = serviceCreds(KDCOptions.with(KDCOptions.FORWARDABLE), + ccreds, ccreds.getClient(), ccreds.getClient(), null, + new PAData[] {new PAData(Krb5.PA_FOR_USER, + new PAForUserEnc(client, + ccreds.getSessionKey()).asn1Encode())}); if (!creds.getClient().equals(client)) { throw new KrbException("S4U2self request not honored by KDC"); } @@ -89,11 +89,10 @@ public static Credentials acquireS4U2proxyCreds( String backend, Ticket second, PrincipalName client, Credentials ccreds) throws KrbException, IOException { - KrbTgsReq req = new KrbTgsReq( - ccreds, - second, - new PrincipalName(backend)); - Credentials creds = req.sendAndGetCreds(); + Credentials creds = serviceCreds(KDCOptions.with( + KDCOptions.CNAME_IN_ADDL_TKT, KDCOptions.FORWARDABLE), + ccreds, ccreds.getClient(), new PrincipalName(backend), + new Ticket[] {second}, null); if (!creds.getClient().equals(client)) { throw new KrbException("S4U2proxy request not honored by KDC"); } @@ -114,53 +113,9 @@ public static Credentials acquireS4U2proxyCreds( public static Credentials acquireServiceCreds( String service, Credentials ccreds) throws KrbException, IOException { - PrincipalName sname = new PrincipalName(service); - String serviceRealm = sname.getRealmString(); - String localRealm = ccreds.getClient().getRealmString(); - - if (localRealm.equals(serviceRealm)) { - if (DEBUG) { - System.out.println( - ">>> Credentials acquireServiceCreds: same realm"); - } - return serviceCreds(sname, ccreds); - } - Credentials theCreds = null; - - boolean[] okAsDelegate = new boolean[1]; - Credentials theTgt = getTGTforRealm(localRealm, serviceRealm, - ccreds, okAsDelegate); - if (theTgt != null) { - if (DEBUG) { - System.out.println(">>> Credentials acquireServiceCreds: " - + "got right tgt"); - System.out.println(">>> Credentials acquireServiceCreds: " - + "obtaining service creds for " + sname); - } - - try { - theCreds = serviceCreds(sname, theTgt); - } catch (Exception exc) { - if (DEBUG) { - System.out.println(exc); - } - theCreds = null; - } - } - - if (theCreds != null) { - if (DEBUG) { - System.out.println(">>> Credentials acquireServiceCreds: " - + "returning creds:"); - Credentials.printDebug(theCreds); - } - if (!okAsDelegate[0]) { - theCreds.resetDelegate(); - } - return theCreds; - } - throw new KrbApErrException(Krb5.KRB_AP_ERR_GEN_CRED, - "No service creds"); + PrincipalName sname = new PrincipalName(service, + PrincipalName.KRB_NT_SRV_HST); + return serviceCreds(sname, ccreds); } /** @@ -305,6 +260,148 @@ private static Credentials getTGTforRealm(String localRealm, private static Credentials serviceCreds( PrincipalName service, Credentials ccreds) throws KrbException, IOException { - return new KrbTgsReq(ccreds, service).sendAndGetCreds(); + return serviceCreds(new KDCOptions(), ccreds, + ccreds.getClient(), service, null, null); + } + + /* + * Obtains credentials for a service (TGS). + * Cross-realm referrals are handled if enabled. A fallback scheme + * without cross-realm referrals supports is used in case of server + * error to maintain backward compatibility. + */ + private static Credentials serviceCreds( + KDCOptions options, Credentials asCreds, + PrincipalName cname, PrincipalName sname, + Ticket[] additionalTickets, PAData[] extraPAs) + throws KrbException, IOException { + if (!Config.DISABLE_REFERRALS) { + try { + return serviceCredsReferrals(options, asCreds, + cname, sname, additionalTickets, extraPAs); + } catch (KrbException e) { + // Server may raise an error if CANONICALIZE is true. + // Try CANONICALIZE false. + } + } + return serviceCredsSingle(options, asCreds, + cname, sname, additionalTickets, extraPAs); + } + + /* + * Obtains credentials for a service (TGS). + * May handle and follow cross-realm referrals as defined by RFC 6806. + */ + private static Credentials serviceCredsReferrals( + KDCOptions options, Credentials asCreds, + PrincipalName cname, PrincipalName sname, + Ticket[] additionalTickets, PAData[] extraPAs) + throws KrbException, IOException { + options = new KDCOptions(options.toBooleanArray()); + options.set(KDCOptions.CANONICALIZE, true); + PrincipalName cSname = sname; + Credentials creds = null; + boolean isReferral = false; + List referrals = new LinkedList<>(); + while (referrals.size() <= Config.MAX_REFERRALS) { + ReferralsCache.ReferralCacheEntry ref = + ReferralsCache.get(sname, cSname.getRealmString()); + String toRealm = null; + if (ref == null) { + creds = serviceCredsSingle(options, asCreds, + cname, cSname, additionalTickets, extraPAs); + PrincipalName server = creds.getServer(); + if (!cSname.equals(server)) { + String[] serverNameStrings = server.getNameStrings(); + if (serverNameStrings.length == 2 && + serverNameStrings[0].equals( + PrincipalName.TGS_DEFAULT_SRV_NAME) && + !cSname.getRealmAsString().equals(serverNameStrings[1])) { + // Server Name (sname) has the following format: + // krbtgt/TO-REALM.COM@FROM-REALM.COM + ReferralsCache.put(sname, server.getRealmString(), + serverNameStrings[1], creds); + toRealm = serverNameStrings[1]; + isReferral = true; + asCreds = creds; + } + } + } else { + toRealm = ref.getToRealm(); + asCreds = ref.getCreds(); + isReferral = true; + } + if (isReferral) { + if (referrals.contains(toRealm)) { + // Referrals loop detected + return null; + } + cSname = new PrincipalName(cSname.getNameString(), + cSname.getNameType(), toRealm); + referrals.add(toRealm); + isReferral = false; + continue; + } + break; + } + return creds; + } + + /* + * Obtains credentials for a service (TGS). + * If the service realm is different than the one in the TGT, a new TGT for + * the service realm is obtained first (see getTGTforRealm call). This is + * not expected when following cross-realm referrals because the referral + * TGT realm matches the service realm. + */ + private static Credentials serviceCredsSingle( + KDCOptions options, Credentials asCreds, + PrincipalName cname, PrincipalName sname, + Ticket[] additionalTickets, PAData[] extraPAs) + throws KrbException, IOException { + Credentials theCreds = null; + boolean[] okAsDelegate = new boolean[]{true}; + String[] serverAsCredsNames = asCreds.getServer().getNameStrings(); + String tgtRealm = serverAsCredsNames[1]; + String serviceRealm = sname.getRealmString(); + if (!serviceRealm.equals(tgtRealm)) { + // This is a cross-realm service request + if (DEBUG) { + System.out.println(">>> serviceCredsSingle:" + + " cross-realm authentication"); + System.out.println(">>> serviceCredsSingle:" + + " obtaining credentials from " + tgtRealm + + " to " + serviceRealm); + } + Credentials newTgt = getTGTforRealm(tgtRealm, serviceRealm, + asCreds, okAsDelegate); + if (newTgt == null) { + throw new KrbApErrException(Krb5.KRB_AP_ERR_GEN_CRED, + "No service creds"); + } + if (DEBUG) { + System.out.println(">>> Cross-realm TGT Credentials" + + " serviceCredsSingle: "); + Credentials.printDebug(newTgt); + } + asCreds = newTgt; + cname = asCreds.getClient(); + } else if (DEBUG) { + System.out.println(">>> Credentials serviceCredsSingle:" + + " same realm"); + } + KrbTgsReq req = new KrbTgsReq(options, asCreds, + cname, sname, additionalTickets, extraPAs); + theCreds = req.sendAndGetCreds(); + if (theCreds != null) { + if (DEBUG) { + System.out.println(">>> TGS credentials serviceCredsSingle:"); + Credentials.printDebug(theCreds); + } + if (!okAsDelegate[0]) { + theCreds.resetDelegate(); + } + } + return theCreds; } } diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/EncASRepPart.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/EncASRepPart.java index 7e5d037de5d..ff9382e83f4 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/EncASRepPart.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/EncASRepPart.java @@ -47,7 +47,8 @@ public EncASRepPart( KerberosTime new_endtime, KerberosTime new_renewTill, PrincipalName new_sname, - HostAddresses new_caddr) { + HostAddresses new_caddr, + PAData[] new_pAData) { super( new_key, new_lastReq, @@ -60,6 +61,7 @@ public EncASRepPart( new_renewTill, new_sname, new_caddr, + new_pAData, Krb5.KRB_ENC_AS_REP_PART ); //may need to use Krb5.KRB_ENC_TGS_REP_PART to mimic diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/EncKDCRepPart.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/EncKDCRepPart.java index 19d26b725db..9db87e27bfb 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/EncKDCRepPart.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/EncKDCRepPart.java @@ -31,7 +31,6 @@ package sun.security.krb5.internal; import sun.security.krb5.*; -import sun.security.krb5.EncryptionKey; import sun.security.util.*; import java.util.Vector; import java.io.IOException; @@ -41,19 +40,20 @@ * Implements the ASN.1 EncKDCRepPart type. * *

{@code
- * EncKDCRepPart        ::= SEQUENCE {
- *      key             [0] EncryptionKey,
- *      last-req        [1] LastReq,
- *      nonce           [2] UInt32,
- *      key-expiration  [3] KerberosTime OPTIONAL,
- *      flags           [4] TicketFlags,
- *      authtime        [5] KerberosTime,
- *      starttime       [6] KerberosTime OPTIONAL,
- *      endtime         [7] KerberosTime,
- *      renew-till      [8] KerberosTime OPTIONAL,
- *      srealm          [9] Realm,
- *      sname           [10] PrincipalName,
- *      caddr           [11] HostAddresses OPTIONAL
+ * EncKDCRepPart          ::= SEQUENCE {
+ *      key               [0] EncryptionKey,
+ *      last-req          [1] LastReq,
+ *      nonce             [2] UInt32,
+ *      key-expiration    [3] KerberosTime OPTIONAL,
+ *      flags             [4] TicketFlags,
+ *      authtime          [5] KerberosTime,
+ *      starttime         [6] KerberosTime OPTIONAL,
+ *      endtime           [7] KerberosTime,
+ *      renew-till        [8] KerberosTime OPTIONAL,
+ *      srealm            [9] Realm,
+ *      sname             [10] PrincipalName,
+ *      caddr             [11] HostAddresses OPTIONAL,
+ *      encrypted-pa-data [12] SEQUENCE OF PA-DATA OPTIONAL
  * }
  * }
* @@ -76,6 +76,7 @@ public class EncKDCRepPart { public KerberosTime renewTill; //optional public PrincipalName sname; public HostAddresses caddr; //optional + public PAData[] pAData; //optional public int msgType; //not included in sequence public EncKDCRepPart( @@ -90,6 +91,7 @@ public EncKDCRepPart( KerberosTime new_renewTill, PrincipalName new_sname, HostAddresses new_caddr, + PAData[] new_pAData, int new_msgType) { key = new_key; lastReq = new_lastReq; @@ -102,6 +104,7 @@ public EncKDCRepPart( renewTill = new_renewTill; sname = new_sname; caddr = new_caddr; + pAData = new_pAData; msgType = new_msgType; } @@ -160,6 +163,9 @@ protected void init(DerValue encoding, int rep_type) if (der.getData().available() > 0) { caddr = HostAddresses.parse(der.getData(), (byte) 0x0B, true); } + if (der.getData().available() > 0) { + pAData = PAData.parseSequence(der.getData(), (byte) 0x0C, true); + } // We observe extra data from MSAD /*if (der.getData().available() > 0) { throw new Asn1Exception(Krb5.ASN1_BAD_ID); @@ -175,47 +181,58 @@ protected void init(DerValue encoding, int rep_type) */ public byte[] asn1Encode(int rep_type) throws Asn1Exception, IOException { + DerOutputStream bytes; DerOutputStream temp = new DerOutputStream(); - DerOutputStream bytes = new DerOutputStream(); - bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, + DerOutputStream out = new DerOutputStream(); + out.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x00), key.asn1Encode()); - bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, + out.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x01), lastReq.asn1Encode()); temp.putInteger(BigInteger.valueOf(nonce)); - bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, + out.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x02), temp); if (keyExpiration != null) { - bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, + out.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x03), keyExpiration.asn1Encode()); } - bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, + out.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x04), flags.asn1Encode()); - bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, + out.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x05), authtime.asn1Encode()); if (starttime != null) { - bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, + out.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x06), starttime.asn1Encode()); } - bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, + out.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x07), endtime.asn1Encode()); if (renewTill != null) { - bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, + out.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x08), renewTill.asn1Encode()); } - bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, + out.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x09), sname.getRealm().asn1Encode()); - bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, + out.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x0A), sname.asn1Encode()); if (caddr != null) { - bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, + out.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x0B), caddr.asn1Encode()); } + if (pAData != null && pAData.length > 0) { + temp = new DerOutputStream(); + for (int i = 0; i < pAData.length; i++) { + temp.write(pAData[i].asn1Encode()); + } + bytes = new DerOutputStream(); + bytes.write(DerValue.tag_SequenceOf, temp); + out.write(DerValue.createTag(DerValue.TAG_CONTEXT, + true, (byte) 0x0C), bytes); + } //should use the rep_type to build the encoding //but other implementations do not; it is ignored and //the cached msgType is used instead temp = new DerOutputStream(); - temp.write(DerValue.tag_Sequence, bytes); + temp.write(DerValue.tag_Sequence, out); bytes = new DerOutputStream(); bytes.write(DerValue.createTag(DerValue.TAG_APPLICATION, true, (byte) msgType), temp); diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/EncTGSRepPart.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/EncTGSRepPart.java index cdca881ebe4..b1f192e72e4 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/EncTGSRepPart.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/EncTGSRepPart.java @@ -46,7 +46,8 @@ public EncTGSRepPart( KerberosTime new_endtime, KerberosTime new_renewTill, PrincipalName new_sname, - HostAddresses new_caddr) { + HostAddresses new_caddr, + PAData[] new_pAData) { super( new_key, new_lastReq, @@ -59,6 +60,7 @@ public EncTGSRepPart( new_renewTill, new_sname, new_caddr, + new_pAData, Krb5.KRB_ENC_TGS_REP_PART); } diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/KDCOptions.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/KDCOptions.java index 7cd666390f8..76a71cb603c 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/KDCOptions.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/KDCOptions.java @@ -140,6 +140,7 @@ public class KDCOptions extends KerberosFlags { public static final int UNUSED10 = 10; public static final int UNUSED11 = 11; public static final int CNAME_IN_ADDL_TKT = 14; + public static final int CANONICALIZE = 15; public static final int RENEWABLE_OK = 27; public static final int ENC_TKT_IN_SKEY = 28; public static final int RENEW = 30; @@ -160,7 +161,8 @@ public class KDCOptions extends KerberosFlags { "UNUSED11", //11; null,null, "CNAME_IN_ADDL_TKT",//14; - null,null,null,null,null,null,null,null,null,null,null,null, + "CANONICALIZE", //15; + null,null,null,null,null,null,null,null,null,null,null, "RENEWABLE_OK", //27; "ENC_TKT_IN_SKEY", //28; null, diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/KDCReq.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/KDCReq.java index 1aeab385e6e..39e226a8de2 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/KDCReq.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/KDCReq.java @@ -59,9 +59,9 @@ public class KDCReq { public KDCReqBody reqBody; + public PAData[] pAData = null; //optional private int pvno; private int msgType; - private PAData[] pAData = null; //optional public KDCReq(PAData[] new_pAData, KDCReqBody new_reqBody, int req_type) throws IOException { @@ -144,23 +144,7 @@ protected void init(DerValue encoding, int req_type) throws Asn1Exception, } else { throw new Asn1Exception(Krb5.ASN1_BAD_ID); } - if ((der.getData().peekByte() & 0x1F) == 0x03) { - subDer = der.getData().getDerValue(); - DerValue subsubDer = subDer.getData().getDerValue(); - if (subsubDer.getTag() != DerValue.tag_SequenceOf) { - throw new Asn1Exception(Krb5.ASN1_BAD_ID); - } - Vector v = new Vector<>(); - while (subsubDer.getData().available() > 0) { - v.addElement(new PAData(subsubDer.getData().getDerValue())); - } - if (v.size() > 0) { - pAData = new PAData[v.size()]; - v.copyInto(pAData); - } - } else { - pAData = null; - } + pAData = PAData.parseSequence(der.getData(), (byte) 0x03, true); subDer = der.getData().getDerValue(); if ((subDer.getTag() & 0x01F) == 0x04) { DerValue subsubDer = subDer.getData().getDerValue(); diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/KRBError.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/KRBError.java index 2a885e4f591..ba43305fccb 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/KRBError.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/KRBError.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -90,6 +90,7 @@ public class KRBError implements java.io.Serializable { private KerberosTime sTime; private Integer suSec; private int errorCode; + private Realm crealm; //optional private PrincipalName cname; //optional private PrincipalName sname; private String eText; //optional @@ -138,6 +139,7 @@ public KRBError( sTime = new_sTime; suSec = new_suSec; errorCode = new_errorCode; + crealm = new_cname.getRealm(); cname = new_cname; sname = new_sname; eText = new_eText; @@ -166,6 +168,7 @@ public KRBError( sTime = new_sTime; suSec = new_suSec; errorCode = new_errorCode; + crealm = new_cname.getRealm(); cname = new_cname; sname = new_sname; eText = new_eText; @@ -262,6 +265,10 @@ private void parsePAData(byte[] data) pa = paList.toArray(new PAData[paList.size()]); } + public final Realm getClientRealm() { + return crealm; + } + public final KerberosTime getServerTime() { return sTime; } @@ -349,7 +356,7 @@ private void init(DerValue encoding) throws Asn1Exception, errorCode = subDer.getData().getBigInteger().intValue(); } else throw new Asn1Exception(Krb5.ASN1_BAD_ID); - Realm crealm = Realm.parse(der.getData(), (byte)0x07, true); + crealm = Realm.parse(der.getData(), (byte)0x07, true); cname = PrincipalName.parse(der.getData(), (byte)0x08, true, crealm); Realm realm = Realm.parse(der.getData(), (byte)0x09, false); sname = PrincipalName.parse(der.getData(), (byte)0x0A, false, realm); @@ -393,6 +400,9 @@ private void showDebug() { System.out.println("\t suSec is " + suSec); System.out.println("\t error code is " + errorCode); System.out.println("\t error Message is " + Krb5.getErrorMessage(errorCode)); + if (crealm != null) { + System.out.println("\t crealm is " + crealm.toString()); + } if (cname != null) { System.out.println("\t cname is " + cname.toString()); } @@ -442,8 +452,10 @@ public byte[] asn1Encode() throws Asn1Exception, IOException { temp.putInteger(BigInteger.valueOf(errorCode)); bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x06), temp); + if (crealm != null) { + bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x07), crealm.asn1Encode()); + } if (cname != null) { - bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x07), cname.getRealm().asn1Encode()); bytes.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x08), cname.asn1Encode()); } @@ -488,6 +500,7 @@ public byte[] asn1Encode() throws Asn1Exception, IOException { isEqual(sTime, other.sTime) && isEqual(suSec, other.suSec) && errorCode == other.errorCode && + isEqual(crealm, other.crealm) && isEqual(cname, other.cname) && isEqual(sname, other.sname) && isEqual(eText, other.eText) && @@ -508,6 +521,7 @@ private static boolean isEqual(Object a, Object b) { if (sTime != null) result = 37 * result + sTime.hashCode(); if (suSec != null) result = 37 * result + suSec.hashCode(); result = 37 * result + errorCode; + if (crealm != null) result = 37 * result + crealm.hashCode(); if (cname != null) result = 37 * result + cname.hashCode(); if (sname != null) result = 37 * result + sname.hashCode(); if (eText != null) result = 37 * result + eText.hashCode(); diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/Krb5.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/Krb5.java index 0b9a12240a8..87861883b57 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/Krb5.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/Krb5.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -70,6 +70,7 @@ public class Krb5 { public static final int TKT_OPTS_PRE_AUTHENT = 10; public static final int TKT_OPTS_HW_AUTHENT = 11; public static final int TKT_OPTS_DELEGATE = 13; + public static final int TKT_OPTS_ENC_PA_REP = 15; public static final int TKT_OPTS_MAX = 31; // KDC Options @@ -163,6 +164,9 @@ public class Krb5 { // S4U2user info public static final int PA_FOR_USER = 129; + // FAST (RFC 6806) + public static final int PA_REQ_ENC_PA_REP = 149; + //-------------------------------+------------- //authorization data type |ad-type value //-------------------------------+------------- @@ -265,6 +269,7 @@ public class Krb5 { public static final int KRB_ERR_RESPONSE_TOO_BIG = 52; //Response too big for UDP, retry with TCP public static final int KRB_ERR_GENERIC = 60; //Generic error (description in e-text) public static final int KRB_ERR_FIELD_TOOLONG = 61; //Field is too long for this implementation + public static final int KRB_ERR_WRONG_REALM = 68; //Wrong realm public static final int KRB_CRYPTO_NOT_SUPPORT = 100; //Client does not support this crypto type public static final int KRB_AP_ERR_NOREALM = 62; public static final int KRB_AP_ERR_GEN_CRED = 63; diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/PAData.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/PAData.java index 55bc6f26220..830e1929b5e 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/PAData.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/PAData.java @@ -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 @@ -35,6 +35,8 @@ import sun.security.util.*; import sun.security.krb5.Asn1Exception; import java.io.IOException; +import java.util.Vector; + import sun.security.krb5.internal.util.KerberosString; /** @@ -139,6 +141,41 @@ public byte[] getValue() { return ((pADataValue == null) ? null : pADataValue.clone()); } + /** + * Parse (unmarshal) a PAData from a DER input stream. This form + * parsing might be used when expanding a value which is part of + * a constructed sequence and uses explicitly tagged type. + * + * @exception Asn1Exception if an Asn1Exception occurs. + * @param data the Der input stream value, which contains one or more + * marshaled values. + * @param explicitTag tag number. + * @param optional indicates if this data field is optional. + * @return an array of PAData. + */ + public static PAData[] parseSequence(DerInputStream data, + byte explicitTag, boolean optional) + throws Asn1Exception, IOException { + if ((optional) && + (((byte)data.peekByte() & (byte)0x1F) != explicitTag)) + return null; + DerValue subDer = data.getDerValue(); + DerValue subsubDer = subDer.getData().getDerValue(); + if (subsubDer.getTag() != DerValue.tag_SequenceOf) { + throw new Asn1Exception(Krb5.ASN1_BAD_ID); + } + Vector v = new Vector<>(); + while (subsubDer.getData().available() > 0) { + v.addElement(new PAData(subsubDer.getData().getDerValue())); + } + if (v.size() > 0) { + PAData[] pas = new PAData[v.size()]; + v.copyInto(pas); + return pas; + } + return null; + } + /** * Gets the preferred etype from the PAData array. *
    diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/ReferralsCache.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/ReferralsCache.java new file mode 100644 index 00000000000..d2118160005 --- /dev/null +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/ReferralsCache.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2019, Red Hat, Inc. + * 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. + */ + +package sun.security.krb5.internal; + +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import sun.security.krb5.Credentials; +import sun.security.krb5.PrincipalName; + +/* + * ReferralsCache class implements a cache scheme for referral TGTs as + * described in RFC 6806 - 10. Caching Information. The goal is to optimize + * resources (such as network traffic) when a client requests credentials for a + * service principal to a given KDC. If a referral TGT was previously received, + * cached information is used instead of issuing a new query. Once a referral + * TGT expires, the corresponding referral entry in the cache is removed. + */ +final class ReferralsCache { + + private static Map> referralsMap = + new HashMap<>(); + + static final class ReferralCacheEntry { + private final Credentials creds; + private final String toRealm; + ReferralCacheEntry(Credentials creds, String toRealm) { + this.creds = creds; + this.toRealm = toRealm; + } + Credentials getCreds() { + return creds; + } + String getToRealm() { + return toRealm; + } + } + + /* + * Add a new referral entry to the cache, including: service principal, + * source KDC realm, destination KDC realm and referral TGT. + * + * If a loop is generated when adding the new referral, the first hop is + * automatically removed. For example, let's assume that adding a + * REALM-3.COM -> REALM-1.COM referral generates the following loop: + * REALM-1.COM -> REALM-2.COM -> REALM-3.COM -> REALM-1.COM. Then, + * REALM-1.COM -> REALM-2.COM referral entry is removed from the cache. + */ + static synchronized void put(PrincipalName service, + String fromRealm, String toRealm, Credentials creds) { + pruneExpired(service); + if (creds.getEndTime().before(new Date())) { + return; + } + Map entries = referralsMap.get(service); + if (entries == null) { + entries = new HashMap(); + referralsMap.put(service, entries); + } + entries.remove(fromRealm); + ReferralCacheEntry newEntry = new ReferralCacheEntry(creds, toRealm); + entries.put(fromRealm, newEntry); + + // Remove loops within the cache + ReferralCacheEntry current = newEntry; + List seen = new LinkedList<>(); + while (current != null) { + if (seen.contains(current)) { + // Loop found. Remove the first referral to cut the loop. + entries.remove(newEntry.getToRealm()); + break; + } + seen.add(current); + current = entries.get(current.getToRealm()); + } + } + + /* + * Obtain a referral entry from the cache given a service principal and a + * source KDC realm. + */ + static synchronized ReferralCacheEntry get(PrincipalName service, + String fromRealm) { + pruneExpired(service); + Map entries = referralsMap.get(service); + if (entries != null) { + ReferralCacheEntry toRef = entries.get(fromRealm); + if (toRef != null) { + return toRef; + } + } + return null; + } + + /* + * Remove referral entries from the cache when referral TGTs expire. + */ + private static void pruneExpired(PrincipalName service) { + Date now = new Date(); + Map entries = referralsMap.get(service); + if (entries != null) { + for (Entry mapEntry : + entries.entrySet()) { + if (mapEntry.getValue().getCreds().getEndTime().before(now)) { + entries.remove(mapEntry.getKey()); + } + } + } + } +} diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/TicketFlags.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/TicketFlags.java index 48961fac317..468796ae27c 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/TicketFlags.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/TicketFlags.java @@ -51,7 +51,8 @@ * renewable(8), * initial(9), * pre-authent(10), - * hw-authent(11) + * hw-authent(11), + * enc-pa-rep(15) * } */ public class TicketFlags extends KerberosFlags { @@ -178,6 +179,9 @@ public String toString() { case 11: sb.append("HW-AUTHENT;"); break; + case 15: + sb.append("ENC-PA-REP;"); + break; } } } diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/KeyUsage.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/KeyUsage.java index f9be46c9beb..5179f520024 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/KeyUsage.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/KeyUsage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2012, 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 @@ -56,6 +56,7 @@ private KeyUsage() { public static final int KU_KRB_SAFE_CKSUM = 15; // KrbSafe public static final int KU_PA_FOR_USER_ENC_CKSUM = 17; // S4U2user public static final int KU_AD_KDC_ISSUED_CKSUM = 19; + public static final int KU_AS_REQ = 56; public static final boolean isValid(int usage) { return usage >= 0; diff --git a/test/jdk/sun/security/krb5/auto/KDC.java b/test/jdk/sun/security/krb5/auto/KDC.java index 4868fac67ba..3465f3ac45f 100644 --- a/test/jdk/sun/security/krb5/auto/KDC.java +++ b/test/jdk/sun/security/krb5/auto/KDC.java @@ -163,6 +163,14 @@ public class KDC { private TreeMap s2kparamses = new TreeMap<> (String.CASE_INSENSITIVE_ORDER); + // Alias for referrals. + private TreeMap aliasReferrals = new TreeMap<> + (String.CASE_INSENSITIVE_ORDER); + + // Alias for local resolution. + private TreeMap alias2Principals = new TreeMap<> + (String.CASE_INSENSITIVE_ORDER); + // Realm name private String realm; // KDC @@ -551,6 +559,29 @@ public int getPort() { return port; } + /** + * Register an alias name to be referred to a different KDC for + * resolution, according to RFC 6806. + * @param alias Alias name (i.e. user@REALM.COM). + * @param referredKDC KDC to which the alias is referred for resolution. + */ + public void registerAlias(String alias, KDC referredKDC) { + aliasReferrals.remove(alias); + aliasReferrals.put(alias, referredKDC); + } + + /** + * Register an alias to be resolved to a Principal Name locally, + * according to RFC 6806. + * @param alias Alias name (i.e. user@REALM.COM). + * @param user Principal Name to which the alias is resolved. + */ + public void registerAlias(String alias, String user) + throws RealmException { + alias2Principals.remove(alias); + alias2Principals.put(alias, new PrincipalName(user)); + } + // Private helper methods /** @@ -776,6 +807,17 @@ protected byte[] processTgsReq(byte[] in) throws Exception { PrincipalName cname = null; boolean allowForwardable = true; + if (body.kdcOptions.get(KDCOptions.CANONICALIZE)) { + KDC referral = aliasReferrals.get(body.sname.getNameString()); + if (referral != null) { + service = new PrincipalName( + PrincipalName.TGS_DEFAULT_SRV_NAME + + PrincipalName.NAME_COMPONENT_SEPARATOR_STR + + referral.getRealm(), PrincipalName.KRB_NT_SRV_INST, + this.getRealm()); + } + } + if (pas == null || pas.length == 0) { throw new KrbException(Krb5.KDC_ERR_PADATA_TYPE_NOSUPP); } else { @@ -962,7 +1004,8 @@ protected byte[] processTgsReq(byte[] in) throws Exception { from, till, renewTill, service, - body.addresses + body.addresses, + null ); EncryptedData edata = new EncryptedData(ckey, enc_part.asn1Encode(), KeyUsage.KU_ENC_TGS_REP_PART_SESSKEY); @@ -1006,6 +1049,7 @@ protected byte[] processTgsReq(byte[] in) throws Exception { */ protected byte[] processAsReq(byte[] in) throws Exception { ASReq asReq = new ASReq(in); + byte[] asReqbytes = asReq.asn1Encode(); int[] eTypes = null; List outPAs = new ArrayList<>(); @@ -1028,6 +1072,24 @@ protected byte[] processAsReq(byte[] in) throws Exception { } int eType = eTypes[0]; + if (body.kdcOptions.get(KDCOptions.CANONICALIZE) && + body.cname.getNameType() == PrincipalName.KRB_NT_ENTERPRISE) { + PrincipalName principal = alias2Principals.get( + body.cname.getNameString()); + if (principal != null) { + body.cname = principal; + } else { + KDC referral = aliasReferrals.get(body.cname.getNameString()); + if (referral != null) { + body.cname = new PrincipalName( + PrincipalName.TGS_DEFAULT_SRV_NAME, + PrincipalName.KRB_NT_SRV_INST, + referral.getRealm()); + throw new KrbException(Krb5.KRB_ERR_WRONG_REALM); + } + } + } + EncryptionKey ckey = keyForUser(body.cname, eType, false); EncryptionKey skey = keyForUser(service, eType, true); @@ -1209,17 +1271,18 @@ protected byte[] processAsReq(byte[] in) throws Exception { } PAData[] inPAs = KDCReqDotPAData(asReq); + List enc_outPAs = new ArrayList<>(); if (inPAs == null || inPAs.length == 0) { Object preauth = options.get(Option.PREAUTH_REQUIRED); if (preauth == null || preauth.equals(Boolean.TRUE)) { throw new KrbException(Krb5.KDC_ERR_PREAUTH_REQUIRED); } } else { + EncryptionKey pakey = null; try { EncryptedData data = newEncryptedData( new DerValue(inPAs[0].getValue())); - EncryptionKey pakey - = keyForUser(body.cname, data.getEType(), false); + pakey = keyForUser(body.cname, data.getEType(), false); data.decrypt(pakey, KeyUsage.KU_PA_ENC_TS); } catch (Exception e) { KrbException ke = new KrbException(Krb5.KDC_ERR_PREAUTH_FAILED); @@ -1227,6 +1290,17 @@ protected byte[] processAsReq(byte[] in) throws Exception { throw ke; } bFlags[Krb5.TKT_OPTS_PRE_AUTHENT] = true; + for (PAData pa : inPAs) { + if (pa.getType() == Krb5.PA_REQ_ENC_PA_REP) { + Checksum ckSum = new Checksum( + Checksum.CKSUMTYPE_HMAC_SHA1_96_AES128, + asReqbytes, ckey, KeyUsage.KU_AS_REQ); + enc_outPAs.add(new PAData(Krb5.PA_REQ_ENC_PA_REP, + ckSum.asn1Encode())); + bFlags[Krb5.TKT_OPTS_ENC_PA_REP] = true; + break; + } + } } TicketFlags tFlags = new TicketFlags(bFlags); @@ -1257,7 +1331,8 @@ protected byte[] processAsReq(byte[] in) throws Exception { from, till, rtime, service, - body.addresses + body.addresses, + enc_outPAs.toArray(new PAData[enc_outPAs.size()]) ); EncryptedData edata = new EncryptedData(ckey, enc_part.asn1Encode(), KeyUsage.KU_ENC_AS_REP_PART); @@ -1305,8 +1380,10 @@ protected byte[] processAsReq(byte[] in) throws Exception { if (kerr == null) { if (ke.returnCode() == Krb5.KDC_ERR_PREAUTH_REQUIRED || ke.returnCode() == Krb5.KDC_ERR_PREAUTH_FAILED) { + outPAs.add(new PAData(Krb5.PA_ENC_TIMESTAMP, new byte[0])); + } + if (outPAs.size() > 0) { DerOutputStream bytes = new DerOutputStream(); - bytes.write(new PAData(Krb5.PA_ENC_TIMESTAMP, new byte[0]).asn1Encode()); for (PAData p: outPAs) { bytes.write(p.asn1Encode()); } diff --git a/test/jdk/sun/security/krb5/auto/ReferralsTest.java b/test/jdk/sun/security/krb5/auto/ReferralsTest.java new file mode 100644 index 00000000000..81455229c4a --- /dev/null +++ b/test/jdk/sun/security/krb5/auto/ReferralsTest.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2019, Red Hat, Inc. + * 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 8215032 + * @library /test/lib + * @run main/othervm/timeout=120 -Dsun.security.krb5.debug=true ReferralsTest + * @summary Test Kerberos cross-realm referrals (RFC 6806) + */ + +import java.io.File; +import sun.security.krb5.Credentials; +import sun.security.krb5.internal.CredentialsUtil; +import sun.security.krb5.KrbAsReqBuilder; +import sun.security.krb5.PrincipalName; + +public class ReferralsTest { + private static final boolean DEBUG = true; + private static final String krbConfigName = "krb5-localkdc.conf"; + private static final String realmKDC1 = "RABBIT.HOLE"; + private static final String realmKDC2 = "DEV.RABBIT.HOLE"; + private static final char[] password = "123qwe@Z".toCharArray(); + private static final String clientName = "test"; + + private static final String clientAlias = clientName + + PrincipalName.NAME_REALM_SEPARATOR_STR + realmKDC1; + + private static final String clientKDC1QueryName = clientAlias.replaceAll( + PrincipalName.NAME_REALM_SEPARATOR_STR, "\\\\" + + PrincipalName.NAME_REALM_SEPARATOR_STR) + + PrincipalName.NAME_REALM_SEPARATOR_STR + realmKDC1; + private static PrincipalName clientKDC1QueryPrincipal = null; + static { + try { + clientKDC1QueryPrincipal = new PrincipalName( + clientKDC1QueryName, PrincipalName.KRB_NT_ENTERPRISE, + null); + } catch (Throwable t) {} + } + + private static final String clientKDC2Name = clientName + + PrincipalName.NAME_REALM_SEPARATOR_STR + realmKDC2; + + private static final String serviceName = "http" + + PrincipalName.NAME_COMPONENT_SEPARATOR_STR + + "server.dev.rabbit.hole"; + + private static Credentials tgt; + private static Credentials tgs; + + public static void main(String[] args) throws Exception { + try { + initializeKDCs(); + getTGT(); + getTGS(); + } finally { + cleanup(); + } + } + + private static void initializeKDCs() throws Exception { + KDC kdc1 = KDC.create(realmKDC1, "localhost", 0, true); + kdc1.addPrincipalRandKey(PrincipalName.TGS_DEFAULT_SRV_NAME + + PrincipalName.NAME_COMPONENT_SEPARATOR_STR + realmKDC1); + kdc1.addPrincipal(PrincipalName.TGS_DEFAULT_SRV_NAME + + PrincipalName.NAME_COMPONENT_SEPARATOR_STR + realmKDC1 + + PrincipalName.NAME_REALM_SEPARATOR_STR + realmKDC2, + password); + kdc1.addPrincipal(PrincipalName.TGS_DEFAULT_SRV_NAME + + PrincipalName.NAME_COMPONENT_SEPARATOR_STR + realmKDC2, + password); + + KDC kdc2 = KDC.create(realmKDC2, "localhost", 0, true); + kdc2.addPrincipalRandKey(PrincipalName.TGS_DEFAULT_SRV_NAME + + PrincipalName.NAME_COMPONENT_SEPARATOR_STR + realmKDC2); + kdc2.addPrincipal(clientKDC2Name, password); + kdc2.addPrincipal(serviceName, password); + kdc2.addPrincipal(PrincipalName.TGS_DEFAULT_SRV_NAME + + PrincipalName.NAME_COMPONENT_SEPARATOR_STR + realmKDC1, + password); + kdc2.addPrincipal(PrincipalName.TGS_DEFAULT_SRV_NAME + + PrincipalName.NAME_COMPONENT_SEPARATOR_STR + realmKDC2 + + PrincipalName.NAME_REALM_SEPARATOR_STR + realmKDC1, + password); + + kdc1.registerAlias(clientAlias, kdc2); + kdc1.registerAlias(serviceName, kdc2); + kdc2.registerAlias(clientAlias, clientKDC2Name); + + KDC.saveConfig(krbConfigName, kdc1, kdc2, + "forwardable=true"); + System.setProperty("java.security.krb5.conf", krbConfigName); + } + + private static void cleanup() { + File f = new File(krbConfigName); + if (f.exists()) { + f.delete(); + } + } + + private static void getTGT() throws Exception { + KrbAsReqBuilder builder = new KrbAsReqBuilder(clientKDC1QueryPrincipal, + password); + tgt = builder.action().getCreds(); + builder.destroy(); + if (DEBUG) { + System.out.println("TGT"); + System.out.println("----------------------"); + System.out.println(tgt); + System.out.println("----------------------"); + } + if (tgt == null) { + throw new Exception("TGT is null"); + } + if (!tgt.getClient().getName().equals(clientKDC2Name)) { + throw new Exception("Unexpected TGT client"); + } + String[] tgtServerNames = tgt.getServer().getNameStrings(); + if (tgtServerNames.length != 2 || !tgtServerNames[0].equals( + PrincipalName.TGS_DEFAULT_SRV_NAME) || + !tgtServerNames[1].equals(realmKDC2) || + !tgt.getServer().getRealmString().equals(realmKDC2)) { + throw new Exception("Unexpected TGT server"); + } + } + + private static void getTGS() throws Exception { + tgs = CredentialsUtil.acquireServiceCreds(serviceName + + PrincipalName.NAME_REALM_SEPARATOR_STR + realmKDC1, tgt); + if (DEBUG) { + System.out.println("TGS"); + System.out.println("----------------------"); + System.out.println(tgs); + System.out.println("----------------------"); + } + if (tgs == null) { + throw new Exception("TGS is null"); + } + if (!tgs.getClient().getName().equals(clientKDC2Name)) { + throw new Exception("Unexpected TGS client"); + } + if (!tgs.getServer().getNameString().equals(serviceName) || + !tgs.getServer().getRealmString().equals(realmKDC2)) { + throw new Exception("Unexpected TGS server"); + } + } +} From 60fd404e2d6328c99650843ac7d3f9ac1b53cbea Mon Sep 17 00:00:00 2001 From: roland Date: Tue, 1 Oct 2019 10:28:12 +0200 Subject: [PATCH 130/131] 8231620: assert(bol->is_Bool()) crash during split if due to FastLockNode Reviewed-by: vlivanov, thartmann --- .../SplitIfSharedFastLockBehindCastPP.java | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/loopopts/SplitIfSharedFastLockBehindCastPP.java diff --git a/test/hotspot/jtreg/compiler/loopopts/SplitIfSharedFastLockBehindCastPP.java b/test/hotspot/jtreg/compiler/loopopts/SplitIfSharedFastLockBehindCastPP.java new file mode 100644 index 00000000000..628a5a4cb75 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/SplitIfSharedFastLockBehindCastPP.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2019, Red Hat, 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. + * + * 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 8231620 + * @summary assert(bol->is_Bool()) crash during split if due to FastLockNode + * + * @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement SplitIfSharedFastLockBehindCastPP + */ + + +public class SplitIfSharedFastLockBehindCastPP { + private static boolean field; + private static A obj_field; + + public static void main(String[] args) { + A lock = new A(); + obj_field = lock; + for (int i = 0; i < 20_000; i++) { + test1(true, lock); + test1(false, lock); + test2(true); + test2(false); + } + } + + private static void test1(boolean flag, Object obj) { + if (obj == null) { + } + + boolean flag2; + if (flag) { + flag2 = true; + } else { + flag2 = false; + obj = obj_field; + } + + // This loop will be unswitched. The condition becomes candidate for split if + for (int i = 0; i < 100; i++) { + if (flag2) { + field = true; + } else { + field = false; + } + synchronized (obj) { + field = true; + } + } + } + + private static Object test2(boolean flag) { + int integer; + if (flag) { + field = true; + integer = 1; + } else { + field = false; + integer = 2; + } + + Object obj = integer; + + // This loop will be unswitched. The condition becomes candidate for split if + for (int i = 0; i < 100; i++) { + if (integer == 1) { + field = true; + } else { + field = false; + } + synchronized (obj) { + field = true; + } + } + return obj; + } + + private static final class A { + } +} From ac999a4af3cb1a9f768ea9f613ff61b9580a5069 Mon Sep 17 00:00:00 2001 From: andrew-m-leonard Date: Mon, 11 Nov 2019 15:24:21 +0000 Subject: [PATCH 131/131] Update OPENJDK_TAG to merged level jdk-11.0.6+2 Signed-off-by: andrew-m-leonard --- closed/openjdk-tag.gmk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/closed/openjdk-tag.gmk b/closed/openjdk-tag.gmk index 7080825ca25..7384f05b3fa 100644 --- a/closed/openjdk-tag.gmk +++ b/closed/openjdk-tag.gmk @@ -1 +1 @@ -OPENJDK_TAG := jdk-11.0.5+10 +OPENJDK_TAG := jdk-11.0.6+2
Event setting names and their purpose.