From c83db6b4d13ef015aed654311c10b87e570ac483 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Wed, 6 Jun 2018 17:10:37 -0400 Subject: [PATCH 01/46] 8174734: Safepoint sync time did not increase Reviewed-by: coleenp, hseigel --- test/jdk/ProblemList.txt | 1 - .../GetSafepointSyncTime.java | 77 ++++++++++++------- 2 files changed, 49 insertions(+), 29 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 256a0dbb69d..697d414b3fc 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -545,7 +545,6 @@ java/io/RandomAccessFile/UnreferencedRAFClosesFd.java 8202292 linux-al com/sun/management/OperatingSystemMXBean/GetProcessCpuLoad.java 8030957 aix-all com/sun/management/OperatingSystemMXBean/GetSystemCpuLoad.java 8030957 aix-all -sun/management/HotspotRuntimeMBean/GetSafepointSyncTime.java 8174734 generic-all ############################################################################ diff --git a/test/jdk/sun/management/HotspotRuntimeMBean/GetSafepointSyncTime.java b/test/jdk/sun/management/HotspotRuntimeMBean/GetSafepointSyncTime.java index 7b25aaf81b0..1e60e70d6dd 100644 --- a/test/jdk/sun/management/HotspotRuntimeMBean/GetSafepointSyncTime.java +++ b/test/jdk/sun/management/HotspotRuntimeMBean/GetSafepointSyncTime.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 4858522 + * @bug 4858522 8174734 * @summary Basic unit test of HotspotRuntimeMBean.getSafepointSyncTime() * @author Steve Bohne * @@ -43,50 +43,71 @@ public class GetSafepointSyncTime { private static final long NUM_THREAD_DUMPS = 300; - // Careful with these values. - private static final long MIN_VALUE_FOR_PASS = 1; - private static final long MAX_VALUE_FOR_PASS = Long.MAX_VALUE; + static void checkPositive(long value, String label) { + if (value < 0) + throw new RuntimeException(label + " had a negative value of " + + value); + } + + static void validate(long count1, long count2, long time1, long time2, + String label) { + checkPositive(count1, label + ":count1"); + checkPositive(count2, label + ":count2"); + checkPositive(time1, label + ":time1"); + checkPositive(time2, label + ":time2"); + + long countDiff = count2 - count1; + long timeDiff = time2 - time1; + + if (countDiff < NUM_THREAD_DUMPS) { + throw new RuntimeException(label + + ": Expected at least " + NUM_THREAD_DUMPS + + " safepoints but only got " + countDiff); + } + + // getSafepointSyncTime is the accumulated time spent getting to a + // safepoint, so each safepoint will add a little to this, but the + // resolution is only milliseconds so we may not see it. + if (timeDiff < 0) { + throw new RuntimeException(label + ": Safepoint sync time " + + "decreased unexpectedly " + + "(time1 = " + time1 + "; " + + "time2 = " + time2 + ")"); + } + + System.out.format("%s: Safepoint count=%d (diff=%d), sync time=%d ms (diff=%d)%n", + label, count2, countDiff, time2, timeDiff); + + } public static void main(String args[]) throws Exception { long count = mbean.getSafepointCount(); - long value = mbean.getSafepointSyncTime(); + long time = mbean.getSafepointSyncTime(); + + checkPositive(count, "count"); + checkPositive(time, "time"); + + // Thread.getAllStackTraces() should cause a safepoint. - // Thread.getAllStackTraces() should cause safepoints. - // If this test is failing because it doesn't, - // MIN_VALUE_FOR_PASS should be reset to 0 for (int i = 0; i < NUM_THREAD_DUMPS; i++) { Thread.getAllStackTraces(); } long count1 = mbean.getSafepointCount(); - long value1 = mbean.getSafepointSyncTime(); + long time1 = mbean.getSafepointSyncTime(); - System.out.format("Safepoint count=%d (diff=%d), sync time=%d ms (diff=%d)%n", - count1, count1-count, value1, value1-value); + validate(count, count1, time, time1, "Pass 1"); - if (value1 < MIN_VALUE_FOR_PASS || value1 > MAX_VALUE_FOR_PASS) { - throw new RuntimeException("Safepoint sync time " + - "illegal value: " + value1 + " ms " + - "(MIN = " + MIN_VALUE_FOR_PASS + "; " + - "MAX = " + MAX_VALUE_FOR_PASS + ")"); - } + // repeat the experiment for (int i = 0; i < NUM_THREAD_DUMPS; i++) { Thread.getAllStackTraces(); } long count2 = mbean.getSafepointCount(); - long value2 = mbean.getSafepointSyncTime(); + long time2 = mbean.getSafepointSyncTime(); - System.out.format("Safepoint count=%d (diff=%d), sync time=%d ms (diff=%d)%n", - count2, count2-count1, value2, value2-value1); - - if (value2 <= value1) { - throw new RuntimeException("Safepoint sync time " + - "did not increase " + - "(value1 = " + value1 + "; " + - "value2 = " + value2 + ")"); - } + validate(count1, count2, time1, time2, "Pass 2"); System.out.println("Test passed."); } From bb4b38739858014d85e495911f34f0604dc5786c Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Wed, 6 Jun 2018 14:36:48 -0700 Subject: [PATCH 02/46] 8204494: Fix for 8200530 triggered regression, closed/test/jdk/security/infra/java/security/KeyStore/BouncyCastleInterop.java failed Reviewed-by: rriggs --- .../share/classes/java/util/jar/Manifest.java | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/util/jar/Manifest.java b/src/java.base/share/classes/java/util/jar/Manifest.java index 9ee93aa079f..ea73a1f65ac 100644 --- a/src/java.base/share/classes/java/util/jar/Manifest.java +++ b/src/java.base/share/classes/java/util/jar/Manifest.java @@ -393,7 +393,27 @@ public class Manifest implements Cloneable { off += n; total += n; pos = tpos; - if (c == '\n' || c == '\r') { + c = tbuf[tpos-1]; + if (c == '\n') { + break; + } + if (c == '\r') { + if (count == pos) { + // try to see if there is a trailing LF + fill(); + if (pos < count && tbuf[pos] == '\n') { + if (total < len) { + b[off++] = '\n'; + total++; + } else { + // we should always have big enough lbuf but + // just in case we don't, replace the last CR + // with LF. + b[off - 1] = '\n'; + } + pos++; + } + } break; } } From d59da4a4b7f18c977558c1a8ead7041b5008c7d7 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 6 Jun 2018 15:10:12 -0700 Subject: [PATCH 03/46] 8204303: Add redirect for overview-summary.html Reviewed-by: sundar, hannesw --- .../doclets/formats/html/HtmlDoclet.java | 26 +++++--------- .../formats/html/IndexRedirectWriter.java | 35 +++++++++++-------- .../doclets/formats/html/markup/Head.java | 22 ++++++++++-- .../TestFramesNoFrames.java | 20 ++++++++--- 4 files changed, 65 insertions(+), 38 deletions(-) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java index 9ad9e5db556..600b0e0e257 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java @@ -172,8 +172,12 @@ public class HtmlDoclet extends AbstractDoclet { } } - if (!configuration.frames && !configuration.createoverview) { - IndexRedirectWriter.generate(configuration); + if (!configuration.frames) { + if (configuration.createoverview) { + IndexRedirectWriter.generate(configuration, DocPaths.OVERVIEW_SUMMARY, DocPaths.INDEX); + } else { + IndexRedirectWriter.generate(configuration); + } } if (configuration.helpfile.isEmpty() && !configuration.nohelp) { @@ -201,7 +205,7 @@ public class HtmlDoclet extends AbstractDoclet { } } - protected void copyJqueryFiles() throws DocletException { + private void copyJqueryFiles() throws DocletException { List files = Arrays.asList( "jquery-1.12.4.js", "jquery-ui.js", @@ -245,7 +249,6 @@ public class HtmlDoclet extends AbstractDoclet { protected void generateClassFiles(SortedSet arr, ClassTree classtree) throws DocletException { List list = new ArrayList<>(arr); - ListIterator iterator = list.listIterator(); for (TypeElement klass : list) { if (utils.hasHiddenTag(klass) || !(configuration.isGeneratedDoc(klass) && utils.isIncluded(klass))) { @@ -274,7 +277,6 @@ public class HtmlDoclet extends AbstractDoclet { ModuleIndexFrameWriter.generate(configuration); } List mdles = new ArrayList<>(configuration.modulePackages.keySet()); - int i = 0; for (ModuleElement mdle : mdles) { if (configuration.frames && configuration.modules.size() > 1) { ModulePackageIndexFrameWriter.generate(configuration, mdle); @@ -283,21 +285,10 @@ public class HtmlDoclet extends AbstractDoclet { AbstractBuilder moduleSummaryBuilder = configuration.getBuilderFactory().getModuleSummaryBuilder(mdle); moduleSummaryBuilder.build(); - i++; } } } - PackageElement getNamedPackage(List list, int idx) { - if (idx < list.size()) { - PackageElement pkg = list.get(idx); - if (pkg != null && !pkg.isUnnamed()) { - return pkg; - } - } - return null; - } - /** * {@inheritDoc} */ @@ -308,11 +299,10 @@ public class HtmlDoclet extends AbstractDoclet { PackageIndexFrameWriter.generate(configuration); } List pList = new ArrayList<>(packages); - for (int i = 0 ; i < pList.size() ; i++) { + for (PackageElement pkg : pList) { // if -nodeprecated option is set and the package is marked as // deprecated, do not generate the package-summary.html, package-frame.html // and package-tree.html pages for that package. - PackageElement pkg = pList.get(i); if (!(configuration.nodeprecated && utils.isDeprecated(pkg))) { if (configuration.frames) { PackageFrameWriter.generate(configuration, pkg); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java index 2daa6182f75..6295dce952b 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexRedirectWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,8 +41,8 @@ import jdk.javadoc.internal.doclets.toolkit.util.DocPath; import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; /** - * Writes an index.html file that tries to redirect to an alternate page. - * The redirect uses JavaSCript, if enabled, falling back on + * Writes a file that tries to redirect to an alternate page. + * The redirect uses JavaScript, if enabled, falling back on * {@code }. * If neither are supported/enabled in a browser, the page displays the * standard "JavaScipt not enabled" message, and a link to the alternate page. @@ -51,21 +51,27 @@ public class IndexRedirectWriter extends HtmlDocletWriter { public static void generate(HtmlConfiguration configuration) throws DocFileIOException { - IndexRedirectWriter indexRedirect; - DocPath filename = DocPaths.INDEX; - indexRedirect = new IndexRedirectWriter(configuration, filename); - indexRedirect.generateIndexFile(); + generate(configuration, DocPaths.INDEX, configuration.topFile); } - IndexRedirectWriter(HtmlConfiguration configuration, DocPath filename) { + public static void generate(HtmlConfiguration configuration, DocPath fileName, DocPath target) + throws DocFileIOException { + IndexRedirectWriter indexRedirect = new IndexRedirectWriter(configuration, fileName, target); + indexRedirect.generateIndexFile(); + } + + private DocPath target; + + private IndexRedirectWriter(HtmlConfiguration configuration, DocPath filename, DocPath target) { super(configuration, filename); + this.target = target; } /** * Generate an index file that redirects to an alternate file. * @throws DocFileIOException if there is a problem generating the file */ - void generateIndexFile() throws DocFileIOException { + private void generateIndexFile() throws DocFileIOException { DocType htmlDocType = DocType.forVersion(configuration.htmlVersion); Content htmlComment = contents.newPage; Head head = new Head(path, configuration.htmlVersion, configuration.docletVersion) @@ -77,15 +83,16 @@ public class IndexRedirectWriter extends HtmlDocletWriter { : resources.getText("doclet.Generated_Docs_Untitled"); head.setTitle(title) - .setCharset(configuration.charset); + .setCharset(configuration.charset) + .setCanonicalLink(target); - String topFilePath = configuration.topFile.getPath(); + String targetPath = target.getPath(); Script script = new Script("window.location.replace(") - .appendStringLiteral(topFilePath, '\'') + .appendStringLiteral(targetPath, '\'') .append(")"); HtmlTree metaRefresh = new HtmlTree(HtmlTag.META) .addAttr(HtmlAttr.HTTP_EQUIV, "Refresh") - .addAttr(HtmlAttr.CONTENT, "0;" + topFilePath); + .addAttr(HtmlAttr.CONTENT, "0;" + targetPath); head.addContent( script.asContent(), configuration.isOutputHtml5() ? HtmlTree.NOSCRIPT(metaRefresh) : metaRefresh); @@ -94,7 +101,7 @@ public class IndexRedirectWriter extends HtmlDocletWriter { bodyContent.addContent(HtmlTree.NOSCRIPT( HtmlTree.P(contents.getContent("doclet.No_Script_Message")))); - bodyContent.addContent(HtmlTree.P(HtmlTree.A(topFilePath, new StringContent(topFilePath)))); + bodyContent.addContent(HtmlTree.P(HtmlTree.A(targetPath, new StringContent(targetPath)))); Content body = new HtmlTree(HtmlTag.BODY); if (configuration.allowTag(HtmlTag.MAIN)) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java index 6e525d7cd0c..a9d76cda97d 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -67,7 +67,8 @@ public class Head { private Script mainBodyScript; private final List", + "", + "

index.html

"); + } } private void checkWarning() { From ec4ee0eb7389e42ce3310f00bad0c1ea5cd7450b Mon Sep 17 00:00:00 2001 From: Jesper Wilhelmsson Date: Thu, 7 Jun 2018 01:33:09 +0200 Subject: [PATCH 04/46] Added tag jdk-11+17 for changeset 64e4b1686141 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index f2cb64f8785..dd49fb5ce19 100644 --- a/.hgtags +++ b/.hgtags @@ -488,3 +488,4 @@ e1e60f75cd39312a7f59d2a4f91d624e5aecc95e jdk-11+11 3595bd343b65f8c37818ebe6a4c343ddeb1a5f88 jdk-11+14 a11c1cb542bbd1671d25b85efe7d09b983c48525 jdk-11+15 02934b0d661b82b7fe1052a04998d2091352e08d jdk-11+16 +64e4b1686141e57a681936a8283983341484676e jdk-11+17 From 552a7d7e7ecde5764c2d29bcd7aea1ed403b4b37 Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Wed, 6 Jun 2018 19:47:22 -0700 Subject: [PATCH 05/46] 8200387: [Graal] fromTonga/nsk/jdi tests hang with Graal as JIT Increase the OVERLOADED_QUEUE value in the JDI client Reviewed-by: cjplummer, amenkov --- .../classes/com/sun/tools/jdi/TargetVM.java | 4 +- test/hotspot/jtreg/ProblemList-graal.txt | 41 ------------------- 2 files changed, 2 insertions(+), 43 deletions(-) diff --git a/src/jdk.jdi/share/classes/com/sun/tools/jdi/TargetVM.java b/src/jdk.jdi/share/classes/com/sun/tools/jdi/TargetVM.java index d73103328ac..8a33c23a70c 100644 --- a/src/jdk.jdi/share/classes/com/sun/tools/jdi/TargetVM.java +++ b/src/jdk.jdi/share/classes/com/sun/tools/jdi/TargetVM.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -53,7 +53,7 @@ public class TargetVM implements Runnable { * TO DO: The limit numbers below are somewhat arbitrary and should * be configurable in the future. */ - static private final int OVERLOADED_QUEUE = 2000; + static private final int OVERLOADED_QUEUE = 10000; static private final int UNDERLOADED_QUEUE = 100; TargetVM(VirtualMachineImpl vm, Connection connection) { diff --git a/test/hotspot/jtreg/ProblemList-graal.txt b/test/hotspot/jtreg/ProblemList-graal.txt index cb91916c324..fd49f237511 100644 --- a/test/hotspot/jtreg/ProblemList-graal.txt +++ b/test/hotspot/jtreg/ProblemList-graal.txt @@ -95,49 +95,8 @@ vmTestbase/nsk/stress/strace/strace006.java 8191047 generi vmTestbase/nsk/jvmti/scenarios/sampling/SP07/sp07t002/TestDescription.java 8191047 generic-all vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn009/forceEarlyReturn009.java 8191047 generic-all -vmTestbase/nsk/jdi/ClassType/invokeMethod/invokemethod012/TestDescription.java 8195600 generic-all -vmTestbase/nsk/jdi/ClassType/setValue/setvalue006/TestDescription.java 8195600 generic-all -vmTestbase/nsk/jdi/ListeningConnector/listennosuspend/listennosuspend001/TestDescription.java 8195600 generic-all -vmTestbase/nsk/jdi/Location/lineNumber_s/lineNumber_s002/lineNumber_s002.java 8195600 generic-all -vmTestbase/nsk/jdi/Location/sourcePath_s/sourcePath_s002/sourcePath_s002.java 8195600 generic-all -vmTestbase/nsk/jdi/Method/allLineLocations_ss/allLineLocations_ss003/allLineLocations_ss003.java 8195600 generic-all -vmTestbase/nsk/jdi/Method/locationsOfLine_ssi/locationsOfLine_ssi003/locationsOfLine_ssi003.java 8195600 generic-all -vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod011/TestDescription.java 8195600 generic-all -vmTestbase/nsk/jdi/ObjectReference/invokeMethod/invokemethod012/TestDescription.java 8195600 generic-all -vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects001/referringObjects001.java 8195600 generic-all -vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects002/referringObjects002.java 8195600 generic-all -vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects004/referringObjects004.java 8195600 generic-all -vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue005/TestDescription.java 8195600 generic-all vmTestbase/nsk/jdi/ReferenceType/instances/instances001/instances001.java 8195600 generic-all -vmTestbase/nsk/jdi/ReferenceType/instances/instances002/instances002.java 8195600 generic-all -vmTestbase/nsk/jdi/ReferenceType/instances/instances005/instances005.java 8195600 generic-all vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn007/TestDescription.java 8195600 generic-all -vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames001/ownedMonitorsAndFrames001.java 8195600 generic-all -vmTestbase/nsk/jdi/VMOutOfMemoryException/VMOutOfMemoryException001/VMOutOfMemoryException001.java 8195600 generic-all -vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts003/instancecounts003.java 8195600 generic-all -vmTestbase/nsk/jdi/stress/serial/ownedMonitorsAndFrames002/TestDescription.java 8195600 generic-all -vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn003/forceEarlyReturn003.java 8195600 generic-all -vmTestbase/nsk/jdi/ThreadReference/forceEarlyReturn/forceEarlyReturn004/forceEarlyReturn004.java 8195600 generic-all - -vmTestbase/nsk/jdi/Location/sourceName_s/sourceName_s002/sourceName_s002.java 8200387 generic-all -vmTestbase/nsk/jdi/Method/allLineLocations_ss/allLineLocations_ss002/allLineLocations_ss002.java 8200387 generic-all -vmTestbase/nsk/jdi/Method/locationsOfLine_ssi/locationsOfLine_ssi002/locationsOfLine_ssi002.java 8200387 generic-all -vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects003/referringObjects003.java 8200387 generic-all -vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/allLineLocations_ss003/allLineLocations_ss003.java 8200387 generic-all -vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/allLineLocations_ss004/allLineLocations_ss004.java 8200387 generic-all -vmTestbase/nsk/jdi/ReferenceType/availableStrata/availableStrata002/availableStrata002.java 8200387 generic-all -vmTestbase/nsk/jdi/ReferenceType/defaultStratum/defaultStratum002/defaultStratum002.java 8200387 generic-all -vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsOfLine_ssi003/locationsOfLine_ssi003.java 8200387 generic-all -vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsOfLine_ssi004/locationsOfLine_ssi004.java 8200387 generic-all -vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourceNames003/sourceNames003.java 8200387 generic-all -vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcePaths003/sourcePaths003.java 8200387 generic-all -vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues002/getArgumentValues002.java 8200387 generic-all -vmTestbase/nsk/jdi/StackFrame/getArgumentValues/getArgumentValues003/getArgumentValues003.java 8200387 generic-all -vmTestbase/nsk/jdi/stress/serial/heapwalking001/TestDescription.java 8200387 generic-all -vmTestbase/nsk/jdi/ThreadReference/ownedMonitorsAndFrames/ownedMonitorsAndFrames004/ownedMonitorsAndFrames004.java 8200387 generic-all -vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts001/instancecounts001.java 8200387 generic-all -vmTestbase/nsk/jdi/VirtualMachine/instanceCounts/instancecounts002/TestDescription.java 8200387 generic-all -vmTestbase/nsk/jdi/VirtualMachine/setDefaultStratum/setDefaultStratum002/setDefaultStratum002.java 8200387 generic-all vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance001/TestDescription.java 8203174 generic-all vmTestbase/nsk/jdi/ArrayType/newInstance/newinstance002/TestDescription.java 8203174 generic-all From f801eef7d1b0f7bbcc2706f380b8b8c7b44e2171 Mon Sep 17 00:00:00 2001 From: Daniil Titov Date: Wed, 6 Jun 2018 13:58:57 -0700 Subject: [PATCH 06/46] 8203033: [Testbug] vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic002/TestDescription.java fails with nestmates Reviewed-by: sspitsyn, dholmes --- .../isSynthetic/issynthetic002.java | 136 ++++++------------ .../isSynthetic/issynthetic002a.java | 33 ++--- 2 files changed, 55 insertions(+), 114 deletions(-) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic002.java index fb684c807c5..c79bc92c3ea 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic002.java @@ -33,55 +33,16 @@ import java.util.*; import java.io.*; public class issynthetic002 { - final static String METHOD_NAME[] = { - "", - "Mv", - "Mz", "Mz1", "Mz2", - "Mb", "Mb1", "Mb2", - "Mc", "Mc1", "Mc2", - "Md", "Md1", "Md2", - "Mf", "Mf1", "Mf2", - "Mi", "Mi1", "Mi2", - "Ml", "Ml1", "Ml2", - "Mr", "Mr1", "Mr2", - "MvF", "MlF", "MlF1", "MlF2", - "MvN", "MlN", "MlN1", "MlN2", - "MvS", "MlS", "MlS1", "MlS2", - "MvI", "MlI", "MlI1", "MlI2", - "MvY", "MlY", "MlY1", "MlY2", - "MvU", "MlU", "MlU1", "MlU2", - "MvR", "MlR", "MlR1", "MlR2", - "MvP", "MlP", "MlP1", "MlP2", - "MX", "MX1", "MX2", - "MO", "MO1", "MO2", - - "MLF", "MLF1", "MLF2", - "MLN", "MLN1", "MLN2", - "MLS", "MLS1", "MLS2", - "MLI", "MLI1", "MLI2", - "MLY", "MLY1", "MLY2", - "MLU", "MLU1", "MLU2", - "MLR", "MLR1", "MLR2", - "MLP", "MLP1", "MLP2", - - "ME", "ME1", "ME2", - "MEF", "MEF1", "MEF2", - "MEN", "MEN1", "MEN2", - "MES", "ME1S", "ME2S", - "MEI", "MEI1", "MEI2", - "MEY", "MEY1", "MEY2", - "MEU", "MEU1", "MEU2", - "MER", "MER1", "MER2", - "MEP", "MEP1", "MEP2" - }; + final static String SYNTHETIC_METHOD_NAME = "test"; + final static String SYNTHETIC_METHOD_SIGNATURE = "(Ljava/lang/Object;)Ljava/lang/Object;"; private static Log log; private final static String prefix = "nsk.jdi.TypeComponent.isSynthetic."; private final static String className = "issynthetic002"; - private final static String debugerName = prefix + className; - private final static String debugeeName = debugerName + "a"; + private final static String debuggerName = prefix + className; + private final static String debuggeeName = debuggerName + "a"; private final static String classToCheckName = prefix + "issynthetic002aClassToCheck"; public static void main(String argv[]) { @@ -92,38 +53,38 @@ public class issynthetic002 { ArgumentHandler argHandler = new ArgumentHandler(argv); log = new Log(out, argHandler); Binder binder = new Binder(argHandler, log); - Debugee debugee = binder.bindToDebugee(debugeeName + Debugee debuggee = binder.bindToDebugee(debuggeeName + (argHandler.verbose() ? " -verbose" : "")); - VirtualMachine vm = debugee.VM(); + VirtualMachine vm = debuggee.VM(); boolean canGetSynthetic = vm.canGetSyntheticAttribute(); - IOPipe pipe = new IOPipe(debugee); + IOPipe pipe = new IOPipe(debuggee); boolean testFailed = false; List methods; int totalSyntheticMethods = 0; - log.display("debuger> Value of canGetSyntheticAttribute in current " + log.display("debugger> Value of canGetSyntheticAttribute in current " + "VM is " + canGetSynthetic); - // Connect with debugee and resume it - debugee.redirectStderr(out); - debugee.resume(); + // Connect with debuggee and resume it + debuggee.redirectStderr(out); + debuggee.resume(); String line = pipe.readln(); if (line == null) { - log.complain("debuger FAILURE> UNEXPECTED debugee's signal - null"); + log.complain("debugger FAILURE> UNEXPECTED debuggee's signal - null"); return 2; } if (!line.equals("ready")) { - log.complain("debuger FAILURE> UNEXPECTED debugee's signal - " + log.complain("debugger FAILURE> UNEXPECTED debuggee's signal - " + line); return 2; } else { - log.display("debuger> debugee's \"ready\" signal recieved."); + log.display("debugger> debuggee's \"ready\" signal received."); } - ReferenceType refType = debugee.classByName(classToCheckName); + ReferenceType refType = debuggee.classByName(classToCheckName); if (refType == null) { - log.complain("debuger FAILURE> Class " + classToCheckName + log.complain("debugger FAILURE> Class " + classToCheckName + " not found."); return 2; } @@ -132,51 +93,50 @@ public class issynthetic002 { try { methods = refType.methods(); } catch (Exception e) { - log.complain("debuger FAILURE> Can't get methods from " + log.complain("debugger FAILURE> Can't get methods from " + classToCheckName); - log.complain("debuger FAILURE> Exception: " + e); + log.complain("debugger FAILURE> Exception: " + e); return 2; } int totalMethods = methods.size(); if (totalMethods < 1) { - log.complain("debuger FAILURE> Total number of methods in debuggee " + log.complain("debugger FAILURE> Total number of methods in debuggee " + "read " + totalMethods); return 2; } - log.display("debuger> Total methods in debuggee read: " - + totalMethods + " total methods in debuger: " - + METHOD_NAME.length); + log.display("debugger> Total methods in debuggee read: " + + totalMethods); for (int i = 0; i < totalMethods; i++) { Method method = (Method)methods.get(i); String name = method.name(); + String signature = method.signature(); boolean isSynthetic; - boolean isRealSynthetic = true; try { isSynthetic = method.isSynthetic(); if (!canGetSynthetic) { - log.complain("debuger FAILURE 1> Value of " + log.complain("debugger FAILURE 1> Value of " + "canGetSyntheticAttribute in current VM is " + "false, so UnsupportedOperationException was " + "expected for " + i + " method " + name); testFailed = true; continue; } else { - log.display("debuger> " + i + " method " + name + " with " + log.display("debugger> " + i + " method " + name + " with " + "synthetic value " + isSynthetic + " read " + "without UnsupportedOperationException"); } } catch (UnsupportedOperationException e) { if (canGetSynthetic) { - log.complain("debuger FAILURE 2> Value of " + log.complain("debugger FAILURE 2> Value of " + "canGetSyntheticAttribute in current VM is " + "true, but cannot get synthetic for method " + "name."); - log.complain("debuger FAILURE 2> Exception: " + e); + log.complain("debugger FAILURE 2> Exception: " + e); testFailed = true; } else { - log.display("debuger> UnsupportedOperationException was " + log.display("debugger> UnsupportedOperationException was " + "thrown while getting isSynthetic for " + i + " method " + name + " because value " + "canGetSynthetic is false."); @@ -184,49 +144,39 @@ public class issynthetic002 { continue; } - // Find out if method exists in list of methods - for (int j = 0; j < METHOD_NAME.length; j++) { - String nameFromList = METHOD_NAME[j]; - - if (nameFromList.equals(name)) { - // Method found in list - is not synthetic - - isRealSynthetic = false; - break; - } - } - - if (isRealSynthetic != isSynthetic) { - log.complain("debuger FAILURE 3> Method's " + name - + " synthetic is " + isSynthetic + ", but expected " - + "is " + isRealSynthetic); - testFailed = true; - continue; - } if (isSynthetic) { - totalSyntheticMethods++; + if (SYNTHETIC_METHOD_NAME.equals(name) && SYNTHETIC_METHOD_SIGNATURE.equals(signature)) { + totalSyntheticMethods++; + } else { + testFailed = true; + log.complain("debugger FAILURE 3> Found unexpected synthetic method " + name + + signature); + } } } if (totalSyntheticMethods == 0) { - log.complain("debuger FAILURE 4> Synthetic methods not found."); + log.complain("debugger FAILURE 4> Synthetic methods not found."); + testFailed = true; + } else if (totalSyntheticMethods > 1 ) { + log.complain("debugger FAILURE 5> More than one Synthetic method is found."); testFailed = true; } pipe.println("quit"); - debugee.waitFor(); - int status = debugee.getStatus(); + debuggee.waitFor(); + int status = debuggee.getStatus(); if (testFailed) { - log.complain("debuger FAILURE> TEST FAILED"); + log.complain("debugger FAILURE> TEST FAILED"); return 2; } else { if (status == 95) { - log.display("debuger> expected Debugee's exit " + log.display("debugger> expected Debuggee's exit " + "status - " + status); return 0; } else { - log.complain("debuger FAILURE> UNEXPECTED Debugee's exit " + log.complain("debugger FAILURE> UNEXPECTED Debuggee's exit " + "status (not 95) - " + status); return 2; } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic002a.java index 710b8e58859..49f55532a2d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic002a.java @@ -51,7 +51,11 @@ public class issynthetic002a { } } -class issynthetic002aClassToCheck { +interface issynthetic002aClassToCheckIntf { + T test(T t); +} + +class issynthetic002aClassToCheck implements issynthetic002aClassToCheckIntf { // Not-synthetic methods // User class and interface @@ -178,26 +182,13 @@ class issynthetic002aClassToCheck { private Inter[] MEP1(Inter[] E) { return E; }; private Inter[][] MEP2(Inter[][] E) { return E; }; - // Synthetic methods - private int i; - private String s; - - class NestedClass { - boolean MS(String str) { - // Method uses private variable s from ClassToCheck, - // so two synthetic methods must appear in ClassToCheck - - s = s + "NestedClass"; - return s.equals(str); - }; - - boolean Mi(int j) { - // Method uses private variable i from ClassToCheck, - // so two synthetic methods must appear in ClassToCheck - - i = i + 1; - return (i == j); - }; + // The implementation of the parametrized interface issynthetic002aClassToCheckIntf + // triggers the compiler to create the synthetic bridge method + // "test(Ljava/lang/Object;)Ljava/lang/Object;". + public String test(String s) { + return s; } + + } From dce30cad153ff0b50aff303d325b37ad5e4af467 Mon Sep 17 00:00:00 2001 From: Stefan Johansson Date: Thu, 7 Jun 2018 09:02:03 +0200 Subject: [PATCH 07/46] 8204287: Phase timings not updated correctly after JDK-6672778 Reviewed-by: tschatzl, kbarrett --- src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp | 13 ++++++++++++- src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp | 4 ++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp index 5aeb4baa453..8d70c0fe108 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp @@ -468,15 +468,24 @@ G1EvacPhaseWithTrimTimeTracker::G1EvacPhaseWithTrimTimeTracker(G1ParScanThreadSt _pss(pss), _start(Ticks::now()), _total_time(total_time), - _trim_time(trim_time) { + _trim_time(trim_time), + _stopped(false) { assert(_pss->trim_ticks().value() == 0, "Possibly remaining trim ticks left over from previous use"); } G1EvacPhaseWithTrimTimeTracker::~G1EvacPhaseWithTrimTimeTracker() { + if (!_stopped) { + stop(); + } +} + +void G1EvacPhaseWithTrimTimeTracker::stop() { + assert(!_stopped, "Should only be called once"); _total_time += (Ticks::now() - _start) - _pss->trim_ticks(); _trim_time += _pss->trim_ticks(); _pss->reset_trim_ticks(); + _stopped = true; } G1GCParPhaseTimesTracker::G1GCParPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCPhaseTimes::GCParPhases phase, uint worker_id) : @@ -504,6 +513,8 @@ G1EvacPhaseTimesTracker::G1EvacPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1EvacPhaseTimesTracker::~G1EvacPhaseTimesTracker() { if (_phase_times != NULL) { + // Explicitly stop the trim tracker since it's not yet destructed. + _trim_tracker.stop(); // Exclude trim time by increasing the start time. _start_time += _trim_time; _phase_times->record_or_add_objcopy_time_secs(_worker_id, _trim_time.seconds()); diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp index d5ec33400c0..3b20cfe4d2d 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp @@ -373,9 +373,13 @@ class G1EvacPhaseWithTrimTimeTracker : public StackObj { Tickspan& _total_time; Tickspan& _trim_time; + + bool _stopped; public: G1EvacPhaseWithTrimTimeTracker(G1ParScanThreadState* pss, Tickspan& total_time, Tickspan& trim_time); ~G1EvacPhaseWithTrimTimeTracker(); + + void stop(); }; class G1GCParPhaseTimesTracker : public CHeapObj { From 2466623e452509a16cd96eb99f7fb835761caeea Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Thu, 7 Jun 2018 09:18:39 +0100 Subject: [PATCH 08/46] 6350055: (se) SelectionKey.interestOps variants to atomically update interest ops Co-authored-by: David M Lloyd Reviewed-by: bpb --- .../java/nio/channels/SelectionKey.java | 77 ++++++++ .../classes/sun/nio/ch/SelectionKeyImpl.java | 40 +++- .../channels/SelectionKey/AtomicUpdates.java | 186 ++++++++++++++++++ 3 files changed, 302 insertions(+), 1 deletion(-) create mode 100644 test/jdk/java/nio/channels/SelectionKey/AtomicUpdates.java diff --git a/src/java.base/share/classes/java/nio/channels/SelectionKey.java b/src/java.base/share/classes/java/nio/channels/SelectionKey.java index ad08fe43822..ceb7f575c4d 100644 --- a/src/java.base/share/classes/java/nio/channels/SelectionKey.java +++ b/src/java.base/share/classes/java/nio/channels/SelectionKey.java @@ -189,6 +189,83 @@ public abstract class SelectionKey { */ public abstract SelectionKey interestOps(int ops); + /** + * Atomically sets this key's interest set to the bitwise union ("or") of + * the existing interest set and the given value. This method is guaranteed + * to be atomic with respect to other concurrent calls to this method or to + * {@link #interestOpsAnd(int)}. + * + *

This method may be invoked at any time. If this method is invoked + * while a selection operation is in progress then it has no effect upon + * that operation; the change to the key's interest set will be seen by the + * next selection operation. + * + * @implSpec The default implementation synchronizes on this key and invokes + * {@code interestOps()} and {@code interestOps(int)} to retrieve and set + * this key's interest set. + * + * @param ops The interest set to apply + * + * @return The previous interest set + * + * @throws IllegalArgumentException + * If a bit in the set does not correspond to an operation that + * is supported by this key's channel, that is, if + * {@code (ops & ~channel().validOps()) != 0} + * + * @throws CancelledKeyException + * If this key has been cancelled + * + * @since 11 + */ + public int interestOpsOr(int ops) { + synchronized (this) { + int oldVal = interestOps(); + interestOps(oldVal | ops); + return oldVal; + } + } + + /** + * Atomically sets this key's interest set to the bitwise intersection ("and") + * of the existing interest set and the given value. This method is guaranteed + * to be atomic with respect to other concurrent calls to this method or to + * {@link #interestOpsOr(int)}. + * + *

This method may be invoked at any time. If this method is invoked + * while a selection operation is in progress then it has no effect upon + * that operation; the change to the key's interest set will be seen by the + * next selection operation. + * + * @apiNote Unlike the {@code interestOps(int)} and {@code interestOpsOr(int)} + * methods, this method does not throw {@code IllegalArgumentException} when + * invoked with bits in the interest set that do not correspond to an + * operation that is supported by this key's channel. This is to allow + * operation bits in the interest set to be cleared using bitwise complement + * values, e.g., {@code interestOpsAnd(~SelectionKey.OP_READ)} will remove + * the {@code OP_READ} from the interest set without affecting other bits. + * + * @implSpec The default implementation synchronizes on this key and invokes + * {@code interestOps()} and {@code interestOps(int)} to retrieve and set + * this key's interest set. + * + * @param ops The interest set to apply + * + * @return The previous interest set + * + * @throws CancelledKeyException + * If this key has been cancelled + * + * @since 11 + */ + public int interestOpsAnd(int ops) { + synchronized (this) { + int oldVal = interestOps(); + interestOps(oldVal & ops); + return oldVal; + } + } + /** * Retrieves this key's ready-operation set. * diff --git a/src/java.base/share/classes/sun/nio/ch/SelectionKeyImpl.java b/src/java.base/share/classes/sun/nio/ch/SelectionKeyImpl.java index 2f917c8d2e3..256c5194e04 100644 --- a/src/java.base/share/classes/sun/nio/ch/SelectionKeyImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/SelectionKeyImpl.java @@ -25,6 +25,9 @@ package sun.nio.ch; +import java.lang.invoke.ConstantBootstraps; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; import java.nio.channels.CancelledKeyException; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; @@ -39,6 +42,13 @@ import java.nio.channels.spi.AbstractSelectionKey; public final class SelectionKeyImpl extends AbstractSelectionKey { + private static final VarHandle INTERESTOPS = + ConstantBootstraps.fieldVarHandle( + MethodHandles.lookup(), + "interestOps", + VarHandle.class, + SelectionKeyImpl.class, int.class); + private final SelChImpl channel; private final SelectorImpl selector; @@ -84,7 +94,35 @@ public final class SelectionKeyImpl @Override public SelectionKey interestOps(int ops) { ensureValid(); - return nioInterestOps(ops); + if ((ops & ~channel().validOps()) != 0) + throw new IllegalArgumentException(); + int oldOps = (int) INTERESTOPS.getAndSet(this, ops); + if (ops != oldOps) { + selector.setEventOps(this); + } + return this; + } + + @Override + public int interestOpsOr(int ops) { + ensureValid(); + if ((ops & ~channel().validOps()) != 0) + throw new IllegalArgumentException(); + int oldVal = (int) INTERESTOPS.getAndBitwiseOr(this, ops); + if (oldVal != (oldVal | ops)) { + selector.setEventOps(this); + } + return oldVal; + } + + @Override + public int interestOpsAnd(int ops) { + ensureValid(); + int oldVal = (int) INTERESTOPS.getAndBitwiseAnd(this, ops); + if (oldVal != (oldVal & ops)) { + selector.setEventOps(this); + } + return oldVal; } @Override diff --git a/test/jdk/java/nio/channels/SelectionKey/AtomicUpdates.java b/test/jdk/java/nio/channels/SelectionKey/AtomicUpdates.java new file mode 100644 index 00000000000..aa986c1d976 --- /dev/null +++ b/test/jdk/java/nio/channels/SelectionKey/AtomicUpdates.java @@ -0,0 +1,186 @@ +/* + * 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. + */ + +/* @test + * @bug 6350055 + * @run testng AtomicUpdates + * @summary Unit test for SelectionKey interestOpsOr and interestOpsAnd + */ + +import java.io.Closeable; +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.channels.CancelledKeyException; +import java.nio.channels.SelectableChannel; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import org.testng.annotations.Test; + +import static java.nio.channels.SelectionKey.OP_READ; +import static java.nio.channels.SelectionKey.OP_WRITE; +import static java.nio.channels.SelectionKey.OP_CONNECT; +import static java.nio.channels.SelectionKey.OP_ACCEPT; +import static org.testng.Assert.*; + +@Test +public class AtomicUpdates { + + private SelectionKey keyFor(SocketChannel sc) { + return new SelectionKey() { + private int ops; + private boolean invalid; + private void ensureValid() { + if (!isValid()) + throw new CancelledKeyException(); + } + @Override + public SelectableChannel channel() { + return sc; + } + @Override + public Selector selector() { + throw new RuntimeException(); + } + @Override + public boolean isValid() { + return !invalid; + } + @Override + public void cancel() { + invalid = true; + } + @Override + public int interestOps() { + ensureValid(); + return ops; + } + @Override + public SelectionKey interestOps(int ops) { + ensureValid(); + if ((ops & ~channel().validOps()) != 0) + throw new IllegalArgumentException(); + this.ops = ops; + return this; + } + @Override + public int readyOps() { + ensureValid(); + return 0; + } + }; + } + + private void test(SelectionKey key) { + assertTrue(key.channel() instanceof SocketChannel); + key.interestOps(0); + + // 0 -> 0 + int previous = key.interestOpsOr(0); + assertTrue(previous == 0); + assertTrue(key.interestOps() == 0); + + // 0 -> OP_CONNECT + previous = key.interestOpsOr(OP_CONNECT); + assertTrue(previous == 0); + assertTrue(key.interestOps() == OP_CONNECT); + + // OP_CONNECT -> OP_CONNECT + previous = key.interestOpsOr(0); + assertTrue(previous == OP_CONNECT); + assertTrue(key.interestOps() == OP_CONNECT); + + // OP_CONNECT -> OP_CONNECT | OP_READ | OP_WRITE + previous = key.interestOpsOr(OP_READ | OP_WRITE); + assertTrue(previous == OP_CONNECT); + assertTrue(key.interestOps() == (OP_CONNECT | OP_READ | OP_WRITE)); + + // OP_CONNECT | OP_READ | OP_WRITE -> OP_CONNECT + previous = key.interestOpsAnd(~(OP_READ | OP_WRITE)); + assertTrue(previous == (OP_CONNECT | OP_READ | OP_WRITE)); + assertTrue(key.interestOps() == OP_CONNECT); + + // OP_CONNECT -> 0 + previous = key.interestOpsAnd(~OP_CONNECT); + assertTrue(previous == OP_CONNECT); + assertTrue(key.interestOps() == 0); + + // OP_READ | OP_WRITE -> OP_READ | OP_WRITE + key.interestOps(OP_READ | OP_WRITE); + previous = key.interestOpsAnd(~OP_ACCEPT); + assertTrue(previous == (OP_READ | OP_WRITE)); + assertTrue(key.interestOps() == (OP_READ | OP_WRITE)); + + // OP_READ | OP_WRITE -> 0 + previous = key.interestOpsAnd(0); + assertTrue(previous == (OP_READ | OP_WRITE)); + assertTrue(key.interestOps() == 0); + + // 0 -> 0 + previous = key.interestOpsAnd(0); + assertTrue(previous == 0); + assertTrue(key.interestOps() == 0); + + try { + key.interestOpsOr(OP_ACCEPT); + fail("IllegalArgumentException expected"); + } catch (IllegalArgumentException expected) { } + + key.cancel(); + try { + key.interestOpsOr(OP_READ); + fail("CancelledKeyException expected"); + } catch (CancelledKeyException expected) { } + try { + key.interestOpsAnd(~OP_READ); + fail("CancelledKeyException expected"); + } catch (CancelledKeyException expected) { } + } + + /** + * Test default implementation of interestOpsOr/interestOpsAnd + */ + public void testDefaultImplementation() throws Exception { + try (SocketChannel sc = SocketChannel.open()) { + SelectionKey key = keyFor(sc); + test(key); + } + } + + /** + * Test the default provider implementation of SelectionKey. + */ + public void testNioImplementation() throws Exception { + try (SocketChannel sc = SocketChannel.open(); + Selector sel = Selector.open()) { + sc.configureBlocking(false); + SelectionKey key = sc.register(sel, 0); + test(key); + } + } +} + From 7f8874a93b2fd10af9a004c0fc997c6f8c310b39 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Thu, 7 Jun 2018 11:20:18 +0200 Subject: [PATCH 09/46] 8204084: Remove the G1RSBarrierRegionFilter develop flag Reviewed-by: sjohanss, shade --- .../cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp | 8 +++----- .../s390/gc/g1/g1BarrierSetAssembler_s390.cpp | 16 +++++++--------- .../sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp | 8 +++----- src/hotspot/share/gc/g1/g1_globals.hpp | 3 --- 4 files changed, 13 insertions(+), 22 deletions(-) diff --git a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp index fba326a74f4..e6b163e46be 100644 --- a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp @@ -214,11 +214,9 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, Decorato assert(sizeof(*ct->card_table()->byte_map_base()) == sizeof(jbyte), "adjust this code"); // Does store cross heap regions? - if (G1RSBarrierRegionFilter) { - __ xorr(tmp1, store_addr, new_val); - __ srdi_(tmp1, tmp1, HeapRegion::LogOfHRGrainBytes); - __ beq(CCR0, filtered); - } + __ xorr(tmp1, store_addr, new_val); + __ srdi_(tmp1, tmp1, HeapRegion::LogOfHRGrainBytes); + __ beq(CCR0, filtered); // Crosses regions, storing NULL? if (not_null) { diff --git a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp index fe7dd910225..c039838953b 100644 --- a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp @@ -273,16 +273,14 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, Decorato // Does store cross heap regions? // It does if the two addresses specify different grain addresses. - if (G1RSBarrierRegionFilter) { - if (VM_Version::has_DistinctOpnds()) { - __ z_xgrk(Rtmp1, Rstore_addr, Rnew_val); - } else { - __ z_lgr(Rtmp1, Rstore_addr); - __ z_xgr(Rtmp1, Rnew_val); - } - __ z_srag(Rtmp1, Rtmp1, HeapRegion::LogOfHRGrainBytes); - __ z_bre(filtered); + if (VM_Version::has_DistinctOpnds()) { + __ z_xgrk(Rtmp1, Rstore_addr, Rnew_val); + } else { + __ z_lgr(Rtmp1, Rstore_addr); + __ z_xgr(Rtmp1, Rnew_val); } + __ z_srag(Rtmp1, Rtmp1, HeapRegion::LogOfHRGrainBytes); + __ z_bre(filtered); // Crosses regions, storing NULL? if (not_null) { diff --git a/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp b/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp index 82d30d69cb4..90bc2b6d801 100644 --- a/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp +++ b/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp @@ -369,12 +369,10 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, Register G1BarrierSet* bs = barrier_set_cast(BarrierSet::barrier_set()); - if (G1RSBarrierRegionFilter) { - __ xor3(store_addr, new_val, tmp); - __ srlx(tmp, HeapRegion::LogOfHRGrainBytes, tmp); + __ xor3(store_addr, new_val, tmp); + __ srlx(tmp, HeapRegion::LogOfHRGrainBytes, tmp); - __ cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pt, filtered); - } + __ cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pt, filtered); // If the "store_addr" register is an "in" or "local" register, move it to // a scratch reg so we can pass it as an argument. diff --git a/src/hotspot/share/gc/g1/g1_globals.hpp b/src/hotspot/share/gc/g1/g1_globals.hpp index 6c2263586e6..8c7aec8472e 100644 --- a/src/hotspot/share/gc/g1/g1_globals.hpp +++ b/src/hotspot/share/gc/g1/g1_globals.hpp @@ -108,9 +108,6 @@ "When expanding, % of uncommitted space to claim.") \ range(0, 100) \ \ - develop(bool, G1RSBarrierRegionFilter, true, \ - "If true, generate region filtering code in RS barrier") \ - \ product(size_t, G1UpdateBufferSize, 256, \ "Size of an update buffer") \ range(1, NOT_LP64(32*M) LP64_ONLY(1*G)) \ From 1c238f0cccf55fb2186df685aea45b2fd1cec946 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Thu, 7 Jun 2018 11:20:30 +0200 Subject: [PATCH 10/46] 8204081: Mismatch in rebuild policy and collection set chooser causes remembered sets to be kept errorneously Due to mismatch in which region's remembered sets should be rebuilt and the ones that are looked at in the collection set chooser superfluous remembered sets might be built and kept alive until the next marking. Reviewed-by: sjohanss, kbarrett --- .../share/gc/g1/collectionSetChooser.cpp | 38 +++++++++---------- src/hotspot/share/gc/g1/g1Policy.cpp | 6 +-- src/hotspot/share/gc/g1/heapRegion.hpp | 4 -- 3 files changed, 22 insertions(+), 26 deletions(-) diff --git a/src/hotspot/share/gc/g1/collectionSetChooser.cpp b/src/hotspot/share/gc/g1/collectionSetChooser.cpp index f9aa2423e02..9d2c90b546c 100644 --- a/src/hotspot/share/gc/g1/collectionSetChooser.cpp +++ b/src/hotspot/share/gc/g1/collectionSetChooser.cpp @@ -147,7 +147,7 @@ void CollectionSetChooser::sort_regions() { void CollectionSetChooser::add_region(HeapRegion* hr) { assert(!hr->is_pinned(), "Pinned region shouldn't be added to the collection set (index %u)", hr->hrm_index()); - assert(!hr->is_young(), "should not be young!"); + assert(hr->is_old(), "should be old but is %s", hr->get_type_str()); assert(hr->rem_set()->is_complete(), "Trying to add region %u to the collection set with incomplete remembered set", hr->hrm_index()); _regions.append(hr); @@ -185,7 +185,7 @@ uint CollectionSetChooser::claim_array_chunk(uint chunk_size) { void CollectionSetChooser::set_region(uint index, HeapRegion* hr) { assert(regions_at(index) == NULL, "precondition"); - assert(!hr->is_young(), "should not be young!"); + assert(hr->is_old(), "should be old but is %s", hr->get_type_str()); regions_at_put(index, hr); hr->calc_gc_efficiency(); } @@ -233,18 +233,19 @@ public: _cset_updater(hrSorted, true /* parallel */, chunk_size) { } bool do_heap_region(HeapRegion* r) { - // Do we have any marking information for this region? - if (r->is_marked()) { - // We will skip any region that's currently used as an old GC - // alloc region (we should not consider those for collection - // before we fill them up). - if (_cset_updater.should_add(r) && !_g1h->is_old_gc_alloc_region(r)) { - _cset_updater.add_region(r); - } else if (r->is_old()) { - // Can clean out the remembered sets of all regions that we did not choose but - // we created the remembered set for. - r->rem_set()->clear(true); - } + // We will skip any region that's currently used as an old GC + // alloc region (we should not consider those for collection + // before we fill them up). + if (_cset_updater.should_add(r) && !_g1h->is_old_gc_alloc_region(r)) { + _cset_updater.add_region(r); + } else if (r->is_old()) { + // Keep remembered sets for humongous regions, otherwise clean out remembered + // sets for old regions. + r->rem_set()->clear(true /* only_cardset */); + } else { + assert(!r->is_old() || !r->rem_set()->is_tracked(), + "Missed to clear unused remembered set of region %u (%s) that is %s", + r->hrm_index(), r->get_type_str(), r->rem_set()->get_state_str()); } return false; } @@ -280,11 +281,10 @@ bool CollectionSetChooser::region_occupancy_low_enough_for_evac(size_t live_byte } bool CollectionSetChooser::should_add(HeapRegion* hr) const { - assert(hr->is_marked(), "pre-condition"); - assert(!hr->is_young(), "should never consider young regions"); - return !hr->is_pinned() && - region_occupancy_low_enough_for_evac(hr->live_bytes()) && - hr->rem_set()->is_complete(); + return !hr->is_young() && + !hr->is_pinned() && + region_occupancy_low_enough_for_evac(hr->live_bytes()) && + hr->rem_set()->is_complete(); } void CollectionSetChooser::rebuild(WorkGang* workers, uint n_regions) { diff --git a/src/hotspot/share/gc/g1/g1Policy.cpp b/src/hotspot/share/gc/g1/g1Policy.cpp index 4f882a1fb20..d94a1173208 100644 --- a/src/hotspot/share/gc/g1/g1Policy.cpp +++ b/src/hotspot/share/gc/g1/g1Policy.cpp @@ -825,10 +825,10 @@ double G1Policy::predict_base_elapsed_time_ms(size_t pending_cards) const { size_t G1Policy::predict_bytes_to_copy(HeapRegion* hr) const { size_t bytes_to_copy; - if (hr->is_marked()) + if (!hr->is_young()) { bytes_to_copy = hr->max_live_bytes(); - else { - assert(hr->is_young() && hr->age_in_surv_rate_group() != -1, "invariant"); + } else { + assert(hr->age_in_surv_rate_group() != -1, "invariant"); int age = hr->age_in_surv_rate_group(); double yg_surv_rate = predict_yg_surv_rate(age, hr->surv_rate_group()); bytes_to_copy = (size_t) (hr->used() * yg_surv_rate); diff --git a/src/hotspot/share/gc/g1/heapRegion.hpp b/src/hotspot/share/gc/g1/heapRegion.hpp index 3bb6049332d..01d3c4d8758 100644 --- a/src/hotspot/share/gc/g1/heapRegion.hpp +++ b/src/hotspot/share/gc/g1/heapRegion.hpp @@ -541,10 +541,6 @@ class HeapRegion: public G1ContiguousSpace { // objects during evac failure handling. void note_self_forwarding_removal_end(size_t marked_bytes); - // Returns "false" iff no object in the region was allocated when the - // last mark phase ended. - bool is_marked() { return _prev_top_at_mark_start != bottom(); } - void reset_during_compaction() { assert(is_humongous(), "should only be called for humongous regions"); From 4c0fa362519e1d4002775068cf2352b1de98b1a0 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Thu, 7 Jun 2018 11:20:55 +0200 Subject: [PATCH 11/46] 8202049: G1: ReferenceProcessor doesn't handle mark stack overflow Issue a fatal error when mark stack overflows during reference processing in the Remark phase Reviewed-by: kbarrett --- src/hotspot/share/gc/g1/g1ConcurrentMark.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 272d91ec869..37ed91d9c73 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -1651,7 +1651,11 @@ void G1ConcurrentMark::weak_refs_work(bool clear_all_soft_refs) { } if (has_overflown()) { - // We can not trust g1_is_alive if the marking stack overflowed + // We can not trust g1_is_alive and the contents of the heap if the marking stack + // overflowed while processing references. Exit the VM. + fatal("Overflow during reference processing, can not continue. Please " + "increase MarkStackSizeMax (current value: " SIZE_FORMAT ") and " + "restart.", MarkStackSizeMax); return; } From 234cd9fca4cd676c6b1a3702900d7b6ce0256425 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Thu, 7 Jun 2018 12:23:46 +0200 Subject: [PATCH 12/46] 8203682: Add jcmd "VM.classloaders" command to print out class loader hierarchy, details Reviewed-by: coleenp, dholmes --- .../classfile/classLoaderHierarchyDCmd.cpp | 456 ++++++++++++++++++ .../classfile/classLoaderHierarchyDCmd.hpp | 58 +++ src/hotspot/share/runtime/vm_operations.hpp | 1 + .../share/services/diagnosticCommand.cpp | 2 + .../dcmd/vm/ClassLoaderHierarchyTest.java | 170 +++++++ 5 files changed, 687 insertions(+) create mode 100644 src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp create mode 100644 src/hotspot/share/classfile/classLoaderHierarchyDCmd.hpp create mode 100644 test/hotspot/jtreg/serviceability/dcmd/vm/ClassLoaderHierarchyTest.java diff --git a/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp b/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp new file mode 100644 index 00000000000..4a5fc402d1a --- /dev/null +++ b/src/hotspot/share/classfile/classLoaderHierarchyDCmd.cpp @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018 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 "classfile/classLoaderData.inline.hpp" +#include "classfile/classLoaderHierarchyDCmd.hpp" +#include "memory/allocation.hpp" +#include "memory/resourceArea.hpp" +#include "runtime/safepoint.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/ostream.hpp" + + +ClassLoaderHierarchyDCmd::ClassLoaderHierarchyDCmd(outputStream* output, bool heap) + : DCmdWithParser(output, heap) + , _show_classes("show-classes", "Print loaded classes.", "BOOLEAN", false, "false") + , _verbose("verbose", "Print detailed information.", "BOOLEAN", false, "false") { + _dcmdparser.add_dcmd_option(&_show_classes); + _dcmdparser.add_dcmd_option(&_verbose); +} + + +int ClassLoaderHierarchyDCmd::num_arguments() { + ResourceMark rm; + ClassLoaderHierarchyDCmd* dcmd = new ClassLoaderHierarchyDCmd(NULL, false); + if (dcmd != NULL) { + DCmdMark mark(dcmd); + return dcmd->_dcmdparser.num_arguments(); + } else { + return 0; + } +} + +// Helper class for drawing the branches to the left of a node. +class BranchTracker : public StackObj { + // "" + // " |---" + // " | | + // " | " + // " | |--- + // " | |--- + // ^^^^^^^ ^^^ + // A B + + // Some terms for the graphics: + // - branch: vertical connection between a node's ancestor to a later sibling. + // - branchwork: (A) the string to print as a prefix at the start of each line, contains all branches. + // - twig (B): Length of the dashed line connecting a node to its branch. + // - branch spacing: how many spaces between branches are printed. + +public: + + enum { max_depth = 64, twig_len = 2, branch_spacing = 5 }; + +private: + + char _branches[max_depth]; + int _pos; + +public: + BranchTracker() + : _pos(0) {} + + void push(bool has_branch) { + if (_pos < max_depth) { + _branches[_pos] = has_branch ? '|' : ' '; + } + _pos ++; // beyond max depth, omit branch drawing but do count on. + } + + void pop() { + assert(_pos > 0, "must be"); + _pos --; + } + + void print(outputStream* st) { + for (int i = 0; i < _pos; i ++) { + st->print("%c%.*s", _branches[i], branch_spacing, " "); + } + } + + class Mark { + BranchTracker& _tr; + public: + Mark(BranchTracker& tr, bool has_branch_here) + : _tr(tr) { _tr.push(has_branch_here); } + ~Mark() { _tr.pop(); } + }; + +}; // end: BranchTracker + +struct LoadedClassInfo : public ResourceObj { +public: + LoadedClassInfo* _next; + Klass* const _klass; + const ClassLoaderData* const _cld; + + LoadedClassInfo(Klass* klass, const ClassLoaderData* cld) + : _klass(klass), _cld(cld) {} + +}; + +class LoaderTreeNode : public ResourceObj { + + // We walk the CLDG and, for each CLD which is non-anonymous, add + // a tree node. To add a node we need its parent node; if it itself + // does not exist yet, we add a preliminary node for it. This preliminary + // node just contains its loader oop; later, when encountering its CLD in + // our CLDG walk, we complete the missing information in this node. + + const oop _loader_oop; + const ClassLoaderData* _cld; + + LoaderTreeNode* _child; + LoaderTreeNode* _next; + + LoadedClassInfo* _classes; + int _num_classes; + + LoadedClassInfo* _anon_classes; + int _num_anon_classes; + + void print_with_childs(outputStream* st, BranchTracker& branchtracker, + bool print_classes, bool verbose) const { + + ResourceMark rm; + + if (_cld == NULL) { + // Not sure how this could happen: we added a preliminary node for a parent but then never encountered + // its CLD? + return; + } + + // Retrieve information. + const Klass* const loader_klass = _cld->class_loader_klass(); + const Symbol* const loader_name = _cld->class_loader_name(); + + branchtracker.print(st); + + // e.g. "+--- jdk.internal.reflect.DelegatingClassLoader" + st->print("+%.*s", BranchTracker::twig_len, "----------"); + if (_cld->is_the_null_class_loader_data()) { + st->print(" "); + } else { + if (loader_name != NULL) { + st->print(" \"%s\",", loader_name->as_C_string()); + } + st->print(" %s", loader_klass != NULL ? loader_klass->external_name() : "??"); + st->print(" {" PTR_FORMAT "}", p2i(_loader_oop)); + } + st->cr(); + + // Output following this node (node details and child nodes) - up to the next sibling node + // needs to be prefixed with "|" if there is a follow up sibling. + const bool have_sibling = _next != NULL; + BranchTracker::Mark trm(branchtracker, have_sibling); + + { + // optional node details following this node needs to be prefixed with "|" + // if there are follow up child nodes. + const bool have_child = _child != NULL; + BranchTracker::Mark trm(branchtracker, have_child); + + // Empty line + branchtracker.print(st); + st->cr(); + + const int indentation = 18; + + if (verbose) { + branchtracker.print(st); + st->print_cr("%*s " PTR_FORMAT, indentation, "Loader Data:", p2i(_cld)); + branchtracker.print(st); + st->print_cr("%*s " PTR_FORMAT, indentation, "Loader Klass:", p2i(loader_klass)); + + // Empty line + branchtracker.print(st); + st->cr(); + } + + if (print_classes) { + + if (_classes != NULL) { + for (LoadedClassInfo* lci = _classes; lci; lci = lci->_next) { + branchtracker.print(st); + if (lci == _classes) { // first iteration + st->print("%*s ", indentation, "Classes:"); + } else { + st->print("%*s ", indentation, ""); + } + st->print("%s", lci->_klass->external_name()); + st->cr(); + // Non-anonymous classes should live in the primary CLD of its loader + assert(lci->_cld == _cld, "must be"); + } + branchtracker.print(st); + st->print("%*s ", indentation, ""); + st->print_cr("(%u class%s)", _num_classes, (_num_classes == 1) ? "" : "es"); + + // Empty line + branchtracker.print(st); + st->cr(); + } + + if (_anon_classes != NULL) { + for (LoadedClassInfo* lci = _anon_classes; lci; lci = lci->_next) { + branchtracker.print(st); + if (lci == _anon_classes) { // first iteration + st->print("%*s ", indentation, "Anonymous Classes:"); + } else { + st->print("%*s ", indentation, ""); + } + st->print("%s", lci->_klass->external_name()); + // For anonymous classes, also print CLD if verbose. Should be a different one than the primary CLD. + assert(lci->_cld != _cld, "must be"); + if (verbose) { + st->print(" (CLD: " PTR_FORMAT ")", p2i(lci->_cld)); + } + st->cr(); + } + branchtracker.print(st); + st->print("%*s ", indentation, ""); + st->print_cr("(%u anonymous class%s)", _num_anon_classes, (_num_anon_classes == 1) ? "" : "es"); + + // Empty line + branchtracker.print(st); + st->cr(); + } + + } // end: print_classes + + } // Pop branchtracker mark + + // Print children, recursively + LoaderTreeNode* c = _child; + while (c != NULL) { + c->print_with_childs(st, branchtracker, print_classes, verbose); + c = c->_next; + } + + } + +public: + + LoaderTreeNode(const oop loader_oop) + : _loader_oop(loader_oop), _cld(NULL) + , _child(NULL), _next(NULL) + , _classes(NULL), _anon_classes(NULL) + , _num_classes(0), _num_anon_classes(0) {} + + void set_cld(const ClassLoaderData* cld) { + _cld = cld; + } + + void add_child(LoaderTreeNode* info) { + info->_next = _child; + _child = info; + } + + void add_sibling(LoaderTreeNode* info) { + assert(info->_next == NULL, "must be"); + info->_next = _next; + _next = info; + } + + void add_classes(LoadedClassInfo* first_class, int num_classes, bool anonymous) { + LoadedClassInfo** p_list_to_add_to = anonymous ? &_anon_classes : &_classes; + // Search tail. + while ((*p_list_to_add_to) != NULL) { + p_list_to_add_to = &(*p_list_to_add_to)->_next; + } + *p_list_to_add_to = first_class; + if (anonymous) { + _num_anon_classes += num_classes; + } else { + _num_classes += num_classes; + } + } + + const ClassLoaderData* cld() const { + return _cld; + } + + const oop loader_oop() const { + return _loader_oop; + } + + LoaderTreeNode* find(const oop loader_oop) { + LoaderTreeNode* result = NULL; + if (_loader_oop == loader_oop) { + result = this; + } else { + LoaderTreeNode* c = _child; + while (c != NULL && result == NULL) { + result = c->find(loader_oop); + c = c->_next; + } + } + return result; + } + + void print_with_childs(outputStream* st, bool print_classes, bool print_add_info) const { + BranchTracker bwt; + print_with_childs(st, bwt, print_classes, print_add_info); + } + +}; + +class LoadedClassCollectClosure : public KlassClosure { +public: + LoadedClassInfo* _list; + const ClassLoaderData* _cld; + int _num_classes; + LoadedClassCollectClosure(const ClassLoaderData* cld) + : _list(NULL), _cld(cld), _num_classes(0) {} + void do_klass(Klass* k) { + LoadedClassInfo* lki = new LoadedClassInfo(k, _cld); + lki->_next = _list; + _list = lki; + _num_classes ++; + } +}; + +class LoaderInfoScanClosure : public CLDClosure { + + const bool _print_classes; + const bool _verbose; + LoaderTreeNode* _root; + + static void fill_in_classes(LoaderTreeNode* info, const ClassLoaderData* cld) { + assert(info != NULL && cld != NULL, "must be"); + LoadedClassCollectClosure lccc(cld); + const_cast(cld)->classes_do(&lccc); + if (lccc._num_classes > 0) { + info->add_classes(lccc._list, lccc._num_classes, cld->is_anonymous()); + } + } + + LoaderTreeNode* find_node_or_add_empty_node(oop loader_oop) { + + assert(_root != NULL, "root node must exist"); + + if (loader_oop == NULL) { + return _root; + } + + // Check if a node for this oop already exists. + LoaderTreeNode* info = _root->find(loader_oop); + + if (info == NULL) { + // It does not. Create a node. + info = new LoaderTreeNode(loader_oop); + + // Add it to tree. + LoaderTreeNode* parent_info = NULL; + + // Recursively add parent nodes if needed. + const oop parent_oop = java_lang_ClassLoader::parent(loader_oop); + if (parent_oop == NULL) { + parent_info = _root; + } else { + parent_info = find_node_or_add_empty_node(parent_oop); + } + assert(parent_info != NULL, "must be"); + + parent_info->add_child(info); + } + return info; + } + + +public: + LoaderInfoScanClosure(bool print_classes, bool verbose) + : _print_classes(print_classes), _verbose(verbose), _root(NULL) { + _root = new LoaderTreeNode(NULL); + } + + void print_results(outputStream* st) const { + _root->print_with_childs(st, _print_classes, _verbose); + } + + void do_cld (ClassLoaderData* cld) { + + // We do not display unloading loaders, for now. + if (cld->is_unloading()) { + return; + } + + const oop loader_oop = cld->class_loader(); + + LoaderTreeNode* info = find_node_or_add_empty_node(loader_oop); + assert(info != NULL, "must be"); + + // Update CLD in node, but only if this is the primary CLD for this loader. + if (cld->is_anonymous() == false) { + assert(info->cld() == NULL, "there should be only one primary CLD per loader"); + info->set_cld(cld); + } + + // Add classes. + fill_in_classes(info, cld); + } + +}; + + +class ClassLoaderHierarchyVMOperation : public VM_Operation { + outputStream* const _out; + const bool _show_classes; + const bool _verbose; +public: + ClassLoaderHierarchyVMOperation(outputStream* out, bool show_classes, bool verbose) : + _out(out), _show_classes(show_classes), _verbose(verbose) + {} + + VMOp_Type type() const { + return VMOp_ClassLoaderHierarchyOperation; + } + + void doit() { + assert(SafepointSynchronize::is_at_safepoint(), "must be a safepoint"); + ResourceMark rm; + LoaderInfoScanClosure cl (_show_classes, _verbose); + ClassLoaderDataGraph::cld_do(&cl); + cl.print_results(_out); + } +}; + +// This command needs to be executed at a safepoint. +void ClassLoaderHierarchyDCmd::execute(DCmdSource source, TRAPS) { + ClassLoaderHierarchyVMOperation op(output(), _show_classes.value(), _verbose.value()); + VMThread::execute(&op); +} diff --git a/src/hotspot/share/classfile/classLoaderHierarchyDCmd.hpp b/src/hotspot/share/classfile/classLoaderHierarchyDCmd.hpp new file mode 100644 index 00000000000..0db0eccf4dc --- /dev/null +++ b/src/hotspot/share/classfile/classLoaderHierarchyDCmd.hpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018 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. + * + */ + +#ifndef HOTSPOT_SHARE_CLASSFILE_CLASSLOADERHIERARCHYDCMD_HPP_ +#define HOTSPOT_SHARE_CLASSFILE_CLASSLOADERHIERARCHYDCMD_HPP_ + +#include "services/diagnosticCommand.hpp" + +class ClassLoaderHierarchyDCmd: public DCmdWithParser { + DCmdArgument _show_classes; + DCmdArgument _verbose; +public: + + ClassLoaderHierarchyDCmd(outputStream* output, bool heap); + + static const char* name() { + return "VM.classloaders"; + } + + static const char* description() { + return "Prints classloader hierarchy."; + } + static const char* impact() { + return "Medium: Depends on number of class loaders and classes loaded."; + } + static const JavaPermission permission() { + JavaPermission p = {"java.lang.management.ManagementPermission", + "monitor", NULL}; + return p; + } + static int num_arguments(); + virtual void execute(DCmdSource source, TRAPS); + +}; + +#endif /* HOTSPOT_SHARE_CLASSFILE_CLASSLOADERHIERARCHYDCMD_HPP_ */ diff --git a/src/hotspot/share/runtime/vm_operations.hpp b/src/hotspot/share/runtime/vm_operations.hpp index 25bc9e72652..56cb4fae9b9 100644 --- a/src/hotspot/share/runtime/vm_operations.hpp +++ b/src/hotspot/share/runtime/vm_operations.hpp @@ -103,6 +103,7 @@ template(RotateGCLog) \ template(WhiteBoxOperation) \ template(ClassLoaderStatsOperation) \ + template(ClassLoaderHierarchyOperation) \ template(DumpHashtable) \ template(DumpTouchedMethods) \ template(MarkActiveNMethods) \ diff --git a/src/hotspot/share/services/diagnosticCommand.cpp b/src/hotspot/share/services/diagnosticCommand.cpp index 490aa3d40d5..ab19c5fa1cf 100644 --- a/src/hotspot/share/services/diagnosticCommand.cpp +++ b/src/hotspot/share/services/diagnosticCommand.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "jvm.h" +#include "classfile/classLoaderHierarchyDCmd.hpp" #include "classfile/classLoaderStats.hpp" #include "classfile/compactHashtable.hpp" #include "compiler/compileBroker.hpp" @@ -101,6 +102,7 @@ void DCmdRegistrant::register_dcmds(){ #endif // INCLUDE_JVMTI DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); diff --git a/test/hotspot/jtreg/serviceability/dcmd/vm/ClassLoaderHierarchyTest.java b/test/hotspot/jtreg/serviceability/dcmd/vm/ClassLoaderHierarchyTest.java new file mode 100644 index 00000000000..8fdfef53207 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/dcmd/vm/ClassLoaderHierarchyTest.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, SAP SE. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Test of diagnostic command VM.classloaders + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.compiler + * java.management + * jdk.internal.jvmstat/sun.jvmstat.monitor + * @run testng ClassLoaderHierarchyTest + */ + +import org.testng.Assert; +import org.testng.annotations.Test; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.dcmd.CommandExecutor; +import jdk.test.lib.dcmd.JMXExecutor; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; + +public class ClassLoaderHierarchyTest { + +//+-- +// | +// +-- "platform", jdk.internal.loader.ClassLoaders$PlatformClassLoader +// | | +// | +-- "app", jdk.internal.loader.ClassLoaders$AppClassLoader +// | +// +-- jdk.internal.reflect.DelegatingClassLoader +// | +// +-- "Kevin", ClassLoaderHierarchyTest$TestClassLoader +// | +// +-- ClassLoaderHierarchyTest$TestClassLoader +// | +// +-- "Bill", ClassLoaderHierarchyTest$TestClassLoader + + public void run(CommandExecutor executor) throws ClassNotFoundException { + + ClassLoader unnamed_cl = new TestClassLoader(null, null); + Class c1 = Class.forName("TestClass2", true, unnamed_cl); + if (c1.getClassLoader() != unnamed_cl) { + Assert.fail("TestClass defined by wrong classloader: " + c1.getClassLoader()); + } + + ClassLoader named_cl = new TestClassLoader("Kevin", null); + Class c2 = Class.forName("TestClass2", true, named_cl); + if (c2.getClassLoader() != named_cl) { + Assert.fail("TestClass defined by wrong classloader: " + c2.getClassLoader()); + } + + ClassLoader named_child_cl = new TestClassLoader("Bill", unnamed_cl); + Class c3 = Class.forName("TestClass2", true, named_child_cl); + if (c3.getClassLoader() != named_child_cl) { + Assert.fail("TestClass defined by wrong classloader: " + c3.getClassLoader()); + } + + // First test: simple output, no classes displayed + OutputAnalyzer output = executor.execute("VM.classloaders"); + output.shouldContain(""); + output.shouldMatch(".*TestClassLoader"); + output.shouldMatch("Kevin.*TestClassLoader"); + output.shouldMatch("Bill.*TestClassLoader"); + + // Second test: print with classes. + output = executor.execute("VM.classloaders show-classes"); + output.shouldContain(""); + output.shouldContain("java.lang.Object"); + output.shouldMatch(".*TestClassLoader"); + output.shouldMatch("Kevin.*TestClassLoader"); + output.shouldMatch("Bill.*TestClassLoader"); + output.shouldContain("TestClass2"); + } + + static class TestClassLoader extends ClassLoader { + + public TestClassLoader() { + super(); + } + + public TestClassLoader(String name, ClassLoader parent) { + super(name, parent); + } + + public static final String CLASS_NAME = "TestClass2"; + + static ByteBuffer readClassFile(String name) + { + File f = new File(System.getProperty("test.classes", "."), + name); + try (FileInputStream fin = new FileInputStream(f); + FileChannel fc = fin.getChannel()) + { + return fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); + } catch (IOException e) { + Assert.fail("Can't open file: " + name, e); + } + + /* Will not reach here as Assert.fail() throws exception */ + return null; + } + + protected Class loadClass(String name, boolean resolve) + throws ClassNotFoundException + { + Class c; + if (!CLASS_NAME.equals(name)) { + c = super.loadClass(name, resolve); + } else { + // should not delegate to the system class loader + c = findClass(name); + if (resolve) { + resolveClass(c); + } + } + return c; + } + + protected Class findClass(String name) + throws ClassNotFoundException + { + if (!CLASS_NAME.equals(name)) { + throw new ClassNotFoundException("Unexpected class: " + name); + } + return defineClass(name, readClassFile(name + ".class"), null); + } + + } + + @Test + public void jmx() throws ClassNotFoundException { + run(new JMXExecutor()); + } + +} + +class TestClass2 { + static { + Runnable r = () -> System.out.println("Hello"); + r.run(); + } +} + From 91f473f2ae7a2f5a147c79199717bfe2a5c7ee0a Mon Sep 17 00:00:00 2001 From: Lance Andersen Date: Thu, 7 Jun 2018 06:27:09 -0400 Subject: [PATCH 13/46] 8201608: fix broken links in javax/sql/rowset/package.html and javax/sql/rowset/spi/package.html Reviewed-by: rriggs, psandoz --- .../javax/sql/rowset/package-info.java | 286 ++++++++++ .../classes/javax/sql/rowset/package.html | 297 ----------- .../javax/sql/rowset/spi/package-info.java | 480 +++++++++++++++++ .../classes/javax/sql/rowset/spi/package.html | 493 ------------------ 4 files changed, 766 insertions(+), 790 deletions(-) create mode 100644 src/java.sql.rowset/share/classes/javax/sql/rowset/package-info.java delete mode 100644 src/java.sql.rowset/share/classes/javax/sql/rowset/package.html create mode 100644 src/java.sql.rowset/share/classes/javax/sql/rowset/spi/package-info.java delete mode 100644 src/java.sql.rowset/share/classes/javax/sql/rowset/spi/package.html diff --git a/src/java.sql.rowset/share/classes/javax/sql/rowset/package-info.java b/src/java.sql.rowset/share/classes/javax/sql/rowset/package-info.java new file mode 100644 index 00000000000..1057b7e37ff --- /dev/null +++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/package-info.java @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * Standard interfaces and base classes for JDBC RowSet + * implementations. This package contains interfaces and classes + * that a standard RowSet implementation either implements or extends. + * + *

Table of Contents

+ * + * + *

1.0 Package Specification

+ * This package specifies five standard JDBC RowSet interfaces. + * All five extend the + * RowSet interface described in the JDBC 3.0 + * specification. It is anticipated that additional definitions + * of more specialized JDBC RowSet types will emerge as this technology + * matures. Future definitions should be specified as subinterfaces using + * inheritance similar to the way it is used in this specification. + *

+ * Note: The interface definitions provided in this package form the basis for + * all compliant JDBC RowSet implementations. Vendors and more advanced + * developers who intend to provide their own compliant RowSet implementations + * should pay particular attention to the assertions detailed in specification + * interfaces. + * + *

2.0 Standard RowSet Definitions

+ *
    + *
  • JdbcRowSet - A wrapper around + * a ResultSet object that makes it possible to use the result set as a + * JavaBeans™ component. Thus, + * a JdbcRowSet object can be a Bean that any tool + * makes available for assembling an application as part of a component based + * architecture. A JdbcRowSet object is a connected RowSet + * object, that is, it + * must continually maintain its connection to its data source using a JDBC + * technology-enabled driver ("JDBC driver"). In addition, a JdbcRowSet + * object provides a fully updatable and scrollable tabular + * data structure as defined in the JDBC 3.0 specification. + * + *
  • + * CachedRowSet + * - A CachedRowSet object is a JavaBeans™ + * component that is scrollable, updatable, serializable, and generally disconnected from + * the source of its data. A CachedRowSet object + * typically contains rows from a result set, but it can also contain rows from any + * file with a tabular format, such as a spreadsheet. CachedRowSet implementations + * must use the SyncFactory to manage and obtain pluggable + * SyncProvider objects to provide synchronization between the + * disconnected RowSet object and the originating data source. + * Typically a SyncProvider implementation relies upon a JDBC + * driver to obtain connectivity to a particular data source. + * Further details on this mechanism are discussed in the javax.sql.rowset.spi package + * specification. + * + *
  • WebRowSet - A + * WebRowSet object is an extension of CachedRowSet + * that can read and write a RowSet object in a well formed XML format. + * This class calls an XmlReader object + * (an extension of the RowSetReader + * interface) to read a rowset in XML format. It calls an + * XmlWriter object (an extension of the + * RowSetWriter interface) + * to write a rowset in XML format. The reader and writer required by + * WebRowSet objects are provided by the + * SyncFactory in the form of SyncProvider + * implementations. In order to ensure well formed XML usage, a standard generic XML + * Schema is defined and published at + * + * http://java.sun.com/xml/ns/jdbc/webrowset.xsd. + * + *
  • FilteredRowSet - A + * FilteredRowSet object provides filtering functionality in a programmatic + * and extensible way. There are many instances when a RowSet object + * has a need to provide filtering in its contents without sacrificing the disconnected + * environment, thus saving the expense of having to create a connection to the data source. + * Solutions to this need vary from providing heavyweight full scale + * SQL query abilities, to portable components, to more lightweight + * approaches. A FilteredRowSet object consumes + * an implementation of the Predicate + * interface, which may define a filter at run time. In turn, a + * FilteredRowSet object is tasked with enforcing the set filter for both + * inbound and outbound read and write operations. That is, all filters can be + * considered as bi-directional. No standard filters are defined; + * however, sufficient mechanics are specified to permit any required filter to be + * implemented. + * + *
  • JoinRowSet - The JoinRowSet + * interface describes a mechanism by which relationships can be established between + * two or more standard RowSet implementations. Any number of RowSet + * objects can be added to a JoinRowSet object provided the RowSetobjects + * can be related in a SQL JOIN like fashion. By definition, the SQL JOIN + * statement is used to combine the data contained in two (or more) relational + * database tables based upon a common attribute. By establishing and then enforcing + * column matches, a JoinRowSet object establishes relationships between + * RowSet instances without the need to touch the originating data source. + *
+ * + *

3.0 Implementer's Guide

+ * Compliant implementations of JDBC RowSet Implementations + * must follow the assertions described in this specification. In accordance + * with the terms of the Java Community Process, a + * Test Compatibility Kit (TCK) can be licensed to ensure compatibility with the + * specification. The following paragraphs outline a number of starting points for + * implementers of the standard JDBC RowSet definitions. Implementers + * should also consult the Implementer's Guide in the javax.sql.rowset.spi package for guidelines + * on SyncProvider implementations. + * + *
    + *
  • 3.1 Constructor + *

    + * All RowSet implementations must provide a + * no-argument constructor. + *

  • + *
  • 3.2 Role of the BaseRowSet Class + *

    + * A compliant JDBC RowSet implementation must implement one or more + * standard interfaces specified in this package and may extend the + * BaseRowSet abstract class. For example, a + * CachedRowSet implementation must implement the CachedRowSet + * interface and extend the BaseRowSet abstract class. The + * BaseRowSet class provides the standard architecture on which all + * RowSet implementations should be built, regardless of whether the + * RowSet objects exist in a connected or disconnected environment. + * The BaseRowSet abstract class provides any RowSet implementation + * with its base functionality, including property manipulation and event notification + * that is fully compliant with JavaBeans + * component requirements. As an example, all implementations provided in the + * reference implementations (contained in the com.sun.rowset package) use + * the BaseRowSet class as a basis for their implementations. + *

    + * The following table illustrates the features that the BaseRowSet + * abstract class provides. + *

    + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    Features in BaseRowSet
    FeatureDetails
    PropertiesProvides standard JavaBeans property manipulation + * mechanisms to allow applications to get and set RowSet command and + * property values. Refer to the documentation of the javax.sql.RowSet + * interface (available in the JDBC 3.0 specification) for more details on + * the standard RowSet properties.
    Event notificationProvides standard JavaBeans event notifications + * to registered event listeners. Refer to the documentation of javax.sql.RowSetEvent + * interface (available in the JDBC 3.0 specification) for + * more details on how to register and handle standard RowSet events generated + * by compliant implementations.
    Setters for a RowSet object's commandProvides a complete set of setter methods + * for setting RowSet command parameters.
    StreamsProvides fields for storing of stream instances + * in addition to providing a set of constants for stream type designation.
    + *
    + * + *
  • 3.3 Connected RowSet Requirements + *

    + * The JdbcRowSet describes a RowSet object that must always + * be connected to the originating data source. Implementations of the JdbcRowSet + * should ensure that this connection is provided solely by a JDBC driver. + * Furthermore, RowSet objects that are implementations of the + * JdbcRowSet interface and are therefore operating in a connected environment + * do not use the SyncFactory to obtain a RowSetReader object + * or a RowSetWriter object. They can safely rely on the JDBC driver to + * supply their needs by virtue of the presence of an underlying updatable and scrollable + * ResultSet implementation. + * + *

  • + * 3.4 Disconnected RowSet Requirements + *

    + * A disconnected RowSet object, such as a CachedRowSet object, + * should delegate + * connection management to a SyncProvider object provided by the + * SyncFactory. To ensure fully disconnected semantics, all + * disconnected RowSet objects must ensure + * that the original connection made to the data source to populate the RowSet + * object is closed to permit the garbage collector to recover and release resources. The + * SyncProvider object ensures that the critical JDBC properties are + * maintained in order to re-establish a connection to the data source when a + * synchronization is required. A disconnected RowSet object should + * therefore ensure that no + * extraneous references remain on the Connection object. + * + *

  • 3.5 Role of RowSetMetaDataImpl + *

    + * The RowsetMetaDataImpl class is a utility class that provides an implementation of the + * RowSetMetaData interface, supplying standard setter + * method implementations for metadata for both connected and disconnected + * RowSet objects. All implementations are free to use this standard + * implementation but are not required to do so. + * + *

  • 3.6 RowSetWarning Class + *

    + * The RowSetWarning class provides warnings that can be set + * on RowSet implementations. + * Similar to SQLWarning objects, + * RowSetWarning objects are silently chained to the object whose method + * caused the warning to be thrown. All RowSet implementations should + * ensure that this chaining occurs if a warning is generated and also ensure that the + * warnings are available via the getRowSetWarnings method defined in either + * the JdbcRowSet interface or the CachedRowSet interface. + * After a warning has been retrieved with one of the + * getRowSetWarnings methods, the RowSetWarning method + * getNextWarning can be called on it to retrieve any warnings that might + * be chained on it. If a warning is returned, getNextWarning can be called + * on it, and so on until there are no more warnings. + * + *

  • 3.7 The Joinable Interface + *

    + * The Joinable interface provides both connected and disconnected + * RowSet objects with the capability to be added to a + * JoinRowSet object in an SQL JOIN operation. + * A RowSet object that has implemented the Joinable + * interface can set a match column, retrieve a match column, or unset a match column. + * A JoinRowSet object can then use the RowSet object's + * match column as a basis for adding the RowSet object. + *

  • + * + *
  • 3.8 The RowSetFactory Interface + *

    + * A RowSetFactory implementation must + * be provided. + *

  • + *
+ * + *

4.0 Related Specifications

+ * + * + *

5.0 Related Documentation

+ * + */ +package javax.sql.rowset; diff --git a/src/java.sql.rowset/share/classes/javax/sql/rowset/package.html b/src/java.sql.rowset/share/classes/javax/sql/rowset/package.html deleted file mode 100644 index 12ee65c9b8e..00000000000 --- a/src/java.sql.rowset/share/classes/javax/sql/rowset/package.html +++ /dev/null @@ -1,297 +0,0 @@ - - - - - - - javax.sql.rowset Package - - - - -Standard interfaces and base classes for JDBC RowSet -implementations. This package contains interfaces and classes -that a standard RowSet implementation either implements or extends. - - -

Table of Contents

- - -

1.0 Package Specification

-This package specifies five standard JDBC RowSet interfaces. - All five extend the -RowSet interface described in the JDBC 3.0 -specification. It is anticipated that additional definitions -of more specialized JDBC RowSet types will emerge as this technology -matures. Future definitions should be specified as subinterfaces using -inheritance similar to the way it is used in this specification. -

-Note: The interface definitions provided in this package form the basis for -all compliant JDBC RowSet implementations. Vendors and more advanced -developers who intend to provide their own compliant RowSet implementations -should pay particular attention to the assertions detailed in specification -interfaces. - -

2.0 Standard RowSet Definitions

-
    -
  • JdbcRowSet - A wrapper around -a ResultSet object that makes it possible to use the result set as a -JavaBeans™ component. Thus, -a JdbcRowSet object can be a Bean that any tool -makes available for assembling an application as part of a component based -architecture. A JdbcRowSet object is a connected RowSet -object, that is, it -must continually maintain its connection to its data source using a JDBC -technology-enabled driver ("JDBC driver"). In addition, a JdbcRowSet -object provides a fully updatable and scrollable tabular -data structure as defined in the JDBC 3.0 specification. - -
  • -CachedRowSet - - A CachedRowSet object is a JavaBeans™ - component that is scrollable, updatable, serializable, and generally disconnected from - the source of its data. A CachedRowSet object -typically contains rows from a result set, but it can also contain rows from any -file with a tabular format, such as a spreadsheet. CachedRowSet implementations -must use the SyncFactory to manage and obtain pluggable -SyncProvider objects to provide synchronization between the -disconnected RowSet object and the originating data source. -Typically a SyncProvider implementation relies upon a JDBC -driver to obtain connectivity to a particular data source. -Further details on this mechanism are discussed in the javax.sql.rowset.spi package -specification. - -
  • WebRowSet - A -WebRowSet object is an extension of CachedRowSet -that can read and write a RowSet object in a well formed XML format. -This class calls an XmlReader object -(an extension of the RowSetReader -interface) to read a rowset in XML format. It calls an -XmlWriter object (an extension of the -RowSetWriter interface) -to write a rowset in XML format. The reader and writer required by -WebRowSet objects are provided by the -SyncFactory in the form of SyncProvider -implementations. In order to ensure well formed XML usage, a standard generic XML -Schema is defined and published at - -http://java.sun.com/xml/ns/jdbc/webrowset.xsd. - -
  • FilteredRowSet - A -FilteredRowSet object provides filtering functionality in a programmatic -and extensible way. There are many instances when a RowSet object -has a need to provide filtering in its contents without sacrificing the disconnected -environment, thus saving the expense of having to create a connection to the data source. -Solutions to this need vary from providing heavyweight full scale -SQL query abilities, to portable components, to more lightweight -approaches. A FilteredRowSet object consumes -an implementation of the Predicate -interface, which may define a filter at run time. In turn, a -FilteredRowSet object is tasked with enforcing the set filter for both -inbound and outbound read and write operations. That is, all filters can be -considered as bi-directional. No standard filters are defined; -however, sufficient mechanics are specified to permit any required filter to be -implemented. - -
  • JoinRowSet - The JoinRowSet -interface describes a mechanism by which relationships can be established between -two or more standard RowSet implementations. Any number of RowSet - objects can be added to a JoinRowSet object provided the RowSetobjects -can be related in a SQL JOIN like fashion. By definition, the SQL JOIN -statement is used to combine the data contained in two (or more) relational -database tables based upon a common attribute. By establishing and then enforcing -column matches, a JoinRowSet object establishes relationships between -RowSet instances without the need to touch the originating data source. -
- -

3.0 Implementer's Guide

-Compliant implementations of JDBC RowSet Implementations -must follow the assertions described in this specification. In accordance -with the terms of the Java Community Process, a -Test Compatibility Kit (TCK) can be licensed to ensure compatibility with the -specification. The following paragraphs outline a number of starting points for -implementers of the standard JDBC RowSet definitions. Implementers -should also consult the Implementer's Guide in the javax.sql.rowset.spi package for guidelines -on SyncProvider implementations. - -
    -
  • 3.1 Constructor -

    - All RowSet implementations must provide a -no-argument constructor. -

  • -
  • 3.2 Role of the BaseRowSet Class -

    -A compliant JDBC RowSet implementation must implement one or more -standard interfaces specified in this package and may extend the -BaseRowSet abstract class. For example, a -CachedRowSet implementation must implement the CachedRowSet -interface and extend the BaseRowSet abstract class. The -BaseRowSet class provides the standard architecture on which all -RowSet implementations should be built, regardless of whether the -RowSet objects exist in a connected or disconnected environment. -The BaseRowSet abstract class provides any RowSet implementation -with its base functionality, including property manipulation and event notification -that is fully compliant with JavaBeans -component requirements. As an example, all implementations provided in the -reference implementations (contained in the com.sun.rowset package) use -the BaseRowSet class as a basis for their implementations. -

    -The following table illustrates the features that the BaseRowSet -abstract class provides. -

    - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Features in BaseRowSet
    FeatureDetails
    PropertiesProvides standard JavaBeans property manipulation -mechanisms to allow applications to get and set RowSet command and -property values. Refer to the documentation of the javax.sql.RowSet -interface (available in the JDBC 3.0 specification) for more details on -the standard RowSet properties.
    Event notificationProvides standard JavaBeans event notifications -to registered event listeners. Refer to the documentation of javax.sql.RowSetEvent -interface (available in the JDBC 3.0 specification) for -more details on how to register and handle standard RowSet events generated -by compliant implementations.
    Setters for a RowSet object's commandProvides a complete set of setter methods - for setting RowSet command parameters.
    StreamsProvides fields for storing of stream instances - in addition to providing a set of constants for stream type designation.
    -
    - -
  • 3.3 Connected RowSet Requirements -

    -The JdbcRowSet describes a RowSet object that must always -be connected to the originating data source. Implementations of the JdbcRowSet -should ensure that this connection is provided solely by a JDBC driver. -Furthermore, RowSet objects that are implementations of the -JdbcRowSet interface and are therefore operating in a connected environment -do not use the SyncFactory to obtain a RowSetReader object -or a RowSetWriter object. They can safely rely on the JDBC driver to -supply their needs by virtue of the presence of an underlying updatable and scrollable -ResultSet implementation. - -

  • -3.4 Disconnected RowSet Requirements -

    -A disconnected RowSet object, such as a CachedRowSet object, -should delegate -connection management to a SyncProvider object provided by the -SyncFactory. To ensure fully disconnected semantics, all -disconnected RowSet objects must ensure -that the original connection made to the data source to populate the RowSet -object is closed to permit the garbage collector to recover and release resources. The -SyncProvider object ensures that the critical JDBC properties are -maintained in order to re-establish a connection to the data source when a -synchronization is required. A disconnected RowSet object should -therefore ensure that no -extraneous references remain on the Connection object. - -

  • 3.5 Role of RowSetMetaDataImpl -

    -The RowsetMetaDataImpl class is a utility class that provides an implementation of the -RowSetMetaData interface, supplying standard setter -method implementations for metadata for both connected and disconnected -RowSet objects. All implementations are free to use this standard -implementation but are not required to do so. - -

  • 3.6 RowSetWarning Class -

    -The RowSetWarning class provides warnings that can be set -on RowSet implementations. -Similar to SQLWarning objects, -RowSetWarning objects are silently chained to the object whose method -caused the warning to be thrown. All RowSet implementations should -ensure that this chaining occurs if a warning is generated and also ensure that the -warnings are available via the getRowSetWarnings method defined in either -the JdbcRowSet interface or the CachedRowSet interface. -After a warning has been retrieved with one of the -getRowSetWarnings methods, the RowSetWarning method -getNextWarning can be called on it to retrieve any warnings that might -be chained on it. If a warning is returned, getNextWarning can be called -on it, and so on until there are no more warnings. - -

  • 3.7 The Joinable Interface -

    -The Joinable interface provides both connected and disconnected -RowSet objects with the capability to be added to a -JoinRowSet object in an SQL JOIN operation. -A RowSet object that has implemented the Joinable -interface can set a match column, retrieve a match column, or unset a match column. -A JoinRowSet object can then use the RowSet object's -match column as a basis for adding the RowSet object. -

  • - -
  • 3.8 The RowSetFactory Interface -

    - A RowSetFactory implementation must - be provided. -

  • -
- -

4.0 Related Specifications

- - -

5.0 Related Documentation

- - - diff --git a/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/package-info.java b/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/package-info.java new file mode 100644 index 00000000000..713b4a1a9a7 --- /dev/null +++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/package-info.java @@ -0,0 +1,480 @@ +/* + * Copyright (c) 2003, 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. + */ + +/** + * The standard classes and interfaces that a third party vendor has to + * use in its implementation of a synchronization provider. These classes and + * interfaces are referred to as the Service Provider Interface (SPI). To make it possible + * for a RowSet object to use an implementation, the vendor must register + * it with the SyncFactory singleton. (See the class comment for + * SyncProvider for a full explanation of the registration process and + * the naming convention to be used.) + * + *

Table of Contents

+ * + * + *

1.0 Package Specification

+ *

+ * The following classes and interfaces make up the javax.sql.rowset.spi + * package: + *

    + *
  • SyncFactory + *
  • SyncProvider + *
  • SyncFactoryException + *
  • SyncProviderException + *
  • SyncResolver + *
  • XmlReader + *
  • XmlWriter + *
  • TransactionalWriter + *
+ * The following interfaces, in the javax.sql package, are also part of the SPI: + *
    + *
  • RowSetReader + *
  • RowSetWriter + *
+ *

+ * A SyncProvider implementation provides a disconnected RowSet + * object with the mechanisms for reading data into it and for writing data that has been + * modified in it + * back to the underlying data source. A reader, a RowSetReader or + * XMLReader object, reads data into a RowSet object when the + * CachedRowSet methods execute or populate + * are called. A writer, a RowSetWriter or XMLWriter + * object, writes changes back to the underlying data source when the + * CachedRowSet method acceptChanges is called. + *

+ * The process of writing changes in a RowSet object to its data source + * is known as synchronization. The SyncProvider implementation that a + * RowSet object is using determines the level of synchronization that the + * RowSet object's writer uses. The various levels of synchronization are + * referred to as grades. + *

+ * The lower grades of synchronization are + * known as optimistic concurrency levels because they optimistically + * assume that there will be no conflicts or very few conflicts. A conflict exists when + * the same data modified in the RowSet object has also been modified + * in the data source. Using the optimistic concurrency model means that if there + * is a conflict, modifications to either the data source or the RowSet + * object will be lost. + *

+ * Higher grades of synchronization are called pessimistic because they assume + * that others will be accessing the data source and making modifications. These + * grades set varying levels of locks to increase the chances that no conflicts + * occur. + *

+ * The lowest level of synchronization is simply writing any changes made to the + * RowSet object to its underlying data source. The writer does + * nothing to check for conflicts. + * If there is a conflict and the data + * source values are overwritten, the changes other parties have made by to the data + * source are lost. + *

+ * The RIXMLProvider implementation uses the lowest level + * of synchronization and just writes RowSet changes to the data source. + * + *

+ * For the next level up, the + * writer checks to see if there are any conflicts, and if there are, + * it does not write anything to the data source. The problem with this concurrency + * level is that if another party has modified the corresponding data in the data source + * since the RowSet object got its data, + * the changes made to the RowSet object are lost. The + * RIOptimisticProvider implementation uses this level of synchronization. + *

+ * At higher levels of synchronization, referred to as pessimistic concurrency, + * the writer take steps to avoid conflicts by setting locks. Setting locks + * can vary from setting a lock on a single row to setting a lock on a table + * or the entire data source. The level of synchronization is therefore a tradeoff + * between the ability of users to access the data source concurrently and the ability + * of the writer to keep the data in the RowSet object and its data source + * synchronized. + *

+ * It is a requirement that all disconnected RowSet objects + * (CachedRowSet, FilteredRowSet, JoinRowSet, + * and WebRowSet objects) obtain their SyncProvider objects + * from the SyncFactory mechanism. + *

+ * The reference implementation (RI) provides two synchronization providers. + *

    + *
  • RIOptimisticProvider
    + * The default provider that the SyncFactory instance will + * supply to a disconnected RowSet object when no provider + * implementation is specified.
    + * This synchronization provider uses an optimistic concurrency model, + * assuming that there will be few conflicts among users + * who are accessing the same data in a database. It avoids + * using locks; rather, it checks to see if there is a conflict + * before trying to synchronize the RowSet object and the + * data source. If there is a conflict, it does nothing, meaning that + * changes to the RowSet object are not persisted to the data + * source. + *
  • RIXMLProvider
    + * A synchronization provider that can be used with a + * WebRowSet object, which is a rowset that can be written + * in XML format or read from XML format. The + * RIXMLProvider implementation does no checking at all for + * conflicts and simply writes any updated data in the + * WebRowSet object to the underlying data source. + * WebRowSet objects use this provider when they are + * dealing with XML data. + *
+ * + * These SyncProvider implementations + * are bundled with the reference implementation, which makes them always available to + * RowSet implementations. + * SyncProvider implementations make themselves available by being + * registered with the SyncFactory singleton. When a RowSet + * object requests a provider, by specifying it in the constructor or as an argument to the + * CachedRowSet method setSyncProvider, + * the SyncFactory singleton + * checks to see if the requested provider has been registered with it. + * If it has, the SyncFactory creates an instance of it and passes it to the + * requesting RowSet object. + * If the SyncProvider implementation that is specified has not been registered, + * the SyncFactory singleton causes a SyncFactoryException object + * to be thrown. If no provider is specified, + * the SyncFactory singleton will create an instance of the default + * provider implementation, RIOptimisticProvider, + * and pass it to the requesting RowSet object. + * + *

+ * If a WebRowSet object does not specify a provider in its constructor, the + * SyncFactory will give it an instance of RIOptimisticProvider. + * However, the constructor for WebRowSet is implemented to set the provider + * to the RIXMLProvider, which reads and writes a RowSet object + * in XML format. + *

+ * See the SyncProvider class + * specification for further details. + *

+ * Vendors may develop a SyncProvider implementation with any one of the possible + * levels of synchronization, thus giving RowSet objects a choice of + * synchronization mechanisms. + * + *

2.0 Service Provider Interface Architecture

+ * 2.1 Overview + *

+ * The Service Provider Interface provides a pluggable mechanism by which + * SyncProvider implementations can be registered and then generated when + * required. The lazy reference mechanism employed by the SyncFactory limits + * unnecessary resource consumption by not creating an instance until it is + * required by a disconnected + * RowSet object. The SyncFactory class also provides + * a standard API to configure logging options and streams that may be provided + * by a particular SyncProvider implementation. + *

+ * 2.2 Registering with the SyncFactory + *

+ * A third party SyncProvider implementation must be registered with the + * SyncFactory in order for a disconnected RowSet object + * to obtain it and thereby use its javax.sql.RowSetReader and + * javax.sql.RowSetWriter + * implementations. The following registration mechanisms are available to all + * SyncProvider implementations: + *

    + *
  • System properties - Properties set at the command line. These + * properties are set at run time and apply system-wide per invocation of the Java + * application. See the section "Related Documentation" + * further related information. + * + *
  • Property Files - Properties specified in a standard property file. + * This can be specified using a System Property or by modifying a standard + * property file located in the platform run-time. The + * reference implementation of this technology includes a standard property + * file than can be edited to add additional SyncProvider objects. + * + *
  • JNDI Context - Available providers can be registered on a JNDI + * context. The SyncFactory will attempt to load SyncProvider + * objects bound to the context and register them with the factory. This + * context must be supplied to the SyncFactory for the mechanism to + * function correctly. + *
+ *

+ * Details on how to specify the system properties or properties in a property file + * and how to configure the JNDI Context are explained in detail in the + * SyncFactory class description. + *

+ * 2.3 SyncFactory Provider Instance Generation Policies + *

+ * The SyncFactory generates a requested SyncProvider + * object if the provider has been correctly registered. The + * following policies are adhered to when either a disconnected RowSet object + * is instantiated with a specified SyncProvider implementation or is + * reconfigured at runtime with an alternative SyncProvider object. + *

    + *
  • If a SyncProvider object is specified and the SyncFactory + * contains no reference to the provider, a SyncFactoryException is + * thrown. + * + *
  • If a SyncProvider object is specified and the SyncFactory + * contains a reference to the provider, the requested provider is supplied. + * + *
  • If no SyncProvider object is specified, the reference + * implementation provider RIOptimisticProvider is supplied. + *
+ *

+ * These policies are explored in more detail in the + * SyncFactory class. + * + *

3.0 SyncProvider Implementer's Guide

+ * + * 3.1 Requirements + *

+ * A compliant SyncProvider implementation that is fully pluggable + * into the SyncFactory must extend and implement all + * abstract methods in the SyncProvider + * class. In addition, an implementation must determine the + * grade, locking and updatable view capabilities defined in the + * SyncProvider class definition. One or more of the + * SyncProvider description criteria must be supported. It + * is expected that vendor implementations will offer a range of grade, locking, and + * updatable view capabilities. + *

+ * Furthermore, the SyncProvider naming convention must be followed as + * detailed in the SyncProvider class + * description. + *

+ * 3.2 Grades + *

+ * JSR 114 defines a set of grades to describe the quality of synchronization + * a SyncProvider object can offer a disconnected RowSet + * object. These grades are listed from the lowest quality of service to the highest. + *

    + *
  • GRADE_NONE - No synchronization with the originating data source is + * provided. A SyncProvider implementation returning this grade will simply + * attempt to write any data that has changed in the RowSet object to the + *underlying data source, overwriting whatever is there. No attempt is made to compare + * original values with current values to see if there is a conflict. The + * RIXMLProvider is implemented with this grade. + * + *
  • GRADE_CHECK_MODIFIED_AT_COMMIT - A low grade of optimistic synchronization. + * A SyncProvider implementation returning this grade + * will check for conflicts in rows that have changed between the last synchronization + * and the current synchronization under way. Any changes in the originating data source + * that have been modified will not be reflected in the disconnected RowSet + * object. If there are no conflicts, changes in the RowSet object will be + * written to the data source. If there are conflicts, no changes are written. + * The RIOptimisticProvider implementation uses this grade. + * + *
  • GRADE_CHECK_ALL_AT_COMMIT - A high grade of optimistic synchronization. + * A SyncProvider implementation returning this grade + * will check all rows, including rows that have not changed in the disconnected + * RowSet object. In this way, any changes to rows in the underlying + * data source will be reflected in the disconnected RowSet object + * when the synchronization finishes successfully. + * + *
  • GRADE_LOCK_WHEN_MODIFIED - A pessimistic grade of synchronization. + * SyncProvider implementations returning this grade will lock + * the row in the originating data source that corresponds to the row being changed + * in the RowSet object to reduce the possibility of other + * processes modifying the same data in the data source. + * + *
  • GRADE_LOCK_WHEN_LOADED - A higher pessimistic synchronization grade. + * A SyncProvider implementation returning this grade will lock + * the entire view and/or table affected by the original query used to + * populate a RowSet object. + *
+ *

+ * 3.3 Locks + *

+ * JSR 114 defines a set of constants that specify whether any locks have been + * placed on a RowSet object's underlying data source and, if so, + * on which constructs the locks are placed. These locks will remain on the data + * source while the RowSet object is disconnected from the data source. + *

+ * These constants should be considered complementary to the + * grade constants. The default setting for the majority of grade settings requires + * that no data source locks remain when a RowSet object is disconnected + * from its data source. + * The grades GRADE_LOCK_WHEN_MODIFIED and + * GRADE_LOCK_WHEN_LOADED allow a disconnected RowSet object + * to have a fine-grained control over the degree of locking. + *

    + *
  • DATASOURCE_NO_LOCK - No locks remain on the originating data source. + * This is the default lock setting for all SyncProvider implementations + * unless otherwise directed by a RowSet object. + * + *
  • DATASOURCE_ROW_LOCK - A lock is placed on the rows that are touched by + * the original SQL query used to populate the RowSet object. + * + *
  • DATASOURCE_TABLE_LOCK - A lock is placed on all tables that are touched + * by the query that was used to populate the RowSet object. + * + *
  • DATASOURCE_DB_LOCK + * A lock is placed on the entire data source that is used by the RowSet + * object. + *
+ *

+ * 3.4 Updatable Views + *

+ * A RowSet object may be populated with data from an SQL VIEW. + * The following constants indicate whether a SyncProvider object can + * update data in the table or tables from which the VIEW was derived. + *

    + *
  • UPDATABLE_VIEW_SYNC + * Indicates that a SyncProvider implementation supports synchronization + * to the table or tables from which the SQL VIEW used to populate + * a RowSet object is derived. + * + *
  • NONUPDATABLE_VIEW_SYNC + * Indicates that a SyncProvider implementation does not support + * synchronization to the table or tables from which the SQL VIEW + * used to populate a RowSet object is derived. + *
+ *

+ * 3.5 Usage of SyncProvider Grading and Locking + *

+ * In the example below, the reference CachedRowSetImpl implementation + * reconfigures its current SyncProvider object by calling the + * setSyncProvider method.
+ * + *

+ *   CachedRowSetImpl crs = new CachedRowSetImpl();
+ *   crs.setSyncProvider("com.foo.bar.HASyncProvider");
+ * 
+ * An application can retrieve the SyncProvider object currently in use + * by a disconnected RowSet object. It can also retrieve the + * grade of synchronization with which the provider was implemented and the degree of + * locking currently in use. In addition, an application has the flexibility to set + * the degree of locking to be used, which can increase the possibilities for successful + * synchronization. These operation are shown in the following code fragment. + *
+ *   SyncProvider sync = crs.getSyncProvider();
+ *
+ *   switch (sync.getProviderGrade()) {
+ *   case: SyncProvider.GRADE_CHECK_ALL_AT_COMMIT
+ *         //A high grade of optimistic synchronization
+ *    break;
+ *    case: SyncProvider.GRADE_CHECK_MODIFIED_AT_COMMIT
+ *         //A low grade of optimistic synchronization
+ *    break;
+ *    case: SyncProvider.GRADE_LOCK_WHEN_LOADED
+ *         // A pessimistic synchronization grade
+ *    break;
+ *    case: SyncProvider.GRADE_LOCK_WHEN_MODIFIED
+ *         // A pessimistic synchronization grade
+ *    break;
+ *    case: SyncProvider.GRADE_NONE
+ *      // No synchronization with the originating data source provided
+ *    break;
+ *    }
+ *
+ *    switch (sync.getDataSourcLock() {
+ *      case: SyncProvider.DATASOURCE_DB_LOCK
+ *       // A lock is placed on the entire datasource that is used by the
+ *       // RowSet object
+ *       break;
+ *
+ *      case: SyncProvider.DATASOURCE_NO_LOCK
+ *       // No locks remain on the  originating data source.
+ *      break;
+ *
+ *      case: SyncProvider.DATASOURCE_ROW_LOCK
+ *       // A lock is placed on the rows that are  touched by the original
+ *       // SQL statement used to populate
+ *       // the RowSet object that is using the SyncProvider
+ *       break;
+ *
+ *      case: DATASOURCE_TABLE_LOCK
+ *       // A lock is placed on  all tables that are touched by the original
+ *       // SQL statement used to populated
+ *       // the RowSet object that is using the SyncProvider
+ *      break;
+ *
+ * 
+ * It is also possible using the static utility method in the + * SyncFactory class to determine the list of SyncProvider + * implementations currently registered with the SyncFactory. + * + *
+ *       Enumeration e = SyncFactory.getRegisteredProviders();
+ * 
+ * + * + *

4.0 Resolving Synchronization Conflicts

+ * + * The interface SyncResolver provides a way for an application to + * decide manually what to do when a conflict occurs. When the CachedRowSet + * method acceptChanges finishes and has detected one or more conflicts, + * it throws a SyncProviderException object. An application can + * catch the exception and + * have it retrieve a SyncResolver object by calling the method + * SyncProviderException.getSyncResolver(). + *

+ * A SyncResolver object, which is a special kind of + * CachedRowSet object or + * a JdbcRowSet object that has implemented the SyncResolver + * interface, examines the conflicts row by row. It is a duplicate of the + * RowSet object being synchronized except that it contains only the data + * from the data source this is causing a conflict. All of the other column values are + * set to null. To navigate from one conflict value to another, a + * SyncResolver object provides the methods nextConflict and + * previousConflict. + *

+ * The SyncResolver interface also + * provides methods for doing the following: + *

    + *
  • finding out whether the conflict involved an update, a delete, or an insert + *
  • getting the value in the data source that caused the conflict + *
  • setting the value that should be in the data source if it needs to be changed + * or setting the value that should be in the RowSet object if it needs + * to be changed + *
+ *

+ * When the CachedRowSet method acceptChanges is called, it + * delegates to the RowSet object's SyncProvider object. + * How the writer provided by that SyncProvider object is implemented + * determines what level (grade) of checking for conflicts will be done. After all + * checking for conflicts is completed and one or more conflicts has been found, the method + * acceptChanges throws a SyncProviderException object. The + * application can catch the exception and use it to obtain a SyncResolver object. + *

+ * The application can then use SyncResolver methods to get information + * about each conflict and decide what to do. If the application logic or the user + * decides that a value in the RowSet object should be the one to + * persist, the application or user can overwrite the data source value with it. + *

+ * The comment for the SyncResolver interface has more detail. + * + *

5.0 Related Specifications

+ * + *

6.0 Related Documentation

+ * + */ +package javax.sql.rowset.spi; diff --git a/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/package.html b/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/package.html deleted file mode 100644 index 786b906fec9..00000000000 --- a/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/package.html +++ /dev/null @@ -1,493 +0,0 @@ - - - - - - - - - javax.sql.rowset.spi - - - - -The standard classes and interfaces that a third party vendor has to -use in its implementation of a synchronization provider. These classes and -interfaces are referred to as the Service Provider Interface (SPI). To make it possible -for a RowSet object to use an implementation, the vendor must register -it with the SyncFactory singleton. (See the class comment for -SyncProvider for a full explanation of the registration process and -the naming convention to be used.) - -

Table of Contents

- - -

1.0 Package Specification

-

-The following classes and interfaces make up the javax.sql.rowset.spi -package: -

    -
  • SyncFactory -
  • SyncProvider -
  • SyncFactoryException -
  • SyncProviderException -
  • SyncResolver -
  • XmlReader -
  • XmlWriter -
  • TransactionalWriter -
-The following interfaces, in the javax.sql package, are also part of the SPI: -
    -
  • RowSetReader -
  • RowSetWriter -
-

-A SyncProvider implementation provides a disconnected RowSet -object with the mechanisms for reading data into it and for writing data that has been -modified in it -back to the underlying data source. A reader, a RowSetReader or -XMLReader object, reads data into a RowSet object when the -CachedRowSet methods execute or populate -are called. A writer, a RowSetWriter or XMLWriter -object, writes changes back to the underlying data source when the -CachedRowSet method acceptChanges is called. -

-The process of writing changes in a RowSet object to its data source -is known as synchronization. The SyncProvider implementation that a -RowSet object is using determines the level of synchronization that the -RowSet object's writer uses. The various levels of synchronization are -referred to as grades. -

-The lower grades of synchronization are -known as optimistic concurrency levels because they optimistically -assume that there will be no conflicts or very few conflicts. A conflict exists when -the same data modified in the RowSet object has also been modified -in the data source. Using the optimistic concurrency model means that if there -is a conflict, modifications to either the data source or the RowSet -object will be lost. -

-Higher grades of synchronization are called pessimistic because they assume -that others will be accessing the data source and making modifications. These -grades set varying levels of locks to increase the chances that no conflicts -occur. -

-The lowest level of synchronization is simply writing any changes made to the -RowSet object to its underlying data source. The writer does -nothing to check for conflicts. -If there is a conflict and the data -source values are overwritten, the changes other parties have made by to the data -source are lost. -

-The RIXMLProvider implementation uses the lowest level -of synchronization and just writes RowSet changes to the data source. - -

-For the next level up, the -writer checks to see if there are any conflicts, and if there are, -it does not write anything to the data source. The problem with this concurrency -level is that if another party has modified the corresponding data in the data source -since the RowSet object got its data, -the changes made to the RowSet object are lost. The -RIOptimisticProvider implementation uses this level of synchronization. -

-At higher levels of synchronization, referred to as pessimistic concurrency, -the writer take steps to avoid conflicts by setting locks. Setting locks -can vary from setting a lock on a single row to setting a lock on a table -or the entire data source. The level of synchronization is therefore a tradeoff -between the ability of users to access the data source concurrently and the ability -of the writer to keep the data in the RowSet object and its data source -synchronized. -

-It is a requirement that all disconnected RowSet objects -(CachedRowSet, FilteredRowSet, JoinRowSet, -and WebRowSet objects) obtain their SyncProvider objects -from the SyncFactory mechanism. -

-The reference implementation (RI) provides two synchronization providers. -

    -
  • RIOptimisticProvider
    - The default provider that the SyncFactory instance will - supply to a disconnected RowSet object when no provider - implementation is specified.
    - This synchronization provider uses an optimistic concurrency model, - assuming that there will be few conflicts among users - who are accessing the same data in a database. It avoids - using locks; rather, it checks to see if there is a conflict - before trying to synchronize the RowSet object and the - data source. If there is a conflict, it does nothing, meaning that - changes to the RowSet object are not persisted to the data - source. -
  • RIXMLProvider
    - A synchronization provider that can be used with a - WebRowSet object, which is a rowset that can be written - in XML format or read from XML format. The - RIXMLProvider implementation does no checking at all for - conflicts and simply writes any updated data in the - WebRowSet object to the underlying data source. - WebRowSet objects use this provider when they are - dealing with XML data. -
- -These SyncProvider implementations -are bundled with the reference implementation, which makes them always available to -RowSet implementations. -SyncProvider implementations make themselves available by being -registered with the SyncFactory singleton. When a RowSet -object requests a provider, by specifying it in the constructor or as an argument to the -CachedRowSet method setSyncProvider, -the SyncFactory singleton -checks to see if the requested provider has been registered with it. -If it has, the SyncFactory creates an instance of it and passes it to the -requesting RowSet object. -If the SyncProvider implementation that is specified has not been registered, -the SyncFactory singleton causes a SyncFactoryException object -to be thrown. If no provider is specified, -the SyncFactory singleton will create an instance of the default -provider implementation, RIOptimisticProvider, -and pass it to the requesting RowSet object. - -

-If a WebRowSet object does not specify a provider in its constructor, the -SyncFactory will give it an instance of RIOptimisticProvider. -However, the constructor for WebRowSet is implemented to set the provider -to the RIXMLProvider, which reads and writes a RowSet object -in XML format. -

-See the SyncProvider class -specification for further details. -

-Vendors may develop a SyncProvider implementation with any one of the possible -levels of synchronization, thus giving RowSet objects a choice of -synchronization mechanisms. - -

2.0 Service Provider Interface Architecture

-2.1 Overview -

-The Service Provider Interface provides a pluggable mechanism by which -SyncProvider implementations can be registered and then generated when -required. The lazy reference mechanism employed by the SyncFactory limits -unnecessary resource consumption by not creating an instance until it is -required by a disconnected -RowSet object. The SyncFactory class also provides -a standard API to configure logging options and streams that may be provided -by a particular SyncProvider implementation. -

-2.2 Registering with the SyncFactory -

-A third party SyncProvider implementation must be registered with the -SyncFactory in order for a disconnected RowSet object -to obtain it and thereby use its javax.sql.RowSetReader and -javax.sql.RowSetWriter -implementations. The following registration mechanisms are available to all -SyncProvider implementations: -

    -
  • System properties - Properties set at the command line. These -properties are set at run time and apply system-wide per invocation of the Java -application. See the section "Related Documentation" -further related information. - -
  • Property Files - Properties specified in a standard property file. -This can be specified using a System Property or by modifying a standard -property file located in the platform run-time. The -reference implementation of this technology includes a standard property -file than can be edited to add additional SyncProvider objects. - -
  • JNDI Context - Available providers can be registered on a JNDI -context. The SyncFactory will attempt to load SyncProvider -objects bound to the context and register them with the factory. This -context must be supplied to the SyncFactory for the mechanism to -function correctly. -
-

-Details on how to specify the system properties or properties in a property file -and how to configure the JNDI Context are explained in detail in the -SyncFactory class description. -

-2.3 SyncFactory Provider Instance Generation Policies -

-The SyncFactory generates a requested SyncProvider -object if the provider has been correctly registered. The -following policies are adhered to when either a disconnected RowSet object -is instantiated with a specified SyncProvider implementation or is -reconfigured at runtime with an alternative SyncProvider object. -

    -
  • If a SyncProvider object is specified and the SyncFactory -contains no reference to the provider, a SyncFactoryException is -thrown. - -
  • If a SyncProvider object is specified and the SyncFactory -contains a reference to the provider, the requested provider is supplied. - -
  • If no SyncProvider object is specified, the reference -implementation provider RIOptimisticProvider is supplied. -
-

-These policies are explored in more detail in the -SyncFactory class. - -

3.0 SyncProvider Implementer's Guide

- -3.1 Requirements -

-A compliant SyncProvider implementation that is fully pluggable -into the SyncFactory must extend and implement all -abstract methods in the SyncProvider -class. In addition, an implementation must determine the -grade, locking and updatable view capabilities defined in the -SyncProvider class definition. One or more of the -SyncProvider description criteria must be supported. It -is expected that vendor implementations will offer a range of grade, locking, and -updatable view capabilities. -

-Furthermore, the SyncProvider naming convention must be followed as -detailed in the SyncProvider class -description. -

-3.2 Grades -

-JSR 114 defines a set of grades to describe the quality of synchronization -a SyncProvider object can offer a disconnected RowSet -object. These grades are listed from the lowest quality of service to the highest. -

    -
  • GRADE_NONE - No synchronization with the originating data source is -provided. A SyncProvider implementation returning this grade will simply -attempt to write any data that has changed in the RowSet object to the -underlying data source, overwriting whatever is there. No attempt is made to compare -original values with current values to see if there is a conflict. The -RIXMLProvider is implemented with this grade. - -
  • GRADE_CHECK_MODIFIED_AT_COMMIT - A low grade of optimistic synchronization. -A SyncProvider implementation returning this grade -will check for conflicts in rows that have changed between the last synchronization -and the current synchronization under way. Any changes in the originating data source -that have been modified will not be reflected in the disconnected RowSet -object. If there are no conflicts, changes in the RowSet object will be -written to the data source. If there are conflicts, no changes are written. -The RIOptimisticProvider implementation uses this grade. - -
  • GRADE_CHECK_ALL_AT_COMMIT - A high grade of optimistic synchronization. -A SyncProvider implementation returning this grade -will check all rows, including rows that have not changed in the disconnected -RowSet object. In this way, any changes to rows in the underlying -data source will be reflected in the disconnected RowSet object -when the synchronization finishes successfully. - -
  • GRADE_LOCK_WHEN_MODIFIED - A pessimistic grade of synchronization. -SyncProvider implementations returning this grade will lock -the row in the originating data source that corresponds to the row being changed -in the RowSet object to reduce the possibility of other -processes modifying the same data in the data source. - -
  • GRADE_LOCK_WHEN_LOADED - A higher pessimistic synchronization grade. -A SyncProvider implementation returning this grade will lock -the entire view and/or table affected by the original query used to -populate a RowSet object. -
-

-3.3 Locks -

-JSR 114 defines a set of constants that specify whether any locks have been -placed on a RowSet object's underlying data source and, if so, -on which constructs the locks are placed. These locks will remain on the data -source while the RowSet object is disconnected from the data source. -

-These constants should be considered complementary to the -grade constants. The default setting for the majority of grade settings requires -that no data source locks remain when a RowSet object is disconnected -from its data source. -The grades GRADE_LOCK_WHEN_MODIFIED and -GRADE_LOCK_WHEN_LOADED allow a disconnected RowSet object -to have a fine-grained control over the degree of locking. -

    -
  • DATASOURCE_NO_LOCK - No locks remain on the originating data source. -This is the default lock setting for all SyncProvider implementations -unless otherwise directed by a RowSet object. - -
  • DATASOURCE_ROW_LOCK - A lock is placed on the rows that are touched by -the original SQL query used to populate the RowSet object. - -
  • DATASOURCE_TABLE_LOCK - A lock is placed on all tables that are touched -by the query that was used to populate the RowSet object. - -
  • DATASOURCE_DB_LOCK -A lock is placed on the entire data source that is used by the RowSet -object. -
-

-3.4 Updatable Views -

-A RowSet object may be populated with data from an SQL VIEW. -The following constants indicate whether a SyncProvider object can -update data in the table or tables from which the VIEW was derived. -

    -
  • UPDATABLE_VIEW_SYNC -Indicates that a SyncProvider implementation supports synchronization -to the table or tables from which the SQL VIEW used to populate -a RowSet object is derived. - -
  • NONUPDATABLE_VIEW_SYNC -Indicates that a SyncProvider implementation does not support -synchronization to the table or tables from which the SQL VIEW -used to populate a RowSet object is derived. -
-

-3.5 Usage of SyncProvider Grading and Locking -

-In the example below, the reference CachedRowSetImpl implementation -reconfigures its current SyncProvider object by calling the -setSyncProvider method.
- -

-    CachedRowSetImpl crs = new CachedRowSetImpl();
-    crs.setSyncProvider("com.foo.bar.HASyncProvider");
-
- An application can retrieve the SyncProvider object currently in use -by a disconnected RowSet object. It can also retrieve the -grade of synchronization with which the provider was implemented and the degree of -locking currently in use. In addition, an application has the flexibility to set -the degree of locking to be used, which can increase the possibilities for successful -synchronization. These operation are shown in the following code fragment. -
-    SyncProvider sync = crs.getSyncProvider();
-
-    switch (sync.getProviderGrade()) {
-    case: SyncProvider.GRADE_CHECK_ALL_AT_COMMIT
-         //A high grade of optimistic synchronization
-    break;
-    case: SyncProvider.GRADE_CHECK_MODIFIED_AT_COMMIT
-         //A low grade of optimistic synchronization
-    break;
-    case: SyncProvider.GRADE_LOCK_WHEN_LOADED
-         // A pessimistic synchronization grade
-    break;
-    case: SyncProvider.GRADE_LOCK_WHEN_MODIFIED
-         // A pessimistic synchronization grade
-    break;
-    case: SyncProvider.GRADE_NONE
-      // No synchronization with the originating data source provided
-    break;
-    }
-
-    switch (sync.getDataSourcLock() {
-      case: SyncProvider.DATASOURCE_DB_LOCK
-       // A lock is placed on the entire datasource that is used by the
-       // RowSet object
-       break;
-
-      case: SyncProvider.DATASOURCE_NO_LOCK
-       // No locks remain on the  originating data source.
-      break;
-
-      case: SyncProvider.DATASOURCE_ROW_LOCK
-       // A lock is placed on the rows that are  touched by the original
-       // SQL statement used to populate
-       // the RowSet object that is using the SyncProvider
-       break;
-
-      case: DATASOURCE_TABLE_LOCK
-       // A lock is placed on  all tables that are touched by the original
-       // SQL statement used to populated
-       // the RowSet object that is using the SyncProvider
-       break;
-
-
- It is also possible using the static utility method in the -SyncFactory class to determine the list of SyncProvider -implementations currently registered with the SyncFactory. - -
-       Enumeration e = SyncFactory.getRegisteredProviders();
-
- - -

4.0 Resolving Synchronization Conflicts

- -The interface SyncResolver provides a way for an application to -decide manually what to do when a conflict occurs. When the CachedRowSet -method acceptChanges finishes and has detected one or more conflicts, -it throws a SyncProviderException object. An application can -catch the exception and -have it retrieve a SyncResolver object by calling the method -SyncProviderException.getSyncResolver(). -

-A SyncResolver object, which is a special kind of -CachedRowSet object or -a JdbcRowSet object that has implemented the SyncResolver -interface, examines the conflicts row by row. It is a duplicate of the -RowSet object being synchronized except that it contains only the data -from the data source this is causing a conflict. All of the other column values are -set to null. To navigate from one conflict value to another, a -SyncResolver object provides the methods nextConflict and -previousConflict. -

-The SyncResolver interface also -provides methods for doing the following: -

    -
  • finding out whether the conflict involved an update, a delete, or an insert -
  • getting the value in the data source that caused the conflict -
  • setting the value that should be in the data source if it needs to be changed - or setting the value that should be in the RowSet object if it needs - to be changed -
-

-When the CachedRowSet method acceptChanges is called, it -delegates to the RowSet object's SyncProvider object. -How the writer provided by that SyncProvider object is implemented -determines what level (grade) of checking for conflicts will be done. After all -checking for conflicts is completed and one or more conflicts has been found, the method -acceptChanges throws a SyncProviderException object. The -application can catch the exception and use it to obtain a SyncResolver object. -

-The application can then use SyncResolver methods to get information -about each conflict and decide what to do. If the application logic or the user -decides that a value in the RowSet object should be the one to -persist, the application or user can overwrite the data source value with it. -

-The comment for the SyncResolver interface has more detail. - -

5.0 Related Specifications

- -

6.0 Related Documentation

- - - - From 66f8951e1550b156d67ca1f60dca9b20c90fd133 Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Thu, 7 Jun 2018 14:11:56 +0200 Subject: [PATCH 14/46] 8195097: Make it possible to process StringTable outside safepoint Reviewed-by: coleenp, gziemski, iklam, jiangli --- src/hotspot/share/classfile/stringTable.cpp | 1185 +++++++++-------- src/hotspot/share/classfile/stringTable.hpp | 176 ++- src/hotspot/share/gc/cms/cmsHeap.cpp | 5 +- src/hotspot/share/gc/cms/cmsHeap.hpp | 4 +- .../gc/cms/concurrentMarkSweepGeneration.cpp | 12 +- src/hotspot/share/gc/cms/parNewGeneration.cpp | 7 +- src/hotspot/share/gc/cms/parNewGeneration.hpp | 2 + src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 13 +- src/hotspot/share/gc/g1/g1RootProcessor.cpp | 4 +- src/hotspot/share/gc/g1/g1RootProcessor.hpp | 2 + .../share/gc/shared/genCollectedHeap.cpp | 20 +- .../share/gc/shared/genCollectedHeap.hpp | 10 +- .../share/gc/shared/strongRootsScope.cpp | 2 - src/hotspot/share/memory/metaspaceShared.cpp | 2 +- src/hotspot/share/oops/weakHandle.cpp | 6 + src/hotspot/share/oops/weakHandle.hpp | 5 +- src/hotspot/share/oops/weakHandle.inline.hpp | 6 + src/hotspot/share/runtime/globals.hpp | 5 +- src/hotspot/share/runtime/java.cpp | 9 +- src/hotspot/share/runtime/mutexLocker.cpp | 5 + src/hotspot/share/runtime/mutexLocker.hpp | 2 + src/hotspot/share/runtime/serviceThread.cpp | 9 +- src/hotspot/share/runtime/vmStructs.cpp | 8 - .../share/utilities/concurrentHashTable.hpp | 3 + .../utilities/concurrentHashTable.inline.hpp | 96 +- .../concurrentHashTableTasks.inline.hpp | 2 + .../share/utilities/globalDefinitions.hpp | 4 +- .../sun/jvm/hotspot/memory/StringTable.java | 77 -- .../classes/sun/jvm/hotspot/runtime/VM.java | 8 - .../sun/jvm/hotspot/tools/HeapSummary.java | 38 - .../utilities/test_concurrentHashtable.cpp | 38 + 31 files changed, 917 insertions(+), 848 deletions(-) delete mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/StringTable.java diff --git a/src/hotspot/share/classfile/stringTable.cpp b/src/hotspot/share/classfile/stringTable.cpp index 96e3f858563..fc696792e7d 100644 --- a/src/hotspot/share/classfile/stringTable.cpp +++ b/src/hotspot/share/classfile/stringTable.cpp @@ -29,7 +29,10 @@ #include "classfile/stringTable.hpp" #include "classfile/systemDictionary.hpp" #include "gc/shared/collectedHeap.hpp" +#include "gc/shared/oopStorage.inline.hpp" +#include "gc/shared/oopStorageParState.inline.hpp" #include "logging/log.hpp" +#include "logging/logStream.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" #include "memory/metaspaceShared.hpp" @@ -38,171 +41,196 @@ #include "oops/access.inline.hpp" #include "oops/oop.inline.hpp" #include "oops/typeArrayOop.inline.hpp" +#include "oops/weakHandle.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/handles.inline.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/safepointVerifiers.hpp" +#include "runtime/timerTrace.hpp" +#include "runtime/interfaceSupport.inline.hpp" #include "services/diagnosticCommand.hpp" -#include "utilities/hashtable.inline.hpp" +#include "utilities/concurrentHashTable.inline.hpp" +#include "utilities/concurrentHashTableTasks.inline.hpp" #include "utilities/macros.hpp" -// the number of buckets a thread claims -const int ClaimChunkSize = 32; - -#ifdef ASSERT -class StableMemoryChecker : public StackObj { - enum { _bufsize = wordSize*4 }; - - address _region; - jint _size; - u1 _save_buf[_bufsize]; - - int sample(u1* save_buf) { - if (_size <= _bufsize) { - memcpy(save_buf, _region, _size); - return _size; - } else { - // copy head and tail - memcpy(&save_buf[0], _region, _bufsize/2); - memcpy(&save_buf[_bufsize/2], _region + _size - _bufsize/2, _bufsize/2); - return (_bufsize/2)*2; - } - } - - public: - StableMemoryChecker(const void* region, jint size) { - _region = (address) region; - _size = size; - sample(_save_buf); - } - - bool verify() { - u1 check_buf[sizeof(_save_buf)]; - int check_size = sample(check_buf); - return (0 == memcmp(_save_buf, check_buf, check_size)); - } - - void set_region(const void* region) { _region = (address) region; } -}; -#endif - +// We prefer short chains of avg 2 +#define PREF_AVG_LIST_LEN 2 +// 2^24 is max size +#define END_SIZE 24 +// If a chain gets to 32 something might be wrong +#define REHASH_LEN 32 +// If we have as many dead items as 50% of the number of bucket +#define CLEAN_DEAD_HIGH_WATER_MARK 0.5 // -------------------------------------------------------------------------- StringTable* StringTable::_the_table = NULL; bool StringTable::_shared_string_mapped = false; -bool StringTable::_needs_rehashing = false; - -volatile int StringTable::_parallel_claimed_idx = 0; - CompactHashtable StringTable::_shared_table; +bool StringTable::_alt_hash = false; -// Pick hashing algorithm -unsigned int StringTable::hash_string(const jchar* s, int len) { - return use_alternate_hashcode() ? alt_hash_string(s, len) : - java_lang_String::hash_code(s, len); +static juint murmur_seed = 0; + +uintx hash_string(const jchar* s, int len, bool useAlt) { + return useAlt ? + AltHashing::murmur3_32(murmur_seed, s, len) : + java_lang_String::hash_code(s, len); } -unsigned int StringTable::alt_hash_string(const jchar* s, int len) { - return AltHashing::murmur3_32(seed(), s, len); -} - -unsigned int StringTable::hash_string(oop string) { - EXCEPTION_MARK; - if (string == NULL) { - return hash_string((jchar*)NULL, 0); - } - ResourceMark rm(THREAD); - // All String oops are hashed as unicode - int length; - jchar* chars = java_lang_String::as_unicode_string(string, length, THREAD); - if (chars != NULL) { - return hash_string(chars, length); - } else { - vm_exit_out_of_memory(length, OOM_MALLOC_ERROR, "unable to create Unicode string for verification"); +class StringTableConfig : public StringTableHash::BaseConfig { + private: + public: + static uintx get_hash(WeakHandle const& value, + bool* is_dead) { + EXCEPTION_MARK; + oop val_oop = value.peek(); + if (val_oop == NULL) { + *is_dead = true; + return 0; + } + *is_dead = false; + ResourceMark rm(THREAD); + // All String oops are hashed as unicode + int length; + jchar* chars = java_lang_String::as_unicode_string(val_oop, length, THREAD); + if (chars != NULL) { + return hash_string(chars, length, StringTable::_alt_hash); + } + vm_exit_out_of_memory(length, OOM_MALLOC_ERROR, "get hash from oop"); return 0; } -} + // We use default allocation/deallocation but counted + static void* allocate_node(size_t size, + WeakHandle const& value) { + StringTable::item_added(); + return StringTableHash::BaseConfig::allocate_node(size, value); + } + static void free_node(void* memory, + WeakHandle const& value) { + value.release(); + StringTableHash::BaseConfig::free_node(memory, value); + StringTable::item_removed(); + } +}; -oop StringTable::string_object(HashtableEntry* entry) { - return RootAccess::oop_load(entry->literal_addr()); -} +class StringTableLookupJchar : StackObj { + private: + Thread* _thread; + uintx _hash; + int _len; + const jchar* _str; + Handle _found; -oop StringTable::string_object_no_keepalive(HashtableEntry* entry) { - // The AS_NO_KEEPALIVE peeks at the oop without keeping it alive. - // This is *very dangerous* in general but is okay in this specific - // case. The subsequent oop_load keeps the oop alive if it it matched - // the jchar* string. - return RootAccess::oop_load(entry->literal_addr()); -} - -void StringTable::set_string_object(HashtableEntry* entry, oop string) { - RootAccess::oop_store(entry->literal_addr(), string); -} - -oop StringTable::lookup_shared(jchar* name, int len, unsigned int hash) { - assert(hash == java_lang_String::hash_code(name, len), - "hash must be computed using java_lang_String::hash_code"); - return _shared_table.lookup((const char*)name, hash, len); -} - -oop StringTable::lookup_in_main_table(int index, jchar* name, - int len, unsigned int hash) { - int count = 0; - for (HashtableEntry* l = bucket(index); l != NULL; l = l->next()) { - count++; - if (l->hash() == hash) { - if (java_lang_String::equals(string_object_no_keepalive(l), name, len)) { - // We must perform a new load with string_object() that keeps the string - // alive as we must expose the oop as strongly reachable when exiting - // this context, in case the oop gets published. - return string_object(l); - } + public: + StringTableLookupJchar(Thread* thread, uintx hash, const jchar* key, int len) + : _thread(thread), _hash(hash), _str(key), _len(len) { + } + uintx get_hash() const { + return _hash; + } + bool equals(WeakHandle* value, bool* is_dead) { + oop val_oop = value->peek(); + if (val_oop == NULL) { + // dead oop, mark this hash dead for cleaning + *is_dead = true; + return false; } + bool equals = java_lang_String::equals(val_oop, (jchar*)_str, _len); + if (!equals) { + return false; + } + // Need to resolve weak handle and Handleize through possible safepoint. + _found = Handle(_thread, value->resolve()); + return true; } - // If the bucket size is too deep check if this hash code is insufficient. - if (count >= rehash_count && !needs_rehashing()) { - _needs_rehashing = check_rehash_table(count); +}; + +class StringTableLookupOop : public StackObj { + private: + Thread* _thread; + uintx _hash; + Handle _find; + Handle _found; // Might be a different oop with the same value that's already + // in the table, which is the point. + public: + StringTableLookupOop(Thread* thread, uintx hash, Handle handle) + : _thread(thread), _hash(hash), _find(handle) { } + + uintx get_hash() const { + return _hash; } - return NULL; + + bool equals(WeakHandle* value, bool* is_dead) { + oop val_oop = value->peek(); + if (val_oop == NULL) { + // dead oop, mark this hash dead for cleaning + *is_dead = true; + return false; + } + bool equals = java_lang_String::equals(_find(), val_oop); + if (!equals) { + return false; + } + // Need to resolve weak handle and Handleize through possible safepoint. + _found = Handle(_thread, value->resolve()); + return true; + } +}; + +static size_t ceil_pow_2(uintx val) { + size_t ret; + for (ret = 1; ((size_t)1 << ret) < val; ++ret); + return ret; } - -oop StringTable::basic_add(int index_arg, Handle string, jchar* name, - int len, unsigned int hashValue_arg, TRAPS) { - - assert(java_lang_String::equals(string(), name, len), - "string must be properly initialized"); - // Cannot hit a safepoint in this function because the "this" pointer can move. - NoSafepointVerifier nsv; - - // Check if the symbol table has been rehashed, if so, need to recalculate - // the hash value and index before second lookup. - unsigned int hashValue; - int index; - if (use_alternate_hashcode()) { - hashValue = alt_hash_string(name, len); - index = hash_to_index(hashValue); - } else { - hashValue = hashValue_arg; - index = index_arg; - } - - // Since look-up was done lock-free, we need to check if another - // thread beat us in the race to insert the symbol. - - // No need to lookup the shared table from here since the caller (intern()) already did - oop test = lookup_in_main_table(index, name, len, hashValue); // calls lookup(u1*, int) - if (test != NULL) { - // Entry already added - return test; - } - - HashtableEntry* entry = new_entry(hashValue, string()); - add_entry(index, entry); - return string(); +StringTable::StringTable() : _local_table(NULL), _current_size(0), _has_work(0), + _needs_rehashing(false), _weak_handles(NULL), _items(0), _uncleaned_items(0) { + _weak_handles = new OopStorage("StringTable weak", + StringTableWeakAlloc_lock, + StringTableWeakActive_lock); + size_t start_size_log_2 = ceil_pow_2(StringTableSize); + _current_size = ((size_t)1) << start_size_log_2; + log_trace(stringtable)("Start size: " SIZE_FORMAT " (" SIZE_FORMAT ")", + _current_size, start_size_log_2); + _local_table = new StringTableHash(start_size_log_2, END_SIZE, REHASH_LEN); } +size_t StringTable::item_added() { + return Atomic::add((size_t)1, &(the_table()->_items)); +} +size_t StringTable::items_to_clean(size_t ncl) { + size_t total = Atomic::add((size_t)ncl, &(the_table()->_uncleaned_items)); + log_trace(stringtable)( + "Uncleaned items:" SIZE_FORMAT " added: " SIZE_FORMAT " total:" SIZE_FORMAT, + the_table()->_uncleaned_items, ncl, total); + return total; +} + +void StringTable::item_removed() { + Atomic::add((size_t)-1, &(the_table()->_items)); + Atomic::add((size_t)-1, &(the_table()->_uncleaned_items)); +} + +double StringTable::get_load_factor() { + return (_items*1.0)/_current_size; +} + +double StringTable::get_dead_factor() { + return (_uncleaned_items*1.0)/_current_size; +} + +size_t StringTable::table_size(Thread* thread) { + return ((size_t)(1)) << _local_table->get_size_log2(thread != NULL ? thread + : Thread::current()); +} + +void StringTable::trigger_concurrent_work() { + MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag); + the_table()->_has_work = true; + Service_lock->notify_all(); +} + +// Probing oop StringTable::lookup(Symbol* symbol) { ResourceMark rm; int length; @@ -211,71 +239,45 @@ oop StringTable::lookup(Symbol* symbol) { } oop StringTable::lookup(jchar* name, int len) { - // shared table always uses java_lang_String::hash_code unsigned int hash = java_lang_String::hash_code(name, len); - oop string = lookup_shared(name, len, hash); + oop string = StringTable::the_table()->lookup_shared(name, len, hash); if (string != NULL) { return string; } - if (use_alternate_hashcode()) { - hash = alt_hash_string(name, len); + if (StringTable::_alt_hash) { + hash = hash_string(name, len, true); } - int index = the_table()->hash_to_index(hash); - string = the_table()->lookup_in_main_table(index, name, len, hash); - - return string; + return StringTable::the_table()->do_lookup(name, len, hash); } -oop StringTable::intern(Handle string_or_null, jchar* name, - int len, TRAPS) { - // shared table always uses java_lang_String::hash_code - unsigned int hashValue = java_lang_String::hash_code(name, len); - oop found_string = lookup_shared(name, len, hashValue); - if (found_string != NULL) { - return found_string; +class StringTableGet : public StackObj { + Thread* _thread; + Handle _return; + public: + StringTableGet(Thread* thread) : _thread(thread) {} + void operator()(WeakHandle* val) { + oop result = val->resolve(); + assert(result != NULL, "Result should be reachable"); + _return = Handle(_thread, result); } - if (use_alternate_hashcode()) { - hashValue = alt_hash_string(name, len); + oop get_res_oop() { + return _return(); } - int index = the_table()->hash_to_index(hashValue); - found_string = the_table()->lookup_in_main_table(index, name, len, hashValue); +}; - // Found - if (found_string != NULL) { - return found_string; +oop StringTable::do_lookup(jchar* name, int len, uintx hash) { + Thread* thread = Thread::current(); + StringTableLookupJchar lookup(thread, hash, name, len); + StringTableGet stg(thread); + bool rehash_warning; + _local_table->get(thread, lookup, stg, &rehash_warning); + if (rehash_warning) { + _needs_rehashing = true; } - - debug_only(StableMemoryChecker smc(name, len * sizeof(name[0]))); - assert(!Universe::heap()->is_in_reserved(name), - "proposed name of symbol must be stable"); - - HandleMark hm(THREAD); // cleanup strings created - Handle string; - // try to reuse the string if possible - if (!string_or_null.is_null()) { - string = string_or_null; - } else { - string = java_lang_String::create_from_unicode(name, len, CHECK_NULL); - } - - // Deduplicate the string before it is interned. Note that we should never - // deduplicate a string after it has been interned. Doing so will counteract - // compiler optimizations done on e.g. interned string literals. - Universe::heap()->deduplicate_string(string()); - - // Grab the StringTable_lock before getting the_table() because it could - // change at safepoint. - oop added_or_found; - { - MutexLocker ml(StringTable_lock, THREAD); - // Otherwise, add to symbol to table - added_or_found = the_table()->basic_add(index, string, name, len, - hashValue, CHECK_NULL); - } - - return added_or_found; + return stg.get_res_oop(); } +// Interning oop StringTable::intern(Symbol* symbol, TRAPS) { if (symbol == NULL) return NULL; ResourceMark rm(THREAD); @@ -286,19 +288,17 @@ oop StringTable::intern(Symbol* symbol, TRAPS) { return result; } - -oop StringTable::intern(oop string, TRAPS) -{ +oop StringTable::intern(oop string, TRAPS) { if (string == NULL) return NULL; ResourceMark rm(THREAD); int length; Handle h_string (THREAD, string); - jchar* chars = java_lang_String::as_unicode_string(string, length, CHECK_NULL); + jchar* chars = java_lang_String::as_unicode_string(string, length, + CHECK_NULL); oop result = intern(h_string, chars, length, CHECK_NULL); return result; } - oop StringTable::intern(const char* utf8_string, TRAPS) { if (utf8_string == NULL) return NULL; ResourceMark rm(THREAD); @@ -310,342 +310,451 @@ oop StringTable::intern(const char* utf8_string, TRAPS) { return result; } -void StringTable::unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int* processed, int* removed) { - BucketUnlinkContext context; - buckets_unlink_or_oops_do(is_alive, f, 0, the_table()->table_size(), &context); - _the_table->bulk_free_entries(&context); - *processed = context._num_processed; - *removed = context._num_removed; -} - -void StringTable::possibly_parallel_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int* processed, int* removed) { - // Readers of the table are unlocked, so we should only be removing - // entries at a safepoint. - assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); - const int limit = the_table()->table_size(); - - BucketUnlinkContext context; - for (;;) { - // Grab next set of buckets to scan - int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize; - if (start_idx >= limit) { - // End of table - break; - } - - int end_idx = MIN2(limit, start_idx + ClaimChunkSize); - buckets_unlink_or_oops_do(is_alive, f, start_idx, end_idx, &context); +oop StringTable::intern(Handle string_or_null_h, jchar* name, int len, TRAPS) { + // shared table always uses java_lang_String::hash_code + unsigned int hash = java_lang_String::hash_code(name, len); + oop found_string = StringTable::the_table()->lookup_shared(name, len, hash); + if (found_string != NULL) { + return found_string; } - _the_table->bulk_free_entries(&context); - *processed = context._num_processed; - *removed = context._num_removed; -} - -void StringTable::buckets_oops_do(OopClosure* f, int start_idx, int end_idx) { - const int limit = the_table()->table_size(); - - assert(0 <= start_idx && start_idx <= limit, - "start_idx (%d) is out of bounds", start_idx); - assert(0 <= end_idx && end_idx <= limit, - "end_idx (%d) is out of bounds", end_idx); - assert(start_idx <= end_idx, - "Index ordering: start_idx=%d, end_idx=%d", - start_idx, end_idx); - - for (int i = start_idx; i < end_idx; i += 1) { - HashtableEntry* entry = the_table()->bucket(i); - while (entry != NULL) { - assert(!entry->is_shared(), "CDS not used for the StringTable"); - - f->do_oop((oop*)entry->literal_addr()); - - entry = entry->next(); - } + if (StringTable::_alt_hash) { + hash = hash_string(name, len, true); } + return StringTable::the_table()->do_intern(string_or_null_h, name, len, + hash, CHECK_NULL); } -void StringTable::buckets_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int start_idx, int end_idx, BucketUnlinkContext* context) { - const int limit = the_table()->table_size(); +class StringTableCreateEntry : public StackObj { + private: + Thread* _thread; + Handle _return; + Handle _store; + public: + StringTableCreateEntry(Thread* thread, Handle store) + : _thread(thread), _store(store) {} - assert(0 <= start_idx && start_idx <= limit, - "start_idx (%d) is out of bounds", start_idx); - assert(0 <= end_idx && end_idx <= limit, - "end_idx (%d) is out of bounds", end_idx); - assert(start_idx <= end_idx, - "Index ordering: start_idx=%d, end_idx=%d", - start_idx, end_idx); + WeakHandle operator()() { // No dups found + WeakHandle wh = + WeakHandle::create(_store); + return wh; + } + void operator()(bool inserted, WeakHandle* val) { + oop result = val->resolve(); + assert(result != NULL, "Result should be reachable"); + _return = Handle(_thread, result); + } + oop get_return() const { + return _return(); + } +}; - for (int i = start_idx; i < end_idx; ++i) { - HashtableEntry** p = the_table()->bucket_addr(i); - HashtableEntry* entry = the_table()->bucket(i); - while (entry != NULL) { - assert(!entry->is_shared(), "CDS not used for the StringTable"); +oop StringTable::do_intern(Handle string_or_null_h, jchar* name, + int len, uintx hash, TRAPS) { + HandleMark hm(THREAD); // cleanup strings created + Handle string_h; - if (is_alive->do_object_b(string_object_no_keepalive(entry))) { - if (f != NULL) { - f->do_oop(entry->literal_addr()); - } - p = entry->next_addr(); - } else { - *p = entry->next(); - context->free_entry(entry); - } - context->_num_processed++; - entry = *p; + if (!string_or_null_h.is_null()) { + string_h = string_or_null_h; + } else { + string_h = java_lang_String::create_from_unicode(name, len, CHECK_NULL); + } + + // Deduplicate the string before it is interned. Note that we should never + // deduplicate a string after it has been interned. Doing so will counteract + // compiler optimizations done on e.g. interned string literals. + Universe::heap()->deduplicate_string(string_h()); + + assert(java_lang_String::equals(string_h(), name, len), + "string must be properly initialized"); + assert(len == java_lang_String::length(string_h()), "Must be same length"); + StringTableLookupOop lookup(THREAD, hash, string_h); + StringTableCreateEntry stc(THREAD, string_h); + + bool rehash_warning; + _local_table->get_insert_lazy(THREAD, lookup, stc, stc, &rehash_warning); + if (rehash_warning) { + _needs_rehashing = true; + } + return stc.get_return(); +} + +// GC support +class StringTableIsAliveCounter : public BoolObjectClosure { + BoolObjectClosure* _real_boc; + public: + size_t _count; + size_t _count_total; + StringTableIsAliveCounter(BoolObjectClosure* boc) : _real_boc(boc), _count(0), + _count_total(0) {} + bool do_object_b(oop obj) { + bool ret = _real_boc->do_object_b(obj); + if (!ret) { + ++_count; } + ++_count_total; + return ret; + } +}; + +void StringTable::unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, + int* processed, int* removed) { + DoNothingClosure dnc; + assert(is_alive != NULL, "No closure"); + StringTableIsAliveCounter stiac(is_alive); + OopClosure* tmp = f != NULL ? f : &dnc; + + StringTable::the_table()->_weak_handles->weak_oops_do(&stiac, tmp); + + StringTable::the_table()->items_to_clean(stiac._count); + StringTable::the_table()->check_concurrent_work(); + if (processed != NULL) { + *processed = (int) stiac._count_total; + } + if (removed != NULL) { + *removed = (int) stiac._count; } } void StringTable::oops_do(OopClosure* f) { - buckets_oops_do(f, 0, the_table()->table_size()); + assert(f != NULL, "No closure"); + StringTable::the_table()->_weak_handles->oops_do(f); } -void StringTable::possibly_parallel_oops_do(OopClosure* f) { - const int limit = the_table()->table_size(); +void StringTable::possibly_parallel_unlink( + OopStorage::ParState* _par_state_string, BoolObjectClosure* cl, + int* processed, int* removed) +{ + DoNothingClosure dnc; + assert(cl != NULL, "No closure"); + StringTableIsAliveCounter stiac(cl); - for (;;) { - // Grab next set of buckets to scan - int start_idx = Atomic::add(ClaimChunkSize, &_parallel_claimed_idx) - ClaimChunkSize; - if (start_idx >= limit) { - // End of table - break; + _par_state_string->weak_oops_do(&stiac, &dnc); + + StringTable::the_table()->items_to_clean(stiac._count); + StringTable::the_table()->check_concurrent_work(); + *processed = (int) stiac._count_total; + *removed = (int) stiac._count; +} + +void StringTable::possibly_parallel_oops_do( + OopStorage::ParState* + _par_state_string, OopClosure* f) +{ + assert(f != NULL, "No closure"); + _par_state_string->oops_do(f); +} + +// Concurrent work +void StringTable::grow(JavaThread* jt) { + StringTableHash::GrowTask gt(_local_table); + if (!gt.prepare(jt)) { + return; + } + log_trace(stringtable)("Started to grow"); + { + TraceTime timer("Grow", TRACETIME_LOG(Debug, stringtable, perf)); + while (gt.doTask(jt)) { + gt.pause(jt); + { + ThreadBlockInVM tbivm(jt); + } + gt.cont(jt); } + } + gt.done(jt); + _current_size = table_size(jt); + log_debug(stringtable)("Grown to size:" SIZE_FORMAT, _current_size); +} - int end_idx = MIN2(limit, start_idx + ClaimChunkSize); - buckets_oops_do(f, start_idx, end_idx); +struct StringTableDoDelete : StackObj { + long _count; + StringTableDoDelete() : _count(0) {} + void operator()(WeakHandle* val) { + ++_count; + } +}; + +struct StringTableDeleteCheck : StackObj { + long _count; + long _item; + StringTableDeleteCheck() : _count(0), _item(0) {} + bool operator()(WeakHandle* val) { + ++_item; + oop tmp = val->peek(); + if (tmp == NULL) { + ++_count; + return true; + } else { + return false; + } + } +}; + +void StringTable::clean_dead_entries(JavaThread* jt) { + StringTableHash::BulkDeleteTask bdt(_local_table); + if (!bdt.prepare(jt)) { + return; + } + + StringTableDeleteCheck stdc; + StringTableDoDelete stdd; + bool interrupted = false; + { + TraceTime timer("Clean", TRACETIME_LOG(Debug, stringtable, perf)); + while(bdt.doTask(jt, stdc, stdd)) { + bdt.pause(jt); + { + ThreadBlockInVM tbivm(jt); + } + if (!bdt.cont(jt)) { + interrupted = true; + break; + } + } + } + if (interrupted) { + _has_work = true; + } else { + bdt.done(jt); + } + log_debug(stringtable)("Cleaned %ld of %ld", stdc._count, stdc._item); +} + +void StringTable::check_concurrent_work() { + if (_has_work) { + return; + } + double load_factor = StringTable::get_load_factor(); + double dead_factor = StringTable::get_dead_factor(); + // We should clean/resize if we have more dead than alive, + // more items than preferred load factor or + // more dead items than water mark. + if ((dead_factor > load_factor) || + (load_factor > PREF_AVG_LIST_LEN) || + (dead_factor > CLEAN_DEAD_HIGH_WATER_MARK)) { + log_debug(stringtable)("Concurrent work triggered, live factor:%g dead factor:%g", + load_factor, dead_factor); + trigger_concurrent_work(); } } +void StringTable::concurrent_work(JavaThread* jt) { + _has_work = false; + double load_factor = get_load_factor(); + log_debug(stringtable, perf)("Concurrent work, live factor: %g", load_factor); + // We prefer growing, since that also removes dead items + if (load_factor > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached()) { + grow(jt); + } else { + clean_dead_entries(jt); + } +} + +void StringTable::do_concurrent_work(JavaThread* jt) { + StringTable::the_table()->concurrent_work(jt); +} + +// Rehash +bool StringTable::do_rehash() { + if (!_local_table->is_safepoint_safe()) { + return false; + } + + // We use max size + StringTableHash* new_table = new StringTableHash(END_SIZE, END_SIZE, REHASH_LEN); + // Use alt hash from now on + _alt_hash = true; + if (!_local_table->try_move_nodes_to(Thread::current(), new_table)) { + _alt_hash = false; + delete new_table; + return false; + } + + // free old table + delete _local_table; + _local_table = new_table; + + return true; +} + +void StringTable::try_rehash_table() { + static bool rehashed = false; + log_debug(stringtable)("Table imbalanced, rehashing called."); + + // Grow instead of rehash. + if (get_load_factor() > PREF_AVG_LIST_LEN && + !_local_table->is_max_size_reached()) { + log_debug(stringtable)("Choosing growing over rehashing."); + trigger_concurrent_work(); + _needs_rehashing = false; + return; + } + // Already rehashed. + if (rehashed) { + log_warning(stringtable)("Rehashing already done, still long lists."); + trigger_concurrent_work(); + _needs_rehashing = false; + return; + } + + murmur_seed = AltHashing::compute_seed(); + { + if (do_rehash()) { + rehashed = true; + } else { + log_info(stringtable)("Resizes in progress rehashing skipped."); + } + } + _needs_rehashing = false; +} + +void StringTable::rehash_table() { + StringTable::the_table()->try_rehash_table(); +} + +// Statistics +static int literal_size(oop obj) { + // NOTE: this would over-count if (pre-JDK8) + // java_lang_Class::has_offset_field() is true and the String.value array is + // shared by several Strings. However, starting from JDK8, the String.value + // array is not shared anymore. + if (obj == NULL) { + return 0; + } else if (obj->klass() == SystemDictionary::String_klass()) { + return (obj->size() + java_lang_String::value(obj)->size()) * HeapWordSize; + } else { + return obj->size(); + } +} + +struct SizeFunc : StackObj { + size_t operator()(WeakHandle* val) { + oop s = val->peek(); + if (s == NULL) { + // Dead + return 0; + } + return literal_size(s); + }; +}; + +void StringTable::print_table_statistics(outputStream* st, + const char* table_name) { + SizeFunc sz; + _local_table->statistics_to(Thread::current(), sz, st, table_name); +} + +// Verification +class VerifyStrings : StackObj { + public: + bool operator()(WeakHandle* val) { + oop s = val->peek(); + if (s != NULL) { + assert(java_lang_String::length(s) >= 0, "Length on string must work."); + } + return true; + }; +}; + // This verification is part of Universe::verify() and needs to be quick. -// See StringTable::verify_and_compare() below for exhaustive verification. void StringTable::verify() { - for (int i = 0; i < the_table()->table_size(); ++i) { - HashtableEntry* p = the_table()->bucket(i); - for ( ; p != NULL; p = p->next()) { - oop s = string_object_no_keepalive(p); - guarantee(s != NULL, "interned string is NULL"); - unsigned int h = hash_string(s); - guarantee(p->hash() == h, "broken hash in string table entry"); - guarantee(the_table()->hash_to_index(h) == i, - "wrong index in string table"); - } + Thread* thr = Thread::current(); + VerifyStrings vs; + if (!the_table()->_local_table->try_scan(thr, vs)) { + log_info(stringtable)("verify unavailable at this moment"); } } +// Verification and comp +class VerifyCompStrings : StackObj { + GrowableArray* _oops; + public: + size_t _errors; + VerifyCompStrings(GrowableArray* oops) : _oops(oops), _errors(0) {} + bool operator()(WeakHandle* val) { + oop s = val->resolve(); + if (s == NULL) { + return true; + } + int len = _oops->length(); + for (int i = 0; i < len; i++) { + bool eq = java_lang_String::equals(s, _oops->at(i)); + assert(!eq, "Duplicate strings"); + if (eq) { + _errors++; + } + } + _oops->push(s); + return true; + }; +}; + +size_t StringTable::verify_and_compare_entries() { + Thread* thr = Thread::current(); + GrowableArray* oops = + new (ResourceObj::C_HEAP, mtInternal) + GrowableArray((int)the_table()->_current_size, true); + + VerifyCompStrings vcs(oops); + if (!the_table()->_local_table->try_scan(thr, vcs)) { + log_info(stringtable)("verify unavailable at this moment"); + } + delete oops; + return vcs._errors; +} + +// Dumping +class PrintString : StackObj { + Thread* _thr; + outputStream* _st; + public: + PrintString(Thread* thr, outputStream* st) : _thr(thr), _st(st) {} + bool operator()(WeakHandle* val) { + oop s = val->peek(); + if (s == NULL) { + return true; + } + typeArrayOop value = java_lang_String::value_no_keepalive(s); + int length = java_lang_String::length(s); + bool is_latin1 = java_lang_String::is_latin1(s); + + if (length <= 0) { + _st->print("%d: ", length); + } else { + ResourceMark rm(_thr); + int utf8_length = length; + char* utf8_string; + + if (!is_latin1) { + jchar* chars = value->char_at_addr(0); + utf8_string = UNICODE::as_utf8(chars, utf8_length); + } else { + jbyte* bytes = value->byte_at_addr(0); + utf8_string = UNICODE::as_utf8(bytes, utf8_length); + } + + _st->print("%d: ", utf8_length); + HashtableTextDump::put_utf8(_st, utf8_string, utf8_length); + } + _st->cr(); + return true; + }; +}; + void StringTable::dump(outputStream* st, bool verbose) { if (!verbose) { - the_table()->print_table_statistics(st, "StringTable", string_object_no_keepalive); + the_table()->print_table_statistics(st, "StringTable"); } else { - Thread* THREAD = Thread::current(); + Thread* thr = Thread::current(); + ResourceMark rm(thr); st->print_cr("VERSION: 1.1"); - for (int i = 0; i < the_table()->table_size(); ++i) { - HashtableEntry* p = the_table()->bucket(i); - for ( ; p != NULL; p = p->next()) { - oop s = string_object_no_keepalive(p); - typeArrayOop value = java_lang_String::value_no_keepalive(s); - int length = java_lang_String::length(s); - bool is_latin1 = java_lang_String::is_latin1(s); - - if (length <= 0) { - st->print("%d: ", length); - } else { - ResourceMark rm(THREAD); - int utf8_length = length; - char* utf8_string; - - if (!is_latin1) { - jchar* chars = value->char_at_addr(0); - utf8_string = UNICODE::as_utf8(chars, utf8_length); - } else { - jbyte* bytes = value->byte_at_addr(0); - utf8_string = UNICODE::as_utf8(bytes, utf8_length); - } - - st->print("%d: ", utf8_length); - HashtableTextDump::put_utf8(st, utf8_string, utf8_length); - } - st->cr(); - } + PrintString ps(thr, st); + if (!the_table()->_local_table->try_scan(thr, ps)) { + st->print_cr("dump unavailable at this moment"); } } } -StringTable::VerifyRetTypes StringTable::compare_entries( - int bkt1, int e_cnt1, - HashtableEntry* e_ptr1, - int bkt2, int e_cnt2, - HashtableEntry* e_ptr2) { - // These entries are sanity checked by verify_and_compare_entries() - // before this function is called. - oop str1 = string_object_no_keepalive(e_ptr1); - oop str2 = string_object_no_keepalive(e_ptr2); - - if (str1 == str2) { - tty->print_cr("ERROR: identical oop values (0x" PTR_FORMAT ") " - "in entry @ bucket[%d][%d] and entry @ bucket[%d][%d]", - p2i(str1), bkt1, e_cnt1, bkt2, e_cnt2); - return _verify_fail_continue; - } - - if (java_lang_String::equals(str1, str2)) { - tty->print_cr("ERROR: identical String values in entry @ " - "bucket[%d][%d] and entry @ bucket[%d][%d]", - bkt1, e_cnt1, bkt2, e_cnt2); - return _verify_fail_continue; - } - - return _verify_pass; -} - -StringTable::VerifyRetTypes StringTable::verify_entry(int bkt, int e_cnt, - HashtableEntry* e_ptr, - StringTable::VerifyMesgModes mesg_mode) { - - VerifyRetTypes ret = _verify_pass; // be optimistic - - oop str = string_object_no_keepalive(e_ptr); - if (str == NULL) { - if (mesg_mode == _verify_with_mesgs) { - tty->print_cr("ERROR: NULL oop value in entry @ bucket[%d][%d]", bkt, - e_cnt); - } - // NULL oop means no more verifications are possible - return _verify_fail_done; - } - - if (str->klass() != SystemDictionary::String_klass()) { - if (mesg_mode == _verify_with_mesgs) { - tty->print_cr("ERROR: oop is not a String in entry @ bucket[%d][%d]", - bkt, e_cnt); - } - // not a String means no more verifications are possible - return _verify_fail_done; - } - - unsigned int h = hash_string(str); - if (e_ptr->hash() != h) { - if (mesg_mode == _verify_with_mesgs) { - tty->print_cr("ERROR: broken hash value in entry @ bucket[%d][%d], " - "bkt_hash=%d, str_hash=%d", bkt, e_cnt, e_ptr->hash(), h); - } - ret = _verify_fail_continue; - } - - if (the_table()->hash_to_index(h) != bkt) { - if (mesg_mode == _verify_with_mesgs) { - tty->print_cr("ERROR: wrong index value for entry @ bucket[%d][%d], " - "str_hash=%d, hash_to_index=%d", bkt, e_cnt, h, - the_table()->hash_to_index(h)); - } - ret = _verify_fail_continue; - } - - return ret; -} - -// See StringTable::verify() above for the quick verification that is -// part of Universe::verify(). This verification is exhaustive and -// reports on every issue that is found. StringTable::verify() only -// reports on the first issue that is found. -// -// StringTable::verify_entry() checks: -// - oop value != NULL (same as verify()) -// - oop value is a String -// - hash(String) == hash in entry (same as verify()) -// - index for hash == index of entry (same as verify()) -// -// StringTable::compare_entries() checks: -// - oops are unique across all entries -// - String values are unique across all entries -// -int StringTable::verify_and_compare_entries() { - assert(StringTable_lock->is_locked(), "sanity check"); - - int fail_cnt = 0; - - // first, verify all the entries individually: - for (int bkt = 0; bkt < the_table()->table_size(); bkt++) { - HashtableEntry* e_ptr = the_table()->bucket(bkt); - for (int e_cnt = 0; e_ptr != NULL; e_ptr = e_ptr->next(), e_cnt++) { - VerifyRetTypes ret = verify_entry(bkt, e_cnt, e_ptr, _verify_with_mesgs); - if (ret != _verify_pass) { - fail_cnt++; - } - } - } - - // Optimization: if the above check did not find any failures, then - // the comparison loop below does not need to call verify_entry() - // before calling compare_entries(). If there were failures, then we - // have to call verify_entry() to see if the entry can be passed to - // compare_entries() safely. When we call verify_entry() in the loop - // below, we do so quietly to void duplicate messages and we don't - // increment fail_cnt because the failures have already been counted. - bool need_entry_verify = (fail_cnt != 0); - - // second, verify all entries relative to each other: - for (int bkt1 = 0; bkt1 < the_table()->table_size(); bkt1++) { - HashtableEntry* e_ptr1 = the_table()->bucket(bkt1); - for (int e_cnt1 = 0; e_ptr1 != NULL; e_ptr1 = e_ptr1->next(), e_cnt1++) { - if (need_entry_verify) { - VerifyRetTypes ret = verify_entry(bkt1, e_cnt1, e_ptr1, - _verify_quietly); - if (ret == _verify_fail_done) { - // cannot use the current entry to compare against other entries - continue; - } - } - - for (int bkt2 = bkt1; bkt2 < the_table()->table_size(); bkt2++) { - HashtableEntry* e_ptr2 = the_table()->bucket(bkt2); - int e_cnt2; - for (e_cnt2 = 0; e_ptr2 != NULL; e_ptr2 = e_ptr2->next(), e_cnt2++) { - if (bkt1 == bkt2 && e_cnt2 <= e_cnt1) { - // skip the entries up to and including the one that - // we're comparing against - continue; - } - - if (need_entry_verify) { - VerifyRetTypes ret = verify_entry(bkt2, e_cnt2, e_ptr2, - _verify_quietly); - if (ret == _verify_fail_done) { - // cannot compare against this entry - continue; - } - } - - // compare two entries, report and count any failures: - if (compare_entries(bkt1, e_cnt1, e_ptr1, bkt2, e_cnt2, e_ptr2) - != _verify_pass) { - fail_cnt++; - } - } - } - } - } - return fail_cnt; -} - -// Create a new table and using alternate hash code, populate the new table -// with the existing strings. Set flag to use the alternate hash code afterwards. -void StringTable::rehash_table() { - assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); - // This should never happen with -Xshare:dump but it might in testing mode. - if (DumpSharedSpaces) return; - StringTable* new_table = new StringTable(); - - // Rehash the table - the_table()->move_to(new_table); - - // Delete the table and buckets (entries are reused in new table). - delete _the_table; - // Don't check if we need rehashing until the table gets unbalanced again. - // Then rehash with a new global seed. - _needs_rehashing = false; - _the_table = new_table; -} - // Utility for dumping strings StringtableDCmd::StringtableDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap), @@ -671,14 +780,21 @@ int StringtableDCmd::num_arguments() { } } -#if INCLUDE_CDS_JAVA_HEAP // Sharing +#if INCLUDE_CDS_JAVA_HEAP +oop StringTable::lookup_shared(jchar* name, int len, unsigned int hash) { + assert(hash == java_lang_String::hash_code(name, len), + "hash must be computed using java_lang_String::hash_code"); + return _shared_table.lookup((const char*)name, hash, len); +} + oop StringTable::create_archived_string(oop s, Thread* THREAD) { assert(DumpSharedSpaces, "this function is only used with -Xshare:dump"); oop new_s = NULL; typeArrayOop v = java_lang_String::value_no_keepalive(s); - typeArrayOop new_v = (typeArrayOop)MetaspaceShared::archive_heap_object(v, THREAD); + typeArrayOop new_v = + (typeArrayOop)MetaspaceShared::archive_heap_object(v, THREAD); if (new_v == NULL) { return NULL; } @@ -692,51 +808,51 @@ oop StringTable::create_archived_string(oop s, Thread* THREAD) { return new_s; } -bool StringTable::copy_shared_string(GrowableArray *string_space, - CompactStringTableWriter* writer) { +struct CopyToArchive : StackObj { + CompactStringTableWriter* _writer; + CopyToArchive(CompactStringTableWriter* writer) : _writer(writer) {} + bool operator()(WeakHandle* val) { + oop s = val->peek(); + if (s == NULL) { + return true; + } + unsigned int hash = java_lang_String::hash_code(s); + if (hash == 0) { + return true; + } + + java_lang_String::set_hash(s, hash); + oop new_s = StringTable::create_archived_string(s, Thread::current()); + if (new_s == NULL) { + return true; + } + + val->replace(new_s); + // add to the compact table + _writer->add(hash, new_s); + return true; + } +}; + +void StringTable::copy_shared_string_table(CompactStringTableWriter* writer) { assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be"); - Thread* THREAD = Thread::current(); - for (int i = 0; i < the_table()->table_size(); ++i) { - HashtableEntry* bucket = the_table()->bucket(i); - for ( ; bucket != NULL; bucket = bucket->next()) { - oop s = string_object_no_keepalive(bucket); - unsigned int hash = java_lang_String::hash_code(s); - if (hash == 0) { - continue; - } - - java_lang_String::set_hash(s, hash); - oop new_s = create_archived_string(s, THREAD); - if (new_s == NULL) { - continue; - } - - // set the archived string in bucket - set_string_object(bucket, new_s); - - // add to the compact table - writer->add(hash, new_s); - } - } - - return true; + CopyToArchive copy(writer); + StringTable::the_table()->_local_table->do_scan(Thread::current(), copy); } -void StringTable::write_to_archive(GrowableArray *string_space) { +void StringTable::write_to_archive() { assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be"); _shared_table.reset(); - int num_buckets = the_table()->number_of_entries() / - SharedSymbolTableBucketSize; + int num_buckets = the_table()->_items / SharedSymbolTableBucketSize; // calculation of num_buckets can result in zero buckets, we need at least one CompactStringTableWriter writer(num_buckets > 1 ? num_buckets : 1, &MetaspaceShared::stats()->string); // Copy the interned strings into the "string space" within the java heap - if (copy_shared_string(string_space, &writer)) { - writer.dump(&_shared_table); - } + copy_shared_string_table(&writer); + writer.dump(&_shared_table); } void StringTable::serialize(SerializeClosure* soc) { @@ -744,7 +860,8 @@ void StringTable::serialize(SerializeClosure* soc) { _shared_table.serialize(soc); if (soc->writing()) { - _shared_table.reset(); // Sanity. Make sure we don't use the shared table at dump time + // Sanity. Make sure we don't use the shared table at dump time + _shared_table.reset(); } else if (!_shared_string_mapped) { _shared_table.reset(); } diff --git a/src/hotspot/share/classfile/stringTable.hpp b/src/hotspot/share/classfile/stringTable.hpp index fa99e4f32cd..ca056949930 100644 --- a/src/hotspot/share/classfile/stringTable.hpp +++ b/src/hotspot/share/classfile/stringTable.hpp @@ -25,109 +25,111 @@ #ifndef SHARE_VM_CLASSFILE_STRINGTABLE_HPP #define SHARE_VM_CLASSFILE_STRINGTABLE_HPP -#include "utilities/hashtable.hpp" +#include "gc/shared/oopStorage.hpp" +#include "gc/shared/oopStorageParState.hpp" +#include "memory/allocation.hpp" +#include "memory/padded.hpp" +#include "oops/oop.hpp" +#include "oops/weakHandle.hpp" +#include "utilities/concurrentHashTable.hpp" template class CompactHashtable; class CompactStringTableWriter; -class FileMapInfo; class SerializeClosure; -class StringTable : public RehashableHashtable { +class StringTable; +class StringTableConfig; +typedef ConcurrentHashTable, + StringTableConfig, mtSymbol> StringTableHash; + +class StringTableCreateEntry; + +class StringTable : public CHeapObj{ friend class VMStructs; friend class Symbol; + friend class StringTableConfig; + friend class StringTableCreateEntry; private: + void grow(JavaThread* jt); + void clean_dead_entries(JavaThread* jt); + // The string table static StringTable* _the_table; - // Shared string table static CompactHashtable _shared_table; static bool _shared_string_mapped; + static bool _alt_hash; +private: - // Set if one bucket is out of balance due to hash algorithm deficiency - static bool _needs_rehashing; + // Set if one bucket is out of balance due to hash algorithm deficiency + StringTableHash* _local_table; + size_t _current_size; + volatile bool _has_work; + volatile bool _needs_rehashing; - // Claimed high water mark for parallel chunked scanning - static volatile int _parallel_claimed_idx; + OopStorage* _weak_handles; - static oop intern(Handle string_or_null, jchar* chars, int length, TRAPS); - oop basic_add(int index, Handle string_or_null, jchar* name, int len, - unsigned int hashValue, TRAPS); + volatile size_t _items; + DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile size_t)); + volatile size_t _uncleaned_items; + DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile size_t)); - oop lookup_in_main_table(int index, jchar* chars, int length, unsigned int hashValue); - static oop lookup_shared(jchar* name, int len, unsigned int hash); + double get_load_factor(); + double get_dead_factor(); - // Apply the give oop closure to the entries to the buckets - // in the range [start_idx, end_idx). - static void buckets_oops_do(OopClosure* f, int start_idx, int end_idx); + void check_concurrent_work(); + void trigger_concurrent_work(); - typedef StringTable::BucketUnlinkContext BucketUnlinkContext; - // Unlink or apply the give oop closure to the entries to the buckets - // in the range [start_idx, end_idx). Unlinked bucket entries are collected in the given - // context to be freed later. - // This allows multiple threads to work on the table at once. - static void buckets_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int start_idx, int end_idx, BucketUnlinkContext* context); + static uintx item_added(); + static void item_removed(); + static size_t items_to_clean(size_t ncl); - // Hashing algorithm, used as the hash value used by the - // StringTable for bucket selection and comparison (stored in the - // HashtableEntry structures). This is used in the String.intern() method. - static unsigned int hash_string(const jchar* s, int len); - static unsigned int hash_string(oop string); - static unsigned int alt_hash_string(const jchar* s, int len); + StringTable(); - // Accessors for the string roots in the hashtable entries. - // Use string_object_no_keepalive() only when the value is not returned - // outside of a scope where a thread transition is possible. - static oop string_object(HashtableEntry* entry); - static oop string_object_no_keepalive(HashtableEntry* entry); - static void set_string_object(HashtableEntry* entry, oop string); + static oop intern(Handle string_or_null_h, jchar* name, int len, TRAPS); + oop do_intern(Handle string_or_null, jchar* name, int len, uintx hash, TRAPS); + oop do_lookup(jchar* name, int len, uintx hash); - StringTable() : RehashableHashtable((int)StringTableSize, - sizeof (HashtableEntry)) {} + void concurrent_work(JavaThread* jt); + void print_table_statistics(outputStream* st, const char* table_name); - StringTable(HashtableBucket* t, int number_of_entries) - : RehashableHashtable((int)StringTableSize, sizeof (HashtableEntry), t, - number_of_entries) {} -public: + void try_rehash_table(); + bool do_rehash(); + + public: // The string table static StringTable* the_table() { return _the_table; } + size_t table_size(Thread* thread = NULL); - // Size of one bucket in the string table. Used when checking for rollover. - static uint bucket_size() { return sizeof(HashtableBucket); } + static OopStorage* weak_storage() { return the_table()->_weak_handles; } static void create_table() { assert(_the_table == NULL, "One string table allowed."); _the_table = new StringTable(); } + static void do_concurrent_work(JavaThread* jt); + static bool has_work() { return the_table()->_has_work; } + // GC support // Delete pointers to otherwise-unreachable objects. - static void unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f) { - int processed = 0; - int removed = 0; - unlink_or_oops_do(cl, f, &processed, &removed); - } static void unlink(BoolObjectClosure* cl) { - int processed = 0; - int removed = 0; - unlink_or_oops_do(cl, NULL, &processed, &removed); - } - static void unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f, int* processed, int* removed); - static void unlink(BoolObjectClosure* cl, int* processed, int* removed) { - unlink_or_oops_do(cl, NULL, processed, removed); + unlink_or_oops_do(cl); } + static void unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f = NULL, + int* processed = NULL, int* removed = NULL); + // Serially invoke "f->do_oop" on the locations of all oops in the table. static void oops_do(OopClosure* f); // Possibly parallel versions of the above - static void possibly_parallel_unlink_or_oops_do(BoolObjectClosure* cl, OopClosure* f, int* processed, int* removed); - static void possibly_parallel_unlink(BoolObjectClosure* cl, int* processed, int* removed) { - possibly_parallel_unlink_or_oops_do(cl, NULL, processed, removed); - } - static void possibly_parallel_oops_do(OopClosure* f); - - // Internal test. - static void test_alt_hash() PRODUCT_RETURN; + static void possibly_parallel_unlink( + OopStorage::ParState* par_state_string, + BoolObjectClosure* cl, int* processed, int* removed); + static void possibly_parallel_oops_do( + OopStorage::ParState* par_state_string, + OopClosure* f); // Probing static oop lookup(Symbol* symbol); @@ -138,46 +140,28 @@ public: static oop intern(oop string, TRAPS); static oop intern(const char *utf8_string, TRAPS); - // Debugging - static void verify(); - static void dump(outputStream* st, bool verbose=false); - - enum VerifyMesgModes { - _verify_quietly = 0, - _verify_with_mesgs = 1 - }; - - enum VerifyRetTypes { - _verify_pass = 0, - _verify_fail_continue = 1, - _verify_fail_done = 2 - }; - - static VerifyRetTypes compare_entries(int bkt1, int e_cnt1, - HashtableEntry* e_ptr1, - int bkt2, int e_cnt2, - HashtableEntry* e_ptr2); - static VerifyRetTypes verify_entry(int bkt, int e_cnt, - HashtableEntry* e_ptr, - VerifyMesgModes mesg_mode); - static int verify_and_compare_entries(); + // Rehash the string table if it gets out of balance + static void rehash_table(); + static bool needs_rehashing() + { return StringTable::the_table()->_needs_rehashing; } // Sharing + private: + oop lookup_shared(jchar* name, int len, unsigned int hash) NOT_CDS_JAVA_HEAP_RETURN_(NULL); + static void copy_shared_string_table(CompactStringTableWriter* ch_table) NOT_CDS_JAVA_HEAP_RETURN; + public: + static oop create_archived_string(oop s, Thread* THREAD); static void set_shared_string_mapped() { _shared_string_mapped = true; } static bool shared_string_mapped() { return _shared_string_mapped; } static void shared_oops_do(OopClosure* f) NOT_CDS_JAVA_HEAP_RETURN; - static bool copy_shared_string(GrowableArray *string_space, - CompactStringTableWriter* ch_table) NOT_CDS_JAVA_HEAP_RETURN_(false); - static oop create_archived_string(oop s, Thread* THREAD) NOT_CDS_JAVA_HEAP_RETURN_(NULL); - static void write_to_archive(GrowableArray *string_space) NOT_CDS_JAVA_HEAP_RETURN; + static void write_to_archive() NOT_CDS_JAVA_HEAP_RETURN; static void serialize(SerializeClosure* soc) NOT_CDS_JAVA_HEAP_RETURN; - // Rehash the symbol table if it gets out of balance - static void rehash_table(); - static bool needs_rehashing() { return _needs_rehashing; } - - // Parallel chunked scanning - static void clear_parallel_claimed_index() { _parallel_claimed_idx = 0; } - static int parallel_claimed_index() { return _parallel_claimed_idx; } + // Jcmd + static void dump(outputStream* st, bool verbose=false); + // Debugging + static size_t verify_and_compare_entries(); + static void verify(); }; + #endif // SHARE_VM_CLASSFILE_STRINGTABLE_HPP diff --git a/src/hotspot/share/gc/cms/cmsHeap.cpp b/src/hotspot/share/gc/cms/cmsHeap.cpp index 838a58cc449..b2c426967cf 100644 --- a/src/hotspot/share/gc/cms/cmsHeap.cpp +++ b/src/hotspot/share/gc/cms/cmsHeap.cpp @@ -220,13 +220,14 @@ void CMSHeap::cms_process_roots(StrongRootsScope* scope, ScanningOption so, bool only_strong_roots, OopsInGenClosure* root_closure, - CLDClosure* cld_closure) { + CLDClosure* cld_closure, + OopStorage::ParState* par_state_string) { MarkingCodeBlobClosure mark_code_closure(root_closure, !CodeBlobToOopClosure::FixRelocations); CLDClosure* weak_cld_closure = only_strong_roots ? NULL : cld_closure; process_roots(scope, so, root_closure, cld_closure, weak_cld_closure, &mark_code_closure); if (!only_strong_roots) { - process_string_table_roots(scope, root_closure); + process_string_table_roots(scope, root_closure, par_state_string); } if (young_gen_as_roots && diff --git a/src/hotspot/share/gc/cms/cmsHeap.hpp b/src/hotspot/share/gc/cms/cmsHeap.hpp index ee800fff7f8..93f177aadec 100644 --- a/src/hotspot/share/gc/cms/cmsHeap.hpp +++ b/src/hotspot/share/gc/cms/cmsHeap.hpp @@ -30,6 +30,7 @@ #include "gc/shared/collectedHeap.hpp" #include "gc/shared/gcCause.hpp" #include "gc/shared/genCollectedHeap.hpp" +#include "gc/shared/oopStorageParState.hpp" #include "utilities/growableArray.hpp" class CLDClosure; @@ -90,7 +91,8 @@ public: ScanningOption so, bool only_strong_roots, OopsInGenClosure* root_closure, - CLDClosure* cld_closure); + CLDClosure* cld_closure, + OopStorage::ParState* par_state_string = NULL); GCMemoryManager* old_manager() const { return _old_manager; } diff --git a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp index 779bc201e10..422ba66bcae 100644 --- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp @@ -54,6 +54,7 @@ #include "gc/shared/genCollectedHeap.hpp" #include "gc/shared/genOopClosures.inline.hpp" #include "gc/shared/isGCActiveMark.hpp" +#include "gc/shared/oopStorageParState.hpp" #include "gc/shared/referencePolicy.hpp" #include "gc/shared/space.inline.hpp" #include "gc/shared/strongRootsScope.hpp" @@ -2769,10 +2770,12 @@ class CMSParMarkTask : public AbstractGangTask { protected: CMSCollector* _collector; uint _n_workers; + OopStorage::ParState _par_state_string; CMSParMarkTask(const char* name, CMSCollector* collector, uint n_workers) : AbstractGangTask(name), _collector(collector), - _n_workers(n_workers) {} + _n_workers(n_workers), + _par_state_string(StringTable::weak_storage()) {} // Work method in support of parallel rescan ... of young gen spaces void do_young_space_rescan(OopsInGenClosure* cl, ContiguousSpace* space, @@ -4274,7 +4277,9 @@ void CMSParInitialMarkTask::work(uint worker_id) { GenCollectedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()), _collector->should_unload_classes(), &par_mri_cl, - &cld_closure); + &cld_closure, + &_par_state_string); + assert(_collector->should_unload_classes() || (_collector->CMSCollector::roots_scanning_options() & GenCollectedHeap::SO_AllCodeCache), "if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops"); @@ -4403,7 +4408,8 @@ void CMSParRemarkTask::work(uint worker_id) { GenCollectedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()), _collector->should_unload_classes(), &par_mrias_cl, - NULL); // The dirty klasses will be handled below + NULL, // The dirty klasses will be handled below + &_par_state_string); assert(_collector->should_unload_classes() || (_collector->CMSCollector::roots_scanning_options() & GenCollectedHeap::SO_AllCodeCache), diff --git a/src/hotspot/share/gc/cms/parNewGeneration.cpp b/src/hotspot/share/gc/cms/parNewGeneration.cpp index 836bd392986..4e625ed1ec3 100644 --- a/src/hotspot/share/gc/cms/parNewGeneration.cpp +++ b/src/hotspot/share/gc/cms/parNewGeneration.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/stringTable.hpp" #include "gc/cms/cmsHeap.inline.hpp" #include "gc/cms/compactibleFreeListSpace.hpp" #include "gc/cms/concurrentMarkSweepGeneration.hpp" @@ -589,7 +590,8 @@ ParNewGenTask::ParNewGenTask(ParNewGeneration* young_gen, _young_gen(young_gen), _old_gen(old_gen), _young_old_boundary(young_old_boundary), _state_set(state_set), - _strong_roots_scope(strong_roots_scope) + _strong_roots_scope(strong_roots_scope), + _par_state_string(StringTable::weak_storage()) {} void ParNewGenTask::work(uint worker_id) { @@ -611,7 +613,8 @@ void ParNewGenTask::work(uint worker_id) { heap->young_process_roots(_strong_roots_scope, &par_scan_state.to_space_root_closure(), &par_scan_state.older_gen_closure(), - &cld_scan_closure); + &cld_scan_closure, + &_par_state_string); par_scan_state.end_strong_roots(); diff --git a/src/hotspot/share/gc/cms/parNewGeneration.hpp b/src/hotspot/share/gc/cms/parNewGeneration.hpp index 92b74004876..3ccd16224d6 100644 --- a/src/hotspot/share/gc/cms/parNewGeneration.hpp +++ b/src/hotspot/share/gc/cms/parNewGeneration.hpp @@ -29,6 +29,7 @@ #include "gc/serial/defNewGeneration.hpp" #include "gc/shared/copyFailedInfo.hpp" #include "gc/shared/gcTrace.hpp" +#include "gc/shared/oopStorageParState.hpp" #include "gc/shared/plab.hpp" #include "gc/shared/preservedMarks.hpp" #include "gc/shared/taskqueue.hpp" @@ -236,6 +237,7 @@ class ParNewGenTask: public AbstractGangTask { HeapWord* _young_old_boundary; class ParScanThreadStateSet* _state_set; StrongRootsScope* _strong_roots_scope; + OopStorage::ParState _par_state_string; public: ParNewGenTask(ParNewGeneration* young_gen, diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 00954e6e940..48cbd9802e2 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -69,6 +69,7 @@ #include "gc/shared/gcTraceTime.inline.hpp" #include "gc/shared/generationSpec.hpp" #include "gc/shared/isGCActiveMark.hpp" +#include "gc/shared/oopStorageParState.hpp" #include "gc/shared/preservedMarks.inline.hpp" #include "gc/shared/suspendibleThreadSet.hpp" #include "gc/shared/referenceProcessor.inline.hpp" @@ -3218,6 +3219,7 @@ class G1StringAndSymbolCleaningTask : public AbstractGangTask { private: BoolObjectClosure* _is_alive; G1StringDedupUnlinkOrOopsDoClosure _dedup_closure; + OopStorage::ParState _par_state_string; int _initial_string_table_size; int _initial_symbol_table_size; @@ -3237,24 +3239,19 @@ public: AbstractGangTask("String/Symbol Unlinking"), _is_alive(is_alive), _dedup_closure(is_alive, NULL, false), + _par_state_string(StringTable::weak_storage()), _process_strings(process_strings), _strings_processed(0), _strings_removed(0), _process_symbols(process_symbols), _symbols_processed(0), _symbols_removed(0), _process_string_dedup(process_string_dedup) { - _initial_string_table_size = StringTable::the_table()->table_size(); + _initial_string_table_size = (int) StringTable::the_table()->table_size(); _initial_symbol_table_size = SymbolTable::the_table()->table_size(); - if (process_strings) { - StringTable::clear_parallel_claimed_index(); - } if (process_symbols) { SymbolTable::clear_parallel_claimed_index(); } } ~G1StringAndSymbolCleaningTask() { - guarantee(!_process_strings || StringTable::parallel_claimed_index() >= _initial_string_table_size, - "claim value %d after unlink less than initial string table size %d", - StringTable::parallel_claimed_index(), _initial_string_table_size); guarantee(!_process_symbols || SymbolTable::parallel_claimed_index() >= _initial_symbol_table_size, "claim value %d after unlink less than initial symbol table size %d", SymbolTable::parallel_claimed_index(), _initial_symbol_table_size); @@ -3273,7 +3270,7 @@ public: int symbols_processed = 0; int symbols_removed = 0; if (_process_strings) { - StringTable::possibly_parallel_unlink(_is_alive, &strings_processed, &strings_removed); + StringTable::possibly_parallel_unlink(&_par_state_string, _is_alive, &strings_processed, &strings_removed); Atomic::add(strings_processed, &_strings_processed); Atomic::add(strings_removed, &_strings_removed); } diff --git a/src/hotspot/share/gc/g1/g1RootProcessor.cpp b/src/hotspot/share/gc/g1/g1RootProcessor.cpp index 73b3c91ab94..e47c9f7baea 100644 --- a/src/hotspot/share/gc/g1/g1RootProcessor.cpp +++ b/src/hotspot/share/gc/g1/g1RootProcessor.cpp @@ -38,6 +38,7 @@ #include "gc/g1/g1RootClosures.hpp" #include "gc/g1/g1RootProcessor.hpp" #include "gc/g1/heapRegion.inline.hpp" +#include "gc/shared/oopStorageParState.hpp" #include "gc/shared/referenceProcessor.hpp" #include "gc/shared/weakProcessor.hpp" #include "memory/allocation.inline.hpp" @@ -72,6 +73,7 @@ G1RootProcessor::G1RootProcessor(G1CollectedHeap* g1h, uint n_workers) : _process_strong_tasks(G1RP_PS_NumElements), _srs(n_workers), _lock(Mutex::leaf, "G1 Root Scanning barrier lock", false, Monitor::_safepoint_check_never), + _par_state_string(StringTable::weak_storage()), _n_workers_discovered_strong_classes(0) {} void G1RootProcessor::evacuate_roots(G1ParScanThreadState* pss, uint worker_i) { @@ -301,7 +303,7 @@ void G1RootProcessor::process_string_table_roots(G1RootClosures* closures, G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::StringTableRoots, worker_i); // All threads execute the following. A specific chunk of buckets // from the StringTable are the individual tasks. - StringTable::possibly_parallel_oops_do(closures->weak_oops()); + StringTable::possibly_parallel_oops_do(&_par_state_string, closures->weak_oops()); } void G1RootProcessor::process_code_cache_roots(CodeBlobClosure* code_closure, diff --git a/src/hotspot/share/gc/g1/g1RootProcessor.hpp b/src/hotspot/share/gc/g1/g1RootProcessor.hpp index c4b5f03016e..3c2e811cb80 100644 --- a/src/hotspot/share/gc/g1/g1RootProcessor.hpp +++ b/src/hotspot/share/gc/g1/g1RootProcessor.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_VM_GC_G1_G1ROOTPROCESSOR_HPP #define SHARE_VM_GC_G1_G1ROOTPROCESSOR_HPP +#include "gc/shared/oopStorageParState.hpp" #include "gc/shared/strongRootsScope.hpp" #include "memory/allocation.hpp" #include "runtime/mutex.hpp" @@ -49,6 +50,7 @@ class G1RootProcessor : public StackObj { G1CollectedHeap* _g1h; SubTasksDone _process_strong_tasks; StrongRootsScope _srs; + OopStorage::ParState _par_state_string; // Used to implement the Thread work barrier. Monitor _lock; diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.cpp b/src/hotspot/share/gc/shared/genCollectedHeap.cpp index efd714ef7b0..5a5804f053e 100644 --- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp @@ -44,6 +44,7 @@ #include "gc/shared/genCollectedHeap.hpp" #include "gc/shared/genOopClosures.inline.hpp" #include "gc/shared/generationSpec.hpp" +#include "gc/shared/oopStorageParState.inline.hpp" #include "gc/shared/space.hpp" #include "gc/shared/strongRootsScope.hpp" #include "gc/shared/vmGCOperations.hpp" @@ -851,12 +852,17 @@ void GenCollectedHeap::process_roots(StrongRootsScope* scope, } void GenCollectedHeap::process_string_table_roots(StrongRootsScope* scope, - OopClosure* root_closure) { + OopClosure* root_closure, + OopStorage::ParState* par_state_string) { assert(root_closure != NULL, "Must be set"); // All threads execute the following. A specific chunk of buckets // from the StringTable are the individual tasks. + + // Either we should be single threaded or have a ParState + assert((scope->n_threads() <= 1) || par_state_string != NULL, "Parallel but no ParState"); + if (scope->n_threads() > 1) { - StringTable::possibly_parallel_oops_do(root_closure); + StringTable::possibly_parallel_oops_do(par_state_string, root_closure); } else { StringTable::oops_do(root_closure); } @@ -865,12 +871,13 @@ void GenCollectedHeap::process_string_table_roots(StrongRootsScope* scope, void GenCollectedHeap::young_process_roots(StrongRootsScope* scope, OopsInGenClosure* root_closure, OopsInGenClosure* old_gen_closure, - CLDClosure* cld_closure) { + CLDClosure* cld_closure, + OopStorage::ParState* par_state_string) { MarkingCodeBlobClosure mark_code_closure(root_closure, CodeBlobToOopClosure::FixRelocations); process_roots(scope, SO_ScavengeCodeCache, root_closure, cld_closure, cld_closure, &mark_code_closure); - process_string_table_roots(scope, root_closure); + process_string_table_roots(scope, root_closure, par_state_string); if (!_process_strong_tasks->is_task_claimed(GCH_PS_younger_gens)) { root_closure->reset_generation(); @@ -890,7 +897,8 @@ void GenCollectedHeap::full_process_roots(StrongRootsScope* scope, ScanningOption so, bool only_strong_roots, OopsInGenClosure* root_closure, - CLDClosure* cld_closure) { + CLDClosure* cld_closure, + OopStorage::ParState* par_state_string) { MarkingCodeBlobClosure mark_code_closure(root_closure, is_adjust_phase); CLDClosure* weak_cld_closure = only_strong_roots ? NULL : cld_closure; @@ -899,7 +907,7 @@ void GenCollectedHeap::full_process_roots(StrongRootsScope* scope, // We never treat the string table as roots during marking // for the full gc, so we only need to process it during // the adjust phase. - process_string_table_roots(scope, root_closure); + process_string_table_roots(scope, root_closure, par_state_string); } _process_strong_tasks->all_tasks_completed(scope->n_threads()); diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.hpp b/src/hotspot/share/gc/shared/genCollectedHeap.hpp index a56eff2190e..a250fcd8a14 100644 --- a/src/hotspot/share/gc/shared/genCollectedHeap.hpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.hpp @@ -28,6 +28,7 @@ #include "gc/shared/collectedHeap.hpp" #include "gc/shared/collectorPolicy.hpp" #include "gc/shared/generation.hpp" +#include "gc/shared/oopStorageParState.hpp" #include "gc/shared/softRefGenPolicy.hpp" class AdaptiveSizePolicy; @@ -401,7 +402,8 @@ public: CodeBlobToOopClosure* code_roots); void process_string_table_roots(StrongRootsScope* scope, - OopClosure* root_closure); + OopClosure* root_closure, + OopStorage::ParState* par_state_string); // Accessor for memory state verification support NOT_PRODUCT( @@ -415,14 +417,16 @@ public: void young_process_roots(StrongRootsScope* scope, OopsInGenClosure* root_closure, OopsInGenClosure* old_gen_closure, - CLDClosure* cld_closure); + CLDClosure* cld_closure, + OopStorage::ParState* par_state_string = NULL); void full_process_roots(StrongRootsScope* scope, bool is_adjust_phase, ScanningOption so, bool only_strong_roots, OopsInGenClosure* root_closure, - CLDClosure* cld_closure); + CLDClosure* cld_closure, + OopStorage::ParState* par_state_string = NULL); // Apply "root_closure" to all the weak roots of the system. // These include JNI weak roots, string table, diff --git a/src/hotspot/share/gc/shared/strongRootsScope.cpp b/src/hotspot/share/gc/shared/strongRootsScope.cpp index 43a697f8cda..a167ba48958 100644 --- a/src/hotspot/share/gc/shared/strongRootsScope.cpp +++ b/src/hotspot/share/gc/shared/strongRootsScope.cpp @@ -38,8 +38,6 @@ MarkScope::~MarkScope() { StrongRootsScope::StrongRootsScope(uint n_threads) : _n_threads(n_threads) { Threads::change_thread_claim_parity(); - // Zero the claimed high water mark in the StringTable - StringTable::clear_parallel_claimed_index(); } StrongRootsScope::~StrongRootsScope() { diff --git a/src/hotspot/share/memory/metaspaceShared.cpp b/src/hotspot/share/memory/metaspaceShared.cpp index 72bd6e99205..a89cfd0d25f 100644 --- a/src/hotspot/share/memory/metaspaceShared.cpp +++ b/src/hotspot/share/memory/metaspaceShared.cpp @@ -1841,7 +1841,7 @@ void MetaspaceShared::dump_closed_archive_heap_objects( G1CollectedHeap::heap()->begin_archive_alloc_range(); // Archive interned string objects - StringTable::write_to_archive(closed_archive); + StringTable::write_to_archive(); G1CollectedHeap::heap()->end_archive_alloc_range(closed_archive, os::vm_allocation_granularity()); diff --git a/src/hotspot/share/oops/weakHandle.cpp b/src/hotspot/share/oops/weakHandle.cpp index 82072718334..7de613d1391 100644 --- a/src/hotspot/share/oops/weakHandle.cpp +++ b/src/hotspot/share/oops/weakHandle.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/systemDictionary.hpp" +#include "classfile/stringTable.hpp" #include "gc/shared/oopStorage.hpp" #include "oops/access.inline.hpp" #include "oops/oop.hpp" @@ -35,6 +36,10 @@ template <> OopStorage* WeakHandle::get_storage() { return SystemDictionary::vm_weak_oop_storage(); } +template <> OopStorage* WeakHandle::get_storage() { + return StringTable::weak_storage(); +} + template WeakHandle WeakHandle::create(Handle obj) { assert(obj() != NULL, "no need to create weak null oop"); @@ -68,4 +73,5 @@ void WeakHandle::print_on(outputStream* st) const { // Provide instantiation. template class WeakHandle; +template class WeakHandle; diff --git a/src/hotspot/share/oops/weakHandle.hpp b/src/hotspot/share/oops/weakHandle.hpp index d1054efbd9c..57587c4f224 100644 --- a/src/hotspot/share/oops/weakHandle.hpp +++ b/src/hotspot/share/oops/weakHandle.hpp @@ -39,12 +39,11 @@ class OopStorage; // This is the vm version of jweak but has different GC lifetimes and policies, // depending on the type. -enum WeakHandleType { vm_class_loader_data, vm_string }; +enum WeakHandleType { vm_class_loader_data, vm_string, vm_string_table_data }; template class WeakHandle { public: - private: oop* _obj; @@ -59,6 +58,8 @@ class WeakHandle { void release() const; bool is_null() const { return _obj == NULL; } + void replace(oop with_obj); + void print() const; void print_on(outputStream* st) const; }; diff --git a/src/hotspot/share/oops/weakHandle.inline.hpp b/src/hotspot/share/oops/weakHandle.inline.hpp index 6b8b5ffc2b4..7037fcea796 100644 --- a/src/hotspot/share/oops/weakHandle.inline.hpp +++ b/src/hotspot/share/oops/weakHandle.inline.hpp @@ -40,4 +40,10 @@ oop WeakHandle::peek() const { return RootAccess::oop_load(_obj); } +template +void WeakHandle::replace(oop with_obj) { + RootAccess::oop_store(_obj, with_obj); +} + #endif // SHARE_VM_OOPS_WEAKHANDLE_INLINE_HPP + diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 3729eb2992c..412c440a790 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -2542,8 +2542,9 @@ define_pd_global(uint64_t,MaxRAM, 1ULL*G); "Relax the access control checks in the verifier") \ \ product(uintx, StringTableSize, defaultStringTableSize, \ - "Number of buckets in the interned String table") \ - range(minimumStringTableSize, 111*defaultStringTableSize) \ + "Number of buckets in the interned String table " \ + "(will be rounded to nearest higher power of 2)") \ + range(minimumStringTableSize, 16777216ul) \ \ experimental(uintx, SymbolTableSize, defaultSymbolTableSize, \ "Number of buckets in the JVM internal Symbol table") \ diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp index f557239aea6..f5dab8d4447 100644 --- a/src/hotspot/share/runtime/java.cpp +++ b/src/hotspot/share/runtime/java.cpp @@ -524,14 +524,9 @@ void before_exit(JavaThread* thread) { } if (VerifyStringTableAtExit) { - int fail_cnt = 0; - { - MutexLocker ml(StringTable_lock); - fail_cnt = StringTable::verify_and_compare_entries(); - } - + size_t fail_cnt = StringTable::verify_and_compare_entries(); if (fail_cnt != 0) { - tty->print_cr("ERROR: fail_cnt=%d", fail_cnt); + tty->print_cr("ERROR: fail_cnt=" SIZE_FORMAT, fail_cnt); guarantee(fail_cnt == 0, "unexpected StringTable verification failures"); } } diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp index 485cd6d7c0a..7eb058385bf 100644 --- a/src/hotspot/share/runtime/mutexLocker.cpp +++ b/src/hotspot/share/runtime/mutexLocker.cpp @@ -48,6 +48,8 @@ Mutex* JNIGlobalAlloc_lock = NULL; Mutex* JNIGlobalActive_lock = NULL; Mutex* JNIWeakAlloc_lock = NULL; Mutex* JNIWeakActive_lock = NULL; +Mutex* StringTableWeakAlloc_lock = NULL; +Mutex* StringTableWeakActive_lock = NULL; Mutex* JNIHandleBlockFreeList_lock = NULL; Mutex* VMWeakAlloc_lock = NULL; Mutex* VMWeakActive_lock = NULL; @@ -186,6 +188,9 @@ void mutex_init() { def(VMWeakAlloc_lock , PaddedMutex , vmweak, true, Monitor::_safepoint_check_never); def(VMWeakActive_lock , PaddedMutex , vmweak-1, true, Monitor::_safepoint_check_never); + def(StringTableWeakAlloc_lock , PaddedMutex , vmweak, true, Monitor::_safepoint_check_never); + def(StringTableWeakActive_lock , PaddedMutex , vmweak-1, true, Monitor::_safepoint_check_never); + if (UseConcMarkSweepGC || UseG1GC) { def(FullGCCount_lock , PaddedMonitor, leaf, true, Monitor::_safepoint_check_never); // in support of ExplicitGCInvokesConcurrent } diff --git a/src/hotspot/share/runtime/mutexLocker.hpp b/src/hotspot/share/runtime/mutexLocker.hpp index 673d7ed56c6..a477899929c 100644 --- a/src/hotspot/share/runtime/mutexLocker.hpp +++ b/src/hotspot/share/runtime/mutexLocker.hpp @@ -42,6 +42,8 @@ extern Mutex* JNIGlobalAlloc_lock; // JNI global storage allocate extern Mutex* JNIGlobalActive_lock; // JNI global storage active list lock extern Mutex* JNIWeakAlloc_lock; // JNI weak storage allocate list lock extern Mutex* JNIWeakActive_lock; // JNI weak storage active list lock +extern Mutex* StringTableWeakAlloc_lock; // StringTable weak storage allocate list lock +extern Mutex* StringTableWeakActive_lock; // STringTable weak storage active list lock extern Mutex* JNIHandleBlockFreeList_lock; // a lock on the JNI handle block free list extern Mutex* VMWeakAlloc_lock; // VM Weak Handles storage allocate list lock extern Mutex* VMWeakActive_lock; // VM Weak Handles storage active list lock diff --git a/src/hotspot/share/runtime/serviceThread.cpp b/src/hotspot/share/runtime/serviceThread.cpp index 5174a32ebfa..364a62ff1b1 100644 --- a/src/hotspot/share/runtime/serviceThread.cpp +++ b/src/hotspot/share/runtime/serviceThread.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/stringTable.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/javaCalls.hpp" #include "runtime/serviceThread.hpp" @@ -82,6 +83,7 @@ void ServiceThread::service_thread_entry(JavaThread* jt, TRAPS) { bool has_gc_notification_event = false; bool has_dcmd_notification_event = false; bool acs_notify = false; + bool stringtable_work = false; JvmtiDeferredEvent jvmti_event; { // Need state transition ThreadBlockInVM so that this thread @@ -98,7 +100,8 @@ void ServiceThread::service_thread_entry(JavaThread* jt, TRAPS) { while (!(sensors_changed = LowMemoryDetector::has_pending_requests()) && !(has_jvmti_events = JvmtiDeferredEventQueue::has_events()) && !(has_gc_notification_event = GCNotifier::has_event()) && - !(has_dcmd_notification_event = DCmdFactory::has_pending_jmx_notification())) { + !(has_dcmd_notification_event = DCmdFactory::has_pending_jmx_notification()) && + !(stringtable_work = StringTable::has_work())) { // wait until one of the sensors has pending requests, or there is a // pending JVMTI event or JMX GC notification to post Service_lock->wait(Mutex::_no_safepoint_check_flag); @@ -109,6 +112,10 @@ void ServiceThread::service_thread_entry(JavaThread* jt, TRAPS) { } } + if (stringtable_work) { + StringTable::do_concurrent_work(jt); + } + if (has_jvmti_events) { jvmti_event.post(); } diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 48a51aba18e..68739477371 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -164,7 +164,6 @@ typedef HashtableEntry IntptrHashtableEntry; typedef Hashtable IntptrHashtable; typedef Hashtable SymbolHashtable; typedef HashtableEntry SymbolHashtableEntry; -typedef Hashtable StringHashtable; typedef Hashtable KlassHashtable; typedef HashtableEntry KlassHashtableEntry; typedef CompactHashtable SymbolCompactHashTable; @@ -476,12 +475,6 @@ typedef PaddedEnd PaddedObjectMonitor; static_field(SymbolTable, _shared_table, SymbolCompactHashTable) \ static_field(RehashableSymbolHashtable, _seed, juint) \ \ - /***************/ \ - /* StringTable */ \ - /***************/ \ - \ - static_field(StringTable, _the_table, StringTable*) \ - \ /********************/ \ /* CompactHashTable */ \ /********************/ \ @@ -1365,7 +1358,6 @@ typedef PaddedEnd PaddedObjectMonitor; declare_toplevel_type(BasicHashtable) \ declare_type(RehashableSymbolHashtable, BasicHashtable) \ declare_type(SymbolTable, SymbolHashtable) \ - declare_type(StringTable, StringHashtable) \ declare_type(Dictionary, KlassHashtable) \ declare_toplevel_type(BasicHashtableEntry) \ declare_type(IntptrHashtableEntry, BasicHashtableEntry) \ diff --git a/src/hotspot/share/utilities/concurrentHashTable.hpp b/src/hotspot/share/utilities/concurrentHashTable.hpp index 545f8e73dfe..6d5ab1c42fd 100644 --- a/src/hotspot/share/utilities/concurrentHashTable.hpp +++ b/src/hotspot/share/utilities/concurrentHashTable.hpp @@ -484,6 +484,9 @@ class ConcurrentHashTable : public CHeapObj { void statistics_to(Thread* thread, VALUE_SIZE_FUNC& vs_f, outputStream* st, const char* table_name); + // Moves all nodes from this table to to_cht + bool try_move_nodes_to(Thread* thread, ConcurrentHashTable* to_cht); + // This is a Curiously Recurring Template Pattern (CRPT) interface for the // specialization. struct BaseConfig { diff --git a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp index 089cd79c5e7..71487d8234e 100644 --- a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp +++ b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp @@ -293,7 +293,7 @@ template inline void ConcurrentHashTable:: write_synchonize_on_visible_epoch(Thread* thread) { - assert(_resize_lock->owned_by_self(), "Re-size lock not held"); + assert(_resize_lock_owner == thread, "Re-size lock not held"); OrderAccess::fence(); // Prevent below load from floating up. // If no reader saw this version we can skip write_synchronize. if (OrderAccess::load_acquire(&_invisible_epoch) == thread) { @@ -488,7 +488,7 @@ inline void ConcurrentHashTable:: { // Here we have resize lock so table is SMR safe, and there is no new // table. Can do this in parallel if we want. - assert(_resize_lock->owned_by_self(), "Re-size lock not held"); + assert(_resize_lock_owner == thread, "Re-size lock not held"); Node* ndel[BULK_DELETE_LIMIT]; InternalTable* table = get_table(); assert(start_idx < stop_idx, "Must be"); @@ -500,9 +500,9 @@ inline void ConcurrentHashTable:: // own read-side. GlobalCounter::critical_section_begin(thread); for (size_t bucket_it = start_idx; bucket_it < stop_idx; bucket_it++) { - Bucket* bucket = _table->get_bucket(bucket_it); + Bucket* bucket = table->get_bucket(bucket_it); Bucket* prefetch_bucket = (bucket_it+1) < stop_idx ? - _table->get_bucket(bucket_it+1) : NULL; + table->get_bucket(bucket_it+1) : NULL; if (!HaveDeletables::value, EVALUATE_FUNC>:: have_deletable(bucket, eval_f, prefetch_bucket)) { @@ -695,17 +695,13 @@ inline bool ConcurrentHashTable:: if (!try_resize_lock(thread)) { return false; } - - assert(_resize_lock->owned_by_self(), "Re-size lock not held"); - + assert(_resize_lock_owner == thread, "Re-size lock not held"); if (_table->_log2_size == _log2_start_size || _table->_log2_size <= log2_size) { unlock_resize_lock(thread); return false; } - _new_table = new InternalTable(_table->_log2_size - 1); - return true; } @@ -713,8 +709,7 @@ template inline void ConcurrentHashTable:: internal_shrink_epilog(Thread* thread) { - assert(_resize_lock->owned_by_self(), "Re-size lock not held"); - assert(_resize_lock_owner, "Should be locked"); + assert(_resize_lock_owner == thread, "Re-size lock not held"); InternalTable* old_table = set_table_from_new(); _size_limit_reached = false; @@ -771,14 +766,13 @@ inline bool ConcurrentHashTable:: internal_shrink(Thread* thread, size_t log2_size) { if (!internal_shrink_prolog(thread, log2_size)) { - assert(!_resize_lock->owned_by_self(), "Re-size lock held"); + assert(_resize_lock_owner != thread, "Re-size lock held"); return false; } - assert(_resize_lock->owned_by_self(), "Re-size lock not held"); assert(_resize_lock_owner == thread, "Should be locked by me"); internal_shrink_range(thread, 0, _new_table->_size); internal_shrink_epilog(thread); - assert(!_resize_lock->owned_by_self(), "Re-size lock not held"); + assert(_resize_lock_owner != thread, "Re-size lock held"); return true; } @@ -815,8 +809,7 @@ template inline void ConcurrentHashTable:: internal_grow_epilog(Thread* thread) { - assert(_resize_lock->owned_by_self(), "Re-size lock not held"); - assert(_resize_lock_owner, "Should be locked"); + assert(_resize_lock_owner == thread, "Should be locked"); InternalTable* old_table = set_table_from_new(); unlock_resize_lock(thread); @@ -835,14 +828,13 @@ inline bool ConcurrentHashTable:: internal_grow(Thread* thread, size_t log2_size) { if (!internal_grow_prolog(thread, log2_size)) { - assert(!_resize_lock->owned_by_self(), "Re-size lock held"); + assert(_resize_lock_owner != thread, "Re-size lock held"); return false; } - assert(_resize_lock->owned_by_self(), "Re-size lock not held"); assert(_resize_lock_owner == thread, "Should be locked by me"); internal_grow_range(thread, 0, _table->_size); internal_grow_epilog(thread); - assert(!_resize_lock->owned_by_self(), "Re-size lock not held"); + assert(_resize_lock_owner != thread, "Re-size lock held"); return true; } @@ -955,15 +947,13 @@ template inline void ConcurrentHashTable:: do_scan_locked(Thread* thread, FUNC& scan_f) { - assert(_resize_lock->owned_by_self() || - (thread->is_VM_thread() && SafepointSynchronize::is_at_safepoint()), - "Re-size lock not held or not VMThread at safepoint"); + assert(_resize_lock_owner == thread, "Re-size lock not held"); // We can do a critical section over the entire loop but that would block // updates for a long time. Instead we choose to block resizes. InternalTable* table = get_table(); - for (size_t bucket_it = 0; bucket_it < _table->_size; bucket_it++) { + for (size_t bucket_it = 0; bucket_it < table->_size; bucket_it++) { ScopedCS cs(thread, this); - if (!visit_nodes(_table->get_bucket(bucket_it), scan_f)) { + if (!visit_nodes(table->get_bucket(bucket_it), scan_f)) { break; /* ends critical section */ } } /* ends critical section */ @@ -1094,17 +1084,11 @@ template inline bool ConcurrentHashTable:: try_scan(Thread* thread, SCAN_FUNC& scan_f) { - assert(!_resize_lock->owned_by_self(), "Re-size lock not held"); - bool vm_and_safepoint = thread->is_VM_thread() && - SafepointSynchronize::is_at_safepoint(); - if (!vm_and_safepoint && !try_resize_lock(thread)) { + if (!try_resize_lock(thread)) { return false; } do_scan_locked(thread, scan_f); - if (!vm_and_safepoint) { - unlock_resize_lock(thread); - } - assert(!_resize_lock->owned_by_self(), "Re-size lock not held"); + unlock_resize_lock(thread); return true; } @@ -1113,11 +1097,11 @@ template inline void ConcurrentHashTable:: do_scan(Thread* thread, SCAN_FUNC& scan_f) { - assert(!_resize_lock->owned_by_self(), "Re-size lock not held"); + assert(_resize_lock_owner != thread, "Re-size lock held"); lock_resize_lock(thread); do_scan_locked(thread, scan_f); unlock_resize_lock(thread); - assert(!_resize_lock->owned_by_self(), "Re-size lock not held"); + assert(_resize_lock_owner != thread, "Re-size lock held"); } template @@ -1126,12 +1110,11 @@ inline bool ConcurrentHashTable:: try_bulk_delete(Thread* thread, EVALUATE_FUNC& eval_f, DELETE_FUNC& del_f) { if (!try_resize_lock(thread)) { - assert(!_resize_lock->owned_by_self(), "Re-size lock not held"); return false; } do_bulk_delete_locked(thread, eval_f, del_f); unlock_resize_lock(thread); - assert(!_resize_lock->owned_by_self(), "Re-size lock not held"); + assert(_resize_lock_owner != thread, "Re-size lock held"); return true; } @@ -1140,11 +1123,9 @@ template inline void ConcurrentHashTable:: bulk_delete(Thread* thread, EVALUATE_FUNC& eval_f, DELETE_FUNC& del_f) { - assert(!_resize_lock->owned_by_self(), "Re-size lock not held"); lock_resize_lock(thread); do_bulk_delete_locked(thread, eval_f, del_f); unlock_resize_lock(thread); - assert(!_resize_lock->owned_by_self(), "Re-size lock not held"); } template @@ -1155,17 +1136,16 @@ inline void ConcurrentHashTable:: { NumberSeq summary; size_t literal_bytes = 0; - if ((thread->is_VM_thread() && !SafepointSynchronize::is_at_safepoint()) || - (!thread->is_VM_thread() && !try_resize_lock(thread))) { + if (!try_resize_lock(thread)) { st->print_cr("statistics unavailable at this moment"); return; } InternalTable* table = get_table(); - for (size_t bucket_it = 0; bucket_it < _table->_size; bucket_it++) { + for (size_t bucket_it = 0; bucket_it < table->_size; bucket_it++) { ScopedCS cs(thread, this); size_t count = 0; - Bucket* bucket = _table->get_bucket(bucket_it); + Bucket* bucket = table->get_bucket(bucket_it); if (bucket->have_redirect() || bucket->is_locked()) { continue; } @@ -1208,9 +1188,37 @@ inline void ConcurrentHashTable:: st->print_cr("Std. dev. of bucket size: %9.3f", summary.sd()); st->print_cr("Maximum bucket size : %9" PRIuPTR, (size_t)summary.maximum()); - if (!thread->is_VM_thread()) { - unlock_resize_lock(thread); + unlock_resize_lock(thread); +} + +template +inline bool ConcurrentHashTable:: + try_move_nodes_to(Thread* thread, ConcurrentHashTable* to_cht) +{ + if (!try_resize_lock(thread)) { + return false; } + assert(_new_table == NULL, "Must be NULL"); + for (size_t bucket_it = 0; bucket_it < _table->_size; bucket_it++) { + Bucket* bucket = _table->get_bucket(bucket_it); + assert(!bucket->have_redirect() && !bucket->is_locked(), "Table must be uncontended"); + while (bucket->first() != NULL) { + Node* move_node = bucket->first(); + bool ok = bucket->cas_first(move_node->next(), move_node); + assert(ok, "Uncontended cas must work"); + bool dead_hash = false; + size_t insert_hash = CONFIG::get_hash(*move_node->value(), &dead_hash); + if (!dead_hash) { + Bucket* insert_bucket = to_cht->get_bucket(insert_hash); + assert(!bucket->have_redirect() && !bucket->is_locked(), "Not bit should be present"); + move_node->set_next(insert_bucket->first()); + ok = insert_bucket->cas_first(move_node, insert_bucket->first()); + assert(ok, "Uncontended cas must work"); + } + } + } + unlock_resize_lock(thread); + return true; } #endif // include guard diff --git a/src/hotspot/share/utilities/concurrentHashTableTasks.inline.hpp b/src/hotspot/share/utilities/concurrentHashTableTasks.inline.hpp index 8a1bc40d37b..cfee9fb7e22 100644 --- a/src/hotspot/share/utilities/concurrentHashTableTasks.inline.hpp +++ b/src/hotspot/share/utilities/concurrentHashTableTasks.inline.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_UTILITIES_CONCURRENT_HASH_TABLE_TASKS_INLINE_HPP #define SHARE_UTILITIES_CONCURRENT_HASH_TABLE_TASKS_INLINE_HPP +#include "utilities/globalDefinitions.hpp" #include "utilities/concurrentHashTable.inline.hpp" // This inline file contains BulkDeleteTask and GrowTasks which are both bucket @@ -63,6 +64,7 @@ class ConcurrentHashTable::BucketsOperation { // Calculate starting values. void setup() { _size_log2 = _cht->_table->_log2_size; + _task_size_log2 = MIN2(_task_size_log2, _size_log2); size_t tmp = _size_log2 > _task_size_log2 ? _size_log2 - _task_size_log2 : 0; _stop_task = (((size_t)1) << tmp); diff --git a/src/hotspot/share/utilities/globalDefinitions.hpp b/src/hotspot/share/utilities/globalDefinitions.hpp index 088316591ea..2dccbc1fe54 100644 --- a/src/hotspot/share/utilities/globalDefinitions.hpp +++ b/src/hotspot/share/utilities/globalDefinitions.hpp @@ -424,8 +424,8 @@ const int max_method_code_size = 64*K - 1; // JVM spec, 2nd ed. section 4.8.1 ( //---------------------------------------------------------------------------------------------------- // Default and minimum StringTableSize values -const int defaultStringTableSize = NOT_LP64(1009) LP64_ONLY(60013); -const int minimumStringTableSize = 1009; +const int defaultStringTableSize = NOT_LP64(1024) LP64_ONLY(65536); +const int minimumStringTableSize = 128; const int defaultSymbolTableSize = 20011; const int minimumSymbolTableSize = 1009; diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/StringTable.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/StringTable.java deleted file mode 100644 index 8bf42f0415e..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/StringTable.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2005, 2011, 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 sun.jvm.hotspot.memory; - -import java.io.*; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.utilities.*; - -public class StringTable extends sun.jvm.hotspot.utilities.Hashtable { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) { - Type type = db.lookupType("StringTable"); - theTableField = type.getAddressField("_the_table"); - } - - // Fields - private static AddressField theTableField; - - // Accessors - public static StringTable getTheTable() { - Address tmp = theTableField.getValue(); - return (StringTable) VMObjectFactory.newObject(StringTable.class, tmp); - } - - public StringTable(Address addr) { - super(addr); - } - - public interface StringVisitor { - public void visit(Instance string); - } - - public void stringsDo(StringVisitor visitor) { - ObjectHeap oh = VM.getVM().getObjectHeap(); - int numBuckets = tableSize(); - for (int i = 0; i < numBuckets; i++) { - for (HashtableEntry e = (HashtableEntry) bucket(i); e != null; - e = (HashtableEntry) e.next()) { - Instance s = (Instance)oh.newOop(e.literalValue().addOffsetToAsOopHandle(0)); - visitor.visit(s); - } - } - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java index bbfe6e65e99..05e695386d4 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java @@ -79,7 +79,6 @@ public class VM { private Universe universe; private ObjectHeap heap; private SymbolTable symbols; - private StringTable strings; private SystemDictionary dict; private ClassLoaderDataGraph cldGraph; private Threads threads; @@ -655,13 +654,6 @@ public class VM { return symbols; } - public StringTable getStringTable() { - if (strings == null) { - strings = StringTable.getTheTable(); - } - return strings; - } - public SystemDictionary getSystemDictionary() { if (dict == null) { dict = new SystemDictionary(); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java index 0d81604e7d5..7897191b390 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java @@ -129,7 +129,6 @@ public class HeapSummary extends Tool { } System.out.println(); - printInternStringStatistics(); } // Helper methods @@ -258,41 +257,4 @@ public class HeapSummary extends Tool { return -1; } } - - private void printInternStringStatistics() { - class StringStat implements StringTable.StringVisitor { - private int count; - private long size; - private OopField stringValueField; - - StringStat() { - VM vm = VM.getVM(); - SystemDictionary sysDict = vm.getSystemDictionary(); - InstanceKlass strKlass = sysDict.getStringKlass(); - // String has a field named 'value' of type 'byte[]'. - stringValueField = (OopField) strKlass.findField("value", "[B"); - } - - private long stringSize(Instance instance) { - // We include String content in size calculation. - return instance.getObjectSize() + - stringValueField.getValue(instance).getObjectSize(); - } - - public void visit(Instance str) { - count++; - size += stringSize(str); - } - - public void print() { - System.out.println(count + - " interned Strings occupying " + size + " bytes."); - } - } - - StringStat stat = new StringStat(); - StringTable strTable = VM.getVM().getStringTable(); - strTable.stringsDo(stat); - stat.print(); - } } diff --git a/test/hotspot/gtest/utilities/test_concurrentHashtable.cpp b/test/hotspot/gtest/utilities/test_concurrentHashtable.cpp index b877edb96cf..1cffbd300d9 100644 --- a/test/hotspot/gtest/utilities/test_concurrentHashtable.cpp +++ b/test/hotspot/gtest/utilities/test_concurrentHashtable.cpp @@ -265,6 +265,40 @@ static void cht_scan(Thread* thr) { delete cht; } +struct ChtCountScan { + size_t _count; + ChtCountScan() : _count(0) {} + bool operator()(uintptr_t* val) { + _count++; + return true; /* continue scan */ + } +}; + +static void cht_move_to(Thread* thr) { + uintptr_t val1 = 0x2; + uintptr_t val2 = 0xe0000002; + uintptr_t val3 = 0x3; + SimpleTestLookup stl1(val1), stl2(val2), stl3(val3); + SimpleTestTable* from_cht = new SimpleTestTable(); + EXPECT_TRUE(from_cht->insert(thr, stl1, val1)) << "Insert unique value failed."; + EXPECT_TRUE(from_cht->insert(thr, stl2, val2)) << "Insert unique value failed."; + EXPECT_TRUE(from_cht->insert(thr, stl3, val3)) << "Insert unique value failed."; + + SimpleTestTable* to_cht = new SimpleTestTable(); + EXPECT_TRUE(from_cht->try_move_nodes_to(thr, to_cht)) << "Moving nodes to new table failed"; + + ChtCountScan scan_old; + EXPECT_TRUE(from_cht->try_scan(thr, scan_old)) << "Scanning table should work."; + EXPECT_EQ(scan_old._count, (size_t)0) << "All items should be moved"; + + ChtCountScan scan_new; + EXPECT_TRUE(to_cht->try_scan(thr, scan_new)) << "Scanning table should work."; + EXPECT_EQ(scan_new._count, (size_t)3) << "All items should be moved"; + EXPECT_TRUE(to_cht->get_copy(thr, stl1) == val1) << "Getting an inserted value should work."; + EXPECT_TRUE(to_cht->get_copy(thr, stl2) == val2) << "Getting an inserted value should work."; + EXPECT_TRUE(to_cht->get_copy(thr, stl3) == val3) << "Getting an inserted value should work."; +} + static void cht_grow(Thread* thr) { uintptr_t val = 0x2; uintptr_t val2 = 0x22; @@ -371,6 +405,10 @@ TEST_VM(ConcurrentHashTable, basic_scan) { nomt_test_doer(cht_scan); } +TEST_VM(ConcurrentHashTable, basic_move_to) { + nomt_test_doer(cht_move_to); +} + TEST_VM(ConcurrentHashTable, basic_grow) { nomt_test_doer(cht_grow); } From 9f39d8c40859c609adc2e40032923a1daa4ba058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20=C3=96sterlund?= Date: Thu, 7 Jun 2018 15:10:06 +0200 Subject: [PATCH 15/46] 8203353: Fixup inferred decorators in the interpreter Reviewed-by: rkennke, coleenp --- src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp | 7 +++++-- src/hotspot/cpu/aarch64/templateTable_aarch64.cpp | 6 +++--- src/hotspot/cpu/arm/macroAssembler_arm.cpp | 5 ++++- src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp | 3 +++ src/hotspot/cpu/ppc/templateTable_ppc_64.cpp | 6 +++--- src/hotspot/cpu/s390/macroAssembler_s390.cpp | 3 +++ src/hotspot/cpu/s390/templateTable_s390.cpp | 6 +++--- src/hotspot/cpu/sparc/macroAssembler_sparc.cpp | 7 +++++-- src/hotspot/cpu/x86/macroAssembler_x86.cpp | 8 +++++--- 9 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 96ef3f9763f..08ebdf4ac87 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -37,6 +37,7 @@ #include "compiler/disassembler.hpp" #include "memory/resourceArea.hpp" #include "nativeInst_aarch64.hpp" +#include "oops/accessDecorators.hpp" #include "oops/compressedOops.inline.hpp" #include "oops/klass.inline.hpp" #include "oops/oop.hpp" @@ -2127,7 +2128,7 @@ void MacroAssembler::resolve_jobject(Register value, Register thread, Register t bind(not_weak); // Resolve (untagged) jobject. - bs->load_at(this, IN_ROOT | IN_CONCURRENT_ROOT, T_OBJECT, + bs->load_at(this, IN_CONCURRENT_ROOT, T_OBJECT, value, Address(value, 0), tmp, thread); verify_oop(value); bind(done); @@ -3664,7 +3665,7 @@ void MacroAssembler::load_klass(Register dst, Register src) { void MacroAssembler::resolve_oop_handle(Register result, Register tmp) { // OopHandle::resolve is an indirection. BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); - bs->load_at(this, IN_ROOT | IN_CONCURRENT_ROOT, T_OBJECT, + bs->load_at(this, IN_CONCURRENT_ROOT, T_OBJECT, result, Address(result, 0), tmp, rthread); } @@ -3983,6 +3984,7 @@ void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Register dst, Address src, Register tmp1, Register thread_tmp) { BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); + decorators = AccessInternal::decorator_fixup(decorators); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, dst, src, tmp1, thread_tmp); @@ -3995,6 +3997,7 @@ void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, Address dst, Register src, Register tmp1, Register thread_tmp) { BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); + decorators = AccessInternal::decorator_fixup(decorators); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, dst, src, tmp1, thread_tmp); diff --git a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp index 1e6e9d32e61..39fa305f5d2 100644 --- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp @@ -813,7 +813,7 @@ void TemplateTable::aaload() do_oop_load(_masm, Address(r1, arrayOopDesc::base_offset_in_bytes(T_OBJECT)), r0, - IN_HEAP | IN_HEAP_ARRAY); + IN_HEAP_ARRAY); } void TemplateTable::baload() @@ -1141,7 +1141,7 @@ void TemplateTable::aastore() { // Get the value we will store __ ldr(r0, at_tos()); // Now store using the appropriate barrier - do_oop_store(_masm, element_address, r0, IN_HEAP | IN_HEAP_ARRAY); + do_oop_store(_masm, element_address, r0, IN_HEAP_ARRAY); __ b(done); // Have a NULL in r0, r3=array, r2=index. Store NULL at ary[idx] @@ -1149,7 +1149,7 @@ void TemplateTable::aastore() { __ profile_null_seen(r2); // Store a NULL - do_oop_store(_masm, element_address, noreg, IN_HEAP | IN_HEAP_ARRAY); + do_oop_store(_masm, element_address, noreg, IN_HEAP_ARRAY); // Pop stack arguments __ bind(done); diff --git a/src/hotspot/cpu/arm/macroAssembler_arm.cpp b/src/hotspot/cpu/arm/macroAssembler_arm.cpp index 1bca5dc5134..96e84000d0b 100644 --- a/src/hotspot/cpu/arm/macroAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/macroAssembler_arm.cpp @@ -36,6 +36,7 @@ #include "gc/shared/collectedHeap.inline.hpp" #include "interpreter/interpreter.hpp" #include "memory/resourceArea.hpp" +#include "oops/accessDecorators.hpp" #include "oops/klass.inline.hpp" #include "prims/methodHandles.hpp" #include "runtime/biasedLocking.hpp" @@ -2133,7 +2134,7 @@ void MacroAssembler::resolve_jobject(Register value, b(done); bind(not_weak); // Resolve (untagged) jobject. - access_load_at(T_OBJECT, IN_ROOT | IN_CONCURRENT_ROOT, + access_load_at(T_OBJECT, IN_CONCURRENT_ROOT, Address(value, 0), value, tmp1, tmp2, noreg); verify_oop(value); bind(done); @@ -2700,6 +2701,7 @@ void MacroAssembler::store_heap_oop_null(Address obj, Register new_val, Register void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Address src, Register dst, Register tmp1, Register tmp2, Register tmp3) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + decorators = AccessInternal::decorator_fixup(decorators); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, dst, src, tmp1, tmp2, tmp3); @@ -2711,6 +2713,7 @@ void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, Address obj, Register new_val, Register tmp1, Register tmp2, Register tmp3, bool is_null) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + decorators = AccessInternal::decorator_fixup(decorators); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, obj, new_val, tmp1, tmp2, tmp3, is_null); diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp index 10a006cabc4..8466ebb958b 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp @@ -32,6 +32,7 @@ #include "code/codeCache.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSetAssembler.hpp" +#include "oops/accessDecorators.hpp" #include "runtime/safepointMechanism.hpp" inline bool MacroAssembler::is_ld_largeoffset(address a) { @@ -332,6 +333,7 @@ inline void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorat ON_UNKNOWN_OOP_REF)) == 0, "unsupported decorator"); BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); bool as_raw = (decorators & AS_RAW) != 0; + decorators = AccessInternal::decorator_fixup(decorators); if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, base, ind_or_offs, val, @@ -349,6 +351,7 @@ inline void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorato assert((decorators & ~(AS_RAW | IN_HEAP | IN_HEAP_ARRAY | IN_ROOT | OOP_NOT_NULL | ON_PHANTOM_OOP_REF | ON_WEAK_OOP_REF)) == 0, "unsupported decorator"); BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + decorators = AccessInternal::decorator_fixup(decorators); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, diff --git a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp index d22b0d50f94..4b15fb04e0c 100644 --- a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp @@ -688,7 +688,7 @@ void TemplateTable::aaload() { Rtemp2 = R31; __ index_check(Rarray, R17_tos /* index */, UseCompressedOops ? 2 : LogBytesPerWord, Rtemp, Rload_addr); do_oop_load(_masm, Rload_addr, arrayOopDesc::base_offset_in_bytes(T_OBJECT), R17_tos, Rtemp, Rtemp2, - IN_HEAP | IN_HEAP_ARRAY); + IN_HEAP_ARRAY); __ verify_oop(R17_tos); //__ dcbt(R17_tos); // prefetch } @@ -1015,14 +1015,14 @@ void TemplateTable::aastore() { __ bind(Lis_null); do_oop_store(_masm, Rstore_addr, arrayOopDesc::base_offset_in_bytes(T_OBJECT), noreg /* 0 */, - Rscratch, Rscratch2, Rscratch3, IN_HEAP | IN_HEAP_ARRAY); + Rscratch, Rscratch2, Rscratch3, IN_HEAP_ARRAY); __ profile_null_seen(Rscratch, Rscratch2); __ b(Ldone); // Store is OK. __ bind(Lstore_ok); do_oop_store(_masm, Rstore_addr, arrayOopDesc::base_offset_in_bytes(T_OBJECT), R17_tos /* value */, - Rscratch, Rscratch2, Rscratch3, IN_HEAP | IN_HEAP_ARRAY | OOP_NOT_NULL); + Rscratch, Rscratch2, Rscratch3, IN_HEAP_ARRAY | OOP_NOT_NULL); __ bind(Ldone); // Adjust sp (pops array, index and value). diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.cpp b/src/hotspot/cpu/s390/macroAssembler_s390.cpp index 6186428d533..f76720156ae 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp @@ -34,6 +34,7 @@ #include "gc/shared/cardTableBarrierSet.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" +#include "oops/accessDecorators.hpp" #include "oops/compressedOops.inline.hpp" #include "oops/klass.inline.hpp" #include "opto/compile.hpp" @@ -4053,6 +4054,7 @@ void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, assert((decorators & ~(AS_RAW | IN_HEAP | IN_HEAP_ARRAY | IN_ROOT | OOP_NOT_NULL | ON_UNKNOWN_OOP_REF)) == 0, "unsupported decorator"); BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + decorators = AccessInternal::decorator_fixup(decorators); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, @@ -4071,6 +4073,7 @@ void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, assert((decorators & ~(AS_RAW | IN_HEAP | IN_HEAP_ARRAY | IN_ROOT | OOP_NOT_NULL | ON_PHANTOM_OOP_REF | ON_WEAK_OOP_REF)) == 0, "unsupported decorator"); BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + decorators = AccessInternal::decorator_fixup(decorators); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, diff --git a/src/hotspot/cpu/s390/templateTable_s390.cpp b/src/hotspot/cpu/s390/templateTable_s390.cpp index ac8a06c73b5..994e2e36e1f 100644 --- a/src/hotspot/cpu/s390/templateTable_s390.cpp +++ b/src/hotspot/cpu/s390/templateTable_s390.cpp @@ -853,7 +853,7 @@ void TemplateTable::aaload() { index_check(Z_tmp_1, index, shift); // Now load array element. do_oop_load(_masm, Address(Z_tmp_1, index, arrayOopDesc::base_offset_in_bytes(T_OBJECT)), Z_tos, - Z_tmp_2, Z_tmp_3, IN_HEAP | IN_HEAP_ARRAY); + Z_tmp_2, Z_tmp_3, IN_HEAP_ARRAY); __ verify_oop(Z_tos); } @@ -1197,7 +1197,7 @@ void TemplateTable::aastore() { // Store a NULL. do_oop_store(_masm, Address(Rstore_addr, (intptr_t)0), noreg, - tmp3, tmp2, tmp1, IN_HEAP | IN_HEAP_ARRAY); + tmp3, tmp2, tmp1, IN_HEAP_ARRAY); __ z_bru(done); // Come here on success. @@ -1205,7 +1205,7 @@ void TemplateTable::aastore() { // Now store using the appropriate barrier. do_oop_store(_masm, Address(Rstore_addr, (intptr_t)0), Rvalue, - tmp3, tmp2, tmp1, IN_HEAP | IN_HEAP_ARRAY | OOP_NOT_NULL); + tmp3, tmp2, tmp1, IN_HEAP_ARRAY | OOP_NOT_NULL); // Pop stack arguments. __ bind(done); diff --git a/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp b/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp index cddb000724a..17a28f36259 100644 --- a/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp +++ b/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp @@ -32,6 +32,7 @@ #include "interpreter/interpreter.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" +#include "oops/accessDecorators.hpp" #include "oops/klass.inline.hpp" #include "prims/methodHandles.hpp" #include "runtime/biasedLocking.hpp" @@ -181,7 +182,7 @@ void MacroAssembler::resolve_jobject(Register value, Register tmp) { br (Assembler::always, true, Assembler::pt, done); delayed()->nop(); bind(not_weak); - access_load_at(T_OBJECT, IN_ROOT | IN_CONCURRENT_ROOT, + access_load_at(T_OBJECT, IN_CONCURRENT_ROOT, Address(value, 0), value, tmp); verify_oop(value); bind(done); @@ -3401,7 +3402,7 @@ void MacroAssembler::reserved_stack_check() { // ((OopHandle)result).resolve(); void MacroAssembler::resolve_oop_handle(Register result, Register tmp) { // OopHandle::resolve is an indirection. - access_load_at(T_OBJECT, IN_ROOT | IN_CONCURRENT_ROOT, + access_load_at(T_OBJECT, IN_CONCURRENT_ROOT, Address(result, 0), result, tmp); } @@ -3446,6 +3447,7 @@ void MacroAssembler::store_klass_gap(Register s, Register d) { void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, Register src, Address dst, Register tmp) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + decorators = AccessInternal::decorator_fixup(decorators); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, src, dst, tmp); @@ -3457,6 +3459,7 @@ void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Address src, Register dst, Register tmp) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + decorators = AccessInternal::decorator_fixup(decorators); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, src, dst, tmp); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index 7830873de17..df90ffbfbe8 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -33,7 +33,7 @@ #include "interpreter/interpreter.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" -#include "oops/access.hpp" +#include "oops/accessDecorators.hpp" #include "oops/klass.inline.hpp" #include "prims/methodHandles.hpp" #include "runtime/biasedLocking.hpp" @@ -5259,7 +5259,7 @@ void MacroAssembler::resolve_jobject(Register value, jmp(done); bind(not_weak); // Resolve (untagged) jobject. - access_load_at(T_OBJECT, IN_ROOT | IN_CONCURRENT_ROOT, + access_load_at(T_OBJECT, IN_CONCURRENT_ROOT, value, Address(value, 0), tmp, thread); verify_oop(value); bind(done); @@ -6281,7 +6281,7 @@ void MacroAssembler::resolve_oop_handle(Register result, Register tmp) { // Only 64 bit platforms support GCs that require a tmp register // Only IN_HEAP loads require a thread_tmp register // OopHandle::resolve is an indirection like jobject. - access_load_at(T_OBJECT, IN_ROOT | IN_CONCURRENT_ROOT, + access_load_at(T_OBJECT, IN_CONCURRENT_ROOT, result, Address(result, 0), tmp, /*tmp_thread*/noreg); } @@ -6323,6 +6323,7 @@ void MacroAssembler::store_klass(Register dst, Register src) { void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Register dst, Address src, Register tmp1, Register thread_tmp) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + decorators = AccessInternal::decorator_fixup(decorators); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, dst, src, tmp1, thread_tmp); @@ -6334,6 +6335,7 @@ void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Reg void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, Address dst, Register src, Register tmp1, Register tmp2) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + decorators = AccessInternal::decorator_fixup(decorators); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, dst, src, tmp1, tmp2); From e9f3b0e52774743f566f19020ad835b65764f0de Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Thu, 7 Jun 2018 07:43:29 -0700 Subject: [PATCH 16/46] 8201407: Files.move throws DirectoryNonEmptyException when moving directory across file system Reviewed-by: alanb --- .../share/classes/java/nio/file/Files.java | 7 ++++--- .../unix/classes/sun/nio/fs/UnixCopyFile.java | 19 ++++++++++++++++++- .../classes/sun/nio/fs/WindowsFileCopy.java | 14 +++++++++++++- test/jdk/java/nio/file/Files/CopyAndMove.java | 8 ++++++-- 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/java.base/share/classes/java/nio/file/Files.java b/src/java.base/share/classes/java/nio/file/Files.java index 41ac57fa3cf..65fb4a5f2bf 100644 --- a/src/java.base/share/classes/java/nio/file/Files.java +++ b/src/java.base/share/classes/java/nio/file/Files.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1391,8 +1391,9 @@ public final class Files { * specific exception) * @throws DirectoryNotEmptyException * the {@code REPLACE_EXISTING} option is specified but the file - * cannot be replaced because it is a non-empty directory - * (optional specific exception) + * cannot be replaced because it is a non-empty directory, or the + * source is a non-empty directory containing entries that would + * be required to be moved (optional specific exceptions) * @throws AtomicMoveNotSupportedException * if the options array contains the {@code ATOMIC_MOVE} option but * the file cannot be moved as an atomic file system operation. diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixCopyFile.java b/src/java.base/unix/classes/sun/nio/fs/UnixCopyFile.java index 34fe5d24526..5d5cca7626d 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixCopyFile.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixCopyFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -373,6 +373,22 @@ class UnixCopyFile { } } + // throw a DirectoryNotEmpty exception if appropriate + static void ensureEmptyDir(UnixPath dir) throws IOException { + try { + long ptr = opendir(dir); + try (UnixDirectoryStream stream = + new UnixDirectoryStream(dir, ptr, e -> true)) { + if (stream.iterator().hasNext()) { + throw new DirectoryNotEmptyException( + dir.getPathForExceptionMessage()); + } + } + } catch (UnixException e) { + e.rethrowAsIOException(dir); + } + } + // move file from source to target static void move(UnixPath source, UnixPath target, CopyOption... options) throws IOException @@ -465,6 +481,7 @@ class UnixCopyFile { // copy source to target if (sourceAttrs.isDirectory()) { + ensureEmptyDir(source); copyDirectory(source, sourceAttrs, target, flags); } else { if (sourceAttrs.isSymbolicLink()) { diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsFileCopy.java b/src/java.base/windows/classes/sun/nio/fs/WindowsFileCopy.java index c96a699370f..2fe40b78204 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsFileCopy.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsFileCopy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -249,6 +249,17 @@ class WindowsFileCopy { } } + // throw a DirectoryNotEmpty exception if not empty + static void ensureEmptyDir(WindowsPath dir) throws IOException { + try (WindowsDirectoryStream dirStream = + new WindowsDirectoryStream(dir, (e) -> true)) { + if (dirStream.iterator().hasNext()) { + throw new DirectoryNotEmptyException( + dir.getPathForExceptionMessage()); + } + } + } + /** * Move file from source to target */ @@ -407,6 +418,7 @@ class WindowsFileCopy { // create new directory or directory junction try { if (sourceAttrs.isDirectory()) { + ensureEmptyDir(source); CreateDirectory(targetPath, 0L); } else { String linkTarget = WindowsLinkSupport.readLink(source); diff --git a/test/jdk/java/nio/file/Files/CopyAndMove.java b/test/jdk/java/nio/file/Files/CopyAndMove.java index ce9f681d4f7..17ff7eec4d3 100644 --- a/test/jdk/java/nio/file/Files/CopyAndMove.java +++ b/test/jdk/java/nio/file/Files/CopyAndMove.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 6838333 6917021 7006126 6950237 8006645 + * @bug 4313887 6838333 6917021 7006126 6950237 8006645 8201407 * @summary Unit test for java.nio.file.Files copy and move methods (use -Dseed=X to set PRNG seed) * @library .. /test/lib * @build jdk.test.lib.RandomFactory @@ -448,6 +448,10 @@ public class CopyAndMove { moveAndVerify(source, target); throw new RuntimeException("IOException expected"); } catch (IOException x) { + if (!(x instanceof DirectoryNotEmptyException)) { + throw new RuntimeException + ("DirectoryNotEmptyException expected", x); + } } delete(source.resolve("foo")); delete(source); From ff7db9b11ace0895a110df09c2d274505f5356ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20=C3=96sterlund?= Date: Thu, 7 Jun 2018 17:40:15 +0200 Subject: [PATCH 17/46] 8204554: JFR TLAB tracing broken after 8202776 Reviewed-by: rkennke, stefank --- src/hotspot/share/gc/shared/collectedHeap.cpp | 3 ++- src/hotspot/share/gc/shared/collectedHeap.hpp | 3 +++ .../share/gc/shared/collectedHeap.inline.hpp | 24 ++++++++++++------- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/hotspot/share/gc/shared/collectedHeap.cpp b/src/hotspot/share/gc/shared/collectedHeap.cpp index 18a5d69d41f..75af999fc0b 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.cpp +++ b/src/hotspot/share/gc/shared/collectedHeap.cpp @@ -373,7 +373,8 @@ HeapWord* CollectedHeap::obj_allocate_raw(Klass* klass, size_t size, return result; } } - return Universe::heap()->mem_allocate(size, gc_overhead_limit_was_exceeded); + + return allocate_outside_tlab(klass, size, gc_overhead_limit_was_exceeded, THREAD); } HeapWord* CollectedHeap::allocate_from_tlab_slow(Klass* klass, size_t size, TRAPS) { diff --git a/src/hotspot/share/gc/shared/collectedHeap.hpp b/src/hotspot/share/gc/shared/collectedHeap.hpp index 3d5c71e46d2..a2ab0d6a253 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.hpp +++ b/src/hotspot/share/gc/shared/collectedHeap.hpp @@ -144,6 +144,9 @@ class CollectedHeap : public CHeapObj { inline static HeapWord* allocate_from_tlab(Klass* klass, size_t size, TRAPS); static HeapWord* allocate_from_tlab_slow(Klass* klass, size_t size, TRAPS); + inline static HeapWord* allocate_outside_tlab(Klass* klass, size_t size, + bool* gc_overhead_limit_was_exceeded, TRAPS); + // Raw memory allocation facilities // The obj and array allocate methods are covers for these methods. // mem_allocate() should never be diff --git a/src/hotspot/share/gc/shared/collectedHeap.inline.hpp b/src/hotspot/share/gc/shared/collectedHeap.inline.hpp index 6c2893d9f54..08c8131333f 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.inline.hpp +++ b/src/hotspot/share/gc/shared/collectedHeap.inline.hpp @@ -142,14 +142,6 @@ HeapWord* CollectedHeap::common_mem_allocate_noinit(Klass* klass, size_t size, T HeapWord* result = heap->obj_allocate_raw(klass, size, &gc_overhead_limit_was_exceeded, THREAD); if (result != NULL) { - NOT_PRODUCT(Universe::heap()-> - check_for_non_bad_heap_word_value(result, size)); - assert(!HAS_PENDING_EXCEPTION, - "Unexpected exception, will result in uninitialized storage"); - THREAD->incr_allocated_bytes(size * HeapWordSize); - - AllocTracer::send_allocation_outside_tlab(klass, result, size * HeapWordSize, THREAD); - return result; } @@ -198,6 +190,22 @@ HeapWord* CollectedHeap::allocate_from_tlab(Klass* klass, size_t size, TRAPS) { return obj; } +HeapWord* CollectedHeap::allocate_outside_tlab(Klass* klass, size_t size, + bool* gc_overhead_limit_was_exceeded, TRAPS) { + HeapWord* result = Universe::heap()->mem_allocate(size, gc_overhead_limit_was_exceeded); + if (result == NULL) { + return result; + } + + NOT_PRODUCT(Universe::heap()->check_for_non_bad_heap_word_value(result, size)); + assert(!HAS_PENDING_EXCEPTION, + "Unexpected exception, will result in uninitialized storage"); + THREAD->incr_allocated_bytes(size * HeapWordSize); + + AllocTracer::send_allocation_outside_tlab(klass, result, size * HeapWordSize, THREAD); + return result; +} + void CollectedHeap::init_obj(HeapWord* obj, size_t size) { assert(obj != NULL, "cannot initialize NULL object"); const size_t hs = oopDesc::header_size(); From ddc42415c0ba989d08106c204de7a0be03608835 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Wed, 6 Jun 2018 23:36:08 +0300 Subject: [PATCH 18/46] 8203480: IncompatibleClassChangeError thrown at sites linked to default interface methods Reviewed-by: kvn --- src/hotspot/share/opto/c2_globals.hpp | 3 + src/hotspot/share/opto/callGenerator.cpp | 2 +- src/hotspot/share/runtime/sharedRuntime.cpp | 10 +- .../jsr292/NonInlinedCall/InvokeTest.java | 105 ++++++++++++++---- 4 files changed, 96 insertions(+), 24 deletions(-) diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp index 1d0e16532b3..ac2e7619951 100644 --- a/src/hotspot/share/opto/c2_globals.hpp +++ b/src/hotspot/share/opto/c2_globals.hpp @@ -53,6 +53,9 @@ diagnostic(bool, StressGCM, false, \ "Randomize instruction scheduling in GCM") \ \ + develop(bool, StressMethodHandleLinkerInlining, false, \ + "Stress inlining through method handle linkers") \ + \ develop(intx, OptoPrologueNops, 0, \ "Insert this many extra nop instructions " \ "in the prologue of every nmethod") \ diff --git a/src/hotspot/share/opto/callGenerator.cpp b/src/hotspot/share/opto/callGenerator.cpp index 3a0dd830ac1..b778b5ebfe9 100644 --- a/src/hotspot/share/opto/callGenerator.cpp +++ b/src/hotspot/share/opto/callGenerator.cpp @@ -932,7 +932,7 @@ CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod* speculative_receiver_type = (receiver_type != NULL) ? receiver_type->speculative_type() : NULL; } CallGenerator* cg = C->call_generator(target, vtable_index, call_does_dispatch, jvms, - true /* allow_inline */, + !StressMethodHandleLinkerInlining /* allow_inline */, PROB_ALWAYS, speculative_receiver_type); return cg; diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index 624f4ace08b..fac653f3dc4 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -1082,6 +1082,7 @@ Handle SharedRuntime::find_callee_info_helper(JavaThread* thread, Bytecode_invoke bytecode(caller, bci); int bytecode_index = bytecode.index(); + bc = bytecode.invoke_code(); methodHandle attached_method = extract_attached_method(vfst); if (attached_method.not_null()) { @@ -1095,6 +1096,11 @@ Handle SharedRuntime::find_callee_info_helper(JavaThread* thread, // Adjust invocation mode according to the attached method. switch (bc) { + case Bytecodes::_invokevirtual: + if (attached_method->method_holder()->is_interface()) { + bc = Bytecodes::_invokeinterface; + } + break; case Bytecodes::_invokeinterface: if (!attached_method->method_holder()->is_interface()) { bc = Bytecodes::_invokevirtual; @@ -1110,10 +1116,10 @@ Handle SharedRuntime::find_callee_info_helper(JavaThread* thread, break; } } - } else { - bc = bytecode.invoke_code(); } + assert(bc != Bytecodes::_illegal, "not initialized"); + bool has_receiver = bc != Bytecodes::_invokestatic && bc != Bytecodes::_invokedynamic && bc != Bytecodes::_invokehandle; diff --git a/test/hotspot/jtreg/compiler/jsr292/NonInlinedCall/InvokeTest.java b/test/hotspot/jtreg/compiler/jsr292/NonInlinedCall/InvokeTest.java index c9569d09f54..e1f3a3a9828 100644 --- a/test/hotspot/jtreg/compiler/jsr292/NonInlinedCall/InvokeTest.java +++ b/test/hotspot/jtreg/compiler/jsr292/NonInlinedCall/InvokeTest.java @@ -52,10 +52,12 @@ import static jdk.test.lib.Asserts.assertEquals; public class InvokeTest { static MethodHandles.Lookup LOOKUP = MethodHandleHelper.IMPL_LOOKUP; - static final MethodHandle virtualMH; // invokevirtual T.f1 - static final MethodHandle staticMH; // invokestatic T.f2 - static final MethodHandle intfMH; // invokeinterface I.f1 - static final MethodHandle specialMH; // invokespecial T.f4 T + static final MethodHandle virtualMH; // invokevirtual T.f1 + static final MethodHandle staticMH; // invokestatic T.f2 + static final MethodHandle intfMH; // invokeinterface I.f3 + static final MethodHandle defaultMH; // invokevirtual T.f3 + static final MethodHandle specialMH; // invokespecial T.f4 T + static final MethodHandle privateMH; // invokespecial I.f4 T static final MethodHandle basicMH; static final WhiteBox WB = WhiteBox.getWhiteBox(); @@ -69,7 +71,9 @@ public class InvokeTest { virtualMH = LOOKUP.findVirtual(T.class, "f1", mtype); staticMH = LOOKUP.findStatic (T.class, "f2", mtype); intfMH = LOOKUP.findVirtual(I.class, "f3", mtype); + defaultMH = LOOKUP.findVirtual(T.class, "f3", mtype); specialMH = LOOKUP.findSpecial(T.class, "f4", mtype, T.class); + privateMH = LOOKUP.findSpecial(I.class, "f4", mtype, I.class); basicMH = NonInlinedReinvoker.make(staticMH); } catch (Exception e) { throw new Error(e); @@ -92,24 +96,51 @@ public class InvokeTest { @DontInline public Class f3() { if (doDeopt) WB.deoptimizeAll(); return P2.class; } } - static interface I { + interface I { @DontInline default Class f3() { if (doDeopt) WB.deoptimizeAll(); return I.class; } + @DontInline private Class f4() { if (doDeopt) WB.deoptimizeAll(); return I.class; } } + interface J1 extends I { + @DontInline default Class f3() { if (doDeopt) WB.deoptimizeAll(); return J1.class; } + } + + interface J2 extends I { + @DontInline default Class f3() { if (doDeopt) WB.deoptimizeAll(); return J2.class; } + } + + interface J3 extends I { + @DontInline default Class f3() { if (doDeopt) WB.deoptimizeAll(); return J3.class; } + } + + static class Q1 extends T implements J1 {} + static class Q2 extends T implements J2 {} + static class Q3 extends T implements J3 {} + @DontInline - static void linkToVirtual(Object obj, Class extecpted) { + static void linkToVirtual(T recv, Class expected) { try { - Class cls = (Class)virtualMH.invokeExact((T)obj); - assertEquals(cls, obj.getClass()); + Class cls = (Class)virtualMH.invokeExact(recv); + assertEquals(cls, expected); } catch (Throwable e) { throw new Error(e); } } @DontInline - static void linkToInterface(Object obj, Class expected) { + static void linkToVirtualDefault(T recv, Class expected) { try { - Class cls = (Class)intfMH.invokeExact((I)obj); + Class cls = (Class)defaultMH.invokeExact(recv); + assertEquals(cls, expected); + } catch (Throwable e) { + throw new Error(e); + } + } + + @DontInline + static void linkToInterface(I recv, Class expected) { + try { + Class cls = (Class)intfMH.invokeExact(recv); assertEquals(cls, expected); } catch (Throwable e) { throw new Error(e); @@ -127,15 +158,26 @@ public class InvokeTest { } @DontInline - static void linkToSpecial(Object obj, Class expected) { + static void linkToSpecial(T recv, Class expected) { try { - Class cls = (Class)specialMH.invokeExact((T)obj); + Class cls = (Class)specialMH.invokeExact(recv); assertEquals(cls, expected); } catch (Throwable e) { throw new Error(e); } } + @DontInline + static void linkToSpecialIntf(I recv, Class expected) { + try { + Class cls = (Class)privateMH.invokeExact(recv); + assertEquals(cls, expected); + } catch (Throwable e) { + throw new Error(e); + } + } + + @DontInline static void invokeBasic() { try { @@ -171,13 +213,33 @@ public class InvokeTest { // Monomorphic case (optimized virtual call) run(() -> linkToVirtual(new T(), T.class)); + run(() -> linkToVirtualDefault(new T(), I.class)); - // Megamorphic case (virtual call) - Object[] recv = new Object[] { new T(), new P1(), new P2() }; + // Megamorphic case (optimized virtual call) run(() -> { - for (Object r : recv) { - linkToVirtual(r, r.getClass()); - }}); + linkToVirtual(new T() {}, T.class); + linkToVirtual(new T() {}, T.class); + linkToVirtual(new T() {}, T.class); + }); + + run(() -> { + linkToVirtualDefault(new T(){}, I.class); + linkToVirtualDefault(new T(){}, I.class); + linkToVirtualDefault(new T(){}, I.class); + }); + + // Megamorphic case (virtual call), multiple implementations + run(() -> { + linkToVirtual(new T(), T.class); + linkToVirtual(new P1(), P1.class); + linkToVirtual(new P2(), P2.class); + }); + + run(() -> { + linkToVirtualDefault(new Q1(), J1.class); + linkToVirtualDefault(new Q2(), J2.class); + linkToVirtualDefault(new Q3(), J3.class); + }); } static void testInterface() { @@ -190,17 +252,18 @@ public class InvokeTest { run(() -> linkToInterface(new T(), I.class)); // Megamorphic case (virtual call) - Object[][] recv = new Object[][] {{new T(), I.class}, {new P1(), P1.class}, {new P2(), P2.class}}; run(() -> { - for (Object[] r : recv) { - linkToInterface(r[0], (Class)r[1]); - }}); + linkToInterface(new T(), I.class); + linkToInterface(new P1(), P1.class); + linkToInterface(new P2(), P2.class); + }); } static void testSpecial() { System.out.println("linkToSpecial"); // Monomorphic case (optimized virtual call) run(() -> linkToSpecial(new T(), T.class)); + run(() -> linkToSpecialIntf(new T(), I.class)); } static void testStatic() { From 977a3ef019bf8965ce4132d38b684db0c8de5162 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20Lid=C3=A9n?= Date: Thu, 7 Jun 2018 21:57:17 +0200 Subject: [PATCH 19/46] 8204474: Have instanceRefKlass use HeapAccess when loading the referent Reviewed-by: stefank, eosterlund --- .../share/oops/instanceRefKlass.inline.hpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/oops/instanceRefKlass.inline.hpp b/src/hotspot/share/oops/instanceRefKlass.inline.hpp index fe6fce234ef..fbbf648c982 100644 --- a/src/hotspot/share/oops/instanceRefKlass.inline.hpp +++ b/src/hotspot/share/oops/instanceRefKlass.inline.hpp @@ -53,13 +53,20 @@ void InstanceRefKlass::do_discovered(oop obj, OopClosureType* closure, Contains& } } +static inline oop load_referent(oop obj, ReferenceType type) { + if (type == REF_PHANTOM) { + return HeapAccess::oop_load(java_lang_ref_Reference::referent_addr_raw(obj)); + } else { + return HeapAccess::oop_load(java_lang_ref_Reference::referent_addr_raw(obj)); + } +} + template bool InstanceRefKlass::try_discover(oop obj, ReferenceType type, OopClosureType* closure) { ReferenceDiscoverer* rd = closure->ref_discoverer(); if (rd != NULL) { - T referent_oop = RawAccess<>::oop_load((T*)java_lang_ref_Reference::referent_addr_raw(obj)); - if (!CompressedOops::is_null(referent_oop)) { - oop referent = CompressedOops::decode_not_null(referent_oop); + oop referent = load_referent(obj, type); + if (referent != NULL) { if (!referent->is_gc_marked()) { // Only try to discover if not yet marked. return rd->discover_reference(obj, type); @@ -179,9 +186,9 @@ void InstanceRefKlass::trace_reference_gc(const char *s, oop obj) { log_develop_trace(gc, ref)("InstanceRefKlass %s for obj " PTR_FORMAT, s, p2i(obj)); log_develop_trace(gc, ref)(" referent_addr/* " PTR_FORMAT " / " PTR_FORMAT, - p2i(referent_addr), p2i(referent_addr ? RawAccess<>::oop_load(referent_addr) : (oop)NULL)); + p2i(referent_addr), p2i((oop)HeapAccess::oop_load_at(obj, java_lang_ref_Reference::referent_offset))); log_develop_trace(gc, ref)(" discovered_addr/* " PTR_FORMAT " / " PTR_FORMAT, - p2i(discovered_addr), p2i(discovered_addr ? RawAccess<>::oop_load(discovered_addr) : (oop)NULL)); + p2i(discovered_addr), p2i((oop)HeapAccess::oop_load(discovered_addr))); } #endif From a78fe0a073eab2ade7ad6e1c9d22aee2703d7b40 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Thu, 7 Jun 2018 13:24:49 -0700 Subject: [PATCH 20/46] 8203839: API clarification: versioned jar entry verification in multi-release jar file Reviewed-by: darcy, psandoz, alanb, weijun --- .../share/classes/java/util/jar/JarFile.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/java.base/share/classes/java/util/jar/JarFile.java b/src/java.base/share/classes/java/util/jar/JarFile.java index ec7fdf0f06a..5562611cfe4 100644 --- a/src/java.base/share/classes/java/util/jar/JarFile.java +++ b/src/java.base/share/classes/java/util/jar/JarFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,10 +93,14 @@ import java.util.zip.ZipFile; * argument. This assures that classes compatible with the major * version of the running JVM are loaded from multi-release jar files. * - *

If the verify flag is on when opening a signed jar file, the content of - * the file is verified against its signature embedded inside the file. Please - * note that the verification process does not include validating the signer's - * certificate. A caller should inspect the return value of + *

If the {@code verify} flag is on when opening a signed jar file, the content + * of the jar entry is verified against the signature embedded inside the manifest + * that is associated with its {@link JarEntry#getRealName() path name}. For a + * multi-release jar file, the content of a versioned entry is verfieid against + * its own signature and {@link JarEntry#getCodeSigners()} returns its own signers. + * + * Please note that the verification process does not include validating the + * signer's certificate. A caller should inspect the return value of * {@link JarEntry#getCodeSigners()} to further determine if the signature * can be trusted. * From 628aec8c75676e46cc557de46db423092a7f9bd4 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Thu, 7 Jun 2018 23:30:05 +0200 Subject: [PATCH 21/46] 8203822: AIX version of jsig.c was not removed in JDK-8200298 Reviewed-by: erikj --- src/java.base/aix/native/libjsig/jsig.c | 238 ------------------------ 1 file changed, 238 deletions(-) delete mode 100644 src/java.base/aix/native/libjsig/jsig.c diff --git a/src/java.base/aix/native/libjsig/jsig.c b/src/java.base/aix/native/libjsig/jsig.c deleted file mode 100644 index 8914e2881a9..00000000000 --- a/src/java.base/aix/native/libjsig/jsig.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 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. - * - */ - -/* CopyrightVersion 1.2 */ - -/* This is a special library that should be loaded before libc & - * libthread to interpose the signal handler installation functions: - * sigaction(), signal(), sigset(). - * Used for signal-chaining. See RFE 4381843. - */ - -#include -#include -#include -#include -#include -#include -#include "jni.h" - -#define bool int -#define true 1 -#define false 0 - -static struct sigaction sact[NSIG]; /* saved signal handlers */ -static sigset_t jvmsigs; /* Signals used by jvm. */ - -/* Used to synchronize the installation of signal handlers. */ -static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; -static pthread_t tid = 0; - -typedef void (*sa_handler_t)(int); -typedef void (*sa_sigaction_t)(int, siginfo_t *, void *); -// signal_t is already defined on AIX. -typedef sa_handler_t (*signal_like_function_t)(int, sa_handler_t); -typedef int (*sigaction_t)(int, const struct sigaction *, struct sigaction *); - -static signal_like_function_t os_signal = 0; /* os's version of signal()/sigset() */ -static sigaction_t os_sigaction = 0; /* os's version of sigaction() */ - -static bool jvm_signal_installing = false; -static bool jvm_signal_installed = false; - -static void signal_lock() { - pthread_mutex_lock(&mutex); - /* When the jvm is installing its set of signal handlers, threads - * other than the jvm thread should wait. */ - if (jvm_signal_installing) { - if (tid != pthread_self()) { - pthread_cond_wait(&cond, &mutex); - } - } -} - -static void signal_unlock() { - pthread_mutex_unlock(&mutex); -} - -static sa_handler_t call_os_signal(int sig, sa_handler_t disp, - bool is_sigset) { - if (os_signal == NULL) { - if (!is_sigset) { - // Aix: call functions directly instead of dlsym'ing them. - os_signal = signal; - } else { - // Aix: call functions directly instead of dlsym'ing them. - os_signal = sigset; - } - if (os_signal == NULL) { - printf("%s\n", dlerror()); - exit(0); - } - } - return (*os_signal)(sig, disp); -} - -static void save_signal_handler(int sig, sa_handler_t disp) { - sigset_t set; - sact[sig].sa_handler = disp; - sigemptyset(&set); - sact[sig].sa_mask = set; - sact[sig].sa_flags = 0; -} - -static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) { - sa_handler_t oldhandler; - bool sigused; - - signal_lock(); - - sigused = sigismember(&jvmsigs, sig); - if (jvm_signal_installed && sigused) { - /* jvm has installed its signal handler for this signal. */ - /* Save the handler. Don't really install it. */ - oldhandler = sact[sig].sa_handler; - save_signal_handler(sig, disp); - - signal_unlock(); - return oldhandler; - } else if (jvm_signal_installing) { - /* jvm is installing its signal handlers. Install the new - * handlers and save the old ones. jvm uses sigaction(). - * Leave the piece here just in case. */ - oldhandler = call_os_signal(sig, disp, is_sigset); - save_signal_handler(sig, oldhandler); - - /* Record the signals used by jvm */ - sigaddset(&jvmsigs, sig); - - signal_unlock(); - return oldhandler; - } else { - /* jvm has no relation with this signal (yet). Install the - * the handler. */ - oldhandler = call_os_signal(sig, disp, is_sigset); - - signal_unlock(); - return oldhandler; - } -} - -JNIEXPORT sa_handler_t JNICALL -signal(int sig, sa_handler_t disp) { - return set_signal(sig, disp, false); -} - -JNIEXPORT sa_handler_t JNICALL -sigset(int sig, sa_handler_t disp) { - return set_signal(sig, disp, true); -} - -static int call_os_sigaction(int sig, const struct sigaction *act, - struct sigaction *oact) { - if (os_sigaction == NULL) { - // Aix: call functions directly instead of dlsym'ing them. - os_sigaction = sigaction; - if (os_sigaction == NULL) { - printf("%s\n", dlerror()); - exit(0); - } - } - return (*os_sigaction)(sig, act, oact); -} - -JNIEXPORT int JNICALL -sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { - int res; - bool sigused; - struct sigaction oldAct; - - signal_lock(); - - sigused = sigismember(&jvmsigs, sig); - if (jvm_signal_installed && sigused) { - /* jvm has installed its signal handler for this signal. */ - /* Save the handler. Don't really install it. */ - if (oact != NULL) { - *oact = sact[sig]; - } - if (act != NULL) { - sact[sig] = *act; - } - - signal_unlock(); - return 0; - } else if (jvm_signal_installing) { - /* jvm is installing its signal handlers. Install the new - * handlers and save the old ones. */ - res = call_os_sigaction(sig, act, &oldAct); - sact[sig] = oldAct; - if (oact != NULL) { - *oact = oldAct; - } - - /* Record the signals used by jvm. */ - sigaddset(&jvmsigs, sig); - - signal_unlock(); - return res; - } else { - /* jvm has no relation with this signal (yet). Install the - * the handler. */ - res = call_os_sigaction(sig, act, oact); - - signal_unlock(); - return res; - } -} - -/* The three functions for the jvm to call into. */ -JNIEXPORT void JNICALL -JVM_begin_signal_setting() { - signal_lock(); - sigemptyset(&jvmsigs); - jvm_signal_installing = true; - tid = pthread_self(); - signal_unlock(); -} - -JNIEXPORT void JNICALL -JVM_end_signal_setting() { - signal_lock(); - jvm_signal_installed = true; - jvm_signal_installing = false; - pthread_cond_broadcast(&cond); - signal_unlock(); -} - -JNIEXPORT struct sigaction * JNICALL -JVM_get_signal_action(int sig) { - /* Does race condition make sense here? */ - if (sigismember(&jvmsigs, sig)) { - return &sact[sig]; - } - return NULL; -} From fe24730ed99f3b12bc0ae72de8654b96412427b7 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Thu, 7 Jun 2018 16:06:49 -0700 Subject: [PATCH 22/46] 8201274: Launch Single-File Source-Code Programs Reviewed-by: mcimadamore, jlahoda, ksrini, mchung, ihse, alanb --- make/gensrc/Gensrc-jdk.compiler.gmk | 5 +- make/langtools/build.properties | 5 +- .../classes/sun/launcher/LauncherHelper.java | 17 +- .../launcher/resources/launcher.properties | 20 +- src/java.base/share/native/launcher/main.c | 2 +- src/java.base/share/native/libjli/args.c | 97 ++- src/java.base/share/native/libjli/emessages.h | 7 +- src/java.base/share/native/libjli/java.c | 73 ++- src/java.base/share/native/libjli/java.h | 5 +- src/java.base/share/native/libjli/jli_util.c | 10 + src/java.base/share/native/libjli/jli_util.h | 5 +- .../windows/native/libjli/cmdtoargs.c | 2 +- .../com/sun/tools/javac/launcher/Main.java | 550 ++++++++++++++++++ .../tools/javac/resources/launcher.properties | 136 +++++ test/jdk/tools/launcher/SourceMode.java | 315 ++++++++++ .../tools/javac/diags/CheckResourceKeys.java | 5 +- .../javac/launcher/SourceLauncherTest.java | 542 +++++++++++++++++ 17 files changed, 1737 insertions(+), 59 deletions(-) create mode 100644 src/jdk.compiler/share/classes/com/sun/tools/javac/launcher/Main.java create mode 100644 src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher.properties create mode 100644 test/jdk/tools/launcher/SourceMode.java create mode 100644 test/langtools/tools/javac/launcher/SourceLauncherTest.java diff --git a/make/gensrc/Gensrc-jdk.compiler.gmk b/make/gensrc/Gensrc-jdk.compiler.gmk index 24be68e89c1..e5a299f7970 100644 --- a/make/gensrc/Gensrc-jdk.compiler.gmk +++ b/make/gensrc/Gensrc-jdk.compiler.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2017, 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 @@ -32,6 +32,7 @@ $(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \ $(JAVAC_VERSION))) $(eval $(call SetupParseProperties,PARSE_PROPERTIES, \ - com/sun/tools/javac/resources/compiler.properties)) + com/sun/tools/javac/resources/compiler.properties \ + com/sun/tools/javac/resources/launcher.properties)) all: $(COMPILE_PROPERTIES) $(PARSE_PROPERTIES) diff --git a/make/langtools/build.properties b/make/langtools/build.properties index 53260739538..30ca441558c 100644 --- a/make/langtools/build.properties +++ b/make/langtools/build.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -38,7 +38,8 @@ module.names = java.compiler \ jdk.jshell langtools.resource.includes = \ - com/sun/tools/javac/resources/compiler.properties + com/sun/tools/javac/resources/compiler.properties \ + com/sun/tools/javac/resources/launcher.properties # Version info -- override as needed jdk.version = 9 diff --git a/src/java.base/share/classes/sun/launcher/LauncherHelper.java b/src/java.base/share/classes/sun/launcher/LauncherHelper.java index 38f9e3a6784..4b10ca85b72 100644 --- a/src/java.base/share/classes/sun/launcher/LauncherHelper.java +++ b/src/java.base/share/classes/sun/launcher/LauncherHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -502,12 +502,13 @@ public final class LauncherHelper { } // From src/share/bin/java.c: - // enum LaunchMode { LM_UNKNOWN = 0, LM_CLASS, LM_JAR, LM_MODULE } + // enum LaunchMode { LM_UNKNOWN = 0, LM_CLASS, LM_JAR, LM_MODULE, LM_SOURCE } private static final int LM_UNKNOWN = 0; private static final int LM_CLASS = 1; private static final int LM_JAR = 2; private static final int LM_MODULE = 3; + private static final int LM_SOURCE = 4; static void abort(Throwable t, String msgKey, Object... args) { if (msgKey != null) { @@ -538,13 +539,21 @@ public final class LauncherHelper { * * @return the application's main class */ + @SuppressWarnings("fallthrough") public static Class checkAndLoadMain(boolean printToStderr, int mode, String what) { initOutput(printToStderr); - Class mainClass = (mode == LM_MODULE) ? loadModuleMainClass(what) - : loadMainClass(mode, what); + Class mainClass = null; + switch (mode) { + case LM_MODULE: case LM_SOURCE: + mainClass = loadModuleMainClass(what); + break; + default: + mainClass = loadMainClass(mode, what); + break; + } // record the real main class for UI purposes // neither method above can return null, they will abort() diff --git a/src/java.base/share/classes/sun/launcher/resources/launcher.properties b/src/java.base/share/classes/sun/launcher/resources/launcher.properties index 6cdde5aadb7..63e21860a09 100644 --- a/src/java.base/share/classes/sun/launcher/resources/launcher.properties +++ b/src/java.base/share/classes/sun/launcher/resources/launcher.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,13 +25,17 @@ # Translators please note do not translate the options themselves java.launcher.opt.header = Usage: {0} [options] [args...]\n\ -\ (to execute a class)\n or {0} [options] -jar [args...]\n\ +\ (to execute a class)\n\ +\ or {0} [options] -jar [args...]\n\ \ (to execute a jar file)\n\ \ or {0} [options] -m [/] [args...]\n\ \ {0} [options] --module [/] [args...]\n\ -\ (to execute the main class in a module)\n\n\ -\ Arguments following the main class, -jar , -m or --module\n\ -\ / are passed as the arguments to main class.\n\n\ +\ (to execute the main class in a module)\n\ +\ or {0} [options] [args]\n\ +\ (to execute a single source-file program)\n\n\ +\ Arguments following the main class, source file, -jar ,\n\ +\ -m or --module / are passed as the arguments to\n\ +\ main class.\n\n\ \ where options include:\n\n java.launcher.opt.vmselect =\ {0}\t to select the "{1}" VM\n @@ -114,7 +118,7 @@ java.launcher.opt.footer = \ \ -disable-@files\n\ \ prevent further argument file expansion\n\ \ --enable-preview\n\ -\ allow classes to depend on preview features of this release +\ allow classes to depend on preview features of this release\n\ \To specify an argument for a long option, you can use --= or\n\ \-- .\n @@ -176,7 +180,9 @@ java.launcher.X.usage=\n\ \ --patch-module =({0})*\n\ \ override or augment a module with classes and resources\n\ \ in JAR files or directories.\n\ -\ --disable-@files disable further argument file expansion\n\n\ +\ --disable-@files disable further argument file expansion\n\ +\ --source \n\ +\ set the version of the source in source-file mode.\n\n\ These extra options are subject to change without notice.\n # Translators please note do not translate the options themselves diff --git a/src/java.base/share/native/launcher/main.c b/src/java.base/share/native/launcher/main.c index a477c80784b..b734fe2ba78 100644 --- a/src/java.base/share/native/launcher/main.c +++ b/src/java.base/share/native/launcher/main.c @@ -183,7 +183,7 @@ main(int argc, char **argv) } // Iterate the rest of command line for (i = 1; i < argc; i++) { - JLI_List argsInFile = JLI_PreprocessArg(argv[i]); + JLI_List argsInFile = JLI_PreprocessArg(argv[i], JNI_TRUE); if (NULL == argsInFile) { JLI_List_add(args, JLI_StringDup(argv[i])); } else { diff --git a/src/java.base/share/native/libjli/args.c b/src/java.base/share/native/libjli/args.c index 4de8f07b633..c8f2c8706b5 100644 --- a/src/java.base/share/native/libjli/args.c +++ b/src/java.base/share/native/libjli/args.c @@ -79,6 +79,11 @@ static size_t argsCount = 1; static jboolean stopExpansion = JNI_FALSE; static jboolean relaunch = JNI_FALSE; +/* + * Prototypes for internal functions. + */ +static jboolean expand(JLI_List args, const char *str, const char *var_name); + JNIEXPORT void JNICALL JLI_InitArgProcessing(jboolean hasJavaArgs, jboolean disableArgFile) { // No expansion for relaunch @@ -376,9 +381,22 @@ static JLI_List expandArgFile(const char *arg) { return rv; } +/* + * expand a string into a list of words separated by whitespace. + */ +static JLI_List expandArg(const char *arg) { + JLI_List rv; + + /* arbitrarily pick 8, seems to be a reasonable number of arguments */ + rv = JLI_List_new(8); + + expand(rv, arg, NULL); + + return rv; +} + JNIEXPORT JLI_List JNICALL -JLI_PreprocessArg(const char *arg) -{ +JLI_PreprocessArg(const char *arg, jboolean expandSourceOpt) { JLI_List rv; if (firstAppArgIndex > 0) { @@ -392,6 +410,12 @@ JLI_PreprocessArg(const char *arg) return NULL; } + if (expandSourceOpt + && JLI_StrCCmp(arg, "--source") == 0 + && JLI_StrChr(arg, ' ') != NULL) { + return expandArg(arg); + } + if (arg[0] != '@') { checkArg(arg); return NULL; @@ -435,9 +459,6 @@ int isTerminalOpt(char *arg) { JNIEXPORT jboolean JNICALL JLI_AddArgsFromEnvVar(JLI_List args, const char *var_name) { char *env = getenv(var_name); - char *p, *arg; - char quote; - JLI_List argsInFile; if (firstAppArgIndex == 0) { // Not 'java', return @@ -453,44 +474,64 @@ JLI_AddArgsFromEnvVar(JLI_List args, const char *var_name) { } JLI_ReportMessage(ARG_INFO_ENVVAR, var_name, env); + return expand(args, env, var_name); +} + +/* + * Expand a string into a list of args. + * If the string is the result of looking up an environment variable, + * var_name should be set to the name of that environment variable, + * for use if needed in error messages. + */ + +static jboolean expand(JLI_List args, const char *str, const char *var_name) { + jboolean inEnvVar = (var_name != NULL); + + char *p, *arg; + char quote; + JLI_List argsInFile; // This is retained until the process terminates as it is saved as the args - p = JLI_MemAlloc(JLI_StrLen(env) + 1); - while (*env != '\0') { - while (*env != '\0' && isspace(*env)) { - env++; + p = JLI_MemAlloc(JLI_StrLen(str) + 1); + while (*str != '\0') { + while (*str != '\0' && isspace(*str)) { + str++; } // Trailing space - if (*env == '\0') { + if (*str == '\0') { break; } arg = p; - while (*env != '\0' && !isspace(*env)) { - if (*env == '"' || *env == '\'') { - quote = *env++; - while (*env != quote && *env != '\0') { - *p++ = *env++; + while (*str != '\0' && !isspace(*str)) { + if (inEnvVar && (*str == '"' || *str == '\'')) { + quote = *str++; + while (*str != quote && *str != '\0') { + *p++ = *str++; } - if (*env == '\0') { + if (*str == '\0') { JLI_ReportMessage(ARG_ERROR8, var_name); exit(1); } - env++; + str++; } else { - *p++ = *env++; + *p++ = *str++; } } *p++ = '\0'; - argsInFile = JLI_PreprocessArg(arg); + argsInFile = JLI_PreprocessArg(arg, JNI_FALSE); if (NULL == argsInFile) { if (isTerminalOpt(arg)) { - JLI_ReportMessage(ARG_ERROR9, arg, var_name); + if (inEnvVar) { + JLI_ReportMessage(ARG_ERROR9, arg, var_name); + } else { + JLI_ReportMessage(ARG_ERROR15, arg); + } exit(1); } JLI_List_add(args, arg); @@ -501,7 +542,11 @@ JLI_AddArgsFromEnvVar(JLI_List args, const char *var_name) { for (idx = 0; idx < cnt; idx++) { arg = argsInFile->elements[idx]; if (isTerminalOpt(arg)) { - JLI_ReportMessage(ARG_ERROR10, arg, argFile, var_name); + if (inEnvVar) { + JLI_ReportMessage(ARG_ERROR10, arg, argFile, var_name); + } else { + JLI_ReportMessage(ARG_ERROR16, arg, argFile); + } exit(1); } JLI_List_add(args, arg); @@ -517,11 +562,15 @@ JLI_AddArgsFromEnvVar(JLI_List args, const char *var_name) { * caught now. */ if (firstAppArgIndex != NOT_FOUND) { - JLI_ReportMessage(ARG_ERROR11, var_name); + if (inEnvVar) { + JLI_ReportMessage(ARG_ERROR11, var_name); + } else { + JLI_ReportMessage(ARG_ERROR17); + } exit(1); } - assert (*env == '\0' || isspace(*env)); + assert (*str == '\0' || isspace(*str)); } return JNI_TRUE; @@ -642,7 +691,7 @@ int main(int argc, char** argv) { if (argc > 1) { for (i = 0; i < argc; i++) { - JLI_List tokens = JLI_PreprocessArg(argv[i]); + JLI_List tokens = JLI_PreprocessArg(argv[i], JNI_FALSE); if (NULL != tokens) { for (j = 0; j < tokens->size; j++) { printf("Token[%lu]: <%s>\n", (unsigned long) j, tokens->elements[j]); diff --git a/src/java.base/share/native/libjli/emessages.h b/src/java.base/share/native/libjli/emessages.h index 2f94a60bce8..3506a886e25 100644 --- a/src/java.base/share/native/libjli/emessages.h +++ b/src/java.base/share/native/libjli/emessages.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -51,6 +51,11 @@ #define ARG_ERROR10 "Error: Option %s in %s is not allowed in environment variable %s" #define ARG_ERROR11 "Error: Cannot specify main class in environment variable %s" #define ARG_ERROR12 "Error: %s requires module name" +#define ARG_ERROR13 "Error: %s requires source version" +#define ARG_ERROR14 "Error: Option %s is not allowed with --source" +#define ARG_ERROR15 "Error: Option %s is not allowed in this context" +#define ARG_ERROR16 "Error: Option %s in %s is not allowed in this context" +#define ARG_ERROR17 "Error: Cannot specify main class in this context" #define JVM_ERROR1 "Error: Could not create the Java Virtual Machine.\n" GEN_ERROR #define JVM_ERROR2 "Error: Could not detach main thread.\n" JNI_ERROR diff --git a/src/java.base/share/native/libjli/java.c b/src/java.base/share/native/libjli/java.c index f274a25da7a..9c6f170ac8c 100644 --- a/src/java.base/share/native/libjli/java.c +++ b/src/java.base/share/native/libjli/java.c @@ -172,6 +172,9 @@ static int KnownVMIndex(const char* name); static void FreeKnownVMs(); static jboolean IsWildCardEnabled(); + +#define SOURCE_LAUNCHER_MAIN_ENTRY "jdk.compiler/com.sun.tools.javac.launcher.Main" + /* * This reports error. VM will not be created and no usage is printed. */ @@ -214,7 +217,7 @@ static jlong initialHeapSize = 0; /* inital heap size */ * Entry point. */ JNIEXPORT int JNICALL -JLI_Launch(int argc, char ** argv, /* main argc, argc */ +JLI_Launch(int argc, char ** argv, /* main argc, argv */ int jargc, const char** jargv, /* java args */ int appclassc, const char** appclassv, /* app classpath */ const char* fullversion, /* full version defined */ @@ -317,8 +320,7 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */ /* Parse command line options; if the return value of * ParseArguments is false, the program should exit. */ - if (!ParseArguments(&argc, &argv, &mode, &what, &ret, jrepath)) - { + if (!ParseArguments(&argc, &argv, &mode, &what, &ret, jrepath)) { return(ret); } @@ -585,7 +587,8 @@ IsLauncherOption(const char* name) { return IsClassPathOption(name) || IsLauncherMainOption(name) || JLI_StrCmp(name, "--describe-module") == 0 || - JLI_StrCmp(name, "-d") == 0; + JLI_StrCmp(name, "-d") == 0 || + JLI_StrCmp(name, "--source") == 0; } /* @@ -626,6 +629,29 @@ IsWhiteSpaceOption(const char* name) { IsLauncherOption(name); } +/* + * Check if it is OK to set the mode. + * If the mode was previously set, and should not be changed, + * a fatal error is reported. + */ +static int +checkMode(int mode, int newMode, const char *arg) { + if (mode == LM_SOURCE) { + JLI_ReportErrorMessage(ARG_ERROR14, arg); + exit(1); + } + return newMode; +} + +/* + * Test if an arg identifies a source file. + */ +jboolean +IsSourceFile(const char *arg) { + struct stat st; + return (JLI_HasSuffix(arg, ".java") && stat(arg, &st) == 0); +} + /* * Checks the command line options to find which JVM type was * specified. If no command line option was given for the JVM type, @@ -1230,7 +1256,8 @@ GetOpt(int *pargc, char ***pargv, char **poption, char **pvalue) { value = equals+1; if (JLI_StrCCmp(arg, "--describe-module=") == 0 || JLI_StrCCmp(arg, "--module=") == 0 || - JLI_StrCCmp(arg, "--class-path=") == 0) { + JLI_StrCCmp(arg, "--class-path=") == 0|| + JLI_StrCCmp(arg, "--source=") == 0) { kind = LAUNCHER_OPTION_WITH_ARGUMENT; } else { kind = VM_LONG_OPTION; @@ -1274,17 +1301,28 @@ ParseArguments(int *pargc, char ***pargv, */ if (JLI_StrCmp(arg, "-jar") == 0) { ARG_CHECK(argc, ARG_ERROR2, arg); - mode = LM_JAR; + mode = checkMode(mode, LM_JAR, arg); } else if (JLI_StrCmp(arg, "--module") == 0 || JLI_StrCCmp(arg, "--module=") == 0 || JLI_StrCmp(arg, "-m") == 0) { REPORT_ERROR (has_arg, ARG_ERROR5, arg); SetMainModule(value); - mode = LM_MODULE; + mode = checkMode(mode, LM_MODULE, arg); if (has_arg) { *pwhat = value; break; } + } else if (JLI_StrCmp(arg, "--source") == 0 || + JLI_StrCCmp(arg, "--source=") == 0) { + REPORT_ERROR (has_arg, ARG_ERROR13, arg); + mode = LM_SOURCE; + if (has_arg) { + const char *prop = "-Djdk.internal.javac.source="; + size_t size = JLI_StrLen(prop) + JLI_StrLen(value) + 1; + char *propValue = (char *)JLI_MemAlloc(size); + JLI_Snprintf(propValue, size, "%s%s", prop, value); + AddOption(propValue, NULL); + } } else if (JLI_StrCmp(arg, "--class-path") == 0 || JLI_StrCCmp(arg, "--class-path=") == 0 || JLI_StrCmp(arg, "-classpath") == 0 || @@ -1435,12 +1473,25 @@ ParseArguments(int *pargc, char ***pargv, if (!_have_classpath) { SetClassPath("."); } - mode = LM_CLASS; + mode = IsSourceFile(arg) ? LM_SOURCE : LM_CLASS; + } else if (mode == LM_CLASS && IsSourceFile(arg)) { + /* override LM_CLASS mode if given a source file */ + mode = LM_SOURCE; } - if (argc >= 0) { - *pargc = argc; - *pargv = argv; + if (mode == LM_SOURCE) { + AddOption("--add-modules=ALL-DEFAULT", NULL); + *pwhat = SOURCE_LAUNCHER_MAIN_ENTRY; + // adjust (argc, argv) so that the name of the source file + // is included in the args passed to the source launcher + // main entry class + *pargc = argc + 1; + *pargv = argv - 1; + } else { + if (argc >= 0) { + *pargc = argc; + *pargv = argv; + } } *pmode = mode; diff --git a/src/java.base/share/native/libjli/java.h b/src/java.base/share/native/libjli/java.h index 3bea2e11eec..0e77e3c4004 100644 --- a/src/java.base/share/native/libjli/java.h +++ b/src/java.base/share/native/libjli/java.h @@ -230,11 +230,12 @@ enum LaunchMode { // cf. sun.launcher.LauncherHelper LM_UNKNOWN = 0, LM_CLASS, LM_JAR, - LM_MODULE + LM_MODULE, + LM_SOURCE }; static const char *launchModeNames[] - = { "Unknown", "Main class", "JAR file", "Module" }; + = { "Unknown", "Main class", "JAR file", "Module", "Source" }; typedef struct { int argc; diff --git a/src/java.base/share/native/libjli/jli_util.c b/src/java.base/share/native/libjli/jli_util.c index 014e810ece7..3b24a784491 100644 --- a/src/java.base/share/native/libjli/jli_util.c +++ b/src/java.base/share/native/libjli/jli_util.c @@ -84,6 +84,16 @@ JLI_MemFree(void *ptr) free(ptr); } +jboolean +JLI_HasSuffix(const char *s1, const char *s2) +{ + char *p = JLI_StrRChr(s1, '.'); + if (p == NULL || *p == '\0') { + return JNI_FALSE; + } + return (JLI_StrCaseCmp(p, s2) == 0); +} + /* * debug helpers we use */ diff --git a/src/java.base/share/native/libjli/jli_util.h b/src/java.base/share/native/libjli/jli_util.h index 2968f1ee7e7..b8987010f31 100644 --- a/src/java.base/share/native/libjli/jli_util.h +++ b/src/java.base/share/native/libjli/jli_util.h @@ -51,7 +51,8 @@ JLI_StringDup(const char *s1); JNIEXPORT void JNICALL JLI_MemFree(void *ptr); -int JLI_StrCCmp(const char *s1, const char* s2); +int JLI_StrCCmp(const char *s1, const char *s2); +jboolean JLI_HasSuffix(const char *s1, const char *s2); typedef struct { char *arg; @@ -158,7 +159,7 @@ JNIEXPORT void JNICALL JLI_InitArgProcessing(jboolean hasJavaArgs, jboolean disableArgFile); JNIEXPORT JLI_List JNICALL -JLI_PreprocessArg(const char *arg); +JLI_PreprocessArg(const char *arg, jboolean expandSourceOpt); JNIEXPORT jboolean JNICALL JLI_AddArgsFromEnvVar(JLI_List args, const char *var_name); diff --git a/src/java.base/windows/native/libjli/cmdtoargs.c b/src/java.base/windows/native/libjli/cmdtoargs.c index 9de0e43c536..9bbbdaf9865 100644 --- a/src/java.base/windows/native/libjli/cmdtoargs.c +++ b/src/java.base/windows/native/libjli/cmdtoargs.c @@ -246,7 +246,7 @@ JLI_CmdToArgs(char* cmdline) { // iterate through rest of command line while (src != NULL) { src = next_arg(src, arg, &wildcard); - argsInFile = JLI_PreprocessArg(arg); + argsInFile = JLI_PreprocessArg(arg, JNI_TRUE); if (argsInFile != NULL) { // resize to accommodate another Arg cnt = argsInFile->size; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/launcher/Main.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/launcher/Main.java new file mode 100644 index 00000000000..c3afaea1945 --- /dev/null +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/launcher/Main.java @@ -0,0 +1,550 @@ +/* + * 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 com.sun.tools.javac.launcher; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.URI; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.InvalidPathException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +import javax.lang.model.SourceVersion; +import javax.lang.model.element.NestingKind; +import javax.lang.model.element.TypeElement; +import javax.tools.FileObject; +import javax.tools.ForwardingJavaFileManager; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileManager.Location; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; + +import com.sun.source.util.JavacTask; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskListener; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.code.Source; +import com.sun.tools.javac.resources.LauncherProperties.Errors; +import com.sun.tools.javac.util.JCDiagnostic.Error; + +import jdk.internal.misc.VM; + +import static javax.tools.JavaFileObject.Kind.SOURCE; + +/** + * Compiles a source file, and executes the main method it contains. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own + * risk. This code and its internal interfaces are subject to change + * or deletion without notice.

+ */ +public class Main { + /** + * An exception used to report errors. + */ + public class Fault extends Exception { + private static final long serialVersionUID = 1L; + Fault(Error error) { + super(Main.this.getMessage(error)); + } + } + + /** + * Compiles a source file, and executes the main method it contains. + * + *

This is normally invoked from the Java launcher, either when + * the {@code --source} option is used, or when the first argument + * that is not part of a runtime option ends in {@code .java}. + * + *

The first entry in the {@code args} array is the source file + * to be compiled and run; all subsequent entries are passed as + * arguments to the main method of the first class found in the file. + * + *

If any problem occurs before executing the main class, it will + * be reported to the standard error stream, and the the JVM will be + * terminated by calling {@code System.exit} with a non-zero return code. + * + * @param args the arguments + * @throws Throwable if the main method throws an exception + */ + public static void main(String... args) throws Throwable { + try { + new Main(System.err).run(VM.getRuntimeArguments(), args); + } catch (Fault f) { + System.err.println(f.getMessage()); + System.exit(1); + } catch (InvocationTargetException e) { + // leave VM to handle the stacktrace, in the standard manner + throw e.getTargetException(); + } + } + + /** Stream for reporting errors, such as compilation errors. */ + private PrintWriter out; + + /** + * Creates an instance of this class, providing a stream to which to report + * any errors. + * + * @param out the stream + */ + public Main(PrintStream out) { + this(new PrintWriter(new OutputStreamWriter(out), true)); + } + + /** + * Creates an instance of this class, providing a stream to which to report + * any errors. + * + * @param out the stream + */ + public Main(PrintWriter out) { + this.out = out; + } + + /** + * Compiles a source file, and executes the main method it contains. + * + *

The first entry in the {@code args} array is the source file + * to be compiled and run; all subsequent entries are passed as + * arguments to the main method of the first class found in the file. + * + *

Options for {@code javac} are obtained by filtering the runtime arguments. + * + *

If the main method throws an exception, it will be propagated in an + * {@code InvocationTargetException}. In that case, the stack trace of the + * target exception will be truncated such that the main method will be the + * last entry on the stack. In other words, the stack frames leading up to the + * invocation of the main method will be removed. + * + * @param runtimeArgs the runtime arguments + * @param args the arguments + * @throws Fault if a problem is detected before the main method can be executed + * @throws InvocationTargetException if the main method throws an exception + */ + public void run(String[] runtimeArgs, String[] args) throws Fault, InvocationTargetException { + Path file = getFile(args); + + Context context = new Context(); + String mainClassName = compile(file, getJavacOpts(runtimeArgs), context); + + String[] appArgs = Arrays.copyOfRange(args, 1, args.length); + execute(mainClassName, appArgs, context); + } + + /** + * Returns the path for the filename found in the first of an array of arguments. + * + * @param args the array + * @return the path + * @throws Fault if there is a problem determining the path, or if the file does not exist + */ + private Path getFile(String[] args) throws Fault { + if (args.length == 0) { + // should not happen when invoked from launcher + throw new Fault(Errors.NoArgs); + } + Path file; + try { + file = Paths.get(args[0]); + } catch (InvalidPathException e) { + throw new Fault(Errors.InvalidFilename(args[0])); + } + if (!Files.exists(file)) { + // should not happen when invoked from launcher + throw new Fault(Errors.FileNotFound(file)); + } + return file; + } + + /** + * Reads a source file, ignoring the first line if it is not a Java source file and + * it begins with {@code #!}. + * + *

If it is not a Java source file, and if the first two bytes are {@code #!}, + * indicating a "magic number" of an executable text file, the rest of the first line + * up to but not including the newline is ignored. All characters after the first two are + * read in the {@link Charset#defaultCharset default platform encoding}. + * + * @param file the file + * @return a file object containing the content of the file + * @throws Fault if an error occurs while reading the file + */ + private JavaFileObject readFile(Path file) throws Fault { + // use a BufferedInputStream to guarantee that we can use mark and reset. + try (BufferedInputStream in = new BufferedInputStream(Files.newInputStream(file))) { + boolean ignoreFirstLine; + if (file.getFileName().toString().endsWith(".java")) { + ignoreFirstLine = false; + } else { + in.mark(2); + ignoreFirstLine = (in.read() == '#') && (in.read() == '!'); + if (!ignoreFirstLine) { + in.reset(); + } + } + try (BufferedReader r = new BufferedReader(new InputStreamReader(in, Charset.defaultCharset()))) { + StringBuilder sb = new StringBuilder(); + if (ignoreFirstLine) { + r.readLine(); + sb.append("\n"); // preserve line numbers + } + char[] buf = new char[1024]; + int n; + while ((n = r.read(buf, 0, buf.length)) != -1) { + sb.append(buf, 0, n); + } + return new SimpleJavaFileObject(file.toUri(), SOURCE) { + @Override + public String getName() { + return file.toString(); + } + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return sb; + } + @Override + public boolean isNameCompatible(String simpleName, JavaFileObject.Kind kind) { + // reject package-info and module-info; accept other names + return (kind == JavaFileObject.Kind.SOURCE) + && SourceVersion.isIdentifier(simpleName); + } + @Override + public String toString() { + return "JavacSourceLauncher[" + file + "]"; + } + }; + } + } catch (IOException e) { + throw new Fault(Errors.CantReadFile(file, e)); + } + } + + /** + * Returns the subset of the runtime arguments that are relevant to {@code javac}. + * Generally, the relevant options are those for setting paths and for configuring the + * module system. + * + * @param runtimeArgs the runtime arguments + * @return the subset of the runtime arguments + **/ + private List getJavacOpts(String... runtimeArgs) throws Fault { + List javacOpts = new ArrayList<>(); + + String sourceOpt = System.getProperty("jdk.internal.javac.source"); + if (sourceOpt != null) { + Source source = Source.lookup(sourceOpt); + if (source == null) { + throw new Fault(Errors.InvalidValueForSource(sourceOpt)); + } + javacOpts.addAll(List.of("--release", sourceOpt)); + } + + for (int i = 0; i < runtimeArgs.length; i++) { + String arg = runtimeArgs[i]; + String opt = arg, value = null; + if (arg.startsWith("--")) { + int eq = arg.indexOf('='); + if (eq > 0) { + opt = arg.substring(0, eq); + value = arg.substring(eq + 1); + } + } + switch (opt) { + // The following options all expect a value, either in the following + // position, or after '=', for options beginning "--". + case "--class-path": case "-classpath": case "-cp": + case "--module-path": case "-p": + case "--add-exports": + case "--add-modules": + case "--limit-modules": + case "--patch-module": + case "--upgrade-module-path": + if (value == null) { + if (i== runtimeArgs.length - 1) { + // should not happen when invoked from launcher + throw new Fault(Errors.NoValueForOption(opt)); + } + value = runtimeArgs[++i]; + } + if (opt.equals("--add-modules") && value.equals("ALL-DEFAULT")) { + // this option is only supported at run time; + // it is not required or supported at compile time + break; + } + javacOpts.add(opt); + javacOpts.add(value); + break; + case "--enable-preview": + javacOpts.add(opt); + if (sourceOpt == null) { + throw new Fault(Errors.EnablePreviewRequiresSource); + } + break; + default: + // ignore all other runtime args + } + } + + // add implicit options + javacOpts.add("-proc:none"); + + return javacOpts; + } + + /** + * Compiles a source file, placing the class files in a map in memory. + * Any messages generated during compilation will be written to the stream + * provided when this object was created. + * + * @param file the source file + * @param javacOpts compilation options for {@code javac} + * @param context the context for the compilation + * @return the name of the first class found in the source file + * @throws Fault if any compilation errors occur, or if no class was found + */ + private String compile(Path file, List javacOpts, Context context) throws Fault { + JavaFileObject fo = readFile(file); + + JavacTool javaCompiler = JavacTool.create(); + StandardJavaFileManager stdFileMgr = javaCompiler.getStandardFileManager(null, null, null); + try { + stdFileMgr.setLocation(StandardLocation.SOURCE_PATH, Collections.emptyList()); + } catch (IOException e) { + throw new java.lang.Error("unexpected exception from file manager", e); + } + JavaFileManager fm = context.getFileManager(stdFileMgr); + JavacTask t = javaCompiler.getTask(out, fm, null, javacOpts, null, List.of(fo)); + MainClassListener l = new MainClassListener(t); + Boolean ok = t.call(); + if (!ok) { + throw new Fault(Errors.CompilationFailed); + } + if (l.mainClass == null) { + throw new Fault(Errors.NoClass); + } + String mainClassName = l.mainClass.getQualifiedName().toString(); + return mainClassName; + } + + /** + * Invokes the {@code main} method of a specified class, using a class loader that + * will load recently compiled classes from memory. + * + * @param mainClassName the class to be executed + * @param appArgs the arguments for the {@code main} method + * @param context the context for the class to be executed + * @throws Fault if there is a problem finding or invoking the {@code main} method + * @throws InvocationTargetException if the {@code main} method throws an exception + */ + private void execute(String mainClassName, String[] appArgs, Context context) + throws Fault, InvocationTargetException { + ClassLoader cl = context.getClassLoader(ClassLoader.getSystemClassLoader()); + try { + Class appClass = Class.forName(mainClassName, true, cl); + if (appClass.getClassLoader() != cl) { + throw new Fault(Errors.UnexpectedClass(mainClassName)); + } + Method main = appClass.getDeclaredMethod("main", String[].class); + int PUBLIC_STATIC = Modifier.PUBLIC | Modifier.STATIC; + if ((main.getModifiers() & PUBLIC_STATIC) != PUBLIC_STATIC) { + throw new Fault(Errors.MainNotPublicStatic); + } + if (!main.getReturnType().equals(void.class)) { + throw new Fault(Errors.MainNotVoid); + } + main.setAccessible(true); + main.invoke(0, (Object) appArgs); + } catch (ClassNotFoundException e) { + throw new Fault(Errors.CantFindClass(mainClassName)); + } catch (NoSuchMethodException e) { + throw new Fault(Errors.CantFindMainMethod(mainClassName)); + } catch (IllegalAccessException e) { + throw new Fault(Errors.CantAccessMainMethod(mainClassName)); + } catch (InvocationTargetException e) { + // remove stack frames for source launcher + int invocationFrames = e.getStackTrace().length; + Throwable target = e.getTargetException(); + StackTraceElement[] targetTrace = target.getStackTrace(); + target.setStackTrace(Arrays.copyOfRange(targetTrace, 0, targetTrace.length - invocationFrames)); + throw e; + } + } + + private static final String bundleName = "com.sun.tools.javac.resources.launcher"; + private ResourceBundle resourceBundle = null; + private String errorPrefix; + + /** + * Returns a localized string from a resource bundle. + * + * @param error the error for which to get the localized text + * @return the localized string + */ + private String getMessage(Error error) { + String key = error.key(); + Object[] args = error.getArgs(); + try { + if (resourceBundle == null) { + resourceBundle = ResourceBundle.getBundle(bundleName); + errorPrefix = resourceBundle.getString("launcher.error"); + } + String resource = resourceBundle.getString(key); + String message = MessageFormat.format(resource, args); + return errorPrefix + message; + } catch (MissingResourceException e) { + return "Cannot access resource; " + key + Arrays.toString(args); + } + } + + /** + * A listener to detect the first class found in a compilation. + */ + static class MainClassListener implements TaskListener { + TypeElement mainClass; + + MainClassListener(JavacTask t) { + t.addTaskListener(this); + } + + @Override + public void started(TaskEvent ev) { + if (ev.getKind() == TaskEvent.Kind.ANALYZE && mainClass == null) { + TypeElement te = ev.getTypeElement(); + if (te.getNestingKind() == NestingKind.TOP_LEVEL) { + mainClass = te; + } + } + } + } + + /** + * An object to encapulate the set of in-memory classes, such that + * they can be written by a file manager and subsequently used by + * a class loader. + */ + private static class Context { + private Map inMemoryClasses = new HashMap<>(); + + JavaFileManager getFileManager(StandardJavaFileManager delegate) { + return new MemoryFileManager(inMemoryClasses, delegate); + } + + ClassLoader getClassLoader(ClassLoader parent) { + return new MemoryClassLoader(inMemoryClasses, parent); + } + } + + /** + * An in-memory file manager. + * + *

Class files (of kind {@link JavaFileObject.Kind#CLASS CLASS} written to + * {@link StandardLocation#CLASS_OUTPUT} will be written to an in-memory cache. + * All other file manager operations will be delegated to a specified file manager. + */ + private static class MemoryFileManager extends ForwardingJavaFileManager { + private final Map map; + + MemoryFileManager(Map map, JavaFileManager delegate) { + super(delegate); + this.map = map; + } + + @Override + public JavaFileObject getJavaFileForOutput(Location location, String className, + JavaFileObject.Kind kind, FileObject sibling) throws IOException { + if (location == StandardLocation.CLASS_OUTPUT && kind == JavaFileObject.Kind.CLASS) { + return createInMemoryClassFile(className); + } else { + return super.getJavaFileForOutput(location, className, kind, sibling); + } + } + + private JavaFileObject createInMemoryClassFile(String className) { + URI uri = URI.create("memory:///" + className.replace('.', '/') + ".class"); + return new SimpleJavaFileObject(uri, JavaFileObject.Kind.CLASS) { + @Override + public OutputStream openOutputStream() { + return new ByteArrayOutputStream() { + @Override + public void close() throws IOException { + super.close(); + map.put(className, toByteArray()); + } + }; + } + }; + } + } + + /** + * An in-memory classloader, that uses an in-memory cache written by {@link MemoryFileManager}. + * + *

The classloader uses the standard parent-delegation model, just providing + * {@code findClass} to find classes in the in-memory cache. + */ + private static class MemoryClassLoader extends ClassLoader { + private final Map map; + + MemoryClassLoader(Map map, ClassLoader parent) { + super(parent); + this.map = map; + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + byte[] bytes = map.get(name); + if (bytes == null) { + throw new ClassNotFoundException(name); + } + return defineClass(name, bytes, 0, bytes.length); + } + } +} diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher.properties new file mode 100644 index 00000000000..1721f9b5fc4 --- /dev/null +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher.properties @@ -0,0 +1,136 @@ +# +# 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. +# + +# Messages in this file which use "placeholders" for values (e.g. {0}, {1}) +# are preceded by a stylized comment describing the type of the corresponding +# values. +# The simple types currently in use are: +# +# annotation annotation compound +# boolean true or false +# diagnostic a sub-message; see compiler.misc.* +# fragment similar to 'message segment', but with more specific type +# modifier a Java modifier; e.g. public, private, protected +# file a file URL +# file object a file URL - similar to 'file' but typically used for source/class files, hence more specific +# flag a Flags.Flag instance +# name a name, typically a Java identifier +# number an integer +# option name the name of a command line option +# source version a source version number, such as 1.5, 1.6, 1.7 +# string a general string +# symbol the name of a declared type +# symbol kind the kind of a symbol (i.e. method, variable) +# kind name an informative description of the kind of a declaration; see compiler.misc.kindname.* +# token the name of a non-terminal in source code; see compiler.misc.token.* +# type a Java type; e.g. int, X, X +# object a Java object (unspecified) +# unused the value is not used in this message +# +# The following compound types are also used: +# +# collection of X a comma-separated collection of items; e.g. collection of type +# list of X a comma-separated list of items; e.g. list of type +# set of X a comma-separated set of items; e.g. set of modifier +# +# These may be composed: +# +# list of type or message segment +# +# The following type aliases are supported: +# +# message segment --> diagnostic or fragment +# file name --> file, path or file object +# +# Custom comments are supported in parenthesis i.e. +# +# number (classfile major version) +# +# These comments are used internally in order to generate an enum-like class declaration containing +# a method/field for each of the diagnostic keys listed here. Those methods/fields can then be used +# by javac code to build diagnostics in a type-safe fashion. +# +# In addition, these comments are verified by the jtreg test test/tools/javac/diags/MessageInfo, +# using info derived from the collected set of examples in test/tools/javac/diags/examples. +# MessageInfo can also be run as a standalone utility providing more facilities +# for manipulating this file. For more details, see MessageInfo.java. + +## All errors are preceded by this string. +launcher.error=\ + error:\u0020 + +launcher.err.no.args=\ + no filename + +# 0: string +launcher.err.invalid.filename=\ + invalid filename: {0} + +# 0: path +launcher.err.file.not.found=\ + file not found: {0} + +launcher.err.compilation.failed=\ + compilation failed + +launcher.err.no.class=\ + no class declared in file + +launcher.err.main.not.public.static=\ + ''main'' method is not declared ''public static'' + +launcher.err.main.not.void=\ + ''main'' method is not declared with a return type of ''void'' + +# 0: string +launcher.err.cant.find.class=\ + can''t find class: {0} + +# 0: string +launcher.err.unexpected.class=\ + class found on application class path: {0} + +# 0: string +launcher.err.cant.find.main.method=\ + can''t find main(String[]) method in class: {0} + +# 0: string +launcher.err.cant.access.main.method=\ + can''t access main method in class: {0} + +# 0: path, 1: object +launcher.err.cant.read.file=\ + error reading file {0}: {1} + +# 0: string +launcher.err.no.value.for.option=\ + no value given for option: {0} + +# 0: string +launcher.err.invalid.value.for.source=\ + invalid value for --source option: {0} + +launcher.err.enable.preview.requires.source=\ + --enable-preview must be used with --source diff --git a/test/jdk/tools/launcher/SourceMode.java b/test/jdk/tools/launcher/SourceMode.java new file mode 100644 index 00000000000..ff5b015fbba --- /dev/null +++ b/test/jdk/tools/launcher/SourceMode.java @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 8192920 + * @summary Test source mode + * @modules jdk.compiler + * @run main SourceMode + */ + + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.PosixFilePermission; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class SourceMode extends TestHelper { + + public static void main(String... args) throws Exception { + new SourceMode().run(args); + } + + // java Simple.java 1 2 3 + @Test + void testSimpleJava() throws IOException { + Path file = getSimpleFile("Simple.java", false); + TestResult tr = doExec(javaCmd, file.toString(), "1", "2", "3"); + if (!tr.isOK()) + error(tr, "Bad exit code: " + tr.exitValue); + if (!tr.contains("[1, 2, 3]")) + error(tr, "Expected output not found"); + System.out.println(tr.testOutput); + } + + // java --source 10 simple 1 2 3 + @Test + void testSimple() throws IOException { + Path file = getSimpleFile("simple", false); + TestResult tr = doExec(javaCmd, "--source", "10", file.toString(), "1", "2", "3"); + if (!tr.isOK()) + error(tr, "Bad exit code: " + tr.exitValue); + if (!tr.contains("[1, 2, 3]")) + error(tr, "Expected output not found"); + System.out.println(tr.testOutput); + } + + // execSimple 1 2 3 + @Test + void testExecSimple() throws IOException { + if (isWindows) // Will not work without cygwin, pass silently + return; + Path file = setExecutable(getSimpleFile("execSimple", true)); + TestResult tr = doExec(file.toAbsolutePath().toString(), "1", "2", "3"); + if (!tr.isOK()) + error(tr, "Bad exit code: " + tr.exitValue); + if (!tr.contains("[1, 2, 3]")) + error(tr, "Expected output not found"); + System.out.println(tr.testOutput); + } + + // java @simpleJava.at (contains Simple.java 1 2 3) + @Test + void testSimpleJavaAtFile() throws IOException { + Path file = getSimpleFile("Simple.java", false); + Path atFile = Paths.get("simpleJava.at"); + createFile(atFile.toFile(), List.of(file + " 1 2 3")); + TestResult tr = doExec(javaCmd, "@" + atFile); + if (!tr.isOK()) + error(tr, "Bad exit code: " + tr.exitValue); + if (!tr.contains("[1, 2, 3]")) + error(tr, "Expected output not found"); + System.out.println(tr.testOutput); + } + + // java @simple.at (contains --source 10 simple 1 2 3) + @Test + void testSimpleAtFile() throws IOException { + Path file = getSimpleFile("simple", false); + Path atFile = Paths.get("simple.at"); + createFile(atFile.toFile(), List.of("--source 10 " + file + " 1 2 3")); + TestResult tr = doExec(javaCmd, "@" + atFile); + if (!tr.isOK()) + error(tr, "Bad exit code: " + tr.exitValue); + if (!tr.contains("[1, 2, 3]")) + error(tr, "Expected output not found"); + System.out.println(tr.testOutput); + } + + // java -cp classes Main.java 1 2 3 + @Test + void testClasspath() throws IOException { + Path base = Files.createDirectories(Paths.get("testClasspath")); + Path otherJava = base.resolve("Other.java"); + createFile(otherJava.toFile(), List.of( + "public class Other {", + " public static String join(String[] args) {", + " return String.join(\"-\", args);", + " }", + "}" + )); + Path classes = Files.createDirectories(base.resolve("classes")); + Path mainJava = base.resolve("Main.java"); + createFile(mainJava.toFile(), List.of( + "class Main {", + " public static void main(String[] args) {", + " System.out.println(Other.join(args));", + " }}" + )); + compile("-d", classes.toString(), otherJava.toString()); + TestResult tr = doExec(javaCmd, "-cp", classes.toString(), + mainJava.toString(), "1", "2", "3"); + if (!tr.isOK()) + error(tr, "Bad exit code: " + tr.exitValue); + if (!tr.contains("1-2-3")) + error(tr, "Expected output not found"); + System.out.println(tr.testOutput); + } + + // java --add-exports=... Export.java --help + @Test + void testAddExports() throws IOException { + Path exportJava = Paths.get("Export.java"); + createFile(exportJava.toFile(), List.of( + "public class Export {", + " public static void main(String[] args) {", + " new com.sun.tools.javac.main.Main(\"demo\").compile(args);", + " }", + "}" + )); + // verify access fails without --add-exports + TestResult tr1 = doExec(javaCmd, exportJava.toString(), "--help"); + if (tr1.isOK()) + error(tr1, "Compilation succeeded unexpectedly"); + // verify access succeeds with --add-exports + TestResult tr2 = doExec(javaCmd, + "--add-exports", "jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", + exportJava.toString(), "--help"); + if (!tr2.isOK()) + error(tr2, "Bad exit code: " + tr2.exitValue); + if (!(tr2.contains("demo") && tr2.contains("Usage"))) + error(tr2, "Expected output not found"); + } + + // java -cp ... HelloWorld.java (for a class "java" in package "HelloWorld") + @Test + void testClassNamedJava() throws IOException { + Path base = Files.createDirectories(Paths.get("testClassNamedJava")); + Path src = Files.createDirectories(base.resolve("src")); + Path srcfile = src.resolve("java.java"); + createFile(srcfile.toFile(), List.of( + "package HelloWorld;", + "class java {", + " public static void main(String... args) {", + " System.out.println(HelloWorld.java.class.getName());", + " }", + "}" + )); + Path classes = base.resolve("classes"); + compile("-d", classes.toString(), srcfile.toString()); + TestResult tr = + doExec(javaCmd, "-cp", classes.toString(), "HelloWorld.java"); + if (!tr.isOK()) + error(tr, "Command failed"); + if (!tr.contains("HelloWorld.java")) + error(tr, "Expected output not found"); + } + + // java --source + @Test + void testSourceNoArg() throws IOException { + TestResult tr = doExec(javaCmd, "--source"); + if (tr.isOK()) + error(tr, "Command succeeded unexpectedly"); + System.err.println(tr); + if (!tr.contains("--source requires source version")) + error(tr, "Expected output not found"); + } + + // java --source 10 -jar simple.jar + @Test + void testSourceJarConflict() throws IOException { + Path base = Files.createDirectories(Paths.get("testSourceJarConflict")); + Path file = getSimpleFile("Simple.java", false); + Path classes = Files.createDirectories(base.resolve("classes")); + compile("-d", classes.toString(), file.toString()); + Path simpleJar = base.resolve("simple.jar"); + createJar("cf", simpleJar.toString(), "-C", classes.toString(), "."); + TestResult tr = + doExec(javaCmd, "--source", "10", "-jar", simpleJar.toString()); + if (tr.isOK()) + error(tr, "Command succeeded unexpectedly"); + if (!tr.contains("Option -jar is not allowed with --source")) + error(tr, "Expected output not found"); + } + + // java --source 10 -m jdk.compiler + @Test + void testSourceModuleConflict() throws IOException { + TestResult tr = doExec(javaCmd, "--source", "10", "-m", "jdk.compiler"); + if (tr.isOK()) + error(tr, "Command succeeded unexpectedly"); + if (!tr.contains("Option -m is not allowed with --source")) + error(tr, "Expected output not found"); + } + + // #!.../java --source 10 -version + @Test + void testTerminalOptionInShebang() throws IOException { + if (isWindows) // Will not work without cygwin, pass silently + return; + Path base = Files.createDirectories( + Paths.get("testTerminalOptionInShebang")); + Path bad = base.resolve("bad"); + createFile(bad.toFile(), List.of( + "#!" + javaCmd + " --source 10 -version")); + setExecutable(bad); + TestResult tr = doExec(bad.toString()); + if (!tr.contains("Option -version is not allowed in this context")) + error(tr, "Expected output not found"); + } + + // #!.../java --source 10 @bad.at (contains -version) + @Test + void testTerminalOptionInShebangAtFile() throws IOException { + if (isWindows) // Will not work without cygwin, pass silently + return; + // Use a short directory name, to avoid line length limitations + Path base = Files.createDirectories(Paths.get("testBadAtFile")); + Path bad_at = base.resolve("bad.at"); + createFile(bad_at.toFile(), List.of("-version")); + Path bad = base.resolve("bad"); + createFile(bad.toFile(), List.of( + "#!" + javaCmd + " --source 10 @" + bad_at)); + setExecutable(bad); + TestResult tr = doExec(bad.toString()); + System.err.println("JJG JJG " + tr); + if (!tr.contains("Option -version in @testBadAtFile/bad.at is " + + "not allowed in this context")) + error(tr, "Expected output not found"); + } + + // #!.../java --source 10 HelloWorld + @Test + void testMainClassInShebang() throws IOException { + if (isWindows) // Will not work without cygwin, pass silently + return; + Path base = Files.createDirectories(Paths.get("testMainClassInShebang")); + Path bad = base.resolve("bad"); + createFile(bad.toFile(), List.of( + "#!" + javaCmd + " --source 10 HelloWorld")); + setExecutable(bad); + TestResult tr = doExec(bad.toString()); + if (!tr.contains("Cannot specify main class in this context")) + error(tr, "Expected output not found"); + } + + //-------------------------------------------------------------------------- + + private Map getLauncherDebugEnv() { + return Map.of("_JAVA_LAUNCHER_DEBUG", "1"); + } + + private Path getSimpleFile(String name, boolean shebang) throws IOException { + Path file = Paths.get(name); + if (!Files.exists(file)) { + createFile(file.toFile(), List.of( + (shebang ? "#!" + javaCmd + " --source 10" : ""), + "public class Simple {", + " public static void main(String[] args) {", + " System.out.println(java.util.Arrays.toString(args));", + " }}")); + } + return file; + } + + private Path setExecutable(Path file) throws IOException { + Set perms = Files.getPosixFilePermissions(file); + perms.add(PosixFilePermission.OWNER_EXECUTE); + Files.setPosixFilePermissions(file, perms); + return file; + } + + private void error(TestResult tr, String message) { + System.err.println(tr); + throw new RuntimeException(message); + } +} diff --git a/test/langtools/tools/javac/diags/CheckResourceKeys.java b/test/langtools/tools/javac/diags/CheckResourceKeys.java index d7965c21b4b..8ce93dc8aa8 100644 --- a/test/langtools/tools/javac/diags/CheckResourceKeys.java +++ b/test/langtools/tools/javac/diags/CheckResourceKeys.java @@ -118,7 +118,8 @@ public class CheckResourceKeys { void findDeadKeys(Set codeStrings, Set resourceKeys) { String[] prefixes = { "compiler.err.", "compiler.warn.", "compiler.note.", "compiler.misc.", - "javac." + "javac.", + "launcher.err." }; for (String rk: resourceKeys) { // some keys are used directly, without a prefix. @@ -395,7 +396,7 @@ public class CheckResourceKeys { Set getResourceKeys() { Module jdk_compiler = ModuleLayer.boot().findModule("jdk.compiler").get(); Set results = new TreeSet(); - for (String name : new String[]{"javac", "compiler"}) { + for (String name : new String[]{"javac", "compiler", "launcher"}) { ResourceBundle b = ResourceBundle.getBundle("com.sun.tools.javac.resources." + name, jdk_compiler); results.addAll(b.keySet()); diff --git a/test/langtools/tools/javac/launcher/SourceLauncherTest.java b/test/langtools/tools/javac/launcher/SourceLauncherTest.java new file mode 100644 index 00000000000..79f5118b9a1 --- /dev/null +++ b/test/langtools/tools/javac/launcher/SourceLauncherTest.java @@ -0,0 +1,542 @@ +/* + * 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 8192920 + * @summary Test source launcher + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.launcher + * jdk.compiler/com.sun.tools.javac.main + * @build toolbox.JavaTask toolbox.JavacTask toolbox.TestRunner toolbox.ToolBox + * @run main SourceLauncherTest + */ + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.InvocationTargetException; +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.List; +import java.util.Properties; + +import com.sun.tools.javac.launcher.Main; + +import toolbox.JavaTask; +import toolbox.JavacTask; +import toolbox.Task; +import toolbox.TestRunner; +import toolbox.TestRunner; +import toolbox.ToolBox; + +public class SourceLauncherTest extends TestRunner { + public static void main(String... args) throws Exception { + SourceLauncherTest t = new SourceLauncherTest(); + t.runTests(m -> new Object[] { Paths.get(m.getName()) }); + } + + SourceLauncherTest() { + super(System.err); + tb = new ToolBox(); + System.err.println("version: " + thisVersion); + } + + private final ToolBox tb; + private static final String thisVersion = System.getProperty("java.specification.version"); + + /* + * Positive tests. + */ + + @Test + public void testHelloWorld(Path base) throws IOException { + tb.writeJavaFiles(base, + "import java.util.Arrays;\n" + + "class HelloWorld {\n" + + " public static void main(String... args) {\n" + + " System.out.println(\"Hello World! \" + Arrays.toString(args));\n" + + " }\n" + + "}"); + testSuccess(base.resolve("HelloWorld.java"), "Hello World! [1, 2, 3]\n"); + } + + @Test + public void testHelloWorldInPackage(Path base) throws IOException { + tb.writeJavaFiles(base, + "package hello;\n" + + "import java.util.Arrays;\n" + + "class World {\n" + + " public static void main(String... args) {\n" + + " System.out.println(\"Hello World! \" + Arrays.toString(args));\n" + + " }\n" + + "}"); + testSuccess(base.resolve("hello").resolve("World.java"), "Hello World! [1, 2, 3]\n"); + } + + @Test + public void testHelloWorldWithAux(Path base) throws IOException { + tb.writeJavaFiles(base, + "import java.util.Arrays;\n" + + "class HelloWorld {\n" + + " public static void main(String... args) {\n" + + " Aux.write(args);\n" + + " }\n" + + "}\n" + + "class Aux {\n" + + " static void write(String... args) {\n" + + " System.out.println(\"Hello World! \" + Arrays.toString(args));\n" + + " }\n" + + "}"); + testSuccess(base.resolve("HelloWorld.java"), "Hello World! [1, 2, 3]\n"); + } + + @Test + public void testHelloWorldWithShebang(Path base) throws IOException { + tb.writeJavaFiles(base, + "#!/usr/bin/java --source 11\n" + + "import java.util.Arrays;\n" + + "class HelloWorld {\n" + + " public static void main(String... args) {\n" + + " System.out.println(\"Hello World! \" + Arrays.toString(args));\n" + + " }\n" + + "}"); + Files.copy(base.resolve("HelloWorld.java"), base.resolve("HelloWorld")); + testSuccess(base.resolve("HelloWorld"), "Hello World! [1, 2, 3]\n"); + } + + @Test + public void testNoAnnoProcessing(Path base) throws IOException { + Path annoSrc = base.resolve("annoSrc"); + tb.writeJavaFiles(annoSrc, + "import java.util.*;\n" + + "import javax.annotation.processing.*;\n" + + "import javax.lang.model.element.*;\n" + + "@SupportedAnnotationTypes(\"*\")\n" + + "public class AnnoProc extends AbstractProcessor {\n" + + " public boolean process(Set annos, RoundEnvironment rEnv) {\n" + + " throw new Error(\"Annotation processor should not be invoked\");\n" + + " }\n" + + "}\n"); + Path annoClasses = Files.createDirectories(base.resolve("classes")); + new JavacTask(tb) + .outdir(annoClasses) + .files(annoSrc.resolve("AnnoProc.java").toString()) + .run(); + Path serviceFile = annoClasses.resolve("META-INF").resolve("services") + .resolve("javax.annotation.processing.Processor"); + tb.writeFile(serviceFile, "AnnoProc"); + + Path mainSrc = base.resolve("mainSrc"); + tb.writeJavaFiles(mainSrc, + "import java.util.Arrays;\n" + + "class HelloWorld {\n" + + " public static void main(String... args) {\n" + + " System.out.println(\"Hello World! \" + Arrays.toString(args));\n" + + " }\n" + + "}"); + + List javacArgs = List.of("-classpath", annoClasses.toString()); + List classArgs = List.of("1", "2", "3"); + String expect = "Hello World! [1, 2, 3]\n"; + Result r = run(mainSrc.resolve("HelloWorld.java"), javacArgs, classArgs); + checkEqual("stdout", r.stdOut, expect); + checkEmpty("stderr", r.stdErr); + checkNull("exception", r.exception); + } + + @Test + public void testEnablePreview(Path base) throws IOException { + tb.writeJavaFiles(base, + "import java.util.Arrays;\n" + + "class HelloWorld {\n" + + " public static void main(String... args) {\n" + + " System.out.println(\"Hello World! \" + Arrays.toString(args));\n" + + " }\n" + + "}"); + + String log = new JavaTask(tb) + .vmOptions("--enable-preview", "--source", thisVersion) + .className(base.resolve("HelloWorld.java").toString()) + .classArgs("1", "2", "3") + .run(Task.Expect.SUCCESS) + .getOutput(Task.OutputKind.STDOUT); + checkEqual("stdout", log.trim(), "Hello World! [1, 2, 3]"); + } + + void testSuccess(Path file, String expect) throws IOException { + Result r = run(file, Collections.emptyList(), List.of("1", "2", "3")); + checkEqual("stdout", r.stdOut, expect); + checkEmpty("stderr", r.stdErr); + checkNull("exception", r.exception); + } + + /* + * Negative tests: such as cannot find or execute main method. + */ + + @Test + public void testHelloWorldWithShebangJava(Path base) throws IOException { + tb.writeJavaFiles(base, + "#!/usr/bin/java --source 11\n" + + "import java.util.Arrays;\n" + + "class HelloWorld {\n" + + " public static void main(String... args) {\n" + + " System.out.println(\"Hello World! \" + Arrays.toString(args));\n" + + " }\n" + + "}"); + Path file = base.resolve("HelloWorld.java"); + testError(file, + file + ":1: error: illegal character: '#'\n" + + "#!/usr/bin/java --source 11\n" + + "^\n" + + file + ":1: error: class, interface, or enum expected\n" + + "#!/usr/bin/java --source 11\n" + + " ^\n" + + "2 errors\n", + "error: compilation failed"); + } + + @Test + public void testNoClass(Path base) throws IOException { + Files.createDirectories(base); + Path file = base.resolve("NoClass.java"); + Files.write(file, List.of("package p;")); + testError(file, "", "error: no class declared in file"); + } + + @Test + public void testWrongClass(Path base) throws IOException { + Path src = base.resolve("src"); + Path file = src.resolve("WrongClass.java"); + tb.writeJavaFiles(src, "class WrongClass { }"); + Path classes = Files.createDirectories(base.resolve("classes")); + new JavacTask(tb) + .outdir(classes) + .files(file) + .run(); + String log = new JavaTask(tb) + .classpath(classes.toString()) + .className(file.toString()) + .run(Task.Expect.FAIL) + .getOutput(Task.OutputKind.STDERR); + checkEqual("stderr", log.trim(), + "error: class found on application class path: WrongClass"); + } + + @Test + public void testSyntaxErr(Path base) throws IOException { + tb.writeJavaFiles(base, "class SyntaxErr {"); + Path file = base.resolve("SyntaxErr.java"); + testError(file, + file + ":1: error: reached end of file while parsing\n" + + "class SyntaxErr {\n" + + " ^\n" + + "1 error\n", + "error: compilation failed"); + } + + @Test + public void testNoSourceOnClassPath(Path base) throws IOException { + Path auxSrc = base.resolve("auxSrc"); + tb.writeJavaFiles(auxSrc, + "public class Aux {\n" + + " static final String MESSAGE = \"Hello World\";\n" + + "}\n"); + + Path mainSrc = base.resolve("mainSrc"); + tb.writeJavaFiles(mainSrc, + "import java.util.Arrays;\n" + + "class HelloWorld {\n" + + " public static void main(String... args) {\n" + + " System.out.println(Aux.MESSAGE + Arrays.toString(args));\n" + + " }\n" + + "}"); + + List javacArgs = List.of("-classpath", auxSrc.toString()); + List classArgs = List.of("1", "2", "3"); + String expectStdErr = + "testNoSourceOnClassPath/mainSrc/HelloWorld.java:4: error: cannot find symbol\n" + + " System.out.println(Aux.MESSAGE + Arrays.toString(args));\n" + + " ^\n" + + " symbol: variable Aux\n" + + " location: class HelloWorld\n" + + "1 error\n"; + Result r = run(mainSrc.resolve("HelloWorld.java"), javacArgs, classArgs); + checkEmpty("stdout", r.stdOut); + checkEqual("stderr", r.stdErr, expectStdErr); + checkFault("exception", r.exception, "error: compilation failed"); + + } + + // For any source file that is invoked through the OS shebang mechanism, invalid shebang + // lines will be caught and handled by the OS, before the launcher is even invoked. + // However, if such a file is passed directly to the launcher, perhaps using the --source + // option, a well-formed shebang line will be removed but a badly-formed one will be not be + // removed and will cause compilation errors. + @Test + public void testBadShebang(Path base) throws IOException { + tb.writeJavaFiles(base, + "#/usr/bin/java --source 11\n" + + "import java.util.Arrays;\n" + + "class HelloWorld {\n" + + " public static void main(String... args) {\n" + + " System.out.println(\"Hello World! \" + Arrays.toString(args));\n" + + " }\n" + + "}"); + Path file = base.resolve("HelloWorld.java"); + testError(file, + file + ":1: error: illegal character: '#'\n" + + "#/usr/bin/java --source 11\n" + + "^\n" + + file + ":1: error: class, interface, or enum expected\n" + + "#/usr/bin/java --source 11\n" + + " ^\n" + + "2 errors\n", + "error: compilation failed"); + } + + @Test + public void testBadSourceOpt(Path base) throws IOException { + Files.createDirectories(base); + Path file = base.resolve("DummyClass.java"); + Files.write(file, List.of("class DummyClass { }")); + Properties sysProps = System.getProperties(); + Properties p = new Properties(sysProps); + p.setProperty("jdk.internal.javac.source", ""); + System.setProperties(p); + try { + testError(file, "", "error: invalid value for --source option: "); + } finally { + System.setProperties(sysProps); + } + } + + @Test + public void testEnablePreviewNoSource(Path base) throws IOException { + tb.writeJavaFiles(base, + "import java.util.Arrays;\n" + + "class HelloWorld {\n" + + " public static void main(String... args) {\n" + + " System.out.println(\"Hello World! \" + Arrays.toString(args));\n" + + " }\n" + + "}"); + + String log = new JavaTask(tb) + .vmOptions("--enable-preview") + .className(base.resolve("HelloWorld.java").toString()) + .run(Task.Expect.FAIL) + .getOutput(Task.OutputKind.STDERR); + checkEqual("stderr", log.trim(), + "error: --enable-preview must be used with --source"); + } + + @Test + public void testNoMain(Path base) throws IOException { + tb.writeJavaFiles(base, "class NoMain { }"); + testError(base.resolve("NoMain.java"), "", + "error: can't find main(String[]) method in class: NoMain"); + } + + @Test + public void testMainBadParams(Path base) throws IOException { + tb.writeJavaFiles(base, + "class BadParams { public static void main() { } }"); + testError(base.resolve("BadParams.java"), "", + "error: can't find main(String[]) method in class: BadParams"); + } + + @Test + public void testMainNotPublic(Path base) throws IOException { + tb.writeJavaFiles(base, + "class NotPublic { static void main(String... args) { } }"); + testError(base.resolve("NotPublic.java"), "", + "error: 'main' method is not declared 'public static'"); + } + + @Test + public void testMainNotStatic(Path base) throws IOException { + tb.writeJavaFiles(base, + "class NotStatic { public void main(String... args) { } }"); + testError(base.resolve("NotStatic.java"), "", + "error: 'main' method is not declared 'public static'"); + } + + @Test + public void testMainNotVoid(Path base) throws IOException { + tb.writeJavaFiles(base, + "class NotVoid { public static int main(String... args) { return 0; } }"); + testError(base.resolve("NotVoid.java"), "", + "error: 'main' method is not declared with a return type of 'void'"); + } + + @Test + public void testClassInModule(Path base) throws IOException { + tb.writeJavaFiles(base, "package java.net; class InModule { }"); + Path file = base.resolve("java").resolve("net").resolve("InModule.java"); + testError(file, + file + ":1: error: package exists in another module: java.base\n" + + "package java.net; class InModule { }\n" + + "^\n" + + "1 error\n", + "error: compilation failed"); + } + + void testError(Path file, String expectStdErr, String expectFault) throws IOException { + Result r = run(file, Collections.emptyList(), List.of("1", "2", "3")); + checkEmpty("stdout", r.stdOut); + checkEqual("stderr", r.stdErr, expectStdErr); + checkFault("exception", r.exception, expectFault); + } + + /* + * Tests in which main throws an exception. + */ + @Test + public void testTargetException1(Path base) throws IOException { + tb.writeJavaFiles(base, + "import java.util.Arrays;\n" + + "class Thrower {\n" + + " public static void main(String... args) {\n" + + " throwWhenZero(Integer.parseInt(args[0]));\n" + + " }\n" + + " static void throwWhenZero(int arg) {\n" + + " if (arg == 0) throw new Error(\"zero!\");\n" + + " throwWhenZero(arg - 1);\n" + + " }\n" + + "}"); + Path file = base.resolve("Thrower.java"); + Result r = run(file, Collections.emptyList(), List.of("3")); + checkEmpty("stdout", r.stdOut); + checkEmpty("stderr", r.stdErr); + checkTrace("exception", r.exception, + "java.lang.Error: zero!", + "at Thrower.throwWhenZero(Thrower.java:7)", + "at Thrower.throwWhenZero(Thrower.java:8)", + "at Thrower.throwWhenZero(Thrower.java:8)", + "at Thrower.throwWhenZero(Thrower.java:8)", + "at Thrower.main(Thrower.java:4)"); + } + + Result run(Path file, List runtimeArgs, List appArgs) { + List args = new ArrayList<>(); + args.add(file.toString()); + args.addAll(appArgs); + + PrintStream prev = System.out; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (PrintStream out = new PrintStream(baos, true)) { + System.setOut(out); + StringWriter sw = new StringWriter(); + try (PrintWriter err = new PrintWriter(sw, true)) { + Main m = new Main(err); + m.run(toArray(runtimeArgs), toArray(args)); + return new Result(baos.toString(), sw.toString(), null); + } catch (Throwable t) { + return new Result(baos.toString(), sw.toString(), t); + } + } finally { + System.setOut(prev); + } + } + + void checkEqual(String name, String found, String expect) { + expect = expect.replace("\n", tb.lineSeparator); + out.println(name + ": " + found); + out.println(name + ": " + found); + if (!expect.equals(found)) { + error("Unexpected output; expected: " + expect); + } + } + + void checkEmpty(String name, String found) { + out.println(name + ": " + found); + if (!found.isEmpty()) { + error("Unexpected output; expected empty string"); + } + } + + void checkNull(String name, Throwable found) { + out.println(name + ": " + found); + if (found != null) { + error("Unexpected exception; expected null"); + } + } + + void checkFault(String name, Throwable found, String expect) { + expect = expect.replace("\n", tb.lineSeparator); + out.println(name + ": " + found); + if (found == null) { + error("No exception thrown; expected Main.Fault"); + } else { + if (!(found instanceof Main.Fault)) { + error("Unexpected exception; expected Main.Fault"); + } + if (!(found.getMessage().equals(expect))) { + error("Unexpected detail message; expected: " + expect); + } + } + } + + void checkTrace(String name, Throwable found, String... expect) { + if (!(found instanceof InvocationTargetException)) { + error("Unexpected exception; expected InvocationTargetException"); + out.println("Found:"); + found.printStackTrace(out); + } + StringWriter sw = new StringWriter(); + try (PrintWriter pw = new PrintWriter(sw)) { + ((InvocationTargetException) found).getTargetException().printStackTrace(pw); + } + String trace = sw.toString(); + out.println(name + ":\n" + trace); + String[] traceLines = trace.trim().split("[\r\n]+\\s+"); + try { + tb.checkEqual(List.of(traceLines), List.of(expect)); + } catch (Error e) { + error(e.getMessage()); + } + } + + String[] toArray(List list) { + return list.toArray(new String[list.size()]); + } + + class Result { + private final String stdOut; + private final String stdErr; + private final Throwable exception; + + Result(String stdOut, String stdErr, Throwable exception) { + this.stdOut = stdOut; + this.stdErr = stdErr; + this.exception = exception; + } + } +} From 658f3a7ee90bba54400065f745621c04fb31dbce Mon Sep 17 00:00:00 2001 From: Igor Ignatyev Date: Thu, 7 Jun 2018 17:10:23 -0700 Subject: [PATCH 23/46] 8204577: jittester generator doesn't kill processes on timeout Reviewed-by: kvn, epavlova --- .../jdk/test/lib/jittester/TestsGenerator.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/TestsGenerator.java b/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/TestsGenerator.java index 952e34182a3..ca6cf25b1c1 100644 --- a/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/TestsGenerator.java +++ b/test/hotspot/jtreg/testlibrary/jittester/src/jdk/test/lib/jittester/TestsGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import jdk.test.lib.jittester.types.TypeKlass; import jdk.test.lib.jittester.utils.PseudoRandom; public abstract class TestsGenerator implements BiConsumer { + private static final int DEFAULT_JTREG_TIMEOUT = 120; protected static final String JAVA_BIN = getJavaPath(); protected static final String JAVAC = Paths.get(JAVA_BIN, "javac").toString(); protected static final String JAVA = Paths.get(JAVA_BIN, "java").toString(); @@ -73,15 +74,17 @@ public abstract class TestsGenerator implements BiConsumer { pb.redirectError(new File(name + ".err")); pb.redirectOutput(new File(name + ".out")); Process process = pb.start(); - if (process.waitFor(Automatic.MINUTES_TO_WAIT, TimeUnit.MINUTES)) { - try (FileWriter file = new FileWriter(name + ".exit")) { - file.write(Integer.toString(process.exitValue())); + try { + if (process.waitFor(DEFAULT_JTREG_TIMEOUT, TimeUnit.SECONDS)) { + try (FileWriter file = new FileWriter(name + ".exit")) { + file.write(Integer.toString(process.exitValue())); + } + return process.exitValue(); } - return process.exitValue(); - } else { + } finally { process.destroyForcibly(); - return -1; } + return -1; } protected static void compilePrinter() { From 42e75b8c791eb3a31ae78f873c26bbb7f6faef0f Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Thu, 7 Jun 2018 17:38:34 -0700 Subject: [PATCH 24/46] 8202611: [GRAAL] Exclude CMS GC testing from runs with Graal Reviewed-by: iignatyev, kbarrett --- test/hotspot/jtreg/gc/TestAgeOutput.java | 16 ++- .../jtreg/gc/TestGenerationPerfCounter.java | 15 +- .../gc/TestMemoryInitializationWithCMS.java | 5 +- .../gc/TestMemoryMXBeansAndPoolsPresence.java | 13 +- .../hotspot/jtreg/gc/TestNumWorkerOutput.java | 16 ++- test/hotspot/jtreg/gc/TestSystemGC.java | 13 +- .../TestAlignmentToUseLargePages.java | 14 +- .../gc/arguments/TestCMSHeapSizeFlags.java | 4 +- .../jtreg/gc/arguments/TestMaxNewSize.java | 16 ++- .../arguments/TestUseCompressedOopsErgo.java | 19 ++- .../TestCMSClassUnloadingEnabledHWM.java | 3 +- .../TestClassUnloadingDisabled.java | 18 ++- .../jtreg/gc/cms/DisableResizePLAB.java | 4 +- .../jtreg/gc/cms/GuardShrinkWarning.java | 3 +- .../hotspot/jtreg/gc/cms/TestBubbleUpRef.java | 4 +- .../gc/cms/TestCMSScavengeBeforeRemark.java | 4 +- test/hotspot/jtreg/gc/cms/TestMBeanCMS.java | 4 +- .../TestConcurrentPhaseControlCMS.java | 4 +- .../gc/metaspace/TestMetaspaceCMSCancel.java | 3 +- .../jtreg/gc/startup_warnings/TestCMS.java | 19 +-- .../stress/TestReclaimStringsLeaksMemory.java | 3 +- .../stress/gcbasher/TestGCBasherWithCMS.java | 4 +- .../stress/gclocker/TestGCLockerWithCMS.java | 4 +- .../gc/stress/gcold/TestGCOldWithCMS.java | 4 +- .../stress/systemgc/TestSystemGCWithCMS.java | 4 +- .../CompressedOops/UseCompressedOops.java | 12 +- .../runtime/MemberName/MemberNameLeak.java | 10 +- .../runtime/appcds/CommandLineFlagCombo.java | 13 +- .../sharedStrings/IncompatibleOptions.java | 14 +- .../jtreg/serviceability/sa/TestUniverse.java | 10 +- test/jdk/ProblemList-graal.txt | 6 + .../HotSpotDiagnosticMXBean/CheckOrigin.java | 4 +- .../CollectionUsageThreshold.java | 14 +- .../MemoryMXBean/LowMemoryTest.java | 14 +- .../MemoryManagementConcMarkSweepGC.sh | 4 +- .../MemoryMXBean/ResetPeakMemoryUsage.java | 14 +- .../TestGCCauseWithCMSConcurrent.java | 2 +- .../TestGCCauseWithCMSMarkSweep.java | 2 +- .../TestGCEventMixedWithCMSConcurrent.java | 2 +- .../TestGCEventMixedWithCMSMarkSweep.java | 2 +- .../TestGCEventMixedWithParNew.java | 2 +- ...YoungGarbageCollectionEventWithParNew.java | 2 +- .../TestCMSConcurrentModeFailureEvent.java | 2 +- .../TestPromotionFailedEventWithParNew.java | 2 +- .../TestStressAllocationGCEventsWithCMS.java | 2 +- ...estStressAllocationGCEventsWithParNew.java | 2 +- ...estStressBigAllocationGCEventsWithCMS.java | 2 +- ...StressBigAllocationGCEventsWithParNew.java | 2 +- .../TestHeapSummaryEventConcurrentCMS.java | 2 +- .../TestHeapSummaryEventParNewCMS.java | 2 +- ...ectCountAfterGCEventWithCMSConcurrent.java | 2 +- ...jectCountAfterGCEventWithCMSMarkSweep.java | 2 +- .../TestRefStatEventWithCMSConcurrent.java | 2 +- .../TestRefStatEventWithCMSMarkSweep.java | 2 +- ...cMarkSweepAllocationPendingStackTrace.java | 2 +- ...arkSweepGCAllocationPendingStackTrace.java | 2 +- ...TestParNewAllocationPendingStackTrace.java | 2 +- test/jdk/jdk/jfr/event/oldobject/TestCMS.java | 2 +- .../jfr/event/runtime/TestModuleEvents.java | 1 + test/jtreg-ext/requires/VMProps.java | 29 +--- test/lib/sun/hotspot/code/Compiler.java | 136 ++++++++++++++++++ 61 files changed, 410 insertions(+), 131 deletions(-) create mode 100644 test/lib/sun/hotspot/code/Compiler.java diff --git a/test/hotspot/jtreg/gc/TestAgeOutput.java b/test/hotspot/jtreg/gc/TestAgeOutput.java index b3289c2f7c4..fcd17e0f597 100644 --- a/test/hotspot/jtreg/gc/TestAgeOutput.java +++ b/test/hotspot/jtreg/gc/TestAgeOutput.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,10 +32,22 @@ * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * @run main/othervm -XX:+UseSerialGC TestAgeOutput UseSerialGC - * @run main/othervm -XX:+UseConcMarkSweepGC TestAgeOutput UseConcMarkSweepGC * @run main/othervm -XX:+UseG1GC TestAgeOutput UseG1GC */ +/* + * @test TestAgeOutputCMS + * @bug 8164936 + * @key gc + * @comment Graal does not support CMS + * @requires vm.gc=="null" & !vm.graal.enabled + * @modules java.base/jdk.internal.misc + * @library /test/lib + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -XX:+UseConcMarkSweepGC TestAgeOutput UseConcMarkSweepGC + */ + import sun.hotspot.WhiteBox; import java.util.regex.Matcher; diff --git a/test/hotspot/jtreg/gc/TestGenerationPerfCounter.java b/test/hotspot/jtreg/gc/TestGenerationPerfCounter.java index d9b4c94c7fb..49bc8ff4971 100644 --- a/test/hotspot/jtreg/gc/TestGenerationPerfCounter.java +++ b/test/hotspot/jtreg/gc/TestGenerationPerfCounter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,8 +38,21 @@ import gc.testlibrary.PerfCounters; * @run main/othervm -XX:+UsePerfData -XX:+UseSerialGC TestGenerationPerfCounter * @run main/othervm -XX:+UsePerfData -XX:+UseParallelGC TestGenerationPerfCounter * @run main/othervm -XX:+UsePerfData -XX:+UseG1GC TestGenerationPerfCounter + */ + +/* @test TestGenerationPerfCounterCMS + * @bug 8080345 + * @comment Graal does not support CMS + * @requires vm.gc=="null" & !vm.graal.enabled + * @library /test/lib / + * @summary Tests that the sun.gc.policy.generations returns 2 for all GCs. + * @modules java.base/jdk.internal.misc + * java.compiler + * java.management/sun.management + * jdk.internal.jvmstat/sun.jvmstat.monitor * @run main/othervm -XX:+UsePerfData -XX:+UseConcMarkSweepGC TestGenerationPerfCounter */ + public class TestGenerationPerfCounter { public static void main(String[] args) throws Exception { long numGenerations = diff --git a/test/hotspot/jtreg/gc/TestMemoryInitializationWithCMS.java b/test/hotspot/jtreg/gc/TestMemoryInitializationWithCMS.java index 4afc81f64e5..cb502bc0a33 100644 --- a/test/hotspot/jtreg/gc/TestMemoryInitializationWithCMS.java +++ b/test/hotspot/jtreg/gc/TestMemoryInitializationWithCMS.java @@ -1,6 +1,5 @@ - /* - * Copyright (c) 2002, 2017 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -26,7 +25,7 @@ * @test TestMemoryInitializationWithCMS * @key gc * @bug 4668531 - * @requires vm.debug & vm.gc.ConcMarkSweep + * @requires vm.debug & vm.gc.ConcMarkSweep & !vm.graal.enabled * @summary Simple test for -XX:+CheckMemoryInitialization doesn't crash VM * @run main/othervm -XX:+UseConcMarkSweepGC -XX:+CheckMemoryInitialization TestMemoryInitializationWithCMS */ diff --git a/test/hotspot/jtreg/gc/TestMemoryMXBeansAndPoolsPresence.java b/test/hotspot/jtreg/gc/TestMemoryMXBeansAndPoolsPresence.java index e923dd4ec1c..12a737a0b71 100644 --- a/test/hotspot/jtreg/gc/TestMemoryMXBeansAndPoolsPresence.java +++ b/test/hotspot/jtreg/gc/TestMemoryMXBeansAndPoolsPresence.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,11 +35,20 @@ import java.util.stream.*; * java.management * @requires vm.gc == null * @run main/othervm -XX:+UseG1GC TestMemoryMXBeansAndPoolsPresence G1 - * @run main/othervm -XX:+UseConcMarkSweepGC TestMemoryMXBeansAndPoolsPresence CMS * @run main/othervm -XX:+UseParallelGC TestMemoryMXBeansAndPoolsPresence Parallel * @run main/othervm -XX:+UseSerialGC TestMemoryMXBeansAndPoolsPresence Serial */ +/* @test TestMemoryMXBeansAndPoolsPresenceCMS + * @bug 8191564 + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @comment Graal does not support CMS + * @requires vm.gc == null & !vm.graal.enabled + * @run main/othervm -XX:+UseConcMarkSweepGC TestMemoryMXBeansAndPoolsPresence CMS + */ + class GCBeanDescription { public String name; public String[] poolNames; diff --git a/test/hotspot/jtreg/gc/TestNumWorkerOutput.java b/test/hotspot/jtreg/gc/TestNumWorkerOutput.java index 7379e1a2829..4ad407d2e18 100644 --- a/test/hotspot/jtreg/gc/TestNumWorkerOutput.java +++ b/test/hotspot/jtreg/gc/TestNumWorkerOutput.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,10 +31,22 @@ * @library /test/lib * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -XX:+UseConcMarkSweepGC TestNumWorkerOutput UseConcMarkSweepGC * @run main/othervm -XX:+UseG1GC TestNumWorkerOutput UseG1GC */ +/* + * @test TestNumWorkerOutputCMS + * @bug 8165292 + * @key gc + * @comment Graal does not support CMS + * @requires vm.gc=="null" & !vm.graal.enabled + * @modules java.base/jdk.internal.misc + * @library /test/lib + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -XX:+UseConcMarkSweepGC TestNumWorkerOutput UseConcMarkSweepGC + */ + import sun.hotspot.WhiteBox; import java.util.regex.Matcher; diff --git a/test/hotspot/jtreg/gc/TestSystemGC.java b/test/hotspot/jtreg/gc/TestSystemGC.java index a3830130ac2..93a81a5dc22 100644 --- a/test/hotspot/jtreg/gc/TestSystemGC.java +++ b/test/hotspot/jtreg/gc/TestSystemGC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, 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 @@ -30,14 +30,21 @@ * @run main/othervm -XX:+UseSerialGC TestSystemGC * @run main/othervm -XX:+UseParallelGC TestSystemGC * @run main/othervm -XX:+UseParallelGC -XX:-UseParallelOldGC TestSystemGC - * @run main/othervm -XX:+UseConcMarkSweepGC TestSystemGC - * @run main/othervm -XX:+UseConcMarkSweepGC -XX:+ExplicitGCInvokesConcurrent TestSystemGC * @run main/othervm -XX:+UseG1GC TestSystemGC * @run main/othervm -XX:+UseG1GC -XX:+ExplicitGCInvokesConcurrent TestSystemGC * @run main/othervm -XX:+UseLargePages TestSystemGC * @run main/othervm -XX:+UseLargePages -XX:+UseLargePagesInMetaspace TestSystemGC */ +/* + * @test TestSystemGCCMS + * @key gc + * @comment Graal does not support CMS + * @requires vm.gc=="null" & !vm.graal.enabled + * @run main/othervm -XX:+UseConcMarkSweepGC TestSystemGC + * @run main/othervm -XX:+UseConcMarkSweepGC -XX:+ExplicitGCInvokesConcurrent TestSystemGC + */ + public class TestSystemGC { public static void main(String args[]) throws Exception { System.gc(); diff --git a/test/hotspot/jtreg/gc/arguments/TestAlignmentToUseLargePages.java b/test/hotspot/jtreg/gc/arguments/TestAlignmentToUseLargePages.java index 0e9a88e57fd..742619bb8d3 100644 --- a/test/hotspot/jtreg/gc/arguments/TestAlignmentToUseLargePages.java +++ b/test/hotspot/jtreg/gc/arguments/TestAlignmentToUseLargePages.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 @@ -34,12 +34,20 @@ * @run main/othervm -Xms71M -Xmx91M -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:-UseLargePages TestAlignmentToUseLargePages * @run main/othervm -Xms71M -Xmx91M -XX:+UseSerialGC -XX:+UseLargePages TestAlignmentToUseLargePages * @run main/othervm -Xms71M -Xmx91M -XX:+UseSerialGC -XX:-UseLargePages TestAlignmentToUseLargePages - * @run main/othervm -Xms71M -Xmx91M -XX:+UseConcMarkSweepGC -XX:+UseLargePages TestAlignmentToUseLargePages - * @run main/othervm -Xms71M -Xmx91M -XX:+UseConcMarkSweepGC -XX:-UseLargePages TestAlignmentToUseLargePages * @run main/othervm -Xms71M -Xmx91M -XX:+UseG1GC -XX:+UseLargePages TestAlignmentToUseLargePages * @run main/othervm -Xms71M -Xmx91M -XX:+UseG1GC -XX:-UseLargePages TestAlignmentToUseLargePages */ +/** + * @test TestAlignmentToUseLargePagesCMS + * @key gc regression + * @bug 8024396 + * @comment Graal does not support CMS + * @requires vm.gc=="null" & !vm.graal.enabled + * @run main/othervm -Xms71M -Xmx91M -XX:+UseConcMarkSweepGC -XX:+UseLargePages TestAlignmentToUseLargePages + * @run main/othervm -Xms71M -Xmx91M -XX:+UseConcMarkSweepGC -XX:-UseLargePages TestAlignmentToUseLargePages + */ + public class TestAlignmentToUseLargePages { public static void main(String args[]) throws Exception { // nothing to do diff --git a/test/hotspot/jtreg/gc/arguments/TestCMSHeapSizeFlags.java b/test/hotspot/jtreg/gc/arguments/TestCMSHeapSizeFlags.java index 2e73a24ddc9..a92306419f4 100644 --- a/test/hotspot/jtreg/gc/arguments/TestCMSHeapSizeFlags.java +++ b/test/hotspot/jtreg/gc/arguments/TestCMSHeapSizeFlags.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 @@ -25,7 +25,7 @@ * @test TestCMSHeapSizeFlags * @key gc * @bug 8006088 - * @requires vm.gc.ConcMarkSweep + * @requires vm.gc.ConcMarkSweep & !vm.graal.enabled * @summary Tests argument processing for initial and maximum heap size for the CMS collector * @library /test/lib * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/gc/arguments/TestMaxNewSize.java b/test/hotspot/jtreg/gc/arguments/TestMaxNewSize.java index c78867f30a7..91eaa677917 100644 --- a/test/hotspot/jtreg/gc/arguments/TestMaxNewSize.java +++ b/test/hotspot/jtreg/gc/arguments/TestMaxNewSize.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 @@ -27,16 +27,28 @@ * @bug 7057939 * @summary Make sure that MaxNewSize always has a useful value after argument * processing. + * @requires vm.gc=="null" * @library /test/lib * @modules java.base/jdk.internal.misc * java.management * @run main TestMaxNewSize -XX:+UseSerialGC * @run main TestMaxNewSize -XX:+UseParallelGC - * @run main TestMaxNewSize -XX:+UseConcMarkSweepGC * @run main TestMaxNewSize -XX:+UseG1GC * @author thomas.schatzl@oracle.com, jesper.wilhelmsson@oracle.com */ +/* + * @test TestMaxNewSizeCMS + * @key gc + * @bug 7057939 + * @comment Graal does not support CMS + * @requires vm.gc=="null" & !vm.graal.enabled + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @run main TestMaxNewSize -XX:+UseConcMarkSweepGC + */ + import java.util.regex.Matcher; import java.util.regex.Pattern; diff --git a/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsErgo.java b/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsErgo.java index 401345d04bc..2c4fd806b1a 100644 --- a/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsErgo.java +++ b/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsErgo.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 @@ -26,6 +26,7 @@ * @key gc * @bug 8010722 * @summary Tests ergonomics for UseCompressedOops. + * @requires vm.gc=="null" * @library /test/lib * @modules java.base/jdk.internal.misc * java.management/sun.management @@ -35,10 +36,24 @@ * @run main/othervm TestUseCompressedOopsErgo -XX:+UseG1GC * @run main/othervm TestUseCompressedOopsErgo -XX:+UseParallelGC * @run main/othervm TestUseCompressedOopsErgo -XX:+UseParallelGC -XX:-UseParallelOldGC - * @run main/othervm TestUseCompressedOopsErgo -XX:+UseConcMarkSweepGC * @run main/othervm TestUseCompressedOopsErgo -XX:+UseSerialGC */ +/* + * @test TestUseCompressedOopsErgoCMS + * @key gc + * @bug 8010722 + * @comment Graal does not support CMS + * @requires vm.gc=="null" & !vm.graal.enabled + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management/sun.management + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm TestUseCompressedOopsErgo -XX:+UseConcMarkSweepGC + */ + public class TestUseCompressedOopsErgo { public static void main(String args[]) throws Exception { diff --git a/test/hotspot/jtreg/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java b/test/hotspot/jtreg/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java index bda9796a0dd..3e799e2d58f 100644 --- a/test/hotspot/jtreg/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java +++ b/test/hotspot/jtreg/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.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 @@ -25,6 +25,7 @@ * @test * @key gc * @bug 8049831 + * @requires !vm.graal.enabled * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/test/hotspot/jtreg/gc/class_unloading/TestClassUnloadingDisabled.java b/test/hotspot/jtreg/gc/class_unloading/TestClassUnloadingDisabled.java index bb2c8db999f..4c1c0a302bd 100644 --- a/test/hotspot/jtreg/gc/class_unloading/TestClassUnloadingDisabled.java +++ b/test/hotspot/jtreg/gc/class_unloading/TestClassUnloadingDisabled.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,22 @@ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:-ClassUnloading -XX:+UseParallelGC TestClassUnloadingDisabled * + */ + +/* + * @test + * @key gc + * @bug 8114823 + * @comment Graal does not support CMS + * @requires vm.gc=="null" & !vm.graal.enabled + * @requires vm.opt.ExplicitGCInvokesConcurrent != true + * @requires vm.opt.ClassUnloading != true + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:-ClassUnloading -XX:+UseConcMarkSweepGC TestClassUnloadingDisabled */ diff --git a/test/hotspot/jtreg/gc/cms/DisableResizePLAB.java b/test/hotspot/jtreg/gc/cms/DisableResizePLAB.java index a8d9861464e..c987ddacd62 100644 --- a/test/hotspot/jtreg/gc/cms/DisableResizePLAB.java +++ b/test/hotspot/jtreg/gc/cms/DisableResizePLAB.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 @@ -26,7 +26,7 @@ * @key gc * @bug 8060467 * @author filipp.zhinkin@oracle.com, john.coomes@oracle.com - * @requires vm.gc.ConcMarkSweep + * @requires vm.gc.ConcMarkSweep & !vm.graal.enabled * @summary Run CMS with PLAB resizing disabled and a small OldPLABSize * @run main/othervm -XX:+UseConcMarkSweepGC -XX:-ResizePLAB -XX:OldPLABSize=1k -Xmx256m -Xlog:gc=debug DisableResizePLAB */ diff --git a/test/hotspot/jtreg/gc/cms/GuardShrinkWarning.java b/test/hotspot/jtreg/gc/cms/GuardShrinkWarning.java index 29ae8969691..8488207ed00 100644 --- a/test/hotspot/jtreg/gc/cms/GuardShrinkWarning.java +++ b/test/hotspot/jtreg/gc/cms/GuardShrinkWarning.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 @@ -26,6 +26,7 @@ * @key gc regression * @summary Remove warning about CMS generation shrinking. * @bug 8012111 + * @requires !vm.graal.enabled * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/test/hotspot/jtreg/gc/cms/TestBubbleUpRef.java b/test/hotspot/jtreg/gc/cms/TestBubbleUpRef.java index 90a9aa5510b..96d0fbfe0ee 100644 --- a/test/hotspot/jtreg/gc/cms/TestBubbleUpRef.java +++ b/test/hotspot/jtreg/gc/cms/TestBubbleUpRef.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2016, 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 @@ -28,7 +28,7 @@ import java.util.ListIterator; /* * @test - * @requires vm.gc.ConcMarkSweep + * @requires vm.gc.ConcMarkSweep & !vm.graal.enabled * @key cte_test * @bug 4950157 * @summary Stress the behavior of ergonomics when the heap is nearly full and diff --git a/test/hotspot/jtreg/gc/cms/TestCMSScavengeBeforeRemark.java b/test/hotspot/jtreg/gc/cms/TestCMSScavengeBeforeRemark.java index f97eeb5a863..97e70ef6088 100644 --- a/test/hotspot/jtreg/gc/cms/TestCMSScavengeBeforeRemark.java +++ b/test/hotspot/jtreg/gc/cms/TestCMSScavengeBeforeRemark.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test TestCMSScavengeBeforeRemark * @key gc * @bug 8139868 - * @requires vm.gc.ConcMarkSweep + * @requires vm.gc.ConcMarkSweep & !vm.graal.enabled * @summary Run CMS with CMSScavengeBeforeRemark * @run main/othervm -XX:+UseConcMarkSweepGC -XX:+CMSScavengeBeforeRemark -XX:+ExplicitGCInvokesConcurrent -Xmx256m -Xlog:gc=debug TestCMSScavengeBeforeRemark */ diff --git a/test/hotspot/jtreg/gc/cms/TestMBeanCMS.java b/test/hotspot/jtreg/gc/cms/TestMBeanCMS.java index 633c78a06ba..646eb1f78da 100644 --- a/test/hotspot/jtreg/gc/cms/TestMBeanCMS.java +++ b/test/hotspot/jtreg/gc/cms/TestMBeanCMS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -24,7 +24,7 @@ /* * @test TestMBeanCMS.java * @bug 6581734 - * @requires vm.gc.ConcMarkSweep + * @requires vm.gc.ConcMarkSweep & !vm.graal.enabled * @summary CMS Old Gen's collection usage is zero after GC which is incorrect * @modules java.management * @run main/othervm -Xmx512m -verbose:gc -XX:+UseConcMarkSweepGC TestMBeanCMS diff --git a/test/hotspot/jtreg/gc/concurrent_phase_control/TestConcurrentPhaseControlCMS.java b/test/hotspot/jtreg/gc/concurrent_phase_control/TestConcurrentPhaseControlCMS.java index 3c3bab76048..e136c99175c 100644 --- a/test/hotspot/jtreg/gc/concurrent_phase_control/TestConcurrentPhaseControlCMS.java +++ b/test/hotspot/jtreg/gc/concurrent_phase_control/TestConcurrentPhaseControlCMS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test TestConcurrentPhaseControlCMS * @bug 8169517 - * @requires vm.gc.ConcMarkSweep + * @requires vm.gc.ConcMarkSweep & !vm.graal.enabled * @summary Verify CMS GC doesn't support WhiteBox concurrent phase control. * @key gc * @modules java.base diff --git a/test/hotspot/jtreg/gc/metaspace/TestMetaspaceCMSCancel.java b/test/hotspot/jtreg/gc/metaspace/TestMetaspaceCMSCancel.java index dfc949ef586..055186d020b 100644 --- a/test/hotspot/jtreg/gc/metaspace/TestMetaspaceCMSCancel.java +++ b/test/hotspot/jtreg/gc/metaspace/TestMetaspaceCMSCancel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ import sun.hotspot.WhiteBox; /* @test TestMetaspaceCMSCancel * @bug 8026752 * @summary Tests cancel of CMS concurrent cycle for Metaspace after a full GC + * @requires !vm.graal.enabled * @library /test/lib * @modules java.base/jdk.internal.misc * @build sun.hotspot.WhiteBox diff --git a/test/hotspot/jtreg/gc/startup_warnings/TestCMS.java b/test/hotspot/jtreg/gc/startup_warnings/TestCMS.java index a5b7cc9fc89..1f5deca3cc2 100644 --- a/test/hotspot/jtreg/gc/startup_warnings/TestCMS.java +++ b/test/hotspot/jtreg/gc/startup_warnings/TestCMS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2017, 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 @@ -22,14 +22,15 @@ */ /* -* @test TestCMS -* @key gc -* @bug 8006398 8155948 8179013 -* @summary Test that CMS prints a warning message -* @library /test/lib -* @modules java.base/jdk.internal.misc -* java.management -*/ + * @test TestCMS + * @key gc + * @bug 8006398 8155948 8179013 + * @summary Test that CMS prints a warning message + * @requires !vm.graal.enabled + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + */ import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; diff --git a/test/hotspot/jtreg/gc/stress/TestReclaimStringsLeaksMemory.java b/test/hotspot/jtreg/gc/stress/TestReclaimStringsLeaksMemory.java index d22447921c4..63e5ad71b00 100644 --- a/test/hotspot/jtreg/gc/stress/TestReclaimStringsLeaksMemory.java +++ b/test/hotspot/jtreg/gc/stress/TestReclaimStringsLeaksMemory.java @@ -25,8 +25,7 @@ * @test TestReclaimStringsLeaksMemory * @bug 8180048 * @summary Ensure that during a Full GC interned string memory is reclaimed completely. - * @requires vm.gc=="null" - * @requires !vm.debug + * @requires vm.gc=="null" & !vm.graal.enabled & !vm.debug * @key gc * @library /test/lib * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/gc/stress/gcbasher/TestGCBasherWithCMS.java b/test/hotspot/jtreg/gc/stress/gcbasher/TestGCBasherWithCMS.java index a8bcfe5e9be..660f7491869 100644 --- a/test/hotspot/jtreg/gc/stress/gcbasher/TestGCBasherWithCMS.java +++ b/test/hotspot/jtreg/gc/stress/gcbasher/TestGCBasherWithCMS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ import java.io.IOException; * @test TestGCBasherWithCMS * @key gc stress * @requires vm.gc.ConcMarkSweep - * @requires vm.flavor == "server" & !vm.emulatedClient + * @requires vm.flavor == "server" & !vm.emulatedClient & !vm.graal.enabled * @summary Stress the CMS GC by trying to make old objects more likely to be garbage than young objects. * @run main/othervm/timeout=200 -Xlog:gc*=info -Xmx256m -server -XX:+UseConcMarkSweepGC TestGCBasherWithCMS 120000 */ diff --git a/test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithCMS.java b/test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithCMS.java index 825a8d4bd00..7228846e626 100644 --- a/test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithCMS.java +++ b/test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithCMS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ /* * @test TestGCLockerWithCMS * @key gc - * @requires vm.gc.ConcMarkSweep + * @requires vm.gc.ConcMarkSweep & !vm.graal.enabled * @summary Stress CMS' GC locker by calling GetPrimitiveArrayCritical while concurrently filling up old gen. * @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xms1500m -Xmx1500m -XX:+UseConcMarkSweepGC TestGCLockerWithCMS */ diff --git a/test/hotspot/jtreg/gc/stress/gcold/TestGCOldWithCMS.java b/test/hotspot/jtreg/gc/stress/gcold/TestGCOldWithCMS.java index e0cd960d0c8..101fbd8e3e7 100644 --- a/test/hotspot/jtreg/gc/stress/gcold/TestGCOldWithCMS.java +++ b/test/hotspot/jtreg/gc/stress/gcold/TestGCOldWithCMS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ /* * @test TestGCOldWithCMS * @key gc - * @requires vm.gc.ConcMarkSweep + * @requires vm.gc.ConcMarkSweep & !vm.graal.enabled * @summary Stress the CMS GC by trying to make old objects more likely to be garbage than young objects. * @run main/othervm -Xmx384M -XX:+UseConcMarkSweepGC TestGCOldWithCMS 50 1 20 10 10000 */ diff --git a/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGCWithCMS.java b/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGCWithCMS.java index 33dec96e5a6..22d2bd80f2b 100644 --- a/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGCWithCMS.java +++ b/test/hotspot/jtreg/gc/stress/systemgc/TestSystemGCWithCMS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ * @test TestSystemGCWithCMS * @key gc stress * @bug 8190703 - * @requires vm.gc.ConcMarkSweep + * @requires vm.gc.ConcMarkSweep & !vm.graal.enabled * @summary Stress the CMS GC full GC by allocating objects of different lifetimes concurrently with System.gc(). * @run main/othervm/timeout=300 -Xlog:gc*=info -Xmx512m -XX:+UseConcMarkSweepGC TestSystemGCWithCMS 270 */ diff --git a/test/hotspot/jtreg/runtime/CompressedOops/UseCompressedOops.java b/test/hotspot/jtreg/runtime/CompressedOops/UseCompressedOops.java index 65874233c8d..659e2ca63fd 100644 --- a/test/hotspot/jtreg/runtime/CompressedOops/UseCompressedOops.java +++ b/test/hotspot/jtreg/runtime/CompressedOops/UseCompressedOops.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 @@ -28,7 +28,9 @@ * @library /test/lib * @modules java.base/jdk.internal.misc * java.management - * @run main UseCompressedOops + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. UseCompressedOops */ import java.util.ArrayList; import java.util.Collections; @@ -36,6 +38,8 @@ import jdk.test.lib.Platform; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; +import sun.hotspot.code.Compiler; + public class UseCompressedOops { public static void main(String[] args) throws Exception { @@ -51,7 +55,9 @@ public class UseCompressedOops { testCompressedOopsModes(args); // Test GCs. testCompressedOopsModes(args, "-XX:+UseG1GC"); - testCompressedOopsModes(args, "-XX:+UseConcMarkSweepGC"); + if (!Compiler.isGraalEnabled()) { // Graal does not support CMS + testCompressedOopsModes(args, "-XX:+UseConcMarkSweepGC"); + } testCompressedOopsModes(args, "-XX:+UseSerialGC"); testCompressedOopsModes(args, "-XX:+UseParallelGC"); testCompressedOopsModes(args, "-XX:+UseParallelOldGC"); diff --git a/test/hotspot/jtreg/runtime/MemberName/MemberNameLeak.java b/test/hotspot/jtreg/runtime/MemberName/MemberNameLeak.java index 9a3395a625d..357f27ff1ae 100644 --- a/test/hotspot/jtreg/runtime/MemberName/MemberNameLeak.java +++ b/test/hotspot/jtreg/runtime/MemberName/MemberNameLeak.java @@ -26,13 +26,17 @@ * @bug 8174749 * @summary MemberNameTable should reuse entries * @library /test/lib - * @run main MemberNameLeak + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. MemberNameLeak */ import java.lang.invoke.*; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; +import sun.hotspot.code.Compiler; + public class MemberNameLeak { static class Leak { public void callMe() { @@ -69,6 +73,8 @@ public class MemberNameLeak { test("-XX:+UseG1GC"); test("-XX:+UseParallelGC"); test("-XX:+UseSerialGC"); - test("-XX:+UseConcMarkSweepGC"); + if (!Compiler.isGraalEnabled()) { // Graal does not support CMS + test("-XX:+UseConcMarkSweepGC"); + } } } diff --git a/test/hotspot/jtreg/runtime/appcds/CommandLineFlagCombo.java b/test/hotspot/jtreg/runtime/appcds/CommandLineFlagCombo.java index ba3f803b95b..c40a196e35d 100644 --- a/test/hotspot/jtreg/runtime/appcds/CommandLineFlagCombo.java +++ b/test/hotspot/jtreg/runtime/appcds/CommandLineFlagCombo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, 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 @@ -32,14 +32,18 @@ * @modules java.base/jdk.internal.misc * java.management * jdk.jartool/sun.tools.jar + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @compile test-classes/Hello.java - * @run main/timeout=240 CommandLineFlagCombo + * @run main/othervm/timeout=240 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. CommandLineFlagCombo */ import jdk.test.lib.BuildHelper; import jdk.test.lib.Platform; import jdk.test.lib.process.OutputAnalyzer; +import sun.hotspot.code.Compiler; + public class CommandLineFlagCombo { // shared base address test table @@ -122,6 +126,11 @@ public class CommandLineFlagCombo { System.out.println("Test case not applicable on non-commercial builds"); return true; } + if (Compiler.isGraalEnabled() && testEntry.equals("-XX:+UseConcMarkSweepGC")) + { + System.out.println("Graal does not support CMS"); + return true; + } return false; } diff --git a/test/hotspot/jtreg/runtime/appcds/sharedStrings/IncompatibleOptions.java b/test/hotspot/jtreg/runtime/appcds/sharedStrings/IncompatibleOptions.java index 311937479bd..46840e0e1d3 100644 --- a/test/hotspot/jtreg/runtime/appcds/sharedStrings/IncompatibleOptions.java +++ b/test/hotspot/jtreg/runtime/appcds/sharedStrings/IncompatibleOptions.java @@ -32,13 +32,17 @@ * @modules java.base/jdk.internal.misc * @modules java.management * jdk.jartool/sun.tools.jar + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @build HelloString - * @run main IncompatibleOptions + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. IncompatibleOptions */ import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; +import sun.hotspot.code.Compiler; + public class IncompatibleOptions { static final String COOPS_DUMP_WARNING = "Cannot dump shared archive when UseCompressedOops or UseCompressedClassPointers is off"; @@ -62,7 +66,9 @@ public class IncompatibleOptions { // incompatible GCs testDump(2, "-XX:+UseParallelGC", "", GC_WARNING, false); testDump(3, "-XX:+UseSerialGC", "", GC_WARNING, false); - testDump(4, "-XX:+UseConcMarkSweepGC", "", GC_WARNING, false); + if (!Compiler.isGraalEnabled()) { // Graal does not support CMS + testDump(4, "-XX:+UseConcMarkSweepGC", "", GC_WARNING, false); + } // ======= archive with compressed oops, run w/o testDump(5, "-XX:+UseG1GC", "-XX:+UseCompressedOops", null, false); @@ -73,7 +79,9 @@ public class IncompatibleOptions { // Still run, to ensure no crash or exception testExec(6, "-XX:+UseParallelGC", "", "", false); testExec(7, "-XX:+UseSerialGC", "", "", false); - testExec(8, "-XX:+UseConcMarkSweepGC", "", "", false); + if (!Compiler.isGraalEnabled()) { // Graal does not support CMS + testExec(8, "-XX:+UseConcMarkSweepGC", "", "", false); + } // Test various oops encodings, by varying ObjectAlignmentInBytes and heap sizes testDump(9, "-XX:+UseG1GC", "-XX:ObjectAlignmentInBytes=8", null, false); diff --git a/test/hotspot/jtreg/serviceability/sa/TestUniverse.java b/test/hotspot/jtreg/serviceability/sa/TestUniverse.java index e820861a2b1..797c94d9cbf 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestUniverse.java +++ b/test/hotspot/jtreg/serviceability/sa/TestUniverse.java @@ -21,6 +21,8 @@ * questions. */ +import sun.hotspot.code.Compiler; + import java.util.ArrayList; import java.util.List; import java.io.IOException; @@ -37,7 +39,9 @@ import jdk.test.lib.process.OutputAnalyzer; * @bug 8190307 * @library /test/lib * @build jdk.test.lib.apps.* - * @run main/othervm TestUniverse + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. TestUniverse */ public class TestUniverse { @@ -132,7 +136,9 @@ public class TestUniverse { test("-XX:+UseG1GC"); test("-XX:+UseParallelGC"); test("-XX:+UseSerialGC"); - test("-XX:+UseConcMarkSweepGC"); + if (!Compiler.isGraalEnabled()) { // Graal does not support CMS + test("-XX:+UseConcMarkSweepGC"); + } } catch (Exception e) { throw new Error("Test failed with " + e); } diff --git a/test/jdk/ProblemList-graal.txt b/test/jdk/ProblemList-graal.txt index c31c7d43b6c..7e0c71319da 100644 --- a/test/jdk/ProblemList-graal.txt +++ b/test/jdk/ProblemList-graal.txt @@ -68,3 +68,9 @@ java/util/concurrent/tck/JSR166TestCase.java 8187486 java/lang/ref/OOMEInReferenceHandler.java 8196611 generic-all java/lang/Runtime/exec/LotsOfOutput.java 8196611 generic-all java/util/concurrent/ScheduledThreadPoolExecutor/BasicCancelTest.java 8196611 generic-all + +# Next JFR tests fail with Graal. Assuming 8193210. +jdk/jfr/event/compiler/TestCodeSweeper.java 8193210 generic-all +jdk/jfr/event/compiler/TestCompilerInlining.java 8193210 generic-all +jdk/jfr/event/compiler/TestCompilerPhase.java 8193210 generic-all + diff --git a/test/jdk/com/sun/management/HotSpotDiagnosticMXBean/CheckOrigin.java b/test/jdk/com/sun/management/HotSpotDiagnosticMXBean/CheckOrigin.java index f2b03d72360..9937d18ae08 100644 --- a/test/jdk/com/sun/management/HotSpotDiagnosticMXBean/CheckOrigin.java +++ b/test/jdk/com/sun/management/HotSpotDiagnosticMXBean/CheckOrigin.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2017, 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 @@ -25,6 +25,8 @@ * @test * @bug 8028994 * @author Staffan Larsen + * @comment Graal does not support CMS + * @requires !vm.graal.enabled * @library /lib/testlibrary * @modules jdk.attach/sun.tools.attach * jdk.management diff --git a/test/jdk/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java b/test/jdk/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java index 894d7a7855e..a081aacca0c 100644 --- a/test/jdk/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java +++ b/test/jdk/java/lang/management/MemoryMXBean/CollectionUsageThreshold.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -30,11 +30,13 @@ * * @author Mandy Chung * - * @library /lib/testlibrary/ + * @library /lib/testlibrary/ /test/lib * @modules jdk.management * @build jdk.testlibrary.* CollectionUsageThreshold MemoryUtil RunUtil * @requires vm.opt.ExplicitGCInvokesConcurrent == "false" | vm.opt.ExplicitGCInvokesConcurrent == "null" - * @run main/timeout=300 CollectionUsageThreshold + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm/timeout=300 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. CollectionUsageThreshold */ import java.util.*; @@ -46,6 +48,8 @@ import java.lang.management.*; import static java.lang.management.MemoryNotificationInfo.*;; import static java.lang.management.ManagementFactory.*; +import sun.hotspot.code.Compiler; + public class CollectionUsageThreshold { private static final MemoryMXBean mm = getMemoryMXBean(); private static final Map result = new HashMap<>(); @@ -72,7 +76,9 @@ public class CollectionUsageThreshold { RunUtil.runTestClearGcOpts(main, "-XX:+UseSerialGC"); RunUtil.runTestClearGcOpts(main, "-XX:+UseParallelGC"); RunUtil.runTestClearGcOpts(main, "-XX:+UseG1GC"); - RunUtil.runTestClearGcOpts(main, "-XX:+UseConcMarkSweepGC"); + if (!Compiler.isGraalEnabled()) { // Graal does not support CMS + RunUtil.runTestClearGcOpts(main, "-XX:+UseConcMarkSweepGC"); + } } static class PoolRecord { diff --git a/test/jdk/java/lang/management/MemoryMXBean/LowMemoryTest.java b/test/jdk/java/lang/management/MemoryMXBean/LowMemoryTest.java index da30cf34170..2348b51cc68 100644 --- a/test/jdk/java/lang/management/MemoryMXBean/LowMemoryTest.java +++ b/test/jdk/java/lang/management/MemoryMXBean/LowMemoryTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -32,10 +32,12 @@ * @requires vm.gc == "null" * @requires vm.opt.ExplicitGCInvokesConcurrent != "true" * @requires vm.opt.DisableExplicitGC != "true" - * @library /lib/testlibrary/ + * @library /lib/testlibrary/ /test/lib * * @build jdk.testlibrary.* LowMemoryTest MemoryUtil RunUtil - * @run main/timeout=600 LowMemoryTest + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm/timeout=600 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. LowMemoryTest */ import java.lang.management.*; @@ -47,6 +49,8 @@ import jdk.testlibrary.ProcessTools; import jdk.testlibrary.JDKToolFinder; import jdk.testlibrary.Utils; +import sun.hotspot.code.Compiler; + public class LowMemoryTest { private static final MemoryMXBean mm = ManagementFactory.getMemoryMXBean(); private static final List pools = ManagementFactory.getMemoryPoolMXBeans(); @@ -80,7 +84,9 @@ public class LowMemoryTest { traceTest(classMain + ", -XX:+UseSerialGC", nmFlag, lpFlag, "-XX:+UseSerialGC"); traceTest(classMain + ", -XX:+UseParallelGC", nmFlag, lpFlag, "-XX:+UseParallelGC"); traceTest(classMain + ", -XX:+UseG1GC", nmFlag, lpFlag, "-XX:+UseG1GC", g1Flag); - traceTest(classMain + ", -XX:+UseConcMarkSweepGC", nmFlag, lpFlag, "-XX:+UseConcMarkSweepGC"); + if (!Compiler.isGraalEnabled()) { // Graal does not support CMS + traceTest(classMain + ", -XX:+UseConcMarkSweepGC", nmFlag, lpFlag, "-XX:+UseConcMarkSweepGC"); + } } /* diff --git a/test/jdk/java/lang/management/MemoryMXBean/MemoryManagementConcMarkSweepGC.sh b/test/jdk/java/lang/management/MemoryMXBean/MemoryManagementConcMarkSweepGC.sh index 563ffe326f0..883783b3d74 100644 --- a/test/jdk/java/lang/management/MemoryMXBean/MemoryManagementConcMarkSweepGC.sh +++ b/test/jdk/java/lang/management/MemoryMXBean/MemoryManagementConcMarkSweepGC.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 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 @@ -27,7 +27,7 @@ # @summary Run MemoryManagement test with concurrent mark sweep GC # @author Mandy Chung # -# @requires vm.gc=="ConcMarkSweep" | vm.gc=="null" +# @requires (vm.gc=="ConcMarkSweep" | vm.gc=="null") & !vm.graal.enabled # # @run build MemoryManagement # @run shell/timeout=600 MemoryManagementConcMarkSweepGC.sh diff --git a/test/jdk/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java b/test/jdk/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java index 8e86042ac6d..9427c17b54b 100644 --- a/test/jdk/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java +++ b/test/jdk/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -34,17 +34,21 @@ * * @requires vm.opt.ExplicitGCInvokesConcurrent != "true" * @requires vm.opt.DisableExplicitGC != "true" - * @library /lib/testlibrary/ + * @library /lib/testlibrary/ /test/lib * @modules jdk.management * * @build jdk.testlibrary.* ResetPeakMemoryUsage MemoryUtil RunUtil - * @run main ResetPeakMemoryUsage + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. ResetPeakMemoryUsage */ import java.lang.management.*; import java.lang.ref.WeakReference; import java.util.*; +import sun.hotspot.code.Compiler; + public class ResetPeakMemoryUsage { private static MemoryMXBean mbean = ManagementFactory.getMemoryMXBean(); // make public so that it can't be optimized away easily @@ -59,7 +63,9 @@ public class ResetPeakMemoryUsage { final String main = "ResetPeakMemoryUsage$TestMain"; final String ms = "-Xms256m"; final String mn = "-Xmn8m"; - RunUtil.runTestClearGcOpts(main, ms, mn, "-XX:+UseConcMarkSweepGC"); + if (!Compiler.isGraalEnabled()) { // Graal does not support CMS + RunUtil.runTestClearGcOpts(main, ms, mn, "-XX:+UseConcMarkSweepGC"); + } RunUtil.runTestClearGcOpts(main, ms, mn, "-XX:+UseParallelGC"); RunUtil.runTestClearGcOpts(main, ms, mn, "-XX:+UseG1GC", "-XX:G1HeapRegionSize=1m"); RunUtil.runTestClearGcOpts(main, ms, mn, "-XX:+UseSerialGC", diff --git a/test/jdk/jdk/jfr/event/gc/collection/TestGCCauseWithCMSConcurrent.java b/test/jdk/jdk/jfr/event/gc/collection/TestGCCauseWithCMSConcurrent.java index 5f7caa924ea..ab939ee579d 100644 --- a/test/jdk/jdk/jfr/event/gc/collection/TestGCCauseWithCMSConcurrent.java +++ b/test/jdk/jdk/jfr/event/gc/collection/TestGCCauseWithCMSConcurrent.java @@ -29,7 +29,7 @@ import jdk.test.lib.jfr.GCHelper; /* * @test * @key jfr - * @requires vm.gc == "ConcMarkSweep" | vm.gc == null + * @requires (vm.gc == "ConcMarkSweep" | vm.gc == null) & !vm.graal.enabled * @requires vm.opt.ExplicitGCInvokesConcurrent != false * @library /test/lib /test/jdk * @run driver jdk.jfr.event.gc.collection.TestGCCauseWithCMSConcurrent diff --git a/test/jdk/jdk/jfr/event/gc/collection/TestGCCauseWithCMSMarkSweep.java b/test/jdk/jdk/jfr/event/gc/collection/TestGCCauseWithCMSMarkSweep.java index 9d423f3e432..66deb271706 100644 --- a/test/jdk/jdk/jfr/event/gc/collection/TestGCCauseWithCMSMarkSweep.java +++ b/test/jdk/jdk/jfr/event/gc/collection/TestGCCauseWithCMSMarkSweep.java @@ -30,7 +30,7 @@ import jdk.test.lib.jfr.GCHelper; * @test * @key jfr * - * @requires vm.gc == "ConcMarkSweep" | vm.gc == null + * @requires (vm.gc == "ConcMarkSweep" | vm.gc == null) & !vm.graal.enabled * @requires vm.opt.ExplicitGCInvokesConcurrent != true * @library /test/lib /test/jdk * @run driver jdk.jfr.event.gc.collection.TestGCCauseWithCMSMarkSweep diff --git a/test/jdk/jdk/jfr/event/gc/collection/TestGCEventMixedWithCMSConcurrent.java b/test/jdk/jdk/jfr/event/gc/collection/TestGCEventMixedWithCMSConcurrent.java index 6d6ef361440..7ff54ffc763 100644 --- a/test/jdk/jdk/jfr/event/gc/collection/TestGCEventMixedWithCMSConcurrent.java +++ b/test/jdk/jdk/jfr/event/gc/collection/TestGCEventMixedWithCMSConcurrent.java @@ -29,7 +29,7 @@ package jdk.jfr.event.gc.collection; * @test * @key jfr * - * @requires (vm.gc == "ConcMarkSweep" | vm.gc == null) + * @requires (vm.gc == "ConcMarkSweep" | vm.gc == null) & !vm.graal.enabled * & vm.opt.ExplicitGCInvokesConcurrent != false * @library /test/lib /test/jdk * diff --git a/test/jdk/jdk/jfr/event/gc/collection/TestGCEventMixedWithCMSMarkSweep.java b/test/jdk/jdk/jfr/event/gc/collection/TestGCEventMixedWithCMSMarkSweep.java index 0c7d250ce37..875f70606b4 100644 --- a/test/jdk/jdk/jfr/event/gc/collection/TestGCEventMixedWithCMSMarkSweep.java +++ b/test/jdk/jdk/jfr/event/gc/collection/TestGCEventMixedWithCMSMarkSweep.java @@ -29,7 +29,7 @@ package jdk.jfr.event.gc.collection; * @test * @key jfr * - * @requires (vm.gc == "ConcMarkSweep" | vm.gc == null) + * @requires (vm.gc == "ConcMarkSweep" | vm.gc == null) & !vm.graal.enabled * & vm.opt.ExplicitGCInvokesConcurrent != true * @library /test/lib /test/jdk * diff --git a/test/jdk/jdk/jfr/event/gc/collection/TestGCEventMixedWithParNew.java b/test/jdk/jdk/jfr/event/gc/collection/TestGCEventMixedWithParNew.java index 6290e7105fe..ba2603e195c 100644 --- a/test/jdk/jdk/jfr/event/gc/collection/TestGCEventMixedWithParNew.java +++ b/test/jdk/jdk/jfr/event/gc/collection/TestGCEventMixedWithParNew.java @@ -29,7 +29,7 @@ package jdk.jfr.event.gc.collection; * @test * @key jfr * - * @requires vm.gc == "ConcMarkSweep" | vm.gc == null + * @requires (vm.gc == "ConcMarkSweep" | vm.gc == null) & !vm.graal.enabled * @library /test/lib /test/jdk * @run main/othervm -Xmx32m -Xmn8m -XX:+UnlockExperimentalVMOptions -XX:-UseFastUnorderedTimeStamps -XX:+UseConcMarkSweepGC jdk.jfr.event.gc.collection.TestGCEventMixedWithParNew * good debug flags: -Xlog:gc*=debug diff --git a/test/jdk/jdk/jfr/event/gc/collection/TestYoungGarbageCollectionEventWithParNew.java b/test/jdk/jdk/jfr/event/gc/collection/TestYoungGarbageCollectionEventWithParNew.java index 91822c8b4d7..9e6b21a262a 100644 --- a/test/jdk/jdk/jfr/event/gc/collection/TestYoungGarbageCollectionEventWithParNew.java +++ b/test/jdk/jdk/jfr/event/gc/collection/TestYoungGarbageCollectionEventWithParNew.java @@ -28,7 +28,7 @@ package jdk.jfr.event.gc.collection; /* * @test * @key jfr - * @requires vm.gc == "ConcMarkSweep" | vm.gc == null + * @requires (vm.gc == "ConcMarkSweep" | vm.gc == null) & !vm.graal.enabled * @library /test/lib /test/jdk * @run main/othervm -Xmx50m -Xmn2m -XX:+UseConcMarkSweepGC -XX:+UnlockExperimentalVMOptions -XX:-UseFastUnorderedTimeStamps -Xlog:gc+heap=trace,gc*=debug jdk.jfr.event.gc.collection.TestYoungGarbageCollectionEventWithParNew */ diff --git a/test/jdk/jdk/jfr/event/gc/detailed/TestCMSConcurrentModeFailureEvent.java b/test/jdk/jdk/jfr/event/gc/detailed/TestCMSConcurrentModeFailureEvent.java index 2ebb89545f4..9bcf29a7573 100644 --- a/test/jdk/jdk/jfr/event/gc/detailed/TestCMSConcurrentModeFailureEvent.java +++ b/test/jdk/jdk/jfr/event/gc/detailed/TestCMSConcurrentModeFailureEvent.java @@ -42,7 +42,7 @@ import jdk.test.lib.jfr.EventNames; * @test * @key jfr * - * @requires vm.gc == "ConcMarkSweep" | vm.gc == null + * @requires (vm.gc == "ConcMarkSweep" | vm.gc == null) & !vm.graal.enabled * @library /test/lib /test/jdk * * @run main jdk.jfr.event.gc.detailed.TestCMSConcurrentModeFailureEvent diff --git a/test/jdk/jdk/jfr/event/gc/detailed/TestPromotionFailedEventWithParNew.java b/test/jdk/jdk/jfr/event/gc/detailed/TestPromotionFailedEventWithParNew.java index 54126020f0e..f6351485499 100644 --- a/test/jdk/jdk/jfr/event/gc/detailed/TestPromotionFailedEventWithParNew.java +++ b/test/jdk/jdk/jfr/event/gc/detailed/TestPromotionFailedEventWithParNew.java @@ -27,7 +27,7 @@ package jdk.jfr.event.gc.detailed; /* * @test * @key jfr - * @requires vm.gc == "ConcMarkSweep" | vm.gc == null + * @requires (vm.gc == "ConcMarkSweep" | vm.gc == null) & !vm.graal.enabled * @library /test/lib /test/jdk * @run main/othervm jdk.jfr.event.gc.detailed.TestPromotionFailedEventWithParNew */ diff --git a/test/jdk/jdk/jfr/event/gc/detailed/TestStressAllocationGCEventsWithCMS.java b/test/jdk/jdk/jfr/event/gc/detailed/TestStressAllocationGCEventsWithCMS.java index ac93d0b8ff9..bbd2ee39fd5 100644 --- a/test/jdk/jdk/jfr/event/gc/detailed/TestStressAllocationGCEventsWithCMS.java +++ b/test/jdk/jdk/jfr/event/gc/detailed/TestStressAllocationGCEventsWithCMS.java @@ -26,7 +26,7 @@ package jdk.jfr.event.gc.detailed; /* * @test - * @requires vm.gc == "null" | vm.gc == "ConcMarkSweep" + * @requires (vm.gc == "null" | vm.gc == "ConcMarkSweep") & !vm.graal.enabled * @library /test/lib /test/jdk * @run main/othervm -XX:+UseConcMarkSweepGC -Xmx64m jdk.jfr.event.gc.detailed.TestStressAllocationGCEventsWithCMS */ diff --git a/test/jdk/jdk/jfr/event/gc/detailed/TestStressAllocationGCEventsWithParNew.java b/test/jdk/jdk/jfr/event/gc/detailed/TestStressAllocationGCEventsWithParNew.java index 1338dd98bd7..70e8684592b 100644 --- a/test/jdk/jdk/jfr/event/gc/detailed/TestStressAllocationGCEventsWithParNew.java +++ b/test/jdk/jdk/jfr/event/gc/detailed/TestStressAllocationGCEventsWithParNew.java @@ -26,7 +26,7 @@ package jdk.jfr.event.gc.detailed; /* * @test - * @requires vm.gc == "null" + * @requires vm.gc == "null" & !vm.graal.enabled * @library /test/lib /test/jdk * @run main/othervm -XX:+UseConcMarkSweepGC -Xmx64m jdk.jfr.event.gc.detailed.TestStressAllocationGCEventsWithParNew */ diff --git a/test/jdk/jdk/jfr/event/gc/detailed/TestStressBigAllocationGCEventsWithCMS.java b/test/jdk/jdk/jfr/event/gc/detailed/TestStressBigAllocationGCEventsWithCMS.java index abd62373dee..c2271dbfc49 100644 --- a/test/jdk/jdk/jfr/event/gc/detailed/TestStressBigAllocationGCEventsWithCMS.java +++ b/test/jdk/jdk/jfr/event/gc/detailed/TestStressBigAllocationGCEventsWithCMS.java @@ -26,7 +26,7 @@ package jdk.jfr.event.gc.detailed; /* * @test - * @requires vm.gc == "null" | vm.gc == "ConcMarkSweep" + * @requires (vm.gc == "null" | vm.gc == "ConcMarkSweep") & !vm.graal.enabled * @library /test/lib /test/jdk * @run main/othervm -XX:+UseConcMarkSweepGC -Xmx256m jdk.jfr.event.gc.detailed.TestStressBigAllocationGCEventsWithCMS 1048576 */ diff --git a/test/jdk/jdk/jfr/event/gc/detailed/TestStressBigAllocationGCEventsWithParNew.java b/test/jdk/jdk/jfr/event/gc/detailed/TestStressBigAllocationGCEventsWithParNew.java index cee8139cd29..0a0474c6a1b 100644 --- a/test/jdk/jdk/jfr/event/gc/detailed/TestStressBigAllocationGCEventsWithParNew.java +++ b/test/jdk/jdk/jfr/event/gc/detailed/TestStressBigAllocationGCEventsWithParNew.java @@ -26,7 +26,7 @@ package jdk.jfr.event.gc.detailed; /* * @test - * @requires vm.gc == "null" + * @requires vm.gc == "null" & !vm.graal.enabled * @library /test/lib /test/jdk * @run main/othervm -XX:+UseConcMarkSweepGC -Xmx256m jdk.jfr.event.gc.detailed.TestStressBigAllocationGCEventsWithParNew 1048576 */ diff --git a/test/jdk/jdk/jfr/event/gc/heapsummary/TestHeapSummaryEventConcurrentCMS.java b/test/jdk/jdk/jfr/event/gc/heapsummary/TestHeapSummaryEventConcurrentCMS.java index af664387066..cfa10084449 100644 --- a/test/jdk/jdk/jfr/event/gc/heapsummary/TestHeapSummaryEventConcurrentCMS.java +++ b/test/jdk/jdk/jfr/event/gc/heapsummary/TestHeapSummaryEventConcurrentCMS.java @@ -38,7 +38,7 @@ import jdk.test.lib.jfr.GCHelper; /* * @test * @key jfr - * @requires (vm.gc == "ConcMarkSweep" | vm.gc == null) + * @requires (vm.gc == "ConcMarkSweep" | vm.gc == null) & !vm.graal.enabled * & vm.opt.ExplicitGCInvokesConcurrent != false * @library /test/lib /test/jdk * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:-UseFastUnorderedTimeStamps -XX:+UseConcMarkSweepGC -XX:+ExplicitGCInvokesConcurrent jdk.jfr.event.gc.heapsummary.TestHeapSummaryEventConcurrentCMS diff --git a/test/jdk/jdk/jfr/event/gc/heapsummary/TestHeapSummaryEventParNewCMS.java b/test/jdk/jdk/jfr/event/gc/heapsummary/TestHeapSummaryEventParNewCMS.java index 53838b39aea..ee6b65dc003 100644 --- a/test/jdk/jdk/jfr/event/gc/heapsummary/TestHeapSummaryEventParNewCMS.java +++ b/test/jdk/jdk/jfr/event/gc/heapsummary/TestHeapSummaryEventParNewCMS.java @@ -29,7 +29,7 @@ import jdk.test.lib.jfr.GCHelper; /* * @test * @key jfr - * @requires (vm.gc == "ConcMarkSweep" | vm.gc == null) + * @requires (vm.gc == "ConcMarkSweep" | vm.gc == null) & !vm.graal.enabled * & vm.opt.ExplicitGCInvokesConcurrent != true * @library /test/lib /test/jdk * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:-UseFastUnorderedTimeStamps -XX:+UseConcMarkSweepGC jdk.jfr.event.gc.heapsummary.TestHeapSummaryEventParNewCMS diff --git a/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithCMSConcurrent.java b/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithCMSConcurrent.java index 3b0822dcb81..1b1fe2fa57a 100644 --- a/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithCMSConcurrent.java +++ b/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithCMSConcurrent.java @@ -29,7 +29,7 @@ import jdk.test.lib.jfr.GCHelper; /* * @test * @key jfr - * @requires (vm.gc == "ConcMarkSweep" | vm.gc == null) + * @requires (vm.gc == "ConcMarkSweep" | vm.gc == null) & !vm.graal.enabled * & vm.opt.ExplicitGCInvokesConcurrent != false * @library /test/lib /test/jdk * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:-UseFastUnorderedTimeStamps -XX:+UseConcMarkSweepGC -XX:+ExplicitGCInvokesConcurrent -XX:MarkSweepDeadRatio=0 -XX:-UseCompressedOops -XX:+IgnoreUnrecognizedVMOptions jdk.jfr.event.gc.objectcount.TestObjectCountAfterGCEventWithCMSConcurrent diff --git a/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithCMSMarkSweep.java b/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithCMSMarkSweep.java index 62b88cc926d..99302312f01 100644 --- a/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithCMSMarkSweep.java +++ b/test/jdk/jdk/jfr/event/gc/objectcount/TestObjectCountAfterGCEventWithCMSMarkSweep.java @@ -29,7 +29,7 @@ import jdk.test.lib.jfr.GCHelper; /* * @test * @key jfr - * @requires (vm.gc == "ConcMarkSweep" | vm.gc == null) + * @requires (vm.gc == "ConcMarkSweep" | vm.gc == null) & !vm.graal.enabled * & vm.opt.ExplicitGCInvokesConcurrent != true * @library /test/lib /test/jdk * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:-UseFastUnorderedTimeStamps -XX:+UseConcMarkSweepGC -XX:MarkSweepDeadRatio=0 -XX:-UseCompressedOops -XX:+IgnoreUnrecognizedVMOptions jdk.jfr.event.gc.objectcount.TestObjectCountAfterGCEventWithCMSMarkSweep diff --git a/test/jdk/jdk/jfr/event/gc/refstat/TestRefStatEventWithCMSConcurrent.java b/test/jdk/jdk/jfr/event/gc/refstat/TestRefStatEventWithCMSConcurrent.java index 96b56e5c05a..a3a31e0869a 100644 --- a/test/jdk/jdk/jfr/event/gc/refstat/TestRefStatEventWithCMSConcurrent.java +++ b/test/jdk/jdk/jfr/event/gc/refstat/TestRefStatEventWithCMSConcurrent.java @@ -29,7 +29,7 @@ import jdk.test.lib.jfr.GCHelper; /* * @test * @key jfr - * @requires (vm.gc == "ConcMarkSweep" | vm.gc == null) + * @requires (vm.gc == "ConcMarkSweep" | vm.gc == null) & !vm.graal.enabled * & vm.opt.ExplicitGCInvokesConcurrent != false * @library /test/lib /test/jdk * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:-UseFastUnorderedTimeStamps -Xlog:gc+heap=trace,gc*=debug -XX:+UseConcMarkSweepGC -XX:+ExplicitGCInvokesConcurrent jdk.jfr.event.gc.refstat.TestRefStatEventWithCMSConcurrent diff --git a/test/jdk/jdk/jfr/event/gc/refstat/TestRefStatEventWithCMSMarkSweep.java b/test/jdk/jdk/jfr/event/gc/refstat/TestRefStatEventWithCMSMarkSweep.java index 090e93d5173..4095421751b 100644 --- a/test/jdk/jdk/jfr/event/gc/refstat/TestRefStatEventWithCMSMarkSweep.java +++ b/test/jdk/jdk/jfr/event/gc/refstat/TestRefStatEventWithCMSMarkSweep.java @@ -29,7 +29,7 @@ import jdk.test.lib.jfr.GCHelper; /* * @test * @key jfr - * @requires (vm.gc == "ConcMarkSweep" | vm.gc == null) + * @requires (vm.gc == "ConcMarkSweep" | vm.gc == null) & !vm.graal.enabled * & vm.opt.ExplicitGCInvokesConcurrent != true * @library /test/lib /test/jdk * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:-UseFastUnorderedTimeStamps -Xlog:gc+heap=trace,gc*=debug -XX:+UseConcMarkSweepGC jdk.jfr.event.gc.refstat.TestRefStatEventWithCMSMarkSweep diff --git a/test/jdk/jdk/jfr/event/gc/stacktrace/TestConcMarkSweepAllocationPendingStackTrace.java b/test/jdk/jdk/jfr/event/gc/stacktrace/TestConcMarkSweepAllocationPendingStackTrace.java index 9e80f08f76b..2344dc97414 100644 --- a/test/jdk/jdk/jfr/event/gc/stacktrace/TestConcMarkSweepAllocationPendingStackTrace.java +++ b/test/jdk/jdk/jfr/event/gc/stacktrace/TestConcMarkSweepAllocationPendingStackTrace.java @@ -28,7 +28,7 @@ package jdk.jfr.event.gc.stacktrace; * @test * @key jfr * - * @requires vm.gc == "null" | vm.gc == "ConcMarkSweep" + * @requires (vm.gc == "null" | vm.gc == "ConcMarkSweep") & !vm.graal.enabled * @library /test/lib /test/jdk * @run main/othervm -XX:MaxNewSize=10M -Xmx64M -XX:+UseConcMarkSweepGC -Xlog:gc* jdk.jfr.event.gc.stacktrace.TestConcMarkSweepAllocationPendingStackTrace */ diff --git a/test/jdk/jdk/jfr/event/gc/stacktrace/TestMetaspaceConcMarkSweepGCAllocationPendingStackTrace.java b/test/jdk/jdk/jfr/event/gc/stacktrace/TestMetaspaceConcMarkSweepGCAllocationPendingStackTrace.java index ded1a09f7c5..8435d3d8168 100644 --- a/test/jdk/jdk/jfr/event/gc/stacktrace/TestMetaspaceConcMarkSweepGCAllocationPendingStackTrace.java +++ b/test/jdk/jdk/jfr/event/gc/stacktrace/TestMetaspaceConcMarkSweepGCAllocationPendingStackTrace.java @@ -28,7 +28,7 @@ package jdk.jfr.event.gc.stacktrace; * @test * @key jfr * - * @requires vm.gc == "null" | vm.gc == "ConcMarkSweep" + * @requires (vm.gc == "null" | vm.gc == "ConcMarkSweep") & !vm.graal.enabled * @requires !(vm.compMode == "Xcomp" & os.arch == "aarch64") * @library /test/lib /test/jdk * @run main/othervm -XX:+UseConcMarkSweepGC -XX:MaxMetaspaceSize=64M -Xlog:gc* jdk.jfr.event.gc.stacktrace.TestMetaspaceConcMarkSweepGCAllocationPendingStackTrace diff --git a/test/jdk/jdk/jfr/event/gc/stacktrace/TestParNewAllocationPendingStackTrace.java b/test/jdk/jdk/jfr/event/gc/stacktrace/TestParNewAllocationPendingStackTrace.java index edb90c76af5..889b8574529 100644 --- a/test/jdk/jdk/jfr/event/gc/stacktrace/TestParNewAllocationPendingStackTrace.java +++ b/test/jdk/jdk/jfr/event/gc/stacktrace/TestParNewAllocationPendingStackTrace.java @@ -28,7 +28,7 @@ package jdk.jfr.event.gc.stacktrace; * @test * @key jfr * - * @requires vm.gc == "null" | vm.gc == "ConcMarkSweep" + * @requires (vm.gc == "null" | vm.gc == "ConcMarkSweep") & !vm.graal.enabled * @library /test/lib /test/jdk * @run main/othervm -XX:+UseConcMarkSweepGC -Xlog:gc* -XX:+FlightRecorder jdk.jfr.event.gc.stacktrace.TestParNewAllocationPendingStackTrace */ diff --git a/test/jdk/jdk/jfr/event/oldobject/TestCMS.java b/test/jdk/jdk/jfr/event/oldobject/TestCMS.java index 45a4c29925a..69f63ba3bb2 100644 --- a/test/jdk/jdk/jfr/event/oldobject/TestCMS.java +++ b/test/jdk/jdk/jfr/event/oldobject/TestCMS.java @@ -37,7 +37,7 @@ import jdk.test.lib.jfr.Events; /* * @test * @key jfr - * @requires vm.gc == "null" + * @requires vm.gc == "null" & !vm.graal.enabled * @summary Test leak profiler with CMS GC * @library /test/lib /test/jdk * @modules jdk.jfr/jdk.jfr.internal.test diff --git a/test/jdk/jdk/jfr/event/runtime/TestModuleEvents.java b/test/jdk/jdk/jfr/event/runtime/TestModuleEvents.java index 5366a8b22d6..baee30b3b14 100644 --- a/test/jdk/jdk/jfr/event/runtime/TestModuleEvents.java +++ b/test/jdk/jdk/jfr/event/runtime/TestModuleEvents.java @@ -40,6 +40,7 @@ import jdk.test.lib.jfr.Events; * @test * @summary Tests the JFR events related to modules * @key jfr + * @requires !vm.graal.enabled * @library /test/lib * @run main/othervm --limit-modules java.base,jdk.jfr jdk.jfr.event.runtime.TestModuleEvents */ diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java index 853e25ce350..53337110427 100644 --- a/test/jtreg-ext/requires/VMProps.java +++ b/test/jtreg-ext/requires/VMProps.java @@ -36,6 +36,7 @@ import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; +import sun.hotspot.code.Compiler; import sun.hotspot.cpuinfo.CPUInfo; import sun.hotspot.gc.GC; import sun.hotspot.WhiteBox; @@ -344,33 +345,7 @@ public class VMProps implements Callable> { * @return true if Graal is used as JIT compiler. */ protected String isGraalEnabled() { - // Graal is enabled if following conditions are true: - // - we are not in Interpreter mode - // - UseJVMCICompiler flag is true - // - jvmci.Compiler variable is equal to 'graal' - // - TieredCompilation is not used or TieredStopAtLevel is greater than 3 - - Boolean useCompiler = WB.getBooleanVMFlag("UseCompiler"); - if (useCompiler == null || !useCompiler) - return "false"; - - Boolean useJvmciComp = WB.getBooleanVMFlag("UseJVMCICompiler"); - if (useJvmciComp == null || !useJvmciComp) - return "false"; - - // This check might be redundant but let's keep it for now. - String jvmciCompiler = System.getProperty("jvmci.Compiler"); - if (jvmciCompiler == null || !jvmciCompiler.equals("graal")) { - return "false"; - } - - Boolean tieredCompilation = WB.getBooleanVMFlag("TieredCompilation"); - Long compLevel = WB.getIntxVMFlag("TieredStopAtLevel"); - // if TieredCompilation is enabled and compilation level is <= 3 then no Graal is used - if (tieredCompilation != null && tieredCompilation && compLevel != null && compLevel <= 3) - return "false"; - - return "true"; + return Compiler.isGraalEnabled() ? "true" : "false"; } diff --git a/test/lib/sun/hotspot/code/Compiler.java b/test/lib/sun/hotspot/code/Compiler.java new file mode 100644 index 00000000000..ae359531faf --- /dev/null +++ b/test/lib/sun/hotspot/code/Compiler.java @@ -0,0 +1,136 @@ +/* + * 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. + */ + +package sun.hotspot.code; + +import sun.hotspot.WhiteBox; + +/** + * API to obtain information about enabled JIT compilers + * retrieved from the VM with the WhiteBox API. + */ +public class Compiler { + + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + + /** + * Check if Graal is used as JIT compiler. + * + * Graal is enabled if following conditions are true: + * - we are not in Interpreter mode + * - UseJVMCICompiler flag is true + * - jvmci.Compiler variable is equal to 'graal' + * - TieredCompilation is not used or TieredStopAtLevel is greater than 3 + * No need to check client mode because it set UseJVMCICompiler to false. + * + * @return true if Graal is used as JIT compiler. + */ + public static boolean isGraalEnabled() { + Boolean useCompiler = WB.getBooleanVMFlag("UseCompiler"); + if (useCompiler == null || !useCompiler) { + return false; + } + Boolean useJvmciComp = WB.getBooleanVMFlag("UseJVMCICompiler"); + if (useJvmciComp == null || !useJvmciComp) { + return false; + } + // This check might be redundant but let's keep it for now. + String jvmciCompiler = System.getProperty("jvmci.Compiler"); + if (jvmciCompiler == null || !jvmciCompiler.equals("graal")) { + return false; + } + + Boolean tieredCompilation = WB.getBooleanVMFlag("TieredCompilation"); + Long compLevel = WB.getIntxVMFlag("TieredStopAtLevel"); + // if TieredCompilation is enabled and compilation level is <= 3 then no Graal is used + if (tieredCompilation != null && tieredCompilation && + compLevel != null && compLevel <= 3) { + return false; + } + return true; + } + + /** + * Check if C2 is used as JIT compiler. + * + * C2 is enabled if following conditions are true: + * - we are not in Interpreter mode + * - we are in Server compilation mode + * - TieredCompilation is not used or TieredStopAtLevel is greater than 3 + * - Graal is not used + * + * @return true if C2 is used as JIT compiler. + */ + public static boolean isC2Enabled() { + Boolean useCompiler = WB.getBooleanVMFlag("UseCompiler"); + if (useCompiler == null || !useCompiler) { + return false; + } + Boolean serverMode = WB.getBooleanVMFlag("ProfileInterpreter"); + if (serverMode == null || !serverMode) { + return false; + } + + Boolean tieredCompilation = WB.getBooleanVMFlag("TieredCompilation"); + Long compLevel = WB.getIntxVMFlag("TieredStopAtLevel"); + // if TieredCompilation is enabled and compilation level is <= 3 then no Graal is used + if (tieredCompilation != null && tieredCompilation && + compLevel != null && compLevel <= 3) { + return false; + } + + if (isGraalEnabled()) { + return false; + } + + return true; + } + + /* + * Check if C1 is used as JIT compiler. + * + * C1 is enabled if following conditions are true: + * - we are not in Interpreter mode + * - we are not in Server compilation mode + * - TieredCompilation is used in Server mode + * + * @return true if C1 is used as JIT compiler. + */ + public static boolean isC1Enabled() { + Boolean useCompiler = WB.getBooleanVMFlag("UseCompiler"); + if (useCompiler == null || !useCompiler) { + return false; + } + Boolean serverMode = WB.getBooleanVMFlag("ProfileInterpreter"); + if (serverMode == null || !serverMode) { + return true; // Client mode + } + + Boolean tieredCompilation = WB.getBooleanVMFlag("TieredCompilation"); + // C1 is not used in server mode if TieredCompilation is off. + if (tieredCompilation != null && !tieredCompilation) { + return false; + } + return true; + } +} From 660dbcc16f2ad24abab9ad88911cf1d4af74407e Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Thu, 7 Jun 2018 19:01:18 -0700 Subject: [PATCH 25/46] 8203329: JDWP/JDI VM information string is incorrect Make sure the native java.vm.info property also gets updated when the java version is. Reviewed-by: sspitsyn, dholmes --- src/hotspot/share/runtime/arguments.cpp | 12 ++++ src/hotspot/share/runtime/arguments.hpp | 1 + src/hotspot/share/runtime/thread.cpp | 10 +++- .../JvmtiGetSystemPropertyTest.java | 46 +++++++++++++++ .../libJvmtiGetSystemPropertyTest.c | 57 +++++++++++++++++++ 5 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 test/hotspot/jtreg/serviceability/jvmti/GetSystemProperty/JvmtiGetSystemPropertyTest.java create mode 100644 test/hotspot/jtreg/serviceability/jvmti/GetSystemProperty/libJvmtiGetSystemPropertyTest.c diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index c223f6e02fe..a01e05e66fa 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -4447,6 +4447,18 @@ void Arguments::PropertyList_unique_add(SystemProperty** plist, const char* k, c PropertyList_add(plist, k, v, writeable == WriteableProperty, internal == InternalProperty); } +// Update existing property with new value. +void Arguments::PropertyList_update_value(SystemProperty* plist, const char* k, const char* v) { + SystemProperty* prop; + for (prop = plist; prop != NULL; prop = prop->next()) { + if (strcmp(k, prop->key()) == 0) { + prop->set_value(v); + return; + } + } + assert(false, "invalid property"); +} + // Copies src into buf, replacing "%%" with "%" and "%p" with pid // Returns true if all of the source pointed by src has been copied over to // the destination buffer pointed by buf. Otherwise, returns false. diff --git a/src/hotspot/share/runtime/arguments.hpp b/src/hotspot/share/runtime/arguments.hpp index edf88193673..42b9933130e 100644 --- a/src/hotspot/share/runtime/arguments.hpp +++ b/src/hotspot/share/runtime/arguments.hpp @@ -651,6 +651,7 @@ class Arguments : AllStatic { static void PropertyList_unique_add(SystemProperty** plist, const char* k, const char* v, PropertyAppendable append, PropertyWriteable writeable, PropertyInternal internal); + static void PropertyList_update_value(SystemProperty* plist, const char* k, const char* v); static const char* PropertyList_get_value(SystemProperty* plist, const char* key); static const char* PropertyList_get_readable_value(SystemProperty* plist, const char* key); static int PropertyList_count(SystemProperty* pl); diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp index 9c25a047e59..7cfdaad2c01 100644 --- a/src/hotspot/share/runtime/thread.cpp +++ b/src/hotspot/share/runtime/thread.cpp @@ -1132,6 +1132,9 @@ static void reset_vm_info_property(TRAPS) { ResourceMark rm(THREAD); const char *vm_info = VM_Version::vm_info_string(); + // update the native system property first + Arguments::PropertyList_update_value(Arguments::system_properties(), "java.vm.info", vm_info); + // java.lang.System class Klass* klass = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK); @@ -3779,9 +3782,10 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { initialize_java_lang_classes(main_thread, CHECK_JNI_ERR); - // We need this for ClassDataSharing - the initial vm.info property is set - // with the default value of CDS "sharing" which may be reset through - // command line options. + // We need this to update the java.vm.info property in case any flags used + // to initially define it have been changed. This is needed for both CDS and + // AOT, since UseSharedSpaces and UseAOT may be changed after java.vm.info + // is initially computed. See Abstract_VM_Version::vm_info_string(). reset_vm_info_property(CHECK_JNI_ERR); quicken_jni_functions(); diff --git a/test/hotspot/jtreg/serviceability/jvmti/GetSystemProperty/JvmtiGetSystemPropertyTest.java b/test/hotspot/jtreg/serviceability/jvmti/GetSystemProperty/JvmtiGetSystemPropertyTest.java new file mode 100644 index 00000000000..7c86182a9fd --- /dev/null +++ b/test/hotspot/jtreg/serviceability/jvmti/GetSystemProperty/JvmtiGetSystemPropertyTest.java @@ -0,0 +1,46 @@ +/* + * 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 8203329 + * @summary Verifies the JVMTI GetSystemProperty API returns the updated java.vm.info value + * @library /test/lib + * @run main/othervm/native -agentlib:JvmtiGetSystemPropertyTest JvmtiGetSystemPropertyTest + * + */ + +public class JvmtiGetSystemPropertyTest { + private static native String getSystemProperty(); + + public static void main(String[] args) throws Exception { + String vm_info = System.getProperty("java.vm.info"); + String vm_info_jvmti = getSystemProperty(); + System.out.println("java.vm.info from java: " + vm_info); + System.out.println("java.vm.info from jvmti: " + vm_info_jvmti); + if (!vm_info.equals(vm_info_jvmti)) { + throw new RuntimeException("java.vm.info poperties not equal: \"" + + vm_info + "\" != \"" + vm_info_jvmti + "\""); + } + } +} diff --git a/test/hotspot/jtreg/serviceability/jvmti/GetSystemProperty/libJvmtiGetSystemPropertyTest.c b/test/hotspot/jtreg/serviceability/jvmti/GetSystemProperty/libJvmtiGetSystemPropertyTest.c new file mode 100644 index 00000000000..ad5f835e4b0 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/jvmti/GetSystemProperty/libJvmtiGetSystemPropertyTest.c @@ -0,0 +1,57 @@ +/* + * 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. + */ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static jvmtiEnv *jvmti = NULL; + +JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) { + int err = (*jvm)->GetEnv(jvm, (void**) &jvmti, JVMTI_VERSION_9); + if (err != JNI_OK) { + return JNI_ERR; + } + return JNI_OK; +} + +JNIEXPORT jstring JNICALL +Java_JvmtiGetSystemPropertyTest_getSystemProperty(JNIEnv *env, jclass cls) { + jvmtiError err; + char* prop_value; + + err = (*jvmti)->GetSystemProperty(jvmti, "java.vm.info", &prop_value); + if (err != JVMTI_ERROR_NONE) { + return NULL; + } + + return (*env)->NewStringUTF(env, prop_value); +} + +#ifdef __cplusplus +} +#endif From 12815851ce47d676fb95533714442e3df3277718 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Thu, 7 Jun 2018 22:26:02 -0400 Subject: [PATCH 26/46] 8204589: ProblemList failing launcher tests Reviewed-by: darcy --- test/jdk/ProblemList.txt | 2 ++ test/langtools/ProblemList.txt | 1 + 2 files changed, 3 insertions(+) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 697d414b3fc..004511cf04a 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -822,6 +822,8 @@ java/awt/im/memoryleak/InputContextMemoryLeakTest.java 8023814 linux-all,solaris # core_tools +tools/launcher/SourceMode.java 8204588 linux-all,macosx-all + tools/pack200/CommandLineTests.java 8059906 generic-all tools/jimage/JImageExtractTest.java 8198405,8198819 generic-all diff --git a/test/langtools/ProblemList.txt b/test/langtools/ProblemList.txt index 1ca93245d58..761c5a737fc 100644 --- a/test/langtools/ProblemList.txt +++ b/test/langtools/ProblemList.txt @@ -57,6 +57,7 @@ tools/javac/warnings/suppress/TypeAnnotations.java tools/javac/modules/SourceInSymlinkTest.java 8180263 windows-all fails when run on a subst drive tools/javac/options/release/ReleaseOptionUnsupported.java 8193784 generic-all temporary until support for --release 11 is worked out tools/javac/importscope/T8193717.java 8203925 generic-all the test requires too much memory +tools/javac/launcher/SourceLauncherTest.java 8204588 windows-all New test needs adjusting for Windows ########################################################################### # From af75effcd20f6fe4843dd8ff37641b1d6c312342 Mon Sep 17 00:00:00 2001 From: Richard Reingruber Date: Fri, 8 Jun 2018 06:59:16 +0200 Subject: [PATCH 27/46] 8204561: JVM_GetClassSigners: wrap signers oop in an objArrayHandle for subsequent safepoint Reviewed-by: coleenp, stuefe --- src/hotspot/share/prims/jvm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index 9c5f49cf173..1b3c2612a01 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -1115,7 +1115,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassSigners(JNIEnv *env, jclass cls)) return NULL; } - objArrayOop signers = java_lang_Class::signers(JNIHandles::resolve_non_null(cls)); + objArrayHandle signers(THREAD, java_lang_Class::signers(JNIHandles::resolve_non_null(cls))); // If there are no signers set in the class, or if the class // is an array, return NULL. From 0bc2cae36373986986b8d61c750a4e16325982e5 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Thu, 7 Jun 2018 15:08:16 +0200 Subject: [PATCH 28/46] 8204549: [aix][testbug] signal tests fail because vm can not start in primordial thread Reviewed-by: stuefe, dholmes --- test/hotspot/jtreg/runtime/signal/TestSigalrm.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigbus.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigcld.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigcont.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigemt.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigfpe.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigfreeze.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSighup.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigill.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigint.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigiot.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSiglost.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSiglwp.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigpipe.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigpoll.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigprof.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigpwr.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigquit.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigsegv.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigstop.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigsys.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigterm.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigthaw.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigtrap.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigtstp.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigttin.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigttou.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigurg.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigusr1.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigusr2.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigvtalrm.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigwinch.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigxcpu.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigxfsz.java | 2 +- test/hotspot/jtreg/runtime/signal/TestSigxres.java | 2 +- 35 files changed, 35 insertions(+), 35 deletions(-) diff --git a/test/hotspot/jtreg/runtime/signal/TestSigalrm.java b/test/hotspot/jtreg/runtime/signal/TestSigalrm.java index 337a97e0706..e90dac0c0f6 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigalrm.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigalrm.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigalrm01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigbus.java b/test/hotspot/jtreg/runtime/signal/TestSigbus.java index ce1c04e50ea..8b81be8caa4 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigbus.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigbus.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigbus01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigcld.java b/test/hotspot/jtreg/runtime/signal/TestSigcld.java index 8b84ed97951..ec847f24d85 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigcld.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigcld.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigcld01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigcont.java b/test/hotspot/jtreg/runtime/signal/TestSigcont.java index d0e3106f251..4e0b9137d42 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigcont.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigcont.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigcont01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigemt.java b/test/hotspot/jtreg/runtime/signal/TestSigemt.java index 0614f87fbcc..295294c92a7 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigemt.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigemt.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigemt01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigfpe.java b/test/hotspot/jtreg/runtime/signal/TestSigfpe.java index bd9977f3855..c790ef6abc9 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigfpe.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigfpe.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigfpe01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigfreeze.java b/test/hotspot/jtreg/runtime/signal/TestSigfreeze.java index d335fd7b129..34ae0a85f01 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigfreeze.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigfreeze.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigfreeze01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSighup.java b/test/hotspot/jtreg/runtime/signal/TestSighup.java index 6ac820d4a1f..3176545d864 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSighup.java +++ b/test/hotspot/jtreg/runtime/signal/TestSighup.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sighup01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigill.java b/test/hotspot/jtreg/runtime/signal/TestSigill.java index f24d9a024d5..6771dda2e3e 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigill.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigill.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigill01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigint.java b/test/hotspot/jtreg/runtime/signal/TestSigint.java index 4c6f8eafb52..d028f2da83e 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigint.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigint.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigint01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigiot.java b/test/hotspot/jtreg/runtime/signal/TestSigiot.java index 107c04422bf..2f20448fc69 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigiot.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigiot.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigiot01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSiglost.java b/test/hotspot/jtreg/runtime/signal/TestSiglost.java index 0b2582a61ea..792806eab8f 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSiglost.java +++ b/test/hotspot/jtreg/runtime/signal/TestSiglost.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/siglost01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSiglwp.java b/test/hotspot/jtreg/runtime/signal/TestSiglwp.java index 3641c827785..66ccb9fda27 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSiglwp.java +++ b/test/hotspot/jtreg/runtime/signal/TestSiglwp.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/siglwp01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigpipe.java b/test/hotspot/jtreg/runtime/signal/TestSigpipe.java index 98476b71912..b82ac815359 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigpipe.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigpipe.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigpipe01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigpoll.java b/test/hotspot/jtreg/runtime/signal/TestSigpoll.java index 777ea2d97ad..016ebcf4ea1 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigpoll.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigpoll.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigpoll01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigprof.java b/test/hotspot/jtreg/runtime/signal/TestSigprof.java index e9185146c4d..8a7e908592b 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigprof.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigprof.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigprof01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigpwr.java b/test/hotspot/jtreg/runtime/signal/TestSigpwr.java index 50c670d468e..415cf8aff42 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigpwr.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigpwr.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigpwr01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigquit.java b/test/hotspot/jtreg/runtime/signal/TestSigquit.java index f83b9f64a20..c896084de5c 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigquit.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigquit.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigquit01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigsegv.java b/test/hotspot/jtreg/runtime/signal/TestSigsegv.java index 2524e6d6dff..ac4c0ef39ab 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigsegv.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigsegv.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigsegv01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigstop.java b/test/hotspot/jtreg/runtime/signal/TestSigstop.java index a6ce690da0f..01e49df22c4 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigstop.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigstop.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigstop01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigsys.java b/test/hotspot/jtreg/runtime/signal/TestSigsys.java index 32fc4dcc07f..db435d417b9 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigsys.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigsys.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigsys01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigterm.java b/test/hotspot/jtreg/runtime/signal/TestSigterm.java index b61897dc210..d7c21a026ca 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigterm.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigterm.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigterm01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigthaw.java b/test/hotspot/jtreg/runtime/signal/TestSigthaw.java index 01e163c4083..62b15cd9517 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigthaw.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigthaw.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigthaw01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigtrap.java b/test/hotspot/jtreg/runtime/signal/TestSigtrap.java index 46ead06c6b0..d91f1310096 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigtrap.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigtrap.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigtrap01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigtstp.java b/test/hotspot/jtreg/runtime/signal/TestSigtstp.java index fcb5e6a0ce9..d2c3fc869c9 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigtstp.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigtstp.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigtstp01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigttin.java b/test/hotspot/jtreg/runtime/signal/TestSigttin.java index 48e35345546..53ad313b2fa 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigttin.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigttin.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigttin01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigttou.java b/test/hotspot/jtreg/runtime/signal/TestSigttou.java index 1a3ffd60d52..68bb92a591e 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigttou.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigttou.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigttou01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigurg.java b/test/hotspot/jtreg/runtime/signal/TestSigurg.java index 05fb609a06a..e12dbe19fda 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigurg.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigurg.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigurg01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigusr1.java b/test/hotspot/jtreg/runtime/signal/TestSigusr1.java index 9f1fadc1968..1177f613624 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigusr1.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigusr1.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigusr101. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigusr2.java b/test/hotspot/jtreg/runtime/signal/TestSigusr2.java index 915c2e97aa8..180c6d730f0 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigusr2.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigusr2.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigusr201. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigvtalrm.java b/test/hotspot/jtreg/runtime/signal/TestSigvtalrm.java index 031e3c679ca..bbeee112c6a 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigvtalrm.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigvtalrm.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigvtalrm01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigwinch.java b/test/hotspot/jtreg/runtime/signal/TestSigwinch.java index de169ffea24..e61d3690413 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigwinch.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigwinch.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigwinch01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigxcpu.java b/test/hotspot/jtreg/runtime/signal/TestSigxcpu.java index c63c68922b6..bfc72259d5a 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigxcpu.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigxcpu.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigxcpu01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigxfsz.java b/test/hotspot/jtreg/runtime/signal/TestSigxfsz.java index 1aecbfdd040..0d3be31888b 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigxfsz.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigxfsz.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigxfsz01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] diff --git a/test/hotspot/jtreg/runtime/signal/TestSigxres.java b/test/hotspot/jtreg/runtime/signal/TestSigxres.java index 7d099e4e8b6..a4c17867b6c 100644 --- a/test/hotspot/jtreg/runtime/signal/TestSigxres.java +++ b/test/hotspot/jtreg/runtime/signal/TestSigxres.java @@ -24,7 +24,7 @@ /* * @test - * @requires os.family != "windows" + * @requires os.family != "windows" & os.family != "aix" * * @summary converted from VM testbase runtime/signal/sigxres01. * VM testbase keywords: [signal, runtime, linux, solaris, macosx] From 414f5b66b8376d21ae4d71bc6fc91d51b5ad4323 Mon Sep 17 00:00:00 2001 From: Volker Simonis Date: Fri, 8 Jun 2018 10:22:26 +0200 Subject: [PATCH 29/46] 8204335: [ppc] Assembler::add_const_optimized incorrect for some inputs Reviewed-by: mdoerr, goetz --- src/hotspot/cpu/ppc/assembler_ppc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/cpu/ppc/assembler_ppc.cpp b/src/hotspot/cpu/ppc/assembler_ppc.cpp index 17cc095b08b..b646371b6d6 100644 --- a/src/hotspot/cpu/ppc/assembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/assembler_ppc.cpp @@ -486,7 +486,7 @@ int Assembler::add_const_optimized(Register d, Register s, long x, Register tmp, // Case 2: Can use addis. if (xd == 0) { short xc = rem & 0xFFFF; // 2nd 16-bit chunk. - rem = (rem >> 16) + ((unsigned short)xd >> 15); + rem = (rem >> 16) + ((unsigned short)xc >> 15); if (rem == 0) { addis(d, s, xc); return 0; From 594e5df577defa61e86b54d9229ad442a1a361b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= Date: Fri, 8 Jun 2018 11:08:38 +0200 Subject: [PATCH 30/46] 8204288: Matching the end of a string followed by an empty greedy regex and a word boundary fails Reviewed-by: sundar, jlaskey --- .../runtime/regexp/joni/ByteCodeMachine.java | 2 -- test/nashorn/script/basic/JDK-8204288.js | 35 +++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 test/nashorn/script/basic/JDK-8204288.js diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java index dbed5d18285..f5fce08bce0 100644 --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java @@ -541,7 +541,6 @@ class ByteCodeMachine extends StackMachine { sprev = s; s++; } - sprev = sbegin; // break; } private void opAnyCharMLStar() { @@ -550,7 +549,6 @@ class ByteCodeMachine extends StackMachine { sprev = s; s++; } - sprev = sbegin; // break; } private void opAnyCharStarPeekNext() { diff --git a/test/nashorn/script/basic/JDK-8204288.js b/test/nashorn/script/basic/JDK-8204288.js new file mode 100644 index 00000000000..2d325782bd3 --- /dev/null +++ b/test/nashorn/script/basic/JDK-8204288.js @@ -0,0 +1,35 @@ +/* + * 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. + */ + +/** + * JDK-8204288: Matching the end of a string followed by an empty greedy regex and a word boundary fails + * + * @test + * @run + */ + + +Assert.assertEquals(new RegExp("c.*\\b").exec("abc")[0], "c"); +Assert.assertEquals(new RegExp("abc.*\\b").exec("abc")[0], "abc"); +Assert.assertEquals(new RegExp("\\b.*abc.*\\b").exec("abc")[0], "abc"); + From e9068bec8c9098543702f657fad60cb972b96bb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= Date: Fri, 8 Jun 2018 11:11:06 +0200 Subject: [PATCH 31/46] 8204290: Add check to limit number of capture groups Reviewed-by: sundar, jlaskey --- .../internal/runtime/regexp/joni/Config.java | 1 + .../runtime/regexp/joni/ScanEnvironment.java | 3 ++ .../regexp/joni/exception/ErrorMessages.java | 1 + test/nashorn/script/basic/JDK-8204290.js | 38 +++++++++++++++++++ 4 files changed, 43 insertions(+) create mode 100644 test/nashorn/script/basic/JDK-8204290.js diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/Config.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/Config.java index 65900538414..f9a8c602848 100644 --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/Config.java +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/Config.java @@ -45,6 +45,7 @@ public interface Config { final int NREGION = 10; final int MAX_BACKREF_NUM = 1000; + final int MAX_CAPTURE_GROUP_NUM = 0x8000; final int MAX_REPEAT_NUM = 100000; final int MAX_MULTI_BYTE_RANGES_NUM = 10000; diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ScanEnvironment.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ScanEnvironment.java index 48f5ce0b547..2e118435d61 100644 --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ScanEnvironment.java +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/ScanEnvironment.java @@ -62,6 +62,9 @@ public final class ScanEnvironment { } public int addMemEntry() { + if (numMem >= Config.MAX_CAPTURE_GROUP_NUM) { + throw new InternalException(ErrorMessages.ERR_TOO_MANY_CAPTURE_GROUPS); + } if (numMem++ == 0) { memNodes = new Node[SCANENV_MEMNODES_SIZE]; } else if (numMem >= memNodes.length) { diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/exception/ErrorMessages.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/exception/ErrorMessages.java index 3c835d7b992..da986489c82 100644 --- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/exception/ErrorMessages.java +++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/regexp/joni/exception/ErrorMessages.java @@ -31,6 +31,7 @@ public interface ErrorMessages { final String ERR_PARSER_BUG = "internal parser error (bug)"; final String ERR_UNDEFINED_BYTECODE = "undefined bytecode (bug)"; final String ERR_UNEXPECTED_BYTECODE = "unexpected bytecode (bug)"; + final String ERR_TOO_MANY_CAPTURE_GROUPS = "too many capture groups"; /* syntax error */ final String ERR_END_PATTERN_AT_LEFT_BRACE = "end pattern at left brace"; diff --git a/test/nashorn/script/basic/JDK-8204290.js b/test/nashorn/script/basic/JDK-8204290.js new file mode 100644 index 00000000000..57193b61cfb --- /dev/null +++ b/test/nashorn/script/basic/JDK-8204290.js @@ -0,0 +1,38 @@ +/* + * 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. + */ + +/** + * JDK-8204290: Add check to limit number of capture groups + * + * @test + * @run + */ + +try { + new RegExp("()".repeat(0x8001)); + fail("Expected exception"); +} catch (e) { + Assert.assertTrue(e instanceof SyntaxError); + Assert.assertEquals(e.message, "too many capture groups"); +} + From bb1c912d9e51ba877010ac83e4d2397137681e40 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Fri, 8 Jun 2018 11:41:43 +0200 Subject: [PATCH 32/46] 8204479: Bitwise AND on byte value sometimes produces wrong result Reviewed-by: kvn, thartmann --- src/hotspot/cpu/x86/x86_64.ad | 20 ---- .../compiler/c2/TestUnsignedByteCompare.java | 94 +++++++++++++++++++ 2 files changed, 94 insertions(+), 20 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/TestUnsignedByteCompare.java diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index ea0f16ac18c..e576342b613 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -11607,16 +11607,6 @@ instruct testUL_reg(rFlagsRegU cr, rRegL src, immL0 zero) ins_pipe(ialu_cr_reg_imm); %} -instruct compUB_mem_imm(rFlagsReg cr, memory mem, immU8 imm) -%{ - match(Set cr (CmpI (LoadUB mem) imm)); - - ins_cost(125); - format %{ "cmpb $mem, $imm" %} - ins_encode %{ __ cmpb($mem$$Address, $imm$$constant); %} - ins_pipe(ialu_cr_reg_mem); -%} - instruct compB_mem_imm(rFlagsReg cr, memory mem, immI8 imm) %{ match(Set cr (CmpI (LoadB mem) imm)); @@ -11627,16 +11617,6 @@ instruct compB_mem_imm(rFlagsReg cr, memory mem, immI8 imm) ins_pipe(ialu_cr_reg_mem); %} -instruct testUB_mem_imm(rFlagsReg cr, memory mem, immU8 imm, immI0 zero) -%{ - match(Set cr (CmpI (AndI (LoadUB mem) imm) zero)); - - ins_cost(125); - format %{ "testb $mem, $imm" %} - ins_encode %{ __ testb($mem$$Address, $imm$$constant); %} - ins_pipe(ialu_cr_reg_mem); -%} - instruct testB_mem_imm(rFlagsReg cr, memory mem, immI8 imm, immI0 zero) %{ match(Set cr (CmpI (AndI (LoadB mem) imm) zero)); diff --git a/test/hotspot/jtreg/compiler/c2/TestUnsignedByteCompare.java b/test/hotspot/jtreg/compiler/c2/TestUnsignedByteCompare.java new file mode 100644 index 00000000000..5616d5b2f6f --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestUnsignedByteCompare.java @@ -0,0 +1,94 @@ +/* + * 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 8204479 + * @summary Bitwise AND on byte value sometimes produces wrong result + * + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation + * -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -Xcomp -XX:-Inline + * compiler.c2.TestUnsignedByteCompare + */ + +package compiler.c2; + +public class TestUnsignedByteCompare { + + static int p, n; + + static void report(byte[] ba, int i, boolean failed) { + // Enable for debugging: + // System.out.println((failed ? "Failed" : "Passed") + " with: " + ba[i] + " at " + i); + } + + static void m1(byte[] ba) { + for (int i = 0; i < ba.length; i++) { + if ((ba[i] & 0xFF) < 0x10) { + p++; + report(ba, i, true); + } else { + n++; + report(ba, i, false); + } + } + } + + static void m2(byte[] ba) { + for (int i = 0; i < ba.length; i++) { + if (((ba[i] & 0xFF) & 0x80) < 0) { + p++; + report(ba, i, true); + } else { + n++; + report(ba, i, false); + } + } + } + + static public void main(String[] args) { + final int tries = 1_000; + final int count = 1_000; + + byte[] ba = new byte[count]; + + for (int i = 0; i < count; i++) { + int v = -(i % 126 + 1); + ba[i] = (byte)v; + } + + for (int t = 0; t < tries; t++) { + m1(ba); + if (p != 0) { + throw new IllegalStateException("m1 error: p = " + p + ", n = " + n); + } + } + + for (int t = 0; t < tries; t++) { + m2(ba); + if (p != 0) { + throw new IllegalStateException("m2 error: p = " + p + ", n = " + n); + } + } + } +} From 48966d03e8cbcd1f03a2588a141814ab431f295b Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Fri, 8 Jun 2018 13:06:08 +0200 Subject: [PATCH 33/46] 8204539: improve error messages in matchJavaTZ [windows] Reviewed-by: coffeys, clanger, goetz --- src/java.base/windows/native/libjava/TimeZone_md.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/java.base/windows/native/libjava/TimeZone_md.c b/src/java.base/windows/native/libjava/TimeZone_md.c index ab89a7d54ed..d46b3c3b57d 100644 --- a/src/java.base/windows/native/libjava/TimeZone_md.c +++ b/src/java.base/windows/native/libjava/TimeZone_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -437,6 +437,8 @@ static char *matchJavaTZ(const char *java_home_dir, int value_type, char *tzName char *mapFileName; char lineBuffer[MAX_ZONE_CHAR * 4]; int noMapID = *mapID == '\0'; /* no mapID on Vista and later */ + int offset = 0; + const char* errorMessage = "unknown error"; mapFileName = malloc(strlen(java_home_dir) + strlen(MAPPINGS_FILE) + 1); if (mapFileName == NULL) { @@ -472,10 +474,14 @@ static char *matchJavaTZ(const char *java_home_dir, int value_type, char *tzName items[itemIndex] = start; while (*idx && *idx != ':') { if (++idx >= endp) { + errorMessage = "premature end of line"; + offset = (int)(idx - lineBuffer); goto illegal_format; } } if (*idx == '\0') { + errorMessage = "illegal null character found"; + offset = (int)(idx - lineBuffer); goto illegal_format; } *idx++ = '\0'; @@ -483,6 +489,8 @@ static char *matchJavaTZ(const char *java_home_dir, int value_type, char *tzName } if (*idx != '\n') { + errorMessage = "illegal non-newline character found"; + offset = (int)(idx - lineBuffer); goto illegal_format; } @@ -516,7 +524,8 @@ static char *matchJavaTZ(const char *java_home_dir, int value_type, char *tzName illegal_format: (void) fclose(fp); - jio_fprintf(stderr, "tzmappings: Illegal format at line %d.\n", line); + jio_fprintf(stderr, "Illegal format in tzmappings file: %s at line %d, offset %d.\n", + errorMessage, line, offset); return NULL; } From 8c75c07f8cb7a8231087682d87b7f1ded26cc66c Mon Sep 17 00:00:00 2001 From: Nils Eliasson Date: Fri, 8 Jun 2018 14:50:18 +0200 Subject: [PATCH 34/46] 8203425: assert(is_Loop()) failed: invalid node class Revert 8203215 Reviewed-by: thartmann --- src/hotspot/share/opto/loopnode.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 7fbf0736f36..9ee22c2e1a0 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -2641,6 +2641,9 @@ void PhaseIdealLoop::build_and_optimize(bool do_split_ifs, bool skip_loop_opts) int old_progress = C->major_progress(); uint orig_worklist_size = _igvn._worklist.size(); + // Reset major-progress flag for the driver's heuristics + C->clear_major_progress(); + #ifndef PRODUCT // Capture for later assert uint unique = C->unique(); @@ -2711,16 +2714,11 @@ void PhaseIdealLoop::build_and_optimize(bool do_split_ifs, bool skip_loop_opts) if( !_verify_me && !_verify_only && _ltree_root->_child ) { C->print_method(PHASE_BEFORE_BEAUTIFY_LOOPS, 3); if( _ltree_root->_child->beautify_loops( this ) ) { - // IdealLoopTree::split_outer_loop may produce phi-nodes with a single in edge. - // Transform them away. - _igvn.optimize(); - // Re-build loop tree! _ltree_root->_child = NULL; _nodes.clear(); reallocate_preorders(); build_loop_tree(); - // Check for bailout, and return if (C->failing()) { return; @@ -2732,9 +2730,6 @@ void PhaseIdealLoop::build_and_optimize(bool do_split_ifs, bool skip_loop_opts) } } - // Reset major-progress flag for the driver's heuristics - C->clear_major_progress(); - // Build Dominators for elision of NULL checks & loop finding. // Since nodes do not have a slot for immediate dominator, make // a persistent side array for that info indexed on node->_idx. From 683eebde095fa16ec054cf5cb7a12972a1f4493c Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Fri, 8 Jun 2018 07:58:19 -0700 Subject: [PATCH 35/46] 8204576: (fs) java/nio/file/Files/CopyAndMove.java does not set isUnix = true on macOS Reviewed-by: alanb --- test/jdk/java/nio/file/Files/CopyAndMove.java | 39 +++++++------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/test/jdk/java/nio/file/Files/CopyAndMove.java b/test/jdk/java/nio/file/Files/CopyAndMove.java index 17ff7eec4d3..1b7362fe93f 100644 --- a/test/jdk/java/nio/file/Files/CopyAndMove.java +++ b/test/jdk/java/nio/file/Files/CopyAndMove.java @@ -25,21 +25,22 @@ * @bug 4313887 6838333 6917021 7006126 6950237 8006645 8201407 * @summary Unit test for java.nio.file.Files copy and move methods (use -Dseed=X to set PRNG seed) * @library .. /test/lib - * @build jdk.test.lib.RandomFactory + * @build jdk.test.lib.Platform jdk.test.lib.RandomFactory * CopyAndMove PassThroughFileSystem * @run main/othervm CopyAndMove * @key randomness */ +import java.io.*; import java.nio.ByteBuffer; import java.nio.file.*; import static java.nio.file.Files.*; import static java.nio.file.StandardCopyOption.*; import static java.nio.file.LinkOption.*; import java.nio.file.attribute.*; -import java.io.*; import java.util.*; import java.util.concurrent.TimeUnit; +import jdk.test.lib.Platform; import jdk.test.lib.RandomFactory; public class CopyAndMove { @@ -169,8 +170,7 @@ public class CopyAndMove { Map namedAttributes = null; // get file attributes of source file - String os = System.getProperty("os.name"); - if (os.startsWith("Windows")) { + if (Platform.isWindows()) { dosAttributes = readAttributes(source, DosFileAttributes.class, NOFOLLOW_LINKS); basicAttributes = dosAttributes; } else { @@ -657,17 +657,14 @@ public class CopyAndMove { if (source.getFileSystem().provider() == target.getFileSystem().provider()) { // check POSIX attributes are copied - String os = System.getProperty("os.name"); - if ((os.equals("SunOS") || os.equals("Linux")) && - testPosixAttributes) - { + if (!Platform.isWindows() && testPosixAttributes) { checkPosixAttributes( readAttributes(source, PosixFileAttributes.class, linkOptions), readAttributes(target, PosixFileAttributes.class, linkOptions)); } // check DOS attributes are copied - if (os.startsWith("Windows")) { + if (Platform.isWindows()) { checkDosAttributes( readAttributes(source, DosFileAttributes.class, linkOptions), readAttributes(target, DosFileAttributes.class, linkOptions)); @@ -925,9 +922,7 @@ public class CopyAndMove { /** * Test: Copy link to UNC (Windows only) */ - if (supportsLinks && - System.getProperty("os.name").startsWith("Windows")) - { + if (supportsLinks && Platform.isWindows()) { Path unc = Paths.get("\\\\rialto\\share\\file"); link = dir1.resolve("link"); createSymbolicLink(link, unc); @@ -1160,12 +1155,14 @@ public class CopyAndMove { // "randomize" the file attributes of the given file. static void randomizeAttributes(Path file) throws IOException { - String os = System.getProperty("os.name"); - boolean isWindows = os.startsWith("Windows"); - boolean isUnix = os.equals("SunOS") || os.equals("Linux"); boolean isDirectory = isDirectory(file, NOFOLLOW_LINKS); - if (isUnix) { + if (Platform.isWindows()) { + DosFileAttributeView view = + getFileAttributeView(file, DosFileAttributeView.class, NOFOLLOW_LINKS); + // only set or unset the hidden attribute + view.setHidden(heads()); + } else { Set perms = getPosixFilePermissions(file, NOFOLLOW_LINKS); PosixFilePermission[] toChange = { @@ -1186,18 +1183,12 @@ public class CopyAndMove { setPosixFilePermissions(file, perms); } - if (isWindows) { - DosFileAttributeView view = - getFileAttributeView(file, DosFileAttributeView.class, NOFOLLOW_LINKS); - // only set or unset the hidden attribute - view.setHidden(heads()); - } - boolean addUserDefinedFileAttributes = heads() && getFileStore(file).supportsFileAttributeView("xattr"); // remove this when copying a direcory copies its named streams - if (isWindows && isDirectory) addUserDefinedFileAttributes = false; + if (Platform.isWindows() && isDirectory) + addUserDefinedFileAttributes = false; if (addUserDefinedFileAttributes) { UserDefinedFileAttributeView view = From b6fd68564b053c4bb064b93085ff8462680c14d7 Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Fri, 8 Jun 2018 08:30:18 -0700 Subject: [PATCH 36/46] 8204584: jdeps generates illegal dot file containing ranksep=0,600000 Reviewed-by: jjg --- .../share/classes/com/sun/tools/jdeps/ModuleDotGraph.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleDotGraph.java b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleDotGraph.java index bf2152a4ec5..a46d3c8b189 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleDotGraph.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleDotGraph.java @@ -44,6 +44,7 @@ import java.util.Collections; import java.util.Deque; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -329,7 +330,7 @@ public class ModuleDotGraph { out.format("digraph \"%s\" {%n", name); out.format(" nodesep=.5;%n"); - out.format(" ranksep=%f;%n", attributes.rankSep()); + out.format((Locale)null, " ranksep=%f;%n", attributes.rankSep()); out.format(" pencolor=transparent;%n"); out.format(" node [shape=plaintext, fontcolor=\"%s\", fontname=\"%s\"," + " fontsize=%d, margin=\".2,.2\"];%n", From 824b2d53ac3debc64f583b0be7fb61c972d8aa8e Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Fri, 8 Jun 2018 16:33:40 +0100 Subject: [PATCH 37/46] 8204610: Compiler confused by parenthesized "this" in final fields assignments Parenthesis are not skipped consistently in DA/DU, forward reference analysis Reviewed-by: vromero --- .../com/sun/tools/javac/comp/Attr.java | 2 +- .../com/sun/tools/javac/comp/Flow.java | 21 +--- .../com/sun/tools/javac/tree/TreeInfo.java | 30 ++++++ .../javac/DefiniteAssignment/T8204610.java | 95 +++++++++++++++++++ 4 files changed, 130 insertions(+), 18 deletions(-) create mode 100644 test/langtools/tools/javac/DefiniteAssignment/T8204610.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index 1f223945b05..8b3bfa1ec5f 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -291,7 +291,7 @@ public class Attr extends JCTree.Visitor { ((v.flags() & HASINIT) != 0 || !((base == null || - (base.hasTag(IDENT) && TreeInfo.name(base) == names._this)) && + TreeInfo.isThisQualifier(base)) && isAssignableAsBlankFinal(v, env)))) { if (v.isResourceVariable()) { //TWR resource log.error(pos, Errors.TryResourceMayNotBeAssigned(v)); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java index 86849f4e41a..1fb91ebcd5f 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java @@ -2391,31 +2391,18 @@ public class Flow { } public void visitAssign(JCAssign tree) { - JCTree lhs = TreeInfo.skipParens(tree.lhs); - if (!isIdentOrThisDotIdent(lhs)) - scanExpr(lhs); + if (!TreeInfo.isIdentOrThisDotIdent(tree.lhs)) + scanExpr(tree.lhs); scanExpr(tree.rhs); - letInit(lhs); - } - private boolean isIdentOrThisDotIdent(JCTree lhs) { - if (lhs.hasTag(IDENT)) - return true; - if (!lhs.hasTag(SELECT)) - return false; - - JCFieldAccess fa = (JCFieldAccess)lhs; - return fa.selected.hasTag(IDENT) && - ((JCIdent)fa.selected).name == names._this; + letInit(tree.lhs); } // check fields accessed through this. are definitely // assigned before reading their value public void visitSelect(JCFieldAccess tree) { super.visitSelect(tree); - JCTree sel = TreeInfo.skipParens(tree.selected); if (enforceThisDotInit && - sel.hasTag(IDENT) && - ((JCIdent)sel).name == names._this && + TreeInfo.isThisQualifier(tree.selected) && tree.sym.kind == VAR) { checkInit(tree.pos(), (VarSymbol)tree.sym); } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java index 27553a36027..bcc14ac0762 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java @@ -148,6 +148,36 @@ public class TreeInfo { } } + /** Is this tree a 'this' identifier? + */ + public static boolean isThisQualifier(JCTree tree) { + switch (tree.getTag()) { + case PARENS: + return isThisQualifier(skipParens(tree)); + case IDENT: { + JCIdent id = (JCIdent)tree; + return id.name == id.name.table.names._this; + } + default: + return false; + } + } + + /** Is this tree an identifier, possibly qualified by 'this'? + */ + public static boolean isIdentOrThisDotIdent(JCTree tree) { + switch (tree.getTag()) { + case PARENS: + return isIdentOrThisDotIdent(skipParens(tree)); + case IDENT: + return true; + case SELECT: + return isThisQualifier(((JCFieldAccess)tree).selected); + default: + return false; + } + } + /** Is this a call to super? */ public static boolean isSuperCall(JCTree tree) { diff --git a/test/langtools/tools/javac/DefiniteAssignment/T8204610.java b/test/langtools/tools/javac/DefiniteAssignment/T8204610.java new file mode 100644 index 00000000000..2827b37038d --- /dev/null +++ b/test/langtools/tools/javac/DefiniteAssignment/T8204610.java @@ -0,0 +1,95 @@ +/* + * 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. + */ + +/* + * @test + * @bug 8204610 + * @summary Compiler confused by parenthesized "this" in final fields assignments + * @library /tools/javac/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build combo.ComboTestHelper + + * @run main T8204610 + */ + +import combo.ComboInstance; +import combo.ComboParameter; +import combo.ComboTask.Result; +import combo.ComboTestHelper; + +public class T8204610 extends ComboInstance { + + enum ParenKind implements ComboParameter { + NONE(""), + ONE("#P"), + TWO("#P#P"), + THREE("#P#P#P"); + + String parensTemplate; + + ParenKind(String parensTemplate) { + this.parensTemplate = parensTemplate; + } + + @Override + public String expand(String optParameter) { + return parensTemplate.replaceAll("#P", optParameter.equals("OPEN") ? "(" : ")"); + } + } + + public static void main(String... args) { + new ComboTestHelper() + .withArrayDimension("PAREN", (x, pk, idx) -> x.parenKinds[idx] = pk, 3, ParenKind.values()) + .run(T8204610::new); + } + + ParenKind[] parenKinds = new ParenKind[3]; + + @Override + public void doWork() { + newCompilationTask() + .withSourceFromTemplate(bodyTemplate) + .analyze(this::check); + } + + String bodyTemplate = "class Test {\n" + + " final int x;\n" + + " Test() {\n" + + " #{PAREN[0].OPEN} #{PAREN[1].OPEN} this #{PAREN[1].CLOSE} . #{PAREN[2].OPEN} x #{PAREN[2].CLOSE} #{PAREN[0].CLOSE} = 1;\n" + + " } }"; + + void check(Result res) { + boolean expectedFail = parenKinds[2] != ParenKind.NONE; + if (expectedFail != res.hasErrors()) { + fail("unexpected compilation result for source:\n" + + res.compilationInfo()); + } + } +} From 79ac24439f19768b1523fe732349c905f2789cee Mon Sep 17 00:00:00 2001 From: Srinivas Dama Date: Fri, 8 Jun 2018 21:06:54 +0530 Subject: [PATCH 38/46] 8196990: Resolve disabled warnings for libjli Initialized uninitialzed data to avoid maybe-uninitialized warnings from gcc Reviewed-by: jlaskey --- make/lib/CoreLibraries.gmk | 1 - src/java.base/share/native/libjli/args.c | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/make/lib/CoreLibraries.gmk b/make/lib/CoreLibraries.gmk index 4a7dae1b7e6..316f014c528 100644 --- a/make/lib/CoreLibraries.gmk +++ b/make/lib/CoreLibraries.gmk @@ -298,7 +298,6 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJLI, \ EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \ OPTIMIZATION := HIGH, \ CFLAGS := $(LIBJLI_CFLAGS), \ - DISABLED_WARNINGS_gcc := maybe-uninitialized, \ DISABLED_WARNINGS_solstudio := \ E_ASM_DISABLES_OPTIMIZATION \ E_STATEMENT_NOT_REACHED, \ diff --git a/src/java.base/share/native/libjli/args.c b/src/java.base/share/native/libjli/args.c index c8f2c8706b5..45954ef78bb 100644 --- a/src/java.base/share/native/libjli/args.c +++ b/src/java.base/share/native/libjli/args.c @@ -305,6 +305,8 @@ static JLI_List readArgFile(FILE *file) { ctx.state = FIND_NEXT; ctx.parts = JLI_List_new(4); + // initialize to avoid -Werror=maybe-uninitialized issues from gcc 7.3 onwards. + ctx.quote_char = '"'; /* arbitrarily pick 8, seems to be a reasonable number of arguments */ rv = JLI_List_new(8); From da0babd9b9d18e903e49ea8ed7e33d608e264889 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20=C3=96sterlund?= Date: Fri, 8 Jun 2018 11:30:10 +0200 Subject: [PATCH 39/46] 8204504: Fix for 8198285 breaks slowdebug builds Reviewed-by: rkennke, mgronlun --- .../share/oops/accessBackend.inline.hpp | 78 ++++++++++++------- 1 file changed, 49 insertions(+), 29 deletions(-) diff --git a/src/hotspot/share/oops/accessBackend.inline.hpp b/src/hotspot/share/oops/accessBackend.inline.hpp index 51ad1b544be..8305b896cde 100644 --- a/src/hotspot/share/oops/accessBackend.inline.hpp +++ b/src/hotspot/share/oops/accessBackend.inline.hpp @@ -247,14 +247,14 @@ RawAccessBarrier::atomic_cmpxchg_maybe_locked(T new_value, void* addr, T com } class RawAccessBarrierArrayCopy: public AllStatic { + template struct IsHeapWordSized: public IntegralConstant { }; public: template static inline typename EnableIf< - HasDecorator::value>::type + HasDecorator::value>::type arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, size_t length) { - src_raw = arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw); dst_raw = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw); @@ -270,48 +270,68 @@ public: template static inline typename EnableIf< - !HasDecorator::value>::type - arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, const T* src_raw, arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, size_t length) { - + !HasDecorator::value && + HasDecorator::value>::type + arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, + arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, + size_t length) { src_raw = arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw); dst_raw = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw); - if (HasDecorator::value) { - AccessInternal::arraycopy_arrayof_conjoint(const_cast(src_raw), dst_raw, length); - } else if (HasDecorator::value && sizeof(T) == HeapWordSize) { - // There is only a disjoint optimization for word granularity copying - if (HasDecorator::value) { - AccessInternal::arraycopy_disjoint_words_atomic(const_cast(src_raw), dst_raw, length); - } else { - AccessInternal::arraycopy_disjoint_words(const_cast(src_raw), dst_raw, length); - } + AccessInternal::arraycopy_arrayof_conjoint(src_raw, dst_raw, length); + } + + template + static inline typename EnableIf< + !HasDecorator::value && + HasDecorator::value && IsHeapWordSized::value>::type + arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, + arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, + size_t length) { + src_raw = arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw); + dst_raw = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw); + + // There is only a disjoint optimization for word granularity copying + if (HasDecorator::value) { + AccessInternal::arraycopy_disjoint_words_atomic(src_raw, dst_raw, length); } else { - if (HasDecorator::value) { - AccessInternal::arraycopy_conjoint_atomic(const_cast(src_raw), dst_raw, length); - } else { - AccessInternal::arraycopy_conjoint(const_cast(src_raw), dst_raw, length); - } + AccessInternal::arraycopy_disjoint_words(src_raw, dst_raw, length); } } - template + template static inline typename EnableIf< - !HasDecorator::value>::type - arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, const void* src_raw, - arrayOop dst_obj, size_t dst_offset_in_bytes, void* dst_raw, + !HasDecorator::value && + !(HasDecorator::value && IsHeapWordSized::value) && + !HasDecorator::value && + !HasDecorator::value>::type + arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, + arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, size_t length) { - src_raw = arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw); dst_raw = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw); - if (HasDecorator::value) { - AccessInternal::arraycopy_conjoint_atomic(const_cast(src_raw), dst_raw, length); - } else { - AccessInternal::arraycopy_conjoint(const_cast(src_raw), dst_raw, length); - } + AccessInternal::arraycopy_conjoint(src_raw, dst_raw, length); + } + + template + static inline typename EnableIf< + !HasDecorator::value && + !(HasDecorator::value && IsHeapWordSized::value) && + !HasDecorator::value && + HasDecorator::value>::type + arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, + arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw, + size_t length) { + src_raw = arrayOopDesc::obj_offset_to_raw(src_obj, src_offset_in_bytes, src_raw); + dst_raw = arrayOopDesc::obj_offset_to_raw(dst_obj, dst_offset_in_bytes, dst_raw); + + AccessInternal::arraycopy_conjoint_atomic(src_raw, dst_raw, length); } }; +template<> struct RawAccessBarrierArrayCopy::IsHeapWordSized: public IntegralConstant { }; + template template inline bool RawAccessBarrier::arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, From 402777ea0f73fcb98300df0f5d853cfc55757188 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Fri, 8 Jun 2018 18:11:32 +0200 Subject: [PATCH 40/46] 8204572: SetupJdkLibrary should setup SRC and -I flags automatically Reviewed-by: erikj --- make/common/JdkNativeCompilation.gmk | 75 ++- make/common/MakeBase.gmk | 2 +- make/lib/Awt2dLibraries.gmk | 523 ++++++++---------- make/lib/CoreLibraries.gmk | 53 +- make/lib/Lib-java.base.gmk | 47 +- make/lib/Lib-java.desktop.gmk | 31 +- make/lib/Lib-java.instrument.gmk | 20 +- make/lib/Lib-java.management.gmk | 10 +- make/lib/Lib-java.prefs.gmk | 10 +- make/lib/Lib-java.rmi.gmk | 3 +- make/lib/Lib-java.security.jgss.gmk | 22 +- make/lib/Lib-java.smartcardio.gmk | 10 +- make/lib/Lib-jdk.accessibility.gmk | 30 +- make/lib/Lib-jdk.attach.gmk | 5 +- make/lib/Lib-jdk.crypto.cryptoki.gmk | 8 +- make/lib/Lib-jdk.crypto.ec.gmk | 24 +- make/lib/Lib-jdk.crypto.mscapi.gmk | 6 +- make/lib/Lib-jdk.crypto.ucrypto.gmk | 6 +- make/lib/Lib-jdk.hotspot.agent.gmk | 18 +- make/lib/Lib-jdk.internal.le.gmk | 11 +- make/lib/Lib-jdk.jdi.gmk | 17 +- make/lib/Lib-jdk.jdwp.agent.gmk | 28 +- make/lib/Lib-jdk.management.agent.gmk | 9 +- make/lib/Lib-jdk.management.gmk | 11 - make/lib/Lib-jdk.net.gmk | 3 +- make/lib/Lib-jdk.pack.gmk | 9 +- make/lib/Lib-jdk.sctp.gmk | 15 +- make/lib/Lib-jdk.security.auth.gmk | 3 +- make/lib/LibCommon.gmk | 17 - .../libpng/{ => zlibwrapper}/zlib.h | 0 .../libsplashscreen/java_awt_SplashScreen.c | 3 +- .../native/libprefs/MacOSXPreferencesFile.m | 3 +- .../native/libprefs/FileSystemPreferences.c | 3 +- .../native/libprefs/WindowsPreferences.c | 2 + .../native/libw2k_lsa_auth/NativeCreds.c | 3 +- .../native/libw2k_lsa_auth/WindowsDirectory.c | 3 +- .../share/native/libsunec/ECC_JNI.cpp | 5 +- .../windows/native/libsunmscapi/security.cpp | 20 +- .../native/libj2ucrypto/nativeCrypto.c | 7 + .../native/libj2ucrypto/nativeCryptoMD.c | 2 +- .../native/libextnet/LinuxSocketOptions.c | 3 +- 41 files changed, 446 insertions(+), 634 deletions(-) rename src/java.desktop/macosx/native/libsplashscreen/libpng/{ => zlibwrapper}/zlib.h (100%) diff --git a/make/common/JdkNativeCompilation.gmk b/make/common/JdkNativeCompilation.gmk index 49b0f3e795c..c1bd70350dd 100644 --- a/make/common/JdkNativeCompilation.gmk +++ b/make/common/JdkNativeCompilation.gmk @@ -32,6 +32,36 @@ endif include NativeCompilation.gmk +# Hook to include the corresponding custom file, if present. +$(eval $(call IncludeCustomExtension, common/JdkNativeCompilation.gmk)) + +FindSrcDirsForLib += \ + $(call uniq, $(wildcard \ + $(TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS)/native/lib$(strip $2) \ + $(TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS_TYPE)/native/lib$(strip $2) \ + $(TOPDIR)/src/$(strip $1)/share/native/lib$(strip $2))) + +FindSrcDirsForComponent += \ + $(call uniq, $(wildcard \ + $(TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS)/native/$(strip $2) \ + $(TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS_TYPE)/native/$(strip $2) \ + $(TOPDIR)/src/$(strip $1)/share/native/$(strip $2))) + +GetJavaHeaderDir = \ + $(wildcard $(SUPPORT_OUTPUTDIR)/headers/$(strip $1)) + +# Process a dir description such as "java.base:headers" into a set of proper absolute paths. +ProcessDir = \ + $(if $(findstring :, $1), \ + $(call FindSrcDirsForComponent, $(firstword $(subst :, , $1)), $(lastword $(subst :, , $1))) \ + , \ + $(if $(filter /%, $1), \ + $1 \ + , \ + $(call FindSrcDirsForComponent, $(MODULE), $1) \ + ) \ + ) + # Setup make rules for creating a native shared library with suitable defaults # for the OpenJDK project. # @@ -39,8 +69,16 @@ include NativeCompilation.gmk # and the targets generated are listed in a variable by that name. # # Remaining parameters are named arguments. These are all passed on to -# SetupNativeCompilation, except for +# SetupNativeCompilation, except for # EXTRA_RC_FLAGS -- additional RC_FLAGS to append. +# EXTRA_HEADER_DIRS -- additional directories to look for headers in +# EXTRA_SRC -- additional directories to look for source in +# EXCLUDE_SRC_PATTERNS -- exclude source dirs matching these patterns from +# appearing in SRC. +# HEADERS_FROM_SRC -- if false, does not add source dirs automatically as +# header include dirs. (Defaults to true.) +# SRC -- this is passed on, but preprocessed to accept source dir designations +# such as "java.base:headers". SetupJdkLibrary = $(NamedParamsMacroTemplate) define SetupJdkLibraryBody ifeq ($$($1_OUTPUT_DIR), ) @@ -51,6 +89,20 @@ define SetupJdkLibraryBody $1_OBJECT_DIR := $$(SUPPORT_OUTPUTDIR)/native/$$(MODULE)/lib$$($1_NAME) endif + ifeq ($$($1_SRC), ) + $1_SRC := $$(call FindSrcDirsForLib, $$(MODULE), $$($1_NAME)) + else + $1_SRC := $$(foreach dir, $$($1_SRC), $$(call ProcessDir, $$(dir))) + endif + ifneq ($$($1_EXTRA_SRC), ) + $1_SRC += $$(foreach dir, $$($1_EXTRA_SRC), $$(call ProcessDir, $$(dir))) + endif + + ifneq ($$($1_EXCLUDE_SRC_PATTERNS), ) + $1_EXCLUDE_SRC := $$(call containing, $$($1_EXCLUDE_SRC_PATTERNS), $$($1_SRC)) + $1_SRC := $$(filter-out $$($1_EXCLUDE_SRC), $$($1_SRC)) + endif + ifeq ($$($1_VERSIONINFO_RESOURCE), ) $1_VERSIONINFO_RESOURCE := $$(GLOBAL_VERSION_INFO_RESOURCE) else ifeq ($$($1_VERSIONINFO_RESOURCE), DISABLE) @@ -66,6 +118,25 @@ define SetupJdkLibraryBody $1_RC_FLAGS := endif + ifneq ($$($1_HEADERS_FROM_SRC), false) + $1_SRC_HEADER_FLAGS := $$(foreach dir, $$(wildcard $$($1_SRC) \ + $$(call GetJavaHeaderDir, $$(MODULE))), -I$$(dir)) + endif + ifneq ($$($1_EXTRA_HEADER_DIRS), ) + $1_PROCESSED_EXTRA_HEADER_DIRS := $$(foreach dir, $$($1_EXTRA_HEADER_DIRS), \ + $$(call ProcessDir, $$(dir))) + $1_EXTRA_HEADER_FLAGS := $$(addprefix -I, $$($1_PROCESSED_EXTRA_HEADER_DIRS)) + endif + + ifneq ($$($1_CFLAGS), ) + $1_CFLAGS += $$($1_SRC_HEADER_FLAGS) $$($1_EXTRA_HEADER_FLAGS) + endif + ifneq ($$($1_CXXFLAGS), ) + $1_CXXFLAGS += $$($1_SRC_HEADER_FLAGS) $$($1_EXTRA_HEADER_FLAGS) + endif + ifeq ($$($1_CFLAGS)$$($1_CXXFLAGS), ) + $1_CFLAGS += $$($1_SRC_HEADER_FLAGS) $$($1_EXTRA_HEADER_FLAGS) + endif $1_RC_FLAGS += $$($1_EXTRA_RC_FLAGS) # Since we reuse the rule name ($1), all our arguments will pass through. @@ -80,7 +151,7 @@ endef # and the targets generated are listed in a variable by that name. # # Remaining parameters are named arguments. These are all passed on to -# SetupNativeCompilation, except for +# SetupNativeCompilation, except for # EXTRA_RC_FLAGS -- additional RC_FLAGS to append. SetupJdkExecutable = $(NamedParamsMacroTemplate) define SetupJdkExecutableBody diff --git a/make/common/MakeBase.gmk b/make/common/MakeBase.gmk index 960e9985206..b3a59e14aa1 100644 --- a/make/common/MakeBase.gmk +++ b/make/common/MakeBase.gmk @@ -634,7 +634,7 @@ endef ################################################################################ # Filter out duplicate sub strings while preserving order. Keeps the first occurance. uniq = \ - $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1))) + $(strip $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))) # Returns all whitespace-separated words in $2 where at least one of the # whitespace-separated words in $1 is a substring. diff --git a/make/lib/Awt2dLibraries.gmk b/make/lib/Awt2dLibraries.gmk index 00d35a69844..e2dad01c042 100644 --- a/make/lib/Awt2dLibraries.gmk +++ b/make/lib/Awt2dLibraries.gmk @@ -27,37 +27,38 @@ $(eval $(call IncludeCustomExtension, lib/Awt2dLibraries-pre.gmk)) WIN_AWT_LIB := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libawt/awt.lib +LIBAWT_DEFAULT_HEADER_DIRS := \ + libawt/awt/image \ + libawt/awt/image/cvutils \ + libawt/java2d \ + libawt/java2d/loops \ + libawt/java2d/pipe \ + # + ################################################################################ -BUILD_LIBMLIB_SRC := $(TOPDIR)/src/java.desktop/share/native/libmlib_image \ - $(TOPDIR)/src/java.desktop/share/native/common/awt/medialib -BUILD_LIBMLIB_CFLAGS := -D__USE_J2D_NAMES -D__MEDIALIB_OLD_NAMES \ - $(addprefix -I, $(BUILD_LIBMLIB_SRC)) \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libmlib_image +# We must not include java.desktop/unix/native/libmlib_image, which is only +# for usage by solaris-sparc in libmlib_image_v. +BUILD_LIBMLIB_EXCLUDE_SRC_PATTERNS := unix -BUILD_LIBMLIB_LDLIBS := - -BUILD_LIBMLIB_CFLAGS += -DMLIB_NO_LIBSUNMATH +BUILD_LIBMLIB_CFLAGS := -D__USE_J2D_NAMES -D__MEDIALIB_OLD_NAMES -DMLIB_NO_LIBSUNMATH ifeq ($(OPENJDK_TARGET_CPU_BITS), 64) BUILD_LIBMLIB_CFLAGS += -DMLIB_OS64BIT endif -ifneq ($(OPENJDK_TARGET_OS), windows) - BUILD_LIBMLIB_LDLIBS += $(LIBM) $(LIBDL) -endif - $(eval $(call SetupJdkLibrary, BUILD_LIBMLIB_IMAGE, \ NAME := mlib_image, \ - SRC := $(BUILD_LIBMLIB_SRC), \ + EXTRA_SRC := common/awt/medialib, \ EXCLUDE_FILES := mlib_c_ImageBlendTable.c, \ + EXCLUDE_SRC_PATTERNS := $(BUILD_LIBMLIB_EXCLUDE_SRC_PATTERNS), \ OPTIMIZATION := HIGHEST, \ CFLAGS := $(CFLAGS_JDKLIB) \ $(BUILD_LIBMLIB_CFLAGS), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ - LIBS := $(BUILD_LIBMLIB_LDLIBS) \ - $(JDKLIB_LIBS), \ + LIBS := $(JDKLIB_LIBS), \ + LIBS_unix := $(LIBM) $(LIBDL), \ )) $(BUILD_LIBMLIB_IMAGE): $(call FindLib, java.base, java) @@ -68,14 +69,19 @@ TARGETS += $(BUILD_LIBMLIB_IMAGE) ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH), solaris-sparc) - LIBMLIB_IMAGE_V_SRC := $(TOPDIR)/src/java.desktop/share/native/libmlib_image \ - $(TOPDIR)/src/java.desktop/unix/native/libmlib_image \ - $(TOPDIR)/src/java.desktop/share/native/common/awt/medialib \ - $(TOPDIR)/src/java.desktop/unix/native/common/awt/medialib \ - # - LIBMLIB_IMAGE_V_CFLAGS := $(TOPDIR)/src/java.desktop/unix/native/libmlib_image/vis_$(OPENJDK_TARGET_CPU_BITS).il \ - $(addprefix -I, $(LIBMLIB_IMAGE_V_SRC)) \ - # + # libmlib_image_v is basically built from mlib_image sources, with some additions + # and some exclusions. + LIBMLIB_IMAGE_V_SRC := \ + libmlib_image \ + common/awt/medialib \ + # + + LIBMLIB_IMAGE_V_CFLAGS := -xarch=sparcvis -D__USE_J2D_NAMES -D__MEDIALIB_OLD_NAMES \ + $(TOPDIR)/src/$(MODULE)/unix/native/libmlib_image/vis_$(OPENJDK_TARGET_CPU_BITS).il + + ifeq ($(OPENJDK_TARGET_CPU_BITS), 64) + LIBMLIB_IMAGE_V_CFLAGS += -DMLIB_OS64BIT + endif BUILD_LIBMLIB_IMAGE_V_EXFILES := \ awt_ImagingLib.c \ @@ -95,19 +101,16 @@ ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH), solaris-sparc) mlib_c_ImageLookUp_f.c \ # - LIBMLIB_IMAGE_V_CFLAGS += $(filter-out -DMLIB_NO_LIBSUNMATH, $(BUILD_LIBMLIB_CFLAGS)) - $(eval $(call SetupJdkLibrary, BUILD_LIBMLIB_IMAGE_V, \ NAME := mlib_image_v, \ SRC := $(LIBMLIB_IMAGE_V_SRC), \ EXCLUDE_FILES := $(BUILD_LIBMLIB_IMAGE_V_EXFILES), \ OPTIMIZATION := HIGHEST, \ - CFLAGS := -xarch=sparcvis \ - $(LIBMLIB_IMAGE_V_CFLAGS) \ - $(CFLAGS_JDKLIB), \ + CFLAGS := $(CFLAGS_JDKLIB) \ + $(LIBMLIB_IMAGE_V_CFLAGS), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ - LIBS := -ljava -ljvm $(BUILD_LIBMLIB_LDLIBS), \ + LIBS := -ljava -ljvm $(LIBM) $(LIBDL), \ )) $(BUILD_LIBMLIB_IMAGE_V): $(call FindLib, java.base, java) @@ -118,18 +121,22 @@ endif ################################################################################ -LIBAWT_DIRS := $(TOPDIR)/src/java.desktop/share/native/libawt \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libawt \ - $(TOPDIR)/src/java.desktop/share/native/common/awt/debug \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt \ +LIBAWT_EXTRA_SRC := \ + common/awt/debug \ + $(TOPDIR)/src/$(MODULE)/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt \ # -ifeq ($(OPENJDK_TARGET_OS), aix) - LIBAWT_DIRS += $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS)/native/libawt +ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH), solaris-sparc) + LIBAWT_EXTRA_SRC += $(TOPDIR)/src/$(MODULE)/share/native/common/awt/medialib endif ifeq ($(OPENJDK_TARGET_OS), windows) - LIBAWT_DIRS += $(TOPDIR)/src/java.desktop/share/native/common/awt/utility + LIBAWT_EXTRA_SRC += \ + $(TOPDIR)/src/$(MODULE)/share/native/common/awt/utility \ + $(TOPDIR)/src/$(MODULE)/share/native/common/font \ + $(TOPDIR)/src/$(MODULE)/share/native/common/java2d/opengl \ + $(TOPDIR)/src/$(MODULE)/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt/systemscale \ + # endif ifneq ($(filter $(OPENJDK_TARGET_OS), solaris linux macosx aix), ) @@ -140,33 +147,45 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) LIBAWT_EXFILES += initIDs.c awt/image/cvutils/img_colors.c endif -LIBAWT_CFLAGS += -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \ - $(addprefix -I, $(shell find $(LIBAWT_DIRS) -type d)) \ - $(LIBJAVA_HEADER_FLAGS) \ - $(addprefix -I, $(BUILD_LIBMLIB_IMAGE_SRC)) \ +ifeq ($(OPENJDK_TARGET_OS), windows) + LIBAWT_EXFILES += \ + java2d/d3d/D3DShaderGen.c \ + awt/image/cvutils/img_colors.c \ + # +endif + +ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU), solaris-sparcv9) + LIBAWT_EXFILES += java2d/loops/MapAccelFunc.c +else + LIBAWT_EXCLUDES += \ + $(TOPDIR)/src/$(MODULE)/unix/native/libawt/awt/medialib \ + $(TOPDIR)/src/$(MODULE)/unix/native/libawt/java2d/loops \ + $(TOPDIR)/src/$(MODULE)/unix/native/common/awt/medialib \ + # +endif + +LIBAWT_EXTRA_HEADER_DIRS := \ + $(LIBAWT_DEFAULT_HEADER_DIRS) \ + $(call GetJavaHeaderDir, java.base) \ + libawt/awt/medialib \ + libawt/java2d/d3d \ + libawt/java2d/opengl \ + libawt/java2d/windows \ + libawt/windows \ + common/awt/medialib \ + libmlib_image \ + include \ + java.base:libjava \ + java.base:include \ # LIBAWT_CFLAGS += -D__MEDIALIB_OLD_NAMES -D__USE_J2D_NAMES $(X_CFLAGS) -ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH), solaris-sparc) - LIBAWT_CFLAGS += -DMLIB_ADD_SUFF - LIBAWT_CFLAGS += -xarch=sparcvis +ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU), solaris-sparcv9) + LIBAWT_CFLAGS += -xarch=sparcvis -DMLIB_ADD_SUFF \ + $(TOPDIR)/src/$(MODULE)/unix/native/libmlib_image/vis_$(OPENJDK_TARGET_CPU_BITS).il - LIBAWT_CFLAGS += $(TOPDIR)/src/java.desktop/unix/native/libmlib_image/vis_$(OPENJDK_TARGET_CPU_BITS).il - LIBAWT_DIRS += $(TOPDIR)/src/java.desktop/share/native/common/awt/medialib - LIBAWT_EXFILES += java2d/loops/MapAccelFunc.c - - ifeq ($(OPENJDK_TARGET_CPU), sparcv9) - LIBAWT_ASFLAGS = -P -xarch=v9a - else - LIBAWT_ASFLAGS = -P -xarch=v8plusa - endif -else - LIBAWT_EXCLUDES += \ - $(TOPDIR)/src/java.desktop/unix/native/libawt/awt/medialib \ - $(TOPDIR)/src/java.desktop/unix/native/libawt/java2d/loops \ - $(TOPDIR)/src/java.desktop/unix/native/common/awt/medialib \ - # + LIBAWT_ASFLAGS = -P -xarch=v9a endif ifneq ($(OPENJDK_TARGET_OS), solaris) @@ -174,29 +193,13 @@ ifneq ($(OPENJDK_TARGET_OS), solaris) endif ifeq ($(OPENJDK_TARGET_OS), windows) - LIBAWT_DIRS += $(TOPDIR)/src/java.desktop/share/native/common/font \ - $(TOPDIR)/src/java.desktop/share/native/common/java2d/opengl \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt/systemscale \ - # Why does libawt need java.base headers? - LIBAWT_CFLAGS += -I$(TOPDIR)/src/java.desktop/share/native/common/font \ - -I$(TOPDIR)/src/java.desktop/share/native/common/java2d/opengl \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/java2d/opengl \ - -I$(TOPDIR)/src/java.desktop/windows/native/include \ - -I$(TOPDIR)/src/java.desktop/share/native/include \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.base \ - # - LIBAWT_EXFILES += \ - java2d/d3d/D3DShaderGen.c \ - awt/image/cvutils/img_colors.c \ - # - LIBAWT_CFLAGS += -EHsc -DUNICODE -D_UNICODE ifeq ($(OPENJDK_TARGET_CPU_BITS), 64) LIBAWT_CFLAGS += -DMLIB_OS64BIT endif LIBAWT_RC_FLAGS ?= -I $(TOPDIR)/src/java.base/windows/native/launcher/icons - LIBAWT_VERSIONINFO_RESOURCE := $(TOPDIR)/src/java.desktop/windows/native/libawt/windows/awt.rc + LIBAWT_VERSIONINFO_RESOURCE := $(TOPDIR)/src/$(MODULE)/windows/native/libawt/windows/awt.rc endif ifeq ($(OPENJDK_TARGET_OS), linux) @@ -215,11 +218,12 @@ endif $(eval $(call SetupJdkLibrary, BUILD_LIBAWT, \ NAME := awt, \ - SRC := $(LIBAWT_DIRS), \ + EXTRA_SRC := $(LIBAWT_EXTRA_SRC), \ EXCLUDES := $(LIBAWT_EXCLUDES), \ EXCLUDE_FILES := $(LIBAWT_EXFILES), \ OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) $(LIBAWT_CFLAGS), \ + EXTRA_HEADER_DIRS := $(LIBAWT_EXTRA_HEADER_DIRS), \ DISABLED_WARNINGS_gcc := sign-compare unused-result maybe-uninitialized \ format-nonliteral parentheses, \ DISABLED_WARNINGS_clang := logical-op-parentheses extern-initializer, \ @@ -265,39 +269,26 @@ TARGETS += $(BUILD_LIBAWT) ################################################################################ -ifeq ($(findstring $(OPENJDK_TARGET_OS),windows macosx),) +ifeq ($(findstring $(OPENJDK_TARGET_OS), windows macosx), ) ifeq ($(ENABLE_HEADLESS_ONLY), false) - LIBAWT_XAWT_DIRS := \ - $(wildcard $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS)/native/libawt_xawt) \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libawt_xawt \ - $(TOPDIR)/src/java.desktop/share/native/common/awt/debug \ - $(TOPDIR)/src/java.desktop/share/native/common/awt/utility \ - $(TOPDIR)/src/java.desktop/share/native/common/font \ - $(TOPDIR)/src/java.desktop/share/native/common/java2d \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/java2d \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt \ + LIBAWT_XAWT_EXTRA_SRC := \ + common/awt \ + common/java2d \ + common/font \ # - ifneq ($(filter $(OPENJDK_TARGET_OS),linux solaris aix), ) - LIBAWT_XAWT_DIRS += $(TOPDIR)/src/java.desktop/unix/native/common/awt/systemscale - endif - LIBAWT_XAWT_EXCLUDES := medialib - LIBAWT_XAWT_CFLAGS := $(addprefix -I, $(shell $(FIND) $(LIBAWT_XAWT_DIRS) -type d)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \ - -I$(TOPDIR)/src/java.desktop/share/native/include \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS)/native/include \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/include \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/java2d \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libawt/java2d \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/java2d/loops \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/java2d/pipe \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/awt/image/cvutils \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/awt/image \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/font \ - $(LIBJAVA_HEADER_FLAGS) + LIBAWT_XAWT_EXTRA_HEADER_DIRS := \ + $(LIBAWT_DEFAULT_HEADER_DIRS) \ + libawt_xawt/awt \ + include \ + common/awt/debug \ + common/awt/systemscale \ + common/font \ + common/java2d/opengl \ + common/java2d/x11 \ # LIBAWT_XAWT_CFLAGS += -DXAWT -DXAWT_HACK \ @@ -334,7 +325,8 @@ ifeq ($(findstring $(OPENJDK_TARGET_OS),windows macosx),) $(eval $(call SetupJdkLibrary, BUILD_LIBAWT_XAWT, \ NAME := awt_xawt, \ - SRC := $(LIBAWT_XAWT_DIRS), \ + EXTRA_SRC := $(LIBAWT_XAWT_EXTRA_SRC), \ + EXTRA_HEADER_DIRS := $(LIBAWT_XAWT_EXTRA_HEADER_DIRS), \ EXCLUDES := $(LIBAWT_XAWT_EXCLUDES), \ OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) $(LIBAWT_XAWT_CFLAGS) \ @@ -350,10 +342,6 @@ ifeq ($(findstring $(OPENJDK_TARGET_OS),windows macosx),) $(call SET_SHARED_LIBRARY_ORIGIN) \ -L$(INSTALL_LIBRARIES_HERE), \ LIBS := $(X_LIBS) $(LIBAWT_XAWT_LIBS), \ - RC_FLAGS := $(RC_FLAGS) \ - -D "JDK_FNAME=xawt.dll" \ - -D "JDK_INTERNAL_NAME=xawt" \ - -D "JDK_FTYPE=0x2L", \ )) $(BUILD_LIBAWT_XAWT): $(call FindLib, java.base, java) @@ -367,36 +355,34 @@ endif ################################################################################ -LIBLCMS_SRC := $(TOPDIR)/src/java.desktop/share/native/liblcms -LIBLCMS_CPPFLAGS += -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/java2d \ - -I$(TOPDIR)/src/java.desktop/share/native/common/awt/debug \ - $(LIBJAVA_HEADER_FLAGS) \ - # # The fast floor code loses precision. LCMS_CFLAGS=-DCMS_DONT_USE_FAST_FLOOR +LCMS_CFLAGS_JDKLIB := $(filter-out -xc99=%none, $(CFLAGS_JDKLIB)) + ifeq ($(USE_EXTERNAL_LCMS), true) # If we're using an external library, we'll just need the wrapper part. # By including it explicitly, all other files will be excluded. BUILD_LIBLCMS_INCLUDE_FILES := LCMS.c + # If we're using an external library, we can't include our own SRC path + # as includes, instead the system headers should be used. + LIBLCMS_HEADERS_FROM_SRC := false else BUILD_LIBLCMS_INCLUDE_FILES := - # If we're using the bundled library, we'll need to include it in the - # include path explicitly. Otherwise the system headers will be used. - LIBLCMS_CPPFLAGS += $(addprefix -I, $(LIBLCMS_SRC)) endif $(eval $(call SetupJdkLibrary, BUILD_LIBLCMS, \ NAME := lcms, \ - SRC := $(LIBLCMS_SRC), \ INCLUDE_FILES := $(BUILD_LIBLCMS_INCLUDE_FILES), \ OPTIMIZATION := HIGHEST, \ - CFLAGS := $(filter-out -xc99=%none, $(CFLAGS_JDKLIB)) \ - $(LIBLCMS_CPPFLAGS) \ + CFLAGS := $(LCMS_CFLAGS_JDKLIB) \ $(LCMS_CFLAGS), \ CFLAGS_solaris := -xc99=no_lib, \ CFLAGS_windows := -DCMS_IS_WINDOWS_, \ + EXTRA_HEADER_DIRS := \ + common/awt/debug \ + libawt/java2d, \ + HEADERS_FROM_SRC := $(LIBLCMS_HEADERS_FROM_SRC), \ DISABLED_WARNINGS_gcc := format-nonliteral type-limits misleading-indentation, \ DISABLED_WARNINGS_clang := tautological-compare, \ DISABLED_WARNINGS_solstudio := E_STATEMENT_NOT_REACHED, \ @@ -414,8 +400,6 @@ $(BUILD_LIBLCMS): $(BUILD_LIBAWT) ################################################################################ -LIBJAVAJPEG_SRC += $(TOPDIR)/src/java.desktop/share/native/libjavajpeg - # "DISABLED_WARNINGS_gcc := clobbered" rationale: # Suppress gcc warnings like "variable might be clobbered by 'longjmp' # or 'vfork'": this warning indicates that some variable is placed to @@ -429,21 +413,20 @@ ifeq ($(USE_EXTERNAL_LIBJPEG), true) BUILD_LIBJAVAJPEG_INCLUDE_FILES := \ imageioJPEG.c \ jpegdecoder.c - BUILD_LIBJAVAJPEG_HEADERS := + # If we're using an external library, we can't include our own SRC path + # as includes, instead the system headers should be used. + LIBJPEG_HEADERS_FROM_SRC := false else LIBJPEG_LIBS := BUILD_LIBJAVAJPEG_INCLUDE_FILES := - BUILD_LIBJAVAJPEG_HEADERS := $(addprefix -I, $(LIBJAVAJPEG_SRC)) endif $(eval $(call SetupJdkLibrary, BUILD_LIBJAVAJPEG, \ NAME := javajpeg, \ - SRC := $(LIBJAVAJPEG_SRC), \ INCLUDE_FILES := $(BUILD_LIBJAVAJPEG_INCLUDE_FILES), \ OPTIMIZATION := HIGHEST, \ - CFLAGS := $(CFLAGS_JDKLIB) $(BUILD_LIBJAVAJPEG_HEADERS) \ - $(LIBJAVA_HEADER_FLAGS) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop, \ + CFLAGS := $(CFLAGS_JDKLIB), \ + HEADERS_FROM_SRC := $(LIBJPEG_HEADERS_FROM_SRC), \ DISABLED_WARNINGS_gcc := clobbered implicit-fallthrough shift-negative-value, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ @@ -460,42 +443,32 @@ TARGETS += $(BUILD_LIBJAVAJPEG) # Mac and Windows only use the native AWT lib, do not build libawt_headless ifeq ($(findstring $(OPENJDK_TARGET_OS), windows macosx),) - LIBAWT_HEADLESS_DIRS := $(TOPDIR)/src/java.desktop/unix/native/libawt_headless/awt \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/java2d \ - $(TOPDIR)/src/java.desktop/share/native/common/java2d \ - $(TOPDIR)/src/java.desktop/share/native/common/font \ + LIBAWT_HEADLESS_EXTRA_SRC := \ + common/font \ + common/java2d \ + $(TOPDIR)/src/$(MODULE)/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt \ # LIBAWT_HEADLESS_EXCLUDES := medialib - LIBAWT_HEADLESS_CFLAGS := -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \ - $(addprefix -I, $(LIBAWT_HEADLESS_DIRS)) \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/awt/image \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/awt/image/cvutils \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/java2d \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libawt/java2d \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/java2d/loops \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/java2d/pipe \ - -I$(TOPDIR)/src/java.desktop/share/native/common/awt/debug \ - -I$(TOPDIR)/src/java.desktop/share/native/common/font \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/font \ - -I$(TOPDIR)/src/java.desktop/share/native/common/java2d/opengl \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/java2d/opengl \ - $(LIBJAVA_HEADER_FLAGS) \ + + LIBAWT_HEADLESS_EXTRA_HEADER_DIRS := \ + $(LIBAWT_DEFAULT_HEADER_DIRS) \ + common/awt/debug \ + common/font \ + common/java2d/opengl \ # + LIBAWT_HEADLESS_CFLAGS := $(CUPS_CFLAGS) $(FONTCONFIG_CFLAGS) $(X_CFLAGS) \ + -DHEADLESS=true -DPACKAGE_PATH=\"$(PACKAGE_PATH)\" + $(eval $(call SetupJdkLibrary, BUILD_LIBAWT_HEADLESS, \ NAME := awt_headless, \ - SRC := $(LIBAWT_HEADLESS_DIRS), \ + EXTRA_SRC := $(LIBAWT_HEADLESS_EXTRA_SRC), \ EXCLUDES := $(LIBAWT_HEADLESS_EXCLUDES), \ OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) \ - -DHEADLESS=true \ - -DPACKAGE_PATH=\"$(PACKAGE_PATH)\" \ - $(CUPS_CFLAGS) \ - $(FONTCONFIG_CFLAGS) \ - $(X_CFLAGS) \ $(LIBAWT_HEADLESS_CFLAGS), \ + EXTRA_HEADER_DIRS := $(LIBAWT_HEADLESS_EXTRA_HEADER_DIRS), \ DISABLED_WARNINGS_xlc := 1506-356, \ DISABLED_WARNINGS_solstudio := E_EMPTY_TRANSLATION_UNIT, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ @@ -519,12 +492,15 @@ endif ################################################################################ ifeq ($(FREETYPE_TO_USE), system) + # For use by libfontmanager: LIBFREETYPE_CFLAGS := $(FREETYPE_CFLAGS) LIBFREETYPE_LIBS := $(FREETYPE_LIBS) else - LIBFREETYPE_SRC := $(TOPDIR)/src/java.desktop/share/native/libfreetype - BUILD_LIBFREETYPE_HEADERS := $(addprefix -I, $(LIBFREETYPE_SRC)/include) - LIBFREETYPE_CFLAGS := $(BUILD_LIBFREETYPE_HEADERS) + BUILD_LIBFREETYPE_HEADER_DIRS := $(TOPDIR)/src/$(MODULE)/share/native/libfreetype/include + BUILD_LIBFREETYPE_CFLAGS := -DFT2_BUILD_LIBRARY $(EXPORT_ALL_SYMBOLS) + + # For use by libfontmanager: + LIBFREETYPE_CFLAGS := -I$(BUILD_LIBFREETYPE_HEADER_DIRS) ifeq ($(OPENJDK_TARGET_OS), windows) LIBFREETYPE_LIBS := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libfreetype/freetype.lib else @@ -533,10 +509,10 @@ else $(eval $(call SetupJdkLibrary, BUILD_LIBFREETYPE, \ NAME := freetype, \ - SRC := $(LIBFREETYPE_SRC)/src, \ OPTIMIZATION := HIGHEST, \ - CFLAGS := $(CFLAGS_JDKLIB) $(BUILD_LIBFREETYPE_HEADERS) \ - -DFT2_BUILD_LIBRARY $(EXPORT_ALL_SYMBOLS), \ + CFLAGS := $(CFLAGS_JDKLIB) \ + $(BUILD_LIBFREETYPE_CFLAGS), \ + EXTRA_HEADER_DIRS := $(BUILD_LIBFREETYPE_HEADER_DIRS), \ DISABLED_WARNINGS_solstudio := \ E_STATEMENT_NOT_REACHED \ E_END_OF_LOOP_CODE_NOT_REACHED, \ @@ -550,19 +526,6 @@ endif ########################################################################### -LIBFONTMANAGER_SRC := $(TOPDIR)/src/java.desktop/share/native/libfontmanager \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libfontmanager -LIBFONTMANAGER_CFLAGS := \ - $(addprefix -I, $(shell $(FIND) \ - $(LIBFONTMANAGER_SRC) \ - $(TOPDIR)/src/java.desktop/share/native/libawt \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libawt \ - $(TOPDIR)/src/java.desktop/share/native/common \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common -type d)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \ - $(LIBJAVA_HEADER_FLAGS) \ - # - #### Begin harfbuzz configuration HARFBUZZ_CFLAGS := -DHAVE_OT -DHAVE_FALLBACK -DHAVE_UCDN @@ -590,6 +553,16 @@ LIBFONTMANAGER_CFLAGS += $(HARFBUZZ_CFLAGS) #### End harfbuzz configuration +LIBFONTMANAGER_EXTRA_HEADER_DIRS := \ + libfontmanager/harfbuzz \ + libfontmanager/harfbuzz/hb-ucdn \ + common/awt \ + common/font \ + libawt/java2d \ + libawt/java2d/pipe \ + libawt/java2d/loops \ + # + LIBFONTMANAGER_CFLAGS += $(LIBFREETYPE_CFLAGS) BUILD_LIBFONTMANAGER_FONTLIB += $(LIBFREETYPE_LIBS) @@ -599,7 +572,6 @@ ifeq ($(OPENJDK_TARGET_OS), windows) LIBFONTMANAGER_EXCLUDE_FILES += X11FontScaler.c \ X11TextRenderer.c LIBFONTMANAGER_OPTIMIZATION := HIGHEST - LIBFONTMANAGER_CFLAGS += -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libawt/windows else ifeq ($(OPENJDK_TARGET_OS), macosx) LIBFONTMANAGER_EXCLUDE_FILES += X11FontScaler.c \ X11TextRenderer.c \ @@ -610,7 +582,7 @@ else lcdglyph.c endif -LIBFONTMANAGER_CFLAGS += $(FONT_HEADERS) $(X_CFLAGS) -DLE_STANDALONE -DHEADLESS +LIBFONTMANAGER_CFLAGS += $(X_CFLAGS) -DLE_STANDALONE -DHEADLESS ifeq ($(TOOLCHAIN_TYPE), gcc) # Turn off all warnings for sunFont.c. This is needed because the specific warning @@ -626,7 +598,6 @@ endif # libawt_xawt). See JDK-8196516 for details. $(eval $(call SetupJdkLibrary, BUILD_LIBFONTMANAGER, \ NAME := fontmanager, \ - SRC := $(LIBFONTMANAGER_SRC), \ EXCLUDE_FILES := $(LIBFONTMANAGER_EXCLUDE_FILES) \ AccelGlyphCache.c, \ TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ @@ -634,6 +605,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBFONTMANAGER, \ CXXFLAGS := $(CXXFLAGS_JDKLIB) $(LIBFONTMANAGER_CFLAGS), \ OPTIMIZATION := $(LIBFONTMANAGER_OPTIMIZATION), \ CFLAGS_windows = -DCC_NOEX, \ + EXTRA_HEADER_DIRS := $(LIBFONTMANAGER_EXTRA_HEADER_DIRS), \ WARNINGS_AS_ERRORS_xlc := false, \ DISABLED_WARNINGS_gcc := sign-compare int-to-pointer-cast \ type-limits missing-field-initializers implicit-fallthrough, \ @@ -665,7 +637,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBFONTMANAGER, \ $(BUILD_LIBFONTMANAGER): $(BUILD_LIBAWT) ifeq ($(OPENJDK_TARGET_OS), macosx) - $(BUILD_LIBFONTMANAGER): $(call FindLib, java.desktop, awt_lwawt) + $(BUILD_LIBFONTMANAGER): $(call FindLib, $(MODULE), awt_lwawt) endif ifeq ($(FREETYPE_TO_USE), bundled) @@ -677,29 +649,30 @@ TARGETS += $(BUILD_LIBFONTMANAGER) ################################################################################ ifeq ($(OPENJDK_TARGET_OS), windows) - LIBJAWT_SRC := $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libjawt - LIBJAWT_CFLAGS := -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libawt/windows \ - -I$(TOPDIR)/src/java.desktop/share/native/common/awt/debug \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/java2d \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/awt/image/cvutils \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libawt/java2d/windows \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \ - -I$(TOPDIR)/src/java.desktop/windows/native/include \ - -I$(TOPDIR)/src/java.desktop/share/native/include \ - $(LIBJAVA_HEADER_FLAGS) \ + + LIBJAWT_CFLAGS := -EHsc -DUNICODE -D_UNICODE + + LIBJAWT_EXTRA_HEADER_DIRS := \ + include \ + common/awt/debug \ + libawt/awt/image/cvutils \ + libawt/java2d \ + libawt/java2d/windows \ + libawt/windows \ + java.base:include \ + java.base:libjava \ # ifeq ($(OPENJDK_TARGET_CPU), x86) KERNEL32_LIB := kernel32.lib endif + $(eval $(call SetupJdkLibrary, BUILD_LIBJAWT, \ NAME := jawt, \ - SRC := $(LIBJAWT_SRC), \ - INCLUDE_FILES := $(LIBJAWT_INCLUDE_FILES), \ OPTIMIZATION := LOW, \ CFLAGS := $(CXXFLAGS_JDKLIB) \ - -EHsc -DUNICODE -D_UNICODE \ $(LIBJAWT_CFLAGS), \ + EXTRA_HEADER_DIRS := $(LIBJAWT_EXTRA_HEADER_DIRS), \ LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK), \ LIBS := $(JDKLIB_LIBS) $(KERNEL32_LIB) advapi32.lib $(WIN_AWT_LIB), \ )) @@ -718,17 +691,9 @@ ifeq ($(OPENJDK_TARGET_OS), windows) else # OPENJDK_TARGET_OS not windows ifeq ($(OPENJDK_TARGET_OS), macosx) - LIBJAWT_SRC := $(TOPDIR)/src/java.desktop/macosx/native/libjawt - else - LIBJAWT_SRC := $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libjawt + # libjawt on macosx do not use the unix code + LIBJAWT_EXCLUDE_SRC_PATTERNS := unix endif - LIBJAWT_CFLAGS := \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS)/native/include \ - -I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/include \ - -I$(TOPDIR)/src/java.desktop/share/native/include \ - $(LIBJAVA_HEADER_FLAGS) \ - # ifeq ($(OPENJDK_TARGET_OS), macosx) JAWT_LIBS := -lawt_lwawt @@ -741,19 +706,22 @@ else # OPENJDK_TARGET_OS not windows JAWT_LIBS += -lawt_xawt else JAWT_LIBS += -lawt_headless - HEADLESS_CFLAG += -DHEADLESS + ifeq ($(OPENJDK_TARGET_OS), linux) + JAWT_CFLAGS += -DHEADLESS + endif endif endif $(eval $(call SetupJdkLibrary, BUILD_LIBJAWT, \ NAME := jawt, \ - SRC := $(LIBJAWT_SRC), \ + EXCLUDE_SRC_PATTERNS := $(LIBJAWT_EXCLUDE_SRC_PATTERNS), \ INCLUDE_FILES := $(JAWT_FILES), \ OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) \ - $(LIBJAWT_CFLAGS), \ - CFLAGS_linux := $(HEADLESS_CFLAG), \ - CFLAGS_macosx := $(LIBJAWT_CFLAGS_macosx), \ + $(JAWT_CFLAGS), \ + EXTRA_HEADER_DIRS := \ + include \ + common/awt, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LDFLAGS_unix := -L$(INSTALL_LIBRARIES_HERE), \ @@ -781,52 +749,56 @@ TARGETS += $(BUILD_LIBJAWT) ifeq ($(ENABLE_HEADLESS_ONLY), false) - LIBSPLASHSCREEN_DIRS := \ - $(TOPDIR)/src/java.desktop/share/native/libjavajpeg \ - $(TOPDIR)/src/java.desktop/share/native/libsplashscreen \ + LIBSPLASHSCREEN_EXTRA_SRC := \ + common/awt/systemscale \ # - ifeq ($(USE_EXTERNAL_LIBGIF), true) - GIFLIB_LIBS := -lgif - LIBSPLASHSCREEN_EXCLUDES := giflib + ifeq ($(USE_EXTERNAL_LIBGIF), false) + LIBSPLASHSCREEN_HEADER_DIRS += libsplashscreen/giflib else - LIBSPLASHSCREEN_CFLAGS += -I$(TOPDIR)/src/java.desktop/share/native/libsplashscreen/giflib + LIBSPLASHSCREEN_EXCLUDES := giflib + GIFLIB_LIBS := -lgif endif - ifeq ($(USE_EXTERNAL_LIBJPEG), true) - LIBJPEG_LIBS := -ljpeg + ifeq ($(USE_EXTERNAL_LIBJPEG), false) + # While the following ought to work, it will currently pull in the closed + # additions to this library, and this was not done previously in the build. + # LIBSPLASHSCREEN_EXTRA_SRC += libjavajpeg + LIBSPLASHSCREEN_EXTRA_SRC += $(TOPDIR)/src/java.desktop/share/native/libjavajpeg else - LIBSPLASHSCREEN_DIRS += $(TOPDIR)/src/java.desktop/share/native/libjavajpeg - LIBJPEG_CFLAGS := -I$(TOPDIR)/src/java.desktop/share/native/libjavajpeg + LIBJPEG_LIBS := -ljpeg endif ifeq ($(USE_EXTERNAL_LIBPNG), false) - LIBSPLASHSCREEN_DIRS += $(TOPDIR)/src/java.desktop/share/native/libsplashscreen/libpng + LIBSPLASHSCREEN_HEADER_DIRS += libsplashscreen/libpng + + ifeq ($(OPENJDK_TARGET_OS), macosx) + ifeq ($(USE_EXTERNAL_LIBZ), true) + # When building our own libpng and using an external libz, we need to + # inject our own libz.h to tweak the exported ZLIB_VERNUM macro. See + # $(TOPDIR)/src/java.desktop/macosx/native/libsplashscreen/libpng/zlibwrapper/zlib.h + # for details. This must be specified with -iquote, not -I to avoid a + # circular include. + LIBSPLASHSCREEN_CFLAGS += -iquote $(TOPDIR)/src/$(MODULE)/macosx/native/libsplashscreen/libpng/zlibwrapper + endif + endif else LIBSPLASHSCREEN_EXCLUDES += libpng endif - ifneq ($(OPENJDK_TARGET_OS), macosx) - LIBSPLASHSCREEN_DIRS += $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libsplashscreen - else - LIBSPLASHSCREEN_DIRS += $(TOPDIR)/src/java.desktop/macosx/native/libsplashscreen + ifeq ($(USE_EXTERNAL_LIBZ), false) + LIBSPLASHSCREEN_EXTRA_SRC += java.base:libzip/zlib endif - ifneq ($(filter $(OPENJDK_TARGET_OS),linux solaris aix), ) - LIBSPLASHSCREEN_DIRS += $(TOPDIR)/src/java.desktop/unix/native/common/awt/systemscale + ifeq ($(OPENJDK_TARGET_OS), macosx) + # libsplashscreen on macosx do not use the unix code + LIBSPLASHSCREEN_EXCLUDE_SRC_PATTERNS := unix endif - ifeq ($(OPENJDK_TARGET_OS), windows) - LIBSPLASHSCREEN_DIRS += $(TOPDIR)/src/java.desktop/windows/native/common/awt/systemscale - endif - LIBSPLASHSCREEN_CFLAGS += -DSPLASHSCREEN -DPNG_NO_MMX_CODE -DPNG_ARM_NEON_OPT=0 \ - $(addprefix -I, $(LIBSPLASHSCREEN_DIRS)) \ - $(LIBJAVA_HEADER_FLAGS) \ - # + LIBSPLASHSCREEN_CFLAGS += -DSPLASHSCREEN -DPNG_NO_MMX_CODE -DPNG_ARM_NEON_OPT=0 ifeq ($(OPENJDK_TARGET_OS), macosx) LIBSPLASHSCREEN_CFLAGS += -DWITH_MACOSX - LIBSPLASHSCREEN_CFLAGS += -I$(TOPDIR)/src/java.desktop/macosx/native/libosxapp BUILD_LIBSPLASHSCREEN_java_awt_SplashScreen.c_CFLAGS := -x objective-c -O0 BUILD_LIBSPLASHSCREEN_splashscreen_gfx_impl.c_CFLAGS := -x objective-c -O0 @@ -844,20 +816,6 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false) LIBSPLASHSCREEN_LIBS := - ifeq ($(USE_EXTERNAL_LIBZ), false) - LIBSPLASHSCREEN_DIRS += $(TOPDIR)/src/java.base/share/native/libzip/zlib - else - ifeq ($(OPENJDK_TARGET_OS), macosx) - ifeq ($(USE_EXTERNAL_LIBPNG), false) - # When building our own libpng and using an external libz, we need to - # inject our own libz.h to tweak the exported ZLIB_VERNUM macro. See - # $(TOPDIR)/src/java.desktop/macosx/native/libsplashscreen/libpng/zlib.h - # for details. - LIBSPLASHSCREEN_CFLAGS += -iquote $(TOPDIR)/src/java.desktop/macosx/native/libsplashscreen/libpng - endif - endif - endif - ifeq ($(OPENJDK_TARGET_OS), macosx) LIBSPLASHSCREEN_LIBS += \ $(LIBM) -lpthread -liconv -losxapp \ @@ -871,14 +829,22 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false) LIBSPLASHSCREEN_LIBS += $(X_LIBS) -lX11 -lXext $(LIBM) -lpthread -ldl endif + LIBSPLASHSCREEN_HEADER_DIRS += \ + libosxapp \ + java.base:include \ + java.base:libjava \ + # + $(eval $(call SetupJdkLibrary, BUILD_LIBSPLASHSCREEN, \ NAME := splashscreen, \ - SRC := $(LIBSPLASHSCREEN_DIRS), \ + EXTRA_SRC := $(LIBSPLASHSCREEN_EXTRA_SRC), \ + EXCLUDE_SRC_PATTERNS := $(LIBSPLASHSCREEN_EXCLUDE_SRC_PATTERNS), \ EXCLUDE_FILES := imageioJPEG.c jpegdecoder.c pngtest.c, \ EXCLUDES := $(LIBSPLASHSCREEN_EXCLUDES), \ OPTIMIZATION := LOW, \ - CFLAGS := $(LIBSPLASHSCREEN_CFLAGS) $(CFLAGS_JDKLIB) \ + CFLAGS := $(CFLAGS_JDKLIB) $(LIBSPLASHSCREEN_CFLAGS) \ $(GIFLIB_CFLAGS) $(LIBJPEG_CFLAGS) $(PNG_CFLAGS) $(LIBZ_CFLAGS), \ + EXTRA_HEADER_DIRS := $(LIBSPLASHSCREEN_HEADER_DIRS), \ DISABLED_WARNINGS_gcc := sign-compare type-limits unused-result \ maybe-uninitialized shift-negative-value implicit-fallthrough, \ DISABLED_WARNINGS_clang := incompatible-pointer-types, \ @@ -897,7 +863,7 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false) TARGETS += $(BUILD_LIBSPLASHSCREEN) ifeq ($(OPENJDK_TARGET_OS), macosx) - $(BUILD_LIBSPLASHSCREEN): $(call FindLib, java.desktop, osxapp) + $(BUILD_LIBSPLASHSCREEN): $(call FindLib, $(MODULE), osxapp) endif endif @@ -906,49 +872,38 @@ endif ifeq ($(OPENJDK_TARGET_OS), macosx) - LIBAWT_LWAWT_DIRS := \ - $(TOPDIR)/src/java.desktop/macosx/native/libawt_lwawt \ - $(TOPDIR)/src/java.desktop/unix/native/common/awt \ - $(TOPDIR)/src/java.desktop/share/native/common/font \ - $(TOPDIR)/src/java.desktop/share/native/common/java2d \ + LIBAWT_LWAWT_EXTRA_SRC := \ + $(TOPDIR)/src/$(MODULE)/unix/native/common/awt \ + $(TOPDIR)/src/$(MODULE)/share/native/common/font \ + $(TOPDIR)/src/$(MODULE)/share/native/common/java2d \ # - LIBAWT_LWAWT_CFLAGS := \ - $(addprefix -I, $(LIBAWT_LWAWT_DIRS)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \ - -I$(TOPDIR)/src/java.desktop/macosx/native/libawt_lwawt/awt \ - -I$(TOPDIR)/src/java.desktop/unix/native/libawt_xawt/awt \ - -I$(TOPDIR)/src/java.desktop/macosx/native/libawt_lwawt/font \ - -I$(TOPDIR)/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl \ - -I$(TOPDIR)/src/java.desktop/share/native/common/awt/debug \ - -I$(TOPDIR)/src/java.desktop/share/native/common/java2d/opengl \ - -I$(TOPDIR)/src/java.desktop/macosx/native/include \ - -I$(TOPDIR)/src/java.desktop/share/native/include \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/awt/image \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/awt/image/cvutils \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/java2d \ - -I$(TOPDIR)/src/java.desktop/unix/native/libawt/java2d \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/java2d/loops \ - -I$(TOPDIR)/src/java.desktop/share/native/libawt/java2d/pipe \ - -I$(TOPDIR)/src/java.desktop/share/native/libmlib_image/ \ - -I$(TOPDIR)/src/java.desktop/macosx/native/libosxapp \ - $(LIBJAVA_HEADER_FLAGS) \ + LIBAWT_LWAWT_EXTRA_HEADER_DIRS := \ + $(LIBAWT_DEFAULT_HEADER_DIRS) \ + libawt_lwawt/awt \ + libawt_lwawt/font \ + libawt_lwawt/java2d/opengl \ + include \ + common/awt/debug \ + common/java2d/opengl \ + libosxapp \ # + LIBAWT_LWAWT_CFLAGS := $(X_CFLAGS) $(X_LIBS) + LIBAWT_LWAWT_EXFILES := fontpath.c awt_Font.c X11Color.c - LIBAWT_LWAWT_EXCLUDES := $(TOPDIR)/src/java.desktop/unix/native/common/awt/medialib + LIBAWT_LWAWT_EXCLUDES := $(TOPDIR)/src/$(MODULE)/unix/native/common/awt/medialib $(eval $(call SetupJdkLibrary, BUILD_LIBAWT_LWAWT, \ NAME := awt_lwawt, \ - SRC := $(LIBAWT_LWAWT_DIRS), \ + EXTRA_SRC := $(LIBAWT_LWAWT_EXTRA_SRC), \ INCLUDE_FILES := $(LIBAWT_LWAWT_FILES), \ EXCLUDE_FILES := $(LIBAWT_LWAWT_EXFILES), \ EXCLUDES := $(LIBAWT_LWAWT_EXCLUDES), \ OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) \ - $(X_CFLAGS) \ - $(X_LIBS) \ $(LIBAWT_LWAWT_CFLAGS), \ + EXTRA_HEADER_DIRS := $(LIBAWT_LWAWT_EXTRA_HEADER_DIRS), \ DISABLED_WARNINGS_clang := incomplete-implementation enum-conversion \ deprecated-declarations objc-method-access bitwise-op-parentheses \ incompatible-pointer-types parentheses-equality extra-tokens, \ @@ -975,7 +930,7 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) $(BUILD_LIBAWT_LWAWT): $(BUILD_LIBMLIB_IMAGE) - $(BUILD_LIBAWT_LWAWT): $(call FindLib, java.desktop, osxapp) + $(BUILD_LIBAWT_LWAWT): $(call FindLib, $(MODULE), osxapp) $(BUILD_LIBAWT_LWAWT): $(call FindLib, java.base, java) @@ -987,15 +942,11 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) $(eval $(call SetupJdkLibrary, BUILD_LIBOSXUI, \ NAME := osxui, \ - SRC := $(TOPDIR)/src/java.desktop/macosx/native/libosxui, \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - -I$(TOPDIR)/src/java.desktop/macosx/native/libosxui \ - -I$(TOPDIR)/src/java.desktop/macosx/native/libawt_lwawt/awt \ - -I$(TOPDIR)/src/java.desktop/macosx/native/libosxapp \ - -I$(TOPDIR)/src/java.base/share/native/libjava \ - -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjava \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop, \ + CFLAGS := $(CFLAGS_JDKLIB), \ + EXTRA_HEADER_DIRS := \ + libawt_lwawt/awt \ + libosxapp, \ DISABLED_WARNINGS_clang := deprecated-declarations, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN) \ @@ -1014,7 +965,7 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) $(BUILD_LIBOSXUI): $(BUILD_LIBAWT) - $(BUILD_LIBOSXUI): $(call FindLib, java.desktop, osxapp) + $(BUILD_LIBOSXUI): $(call FindLib, $(MODULE), osxapp) $(BUILD_LIBOSXUI): $(BUILD_LIBAWT_LWAWT) diff --git a/make/lib/CoreLibraries.gmk b/make/lib/CoreLibraries.gmk index 316f014c528..46edc878893 100644 --- a/make/lib/CoreLibraries.gmk +++ b/make/lib/CoreLibraries.gmk @@ -104,7 +104,6 @@ endif $(eval $(call SetupJdkLibrary, BUILD_LIBVERIFY, \ NAME := verify, \ - SRC := $(TOPDIR)/src/java.base/share/native/libverify, \ OPTIMIZATION := $(LIBVERIFY_OPTIMIZATION), \ CFLAGS := $(CFLAGS_JDKLIB), \ DISABLED_WARNINGS_gcc := implicit-fallthrough, \ @@ -119,13 +118,7 @@ TARGETS += $(BUILD_LIBVERIFY) ########################################################################################## -# Allow a custom makefile to add extra src dirs -LIBJAVA_SRC_DIRS += $(call FindSrcDirsForLib, java.base, java) - -LIBJAVA_CFLAGS := $(addprefix -I, $(LIBJAVA_SRC_DIRS)) \ - -I$(TOPDIR)/src/java.base/share/native/libfdlibm \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.base \ - -DARCHPROPNAME='"$(OPENJDK_TARGET_CPU_OSARCH)"' +LIBJAVA_CFLAGS := -DARCHPROPNAME='"$(OPENJDK_TARGET_CPU_OSARCH)"' ifeq ($(OPENJDK_TARGET_OS), macosx) BUILD_LIBJAVA_java_props_md.c_CFLAGS := -x objective-c @@ -134,12 +127,12 @@ endif $(eval $(call SetupJdkLibrary, BUILD_LIBJAVA, \ NAME := java, \ - SRC := $(LIBJAVA_SRC_DIRS), \ OPTIMIZATION := HIGH, \ CFLAGS := $(CFLAGS_JDKLIB) \ $(LIBJAVA_CFLAGS), \ System.c_CFLAGS := $(VERSION_CFLAGS), \ jdk_util.c_CFLAGS := $(VERSION_CFLAGS), \ + EXTRA_HEADER_DIRS := libfdlibm, \ WARNINGS_AS_ERRORS_xlc := false, \ DISABLED_WARNINGS_gcc := unused-result, \ DISABLED_WARNINGS_solstudio := E_STATEMENT_NOT_REACHED, \ @@ -180,13 +173,9 @@ endif $(eval $(call SetupJdkLibrary, BUILD_LIBZIP, \ NAME := zip, \ OPTIMIZATION := LOW, \ - SRC := $(TOPDIR)/src/java.base/share/native/libzip, \ EXCLUDES := $(LIBZIP_EXCLUDES), \ CFLAGS := $(CFLAGS_JDKLIB) \ - $(LIBZ_CFLAGS) \ - -I$(TOPDIR)/src/java.base/share/native/libjava \ - -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjava \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.base, \ + $(LIBZ_CFLAGS), \ CFLAGS_unix := $(BUILD_LIBZIP_MMAP) -UDEBUG, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ @@ -200,22 +189,12 @@ TARGETS += $(BUILD_LIBZIP) ########################################################################################## -JIMAGELIB_CPPFLAGS := \ - -I$(TOPDIR)/src/java.base/share/native/libjava \ - -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjava \ - -I$(TOPDIR)/src/java.base/share/native/libjimage \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.base \ - # - $(eval $(call SetupJdkLibrary, BUILD_LIBJIMAGE, \ NAME := jimage, \ TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ OPTIMIZATION := LOW, \ - SRC := $(TOPDIR)/src/java.base/share/native/libjimage \ - $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjimage, \ - EXCLUDES := $(LIBJIMAGE_EXCLUDES), \ - CFLAGS := $(CFLAGS_JDKLIB) $(JIMAGELIB_CPPFLAGS), \ - CXXFLAGS := $(CXXFLAGS_JDKLIB) $(JIMAGELIB_CPPFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB), \ + CXXFLAGS := $(CXXFLAGS_JDKLIB), \ DISABLED_WARNINGS_gcc := implicit-fallthrough, \ CFLAGS_unix := -UDEBUG, \ LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \ @@ -231,10 +210,6 @@ TARGETS += $(BUILD_LIBJIMAGE) ########################################################################################## -LIBJLI_SRC_DIRS := $(call FindSrcDirsForLib, java.base, jli) - -LIBJLI_CFLAGS := $(CFLAGS_JDKLIB) - ifeq ($(call check-jvm-variant, zero), true) ERGO_FAMILY := zero else @@ -263,7 +238,7 @@ endif ifeq ($(OPENJDK_TARGET_OS), windows) # Staticically link with c runtime on windows. - LIBJLI_CFLAGS := $(filter-out -MD, $(LIBJLI_CFLAGS)) + LIBJLI_CFLAGS_JDKLIB := $(filter-out -MD, $(CFLAGS_JDKLIB)) LIBJLI_OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE) # Supply the name of the C runtime lib. LIBJLI_CFLAGS += -DMSVCR_DLL_NAME='"$(notdir $(MSVCR_DLL))"' @@ -271,11 +246,10 @@ ifeq ($(OPENJDK_TARGET_OS), windows) LIBJLI_CFLAGS += -DMSVCP_DLL_NAME='"$(notdir $(MSVCP_DLL))"' endif else + LIBJLI_CFLAGS_JDKLIB := $(CFLAGS_JDKLIB) LIBJLI_OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE)/jli endif -LIBJLI_CFLAGS += $(addprefix -I, $(LIBJLI_SRC_DIRS)) - LIBJLI_CFLAGS += $(LIBZ_CFLAGS) ifneq ($(USE_EXTERNAL_LIBZ), true) @@ -293,11 +267,10 @@ endif $(eval $(call SetupJdkLibrary, BUILD_LIBJLI, \ NAME := jli, \ OUTPUT_DIR := $(LIBJLI_OUTPUT_DIR), \ - SRC := $(LIBJLI_SRC_DIRS), \ EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \ EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \ OPTIMIZATION := HIGH, \ - CFLAGS := $(LIBJLI_CFLAGS), \ + CFLAGS := $(LIBJLI_CFLAGS_JDKLIB) $(LIBJLI_CFLAGS), \ DISABLED_WARNINGS_solstudio := \ E_ASM_DISABLES_OPTIMIZATION \ E_STATEMENT_NOT_REACHED, \ @@ -315,6 +288,8 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJLI, \ TARGETS += $(BUILD_LIBJLI) +LIBJLI_SRC_DIRS := $(call FindSrcDirsForComponent, java.base, libjli) + # On windows, the static library has the same suffix as the import library created by # with the shared library, so the static library is given a different name. No harm # in doing it for all platform to reduce complexity. @@ -327,7 +302,8 @@ ifeq ($(OPENJDK_TARGET_OS), windows) EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \ EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \ OPTIMIZATION := HIGH, \ - CFLAGS := $(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS), \ + CFLAGS := $(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS_JDKLIB) $(LIBJLI_CFLAGS) \ + $(addprefix -I, $(LIBJLI_SRC_DIRS)), \ ARFLAGS := $(ARFLAGS), \ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static, \ )) @@ -346,7 +322,8 @@ else ifeq ($(OPENJDK_TARGET_OS), macosx) EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \ EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \ OPTIMIZATION := HIGH, \ - CFLAGS := $(CFLAGS_JDKLIB) $(LIBJLI_CFLAGS), \ + CFLAGS := $(LIBJLI_CFLAGS_JDKLIB) $(LIBJLI_CFLAGS) \ + $(addprefix -I, $(LIBJLI_SRC_DIRS)), \ LDFLAGS := -nostdlib $(ARFLAGS), \ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static, \ )) @@ -370,7 +347,7 @@ else ifeq ($(OPENJDK_TARGET_OS), aix) EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \ EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \ OPTIMIZATION := HIGH, \ - CFLAGS := $(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS), \ + CFLAGS := $(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS_JDKLIB) $(LIBJLI_CFLAGS), \ ARFLAGS := $(ARFLAGS), \ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static)) diff --git a/make/lib/Lib-java.base.gmk b/make/lib/Lib-java.base.gmk index 1d29fb9e820..66327271dd1 100644 --- a/make/lib/Lib-java.base.gmk +++ b/make/lib/Lib-java.base.gmk @@ -29,9 +29,7 @@ include LibCommon.gmk $(eval $(call IncludeCustomExtension, lib/Lib-java.base.gmk)) # Prepare the find cache. -LIB_java.base_SRC_DIRS += $(TOPDIR)/src/java.base/*/native - -$(eval $(call FillCacheFind, $(wildcard $(LIB_java.base_SRC_DIRS)))) +$(eval $(call FillCacheFind, $(wildcard $(TOPDIR)/src/java.base/*/native))) ################################################################################ # Create all the core libraries @@ -41,14 +39,10 @@ include CoreLibraries.gmk ################################################################################ # Create the network library -LIBNET_SRC_DIRS := $(call FindSrcDirsForLib, java.base, net) - $(eval $(call SetupJdkLibrary, BUILD_LIBNET, \ NAME := net, \ - SRC := $(LIBNET_SRC_DIRS), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/java.base \ - $(LIBJAVA_HEADER_FLAGS) $(addprefix -I, $(LIBNET_SRC_DIRS)), \ + CFLAGS := $(CFLAGS_JDKLIB), \ DISABLED_WARNINGS_gcc := format-nonliteral, \ DISABLED_WARNINGS_clang := parentheses-equality constant-logical-operand, \ DISABLED_WARNINGS_microsoft := 4244 4047 4133 4996, \ @@ -72,31 +66,15 @@ TARGETS += $(BUILD_LIBNET) ################################################################################ # Create the nio library -BUILD_LIBNIO_SRC := \ - $(TOPDIR)/src/java.base/share/native/libnio \ - $(TOPDIR)/src/java.base/share/native/libnio/ch \ - $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libnio \ - $(sort $(wildcard \ - $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libnio/ch \ - $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libnio/fs \ - $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/native/libnio/ch \ - $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/native/libnio/fs)) \ - # - -BUILD_LIBNIO_CFLAGS := \ - $(addprefix -I, $(BUILD_LIBNIO_SRC)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.base \ - $(LIBJAVA_HEADER_FLAGS) \ - $(addprefix -I, $(BUILD_LIBNET_SRC)) - $(eval $(call SetupJdkLibrary, BUILD_LIBNIO, \ NAME := nio, \ - SRC := $(BUILD_LIBNIO_SRC), \ - EXCLUDE_FILES := $(BUILD_LIBNIO_EXFILES), \ OPTIMIZATION := HIGH, \ WARNINGS_AS_ERRORS_xlc := false, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - $(BUILD_LIBNIO_CFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB), \ + EXTRA_HEADER_DIRS := \ + libnio/ch \ + libnio/fs \ + libnet, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS_unix := -ljava -lnet, \ @@ -122,17 +100,10 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) # JavaNativeFoundation framework not supported in static builds ifneq ($(STATIC_BUILD), true) - LIBOSXSECURITY_DIRS := $(TOPDIR)/src/java.base/macosx/native/libosxsecurity - LIBOSXSECURITY_CFLAGS := -I$(LIBOSXSECURITY_DIRS) \ - $(LIBJAVA_HEADER_FLAGS) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.base \ - $(eval $(call SetupJdkLibrary, BUILD_LIBOSXSECURITY, \ NAME := osxsecurity, \ - SRC := $(LIBOSXSECURITY_DIRS), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - $(LIBOSXSECURITY_CFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB), \ DISABLED_WARNINGS_clang := deprecated-declarations, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ -L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base \ @@ -158,7 +129,6 @@ endif ifeq ($(OPENJDK_TARGET_OS_TYPE), unix) ifeq ($(STATIC_BUILD), false) - LIBJSIG_SRC_DIR := $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjsig LIBJSIG_MAPFILE := $(wildcard $(TOPDIR)/make/mapfiles/libjsig/mapfile-vers-$(OPENJDK_TARGET_OS)) ifeq ($(OPENJDK_TARGET_OS), linux) @@ -168,7 +138,6 @@ ifeq ($(OPENJDK_TARGET_OS_TYPE), unix) $(eval $(call SetupJdkLibrary, BUILD_LIBJSIG, \ NAME := jsig, \ - SRC := $(LIBJSIG_SRC_DIR), \ CFLAGS := $(CFLAGS_JDKLIB) $(LIBJSIG_CFLAGS), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ diff --git a/make/lib/Lib-java.desktop.gmk b/make/lib/Lib-java.desktop.gmk index 5a2f77f878b..81f85fe28f0 100644 --- a/make/lib/Lib-java.desktop.gmk +++ b/make/lib/Lib-java.desktop.gmk @@ -29,9 +29,7 @@ include LibCommon.gmk $(eval $(call IncludeCustomExtension, lib/Lib-java.desktop.gmk)) # Prepare the find cache. -LIB_java.desktop_SRC_DIRS += $(TOPDIR)/src/java.desktop/*/native - -$(eval $(call FillCacheFind, $(wildcard $(LIB_java.desktop_SRC_DIRS)))) +$(eval $(call FillCacheFind, $(wildcard $(TOPDIR)/src/java.desktop/*/native))) ################################################################################ # Create the AWT/2D libraries @@ -43,16 +41,8 @@ include Awt2dLibraries.gmk ifneq ($(OPENJDK_TARGET_OS), aix) - LIBJSOUND_SRC_DIRS := $(wildcard \ - $(TOPDIR)/src/java.desktop/share/native/libjsound \ - $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS)/native/libjsound \ - ) - LIBJSOUND_CFLAGS := \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \ $(ALSA_CFLAGS) \ - $(LIBJAVA_HEADER_FLAGS) \ - $(foreach dir, $(LIBJSOUND_SRC_DIRS), -I$(dir)) \ -DX_PLATFORM=X_$(OPENJDK_TARGET_OS_UPPERCASE) \ -DUSE_PORTS=TRUE \ -DUSE_DAUDIO=TRUE \ @@ -71,7 +61,6 @@ ifneq ($(OPENJDK_TARGET_OS), aix) $(eval $(call SetupJdkLibrary, BUILD_LIBJSOUND, \ NAME := jsound, \ - SRC := $(LIBJSOUND_SRC_DIRS), \ TOOLCHAIN := $(LIBJSOUND_TOOLCHAIN), \ OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) \ @@ -97,15 +86,11 @@ endif # Create the macosx specific osxapp and osx libraries ifeq ($(OPENJDK_TARGET_OS), macosx) - LIBOSXAPP_SRC := $(TOPDIR)/src/java.desktop/macosx/native/libosxapp $(eval $(call SetupJdkLibrary, BUILD_LIBOSXAPP, \ NAME := osxapp, \ - SRC := $(LIBOSXAPP_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - $(addprefix -I, $(LIBOSXAPP_SRC)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop, \ + CFLAGS := $(CFLAGS_JDKLIB), \ DISABLED_WARNINGS_clang := objc-method-access objc-root-class \ deprecated-declarations, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ @@ -129,19 +114,11 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) ############################################################################## - LIBOSX_DIRS := $(TOPDIR)/src/java.desktop/macosx/native/libosx - LIBOSX_CFLAGS := -I$(LIBOSX_DIRS) \ - -I$(TOPDIR)/src/java.desktop/macosx/native/libosxapp \ - $(LIBJAVA_HEADER_FLAGS) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \ - # - $(eval $(call SetupJdkLibrary, BUILD_LIBOSX, \ NAME := osx, \ - SRC := $(LIBOSX_DIRS), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - $(LIBOSX_CFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB), \ + EXTRA_HEADER_DIRS := libosxapp, \ DISABLED_WARNINGS_clang := deprecated-declarations, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ -L$(SUPPORT_OUTPUTDIR)/modules_libs/java.desktop \ diff --git a/make/lib/Lib-java.instrument.gmk b/make/lib/Lib-java.instrument.gmk index 3ec153ef462..7e625e3a036 100644 --- a/make/lib/Lib-java.instrument.gmk +++ b/make/lib/Lib-java.instrument.gmk @@ -30,32 +30,24 @@ $(eval $(call IncludeCustomExtension, lib/Lib-java.instrument.gmk)) ################################################################################ -LIBINSTRUMENT_SRC := $(TOPDIR)/src/java.instrument/share/native/libinstrument \ - $(TOPDIR)/src/java.instrument/$(OPENJDK_TARGET_OS_TYPE)/native/libinstrument \ - # -LIBINSTRUMENT_CFLAGS := $(CFLAGS_JDKLIB) \ - $(addprefix -I, $(LIBINSTRUMENT_SRC)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.instrument \ - -I$(TOPDIR)/src/java.base/share/native/libjli \ - -I$(TOPDIR)/src/java.base/share/native/libjava \ - # - ifeq ($(OPENJDK_TARGET_OS), windows) # Statically link the C runtime so that there are not dependencies on modules # not on the search patch when invoked from the Windows system directory # (or elsewhere). - LIBINSTRUMENT_CFLAGS := $(filter-out -MD, $(LIBINSTRUMENT_CFLAGS)) + LIBINSTRUMENT_CFLAGS_JDKLIB := $(filter-out -MD, $(CFLAGS_JDKLIB)) # equivalent of strcasecmp is stricmp on Windows - LIBINSTRUMENT_CFLAGS += -Dstrcasecmp=stricmp + LIBINSTRUMENT_CFLAGS := -Dstrcasecmp=stricmp +else + LIBINSTRUMENT_CFLAGS_JDKLIB := $(CFLAGS_JDKLIB) endif $(eval $(call SetupJdkLibrary, BUILD_LIBINSTRUMENT, \ NAME := instrument, \ - SRC := $(LIBINSTRUMENT_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(LIBINSTRUMENT_CFLAGS), \ + CFLAGS := $(LIBINSTRUMENT_CFLAGS_JDKLIB) $(LIBINSTRUMENT_CFLAGS), \ CFLAGS_debug := -DJPLIS_LOGGING, \ CFLAGS_release := -DNO_JPLIS_LOGGING, \ + EXTRA_HEADER_DIRS := java.base:libjli, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN) \ $(LIBINSTRUMENT_LDFLAGS), \ diff --git a/make/lib/Lib-java.management.gmk b/make/lib/Lib-java.management.gmk index 6444feaa2f5..a70a3ccf45a 100644 --- a/make/lib/Lib-java.management.gmk +++ b/make/lib/Lib-java.management.gmk @@ -30,13 +30,6 @@ $(eval $(call IncludeCustomExtension, lib/Lib-java.management.gmk)) ################################################################################ -LIBMANAGEMENT_SRC += $(TOPDIR)/src/java.management/share/native/libmanagement -LIBMANAGEMENT_CFLAGS := -I$(TOPDIR)/src/hotspot/share/include \ - $(addprefix -I,$(LIBMANAGEMENT_SRC)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.management \ - $(LIBJAVA_HEADER_FLAGS) \ - # - LIBMANAGEMENT_OPTIMIZATION := HIGH ifneq ($(findstring $(OPENJDK_TARGET_OS), solaris linux), ) ifeq ($(COMPILE_WITH_DEBUG_SYMBOLS), true) @@ -46,9 +39,8 @@ endif $(eval $(call SetupJdkLibrary, BUILD_LIBMANAGEMENT, \ NAME := management, \ - SRC := $(LIBMANAGEMENT_SRC), \ OPTIMIZATION := $(LIBMANAGEMENT_OPTIMIZATION), \ - CFLAGS := $(CFLAGS_JDKLIB) $(LIBMANAGEMENT_CFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS := $(JDKLIB_LIBS), \ diff --git a/make/lib/Lib-java.prefs.gmk b/make/lib/Lib-java.prefs.gmk index 6d72189d563..cac3b17e26a 100644 --- a/make/lib/Lib-java.prefs.gmk +++ b/make/lib/Lib-java.prefs.gmk @@ -27,18 +27,16 @@ include LibCommon.gmk ################################################################################ +# libprefs on macosx do not use the unix code ifeq ($(OPENJDK_TARGET_OS), macosx) - LIBPREF_SRC_DIRS := $(TOPDIR)/src/java.prefs/macosx/native/libprefs -else - LIBPREF_SRC_DIRS := $(TOPDIR)/src/java.prefs/$(OPENJDK_TARGET_OS_TYPE)/native/libprefs + LIBPREFS_EXCLUDE_SRC_PATTERNS := unix endif $(eval $(call SetupJdkLibrary, BUILD_LIBPREFS, \ NAME := prefs, \ - SRC := $(LIBPREF_SRC_DIRS), \ + EXCLUDE_SRC_PATTERNS := $(LIBPREFS_EXCLUDE_SRC_PATTERNS), \ OPTIMIZATION := HIGH, \ - CFLAGS := $(CFLAGS_JDKLIB) $(addprefix -I, $(LIBPREF_SRC_DIRS)) \ - $(LIBJAVA_HEADER_FLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS_unix := -ljvm, \ diff --git a/make/lib/Lib-java.rmi.gmk b/make/lib/Lib-java.rmi.gmk index f2c09c01829..56b60905603 100644 --- a/make/lib/Lib-java.rmi.gmk +++ b/make/lib/Lib-java.rmi.gmk @@ -29,9 +29,8 @@ include LibCommon.gmk $(eval $(call SetupJdkLibrary, BUILD_LIBRMI, \ NAME := rmi, \ - SRC := $(TOPDIR)/src/java.rmi/share/native/librmi, \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/java.rmi, \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS_unix := -ljvm, \ diff --git a/make/lib/Lib-java.security.jgss.gmk b/make/lib/Lib-java.security.jgss.gmk index 89752deef9f..b130671efd6 100644 --- a/make/lib/Lib-java.security.jgss.gmk +++ b/make/lib/Lib-java.security.jgss.gmk @@ -27,16 +27,10 @@ include LibCommon.gmk ################################################################################ -LIBJ2GSS_SRC := $(TOPDIR)/src/java.security.jgss/share/native/libj2gss \ - # - $(eval $(call SetupJdkLibrary, BUILD_LIBJ2GSS, \ NAME := j2gss, \ - SRC := $(LIBJ2GSS_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) $(addprefix -I, $(LIBJ2GSS_SRC)) \ - $(LIBJAVA_HEADER_FLAGS) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.security.jgss, \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS := $(LIBDL), \ @@ -49,15 +43,10 @@ TARGETS += $(BUILD_LIBJ2GSS) ifneq ($(BUILD_CRYPTO), false) ifeq ($(OPENJDK_TARGET_OS), windows) - BUILD_LIBW2K_LSA_AUTH_SRC := $(call FindSrcDirsForLib, $(MODULE), w2k_lsa_auth) - $(eval $(call SetupJdkLibrary, BUILD_LIBW2K_LSA_AUTH, \ NAME := w2k_lsa_auth, \ - SRC := $(BUILD_LIBW2K_LSA_AUTH_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - $(addprefix -I, $(BUILD_LIBW2K_LSA_AUTH_SRC)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.security.jgss, \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS := advapi32.lib Secur32.lib netapi32.lib kernel32.lib user32.lib \ @@ -69,17 +58,12 @@ ifneq ($(BUILD_CRYPTO), false) endif ifeq ($(OPENJDK_TARGET_OS), macosx) - BUILD_LIBOSXKRB5_SRC := $(call FindSrcDirsForLib, $(MODULE), osxkrb5) - # libosxkrb5 needs to call deprecated krb5 APIs so that java # can use the native credentials cache. $(eval $(call SetupJdkLibrary, BUILD_LIBOSXKRB5, \ NAME := osxkrb5, \ - SRC := $(BUILD_LIBOSXKRB5_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - $(addprefix -I, $(BUILD_LIBOSXKRB5_SRC)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.security.jgss, \ + CFLAGS := $(CFLAGS_JDKLIB), \ DISABLED_WARNINGS_clang := deprecated-declarations, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ diff --git a/make/lib/Lib-java.smartcardio.gmk b/make/lib/Lib-java.smartcardio.gmk index 337daa48e1e..a8c65061521 100644 --- a/make/lib/Lib-java.smartcardio.gmk +++ b/make/lib/Lib-java.smartcardio.gmk @@ -27,18 +27,12 @@ include LibCommon.gmk ################################################################################ -LIBJ2PCSC_SRC := $(TOPDIR)/src/java.smartcardio/share/native/libj2pcsc \ - $(TOPDIR)/src/java.smartcardio/$(OPENJDK_TARGET_OS_TYPE)/native/libj2pcsc -LIBJ2PCSC_CPPFLAGS := $(addprefix -I,$(LIBJ2PCSC_SRC)) \ - -I$(TOPDIR)/src/java.smartcardio/$(OPENJDK_TARGET_OS_TYPE)/native/libj2pcsc/MUSCLE \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.smartcardio - $(eval $(call SetupJdkLibrary, BUILD_LIBJ2PCSC, \ NAME := j2pcsc, \ - SRC := $(LIBJ2PCSC_SRC), \ + CFLAGS := $(CFLAGS_JDKLIB), \ CFLAGS_unix := -D__sun_jdk, \ + EXTRA_HEADER_DIRS := libj2pcsc/MUSCLE, \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) $(LIBJ2PCSC_CPPFLAGS), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS_unix := $(LIBDL), \ diff --git a/make/lib/Lib-jdk.accessibility.gmk b/make/lib/Lib-jdk.accessibility.gmk index ea35ab39293..b7f820b8ba3 100644 --- a/make/lib/Lib-jdk.accessibility.gmk +++ b/make/lib/Lib-jdk.accessibility.gmk @@ -30,12 +30,6 @@ include LibCommon.gmk ifeq ($(OPENJDK_TARGET_OS), windows) ROOT_SRCDIR := $(TOPDIR)/src/jdk.accessibility/windows/native - JAVA_AB_SRCDIR := $(ROOT_SRCDIR)/libjavaaccessbridge $(ROOT_SRCDIR)/common - WIN_AB_SRCDIR := $(ROOT_SRCDIR)/libwindowsaccessbridge $(ROOT_SRCDIR)/common - SYSINFO_SRCDIR := $(ROOT_SRCDIR)/libjabsysinfo - ACCESSBRIDGE_CFLAGS := -I$(SUPPORT_OUTPUTDIR)/headers/jdk.accessibility \ - -I$(TOPDIR)/src/java.desktop/windows/native/include \ - -I$(TOPDIR)/src/java.desktop/share/native/include define SetupJavaDLL # Parameter 1 Suffix @@ -43,13 +37,16 @@ ifeq ($(OPENJDK_TARGET_OS), windows) $(call SetupJdkLibrary, BUILD_JAVAACCESSBRIDGE$1, \ NAME := javaaccessbridge$1, \ - SRC := $(JAVA_AB_SRCDIR), \ + SRC := libjavaaccessbridge, \ + EXTRA_SRC := common, \ OPTIMIZATION := LOW, \ DISABLED_WARNINGS_microsoft := 4311 4302 4312, \ - CFLAGS := $(CFLAGS_JDKLIB) $(ACCESSBRIDGE_CFLAGS) \ - $(addprefix -I,$(JAVA_AB_SRCDIR)) \ - -I$(ROOT_SRCDIR)/include/bridge \ + CFLAGS := $(CFLAGS_JDKLIB) \ -DACCESSBRIDGE_ARCH_$2, \ + EXTRA_HEADER_DIRS := \ + include/bridge \ + java.base:include \ + java.desktop:include, \ LDFLAGS := $(LDFLAGS_JDKLIB), \ LIBS := kernel32.lib user32.lib gdi32.lib \ winspool.lib comdlg32.lib advapi32.lib shell32.lib \ @@ -68,13 +65,15 @@ ifeq ($(OPENJDK_TARGET_OS), windows) # Parameter 2 ACCESSBRIDGE_ARCH_ suffix $(call SetupJdkLibrary, BUILD_WINDOWSACCESSBRIDGE$1, \ NAME := windowsaccessbridge$1, \ - SRC := $(WIN_AB_SRCDIR), \ + SRC := libwindowsaccessbridge, \ + EXTRA_SRC := common, \ OPTIMIZATION := LOW, \ DISABLED_WARNINGS_microsoft := 4311 4302 4312, \ - CFLAGS := $(filter-out -MD, $(CFLAGS_JDKLIB)) -MT $(ACCESSBRIDGE_CFLAGS) \ - $(addprefix -I,$(WIN_AB_SRCDIR)) \ - -I$(ROOT_SRCDIR)/include/bridge \ + CFLAGS := $(filter-out -MD, $(CFLAGS_JDKLIB)) -MT \ -DACCESSBRIDGE_ARCH_$2, \ + EXTRA_HEADER_DIRS := \ + include/bridge \ + java.base:include, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ -def:$(ROOT_SRCDIR)/libwindowsaccessbridge/WinAccessBridge.DEF, \ LIBS := kernel32.lib user32.lib gdi32.lib \ @@ -91,9 +90,8 @@ ifeq ($(OPENJDK_TARGET_OS), windows) $(call SetupJdkLibrary, BUILD_ACCESSBRIDGESYSINFO, \ NAME := jabsysinfo, \ - SRC := $(SYSINFO_SRCDIR), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) $(ACCESSBRIDGE_CFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB), \ VERSIONINFO_RESOURCE := $(ROOT_SRCDIR)/common/AccessBridgeStatusWindow.rc, \ ) diff --git a/make/lib/Lib-jdk.attach.gmk b/make/lib/Lib-jdk.attach.gmk index 827f1bf723e..1c24e554037 100644 --- a/make/lib/Lib-jdk.attach.gmk +++ b/make/lib/Lib-jdk.attach.gmk @@ -36,11 +36,8 @@ endif $(eval $(call SetupJdkLibrary, BUILD_LIBATTACH, \ NAME := attach, \ - SRC := $(call FindSrcDirsForLib, jdk.attach, attach), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - -I$(SUPPORT_OUTPUTDIR)/headers/jdk.attach \ - $(LIBJAVA_HEADER_FLAGS) $(LIBATTACH_CFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB) $(LIBATTACH_CFLAGS), \ CFLAGS_windows := /Gy, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ diff --git a/make/lib/Lib-jdk.crypto.cryptoki.gmk b/make/lib/Lib-jdk.crypto.cryptoki.gmk index 847d5b356be..3f25d7c04fd 100644 --- a/make/lib/Lib-jdk.crypto.cryptoki.gmk +++ b/make/lib/Lib-jdk.crypto.cryptoki.gmk @@ -27,16 +27,10 @@ include LibCommon.gmk ################################################################################ -LIBJ2PKCS11_SRC := $(TOPDIR)/src/jdk.crypto.cryptoki/share/native/libj2pkcs11 \ - $(TOPDIR)/src/jdk.crypto.cryptoki/$(OPENJDK_TARGET_OS_TYPE)/native/libj2pkcs11 - $(eval $(call SetupJdkLibrary, BUILD_LIBJ2PKCS11, \ NAME := j2pkcs11, \ - SRC := $(LIBJ2PKCS11_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) $(addprefix -I, $(LIBJ2PKCS11_SRC)) \ - $(LIBJAVA_HEADER_FLAGS) \ - -I$(SUPPORT_OUTPUTDIR)/headers/jdk.crypto.cryptoki, \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS_unix := $(LIBDL), \ diff --git a/make/lib/Lib-jdk.crypto.ec.gmk b/make/lib/Lib-jdk.crypto.ec.gmk index e30b57d4341..dfecc1d3cbd 100644 --- a/make/lib/Lib-jdk.crypto.ec.gmk +++ b/make/lib/Lib-jdk.crypto.ec.gmk @@ -28,31 +28,23 @@ include LibCommon.gmk ################################################################################ ifeq ($(ENABLE_INTREE_EC), true) - - LIBSUNEC_SRC := $(TOPDIR)/src/jdk.crypto.ec/share/native/libsunec - BUILD_LIBSUNEC_FLAGS := $(addprefix -I, $(SUNEC_SRC)) - - # # On sol-sparc...all libraries are compiled with -xregs=no%appl - # (set in CFLAGS_REQUIRED_sparc) - # - # except!!! libsunec.so - # - ECC_JNI_SOLSPARC_FILTER := + # (set in CFLAGS_REQUIRED_sparc) except libsunec.so ifeq ($(OPENJDK_TARGET_CPU_ARCH), sparc) - ECC_JNI_SOLSPARC_FILTER := -xregs=no%appl + BUILD_LIBSUNEC_CFLAGS_JDKLIB := $(filter-out -xregs=no%appl, $(CFLAGS_JDKLIB)) + BUILD_LIBSUNEC_CXXFLAGS_JDKLIB := $(filter-out -xregs=no%appl, $(CXXFLAGS_JDKLIB)) + else + BUILD_LIBSUNEC_CFLAGS_JDKLIB := $(CFLAGS_JDKLIB) + BUILD_LIBSUNEC_CXXFLAGS_JDKLIB := $(CXXFLAGS_JDKLIB) endif $(eval $(call SetupJdkLibrary, BUILD_LIBSUNEC, \ NAME := sunec, \ - SRC := $(LIBSUNEC_SRC), \ TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ OPTIMIZATION := LOW, \ - CFLAGS := $(filter-out $(ECC_JNI_SOLSPARC_FILTER), $(CFLAGS_JDKLIB)) \ - $(BUILD_LIBSUNEC_FLAGS) \ + CFLAGS := $(BUILD_LIBSUNEC_CFLAGS_JDKLIB) \ -DMP_API_COMPATIBLE -DNSS_ECC_MORE_THAN_SUITE_B, \ - CXXFLAGS := $(filter-out $(ECC_JNI_SOLSPARC_FILTER), $(CXXFLAGS_JDKLIB)) \ - $(BUILD_LIBSUNEC_FLAGS), \ + CXXFLAGS := $(BUILD_LIBSUNEC_CXXFLAGS_JDKLIB), \ DISABLED_WARNINGS_gcc := sign-compare implicit-fallthrough, \ DISABLED_WARNINGS_microsoft := 4101 4244 4146 4018, \ LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK), \ diff --git a/make/lib/Lib-jdk.crypto.mscapi.gmk b/make/lib/Lib-jdk.crypto.mscapi.gmk index 3bd4eb9e357..e28e428f49e 100644 --- a/make/lib/Lib-jdk.crypto.mscapi.gmk +++ b/make/lib/Lib-jdk.crypto.mscapi.gmk @@ -29,14 +29,10 @@ include LibCommon.gmk ifeq ($(OPENJDK_TARGET_OS), windows) - LIBSUNMSCAPI_SRC := $(TOPDIR)/src/jdk.crypto.mscapi/$(OPENJDK_TARGET_OS_TYPE)/native/libsunmscapi - $(eval $(call SetupJdkLibrary, BUILD_LIBSUNMSCAPI, \ NAME := sunmscapi, \ - SRC := $(LIBSUNMSCAPI_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - -I$(LIBSUNMSCAPI_SRC), \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS := crypt32.lib advapi32.lib, \ diff --git a/make/lib/Lib-jdk.crypto.ucrypto.gmk b/make/lib/Lib-jdk.crypto.ucrypto.gmk index 758491007d3..c00e543737b 100644 --- a/make/lib/Lib-jdk.crypto.ucrypto.gmk +++ b/make/lib/Lib-jdk.crypto.ucrypto.gmk @@ -29,14 +29,10 @@ include LibCommon.gmk ifeq ($(OPENJDK_TARGET_OS), solaris) - LIBJ2UCRYPTO_SRC := $(TOPDIR)/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto - $(eval $(call SetupJdkLibrary, BUILD_LIBJ2UCRYPTO, \ NAME := j2ucrypto, \ - SRC := $(LIBJ2UCRYPTO_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - $(addprefix -I, $(LIBJ2UCRYPTO_SRC)), \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB), \ LIBS := $(LIBDL), \ )) diff --git a/make/lib/Lib-jdk.hotspot.agent.gmk b/make/lib/Lib-jdk.hotspot.agent.gmk index 3f023dbd772..2f805c438e8 100644 --- a/make/lib/Lib-jdk.hotspot.agent.gmk +++ b/make/lib/Lib-jdk.hotspot.agent.gmk @@ -29,19 +29,6 @@ $(eval $(call IncludeCustomExtension, hotspot/lib/Lib-jdk.hotspot.agent.gmk)) ################################################################################ -SA_TOPDIR := $(TOPDIR)/src/jdk.hotspot.agent - -SA_SRC += \ - $(SA_TOPDIR)/share/native/libsaproc \ - $(SA_TOPDIR)/$(OPENJDK_TARGET_OS)/native/libsaproc \ - # - -SA_INCLUDES := \ - $(addprefix -I, $(SA_SRC)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/jdk.hotspot.agent \ - -I$(TOPDIR)/src/hotspot/os/$(OPENJDK_TARGET_OS) \ - # - ifeq ($(OPENJDK_TARGET_OS), linux) SA_CFLAGS := -D_FILE_OFFSET_BITS=64 @@ -68,9 +55,8 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBSA, \ DISABLED_WARNINGS_microsoft := 4267, \ DISABLED_WARNINGS_gcc := sign-compare, \ DISABLED_WARNINGS_CXX_solstudio := truncwarn unknownpragma, \ - SRC := $(SA_SRC), \ - CFLAGS := $(CFLAGS_JDKLIB) $(SA_INCLUDES) $(SA_CFLAGS) $(SA_CUSTOM_CFLAGS), \ - CXXFLAGS := $(CXXFLAGS_JDKLIB) $(SA_INCLUDES) $(SA_CFLAGS) $(SA_CXXFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB) $(SA_CFLAGS), \ + CXXFLAGS := $(CXXFLAGS_JDKLIB) $(SA_CFLAGS) $(SA_CXXFLAGS), \ LDFLAGS := $(LDFLAGS_JDKLIB) $(SA_LDFLAGS), \ LIBS_linux := -lthread_db $(LIBDL), \ LIBS_solaris := -ldl -ldemangle -lthread -lproc, \ diff --git a/make/lib/Lib-jdk.internal.le.gmk b/make/lib/Lib-jdk.internal.le.gmk index 62f69bcadd3..0aa7bb273f5 100644 --- a/make/lib/Lib-jdk.internal.le.gmk +++ b/make/lib/Lib-jdk.internal.le.gmk @@ -29,19 +29,10 @@ include LibCommon.gmk ifeq ($(OPENJDK_TARGET_OS), windows) - LIBLE_SRC := $(TOPDIR)/src/jdk.internal.le/$(OPENJDK_TARGET_OS_TYPE)/native/lible \ - # - LIBLE_CPPFLAGS := \ - $(addprefix -I, $(LIBLE_SRC)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/jdk.internal.le \ - # - $(eval $(call SetupJdkLibrary, BUILD_LIBLE, \ NAME := le, \ - SRC := $(LIBLE_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) $(LIBJAVA_HEADER_FLAGS)\ - $(LIBLE_CPPFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB), \ LIBS := $(JDKLIB_LIBS) user32.lib, \ )) diff --git a/make/lib/Lib-jdk.jdi.gmk b/make/lib/Lib-jdk.jdi.gmk index ff0cd954b75..197b95c2e20 100644 --- a/make/lib/Lib-jdk.jdi.gmk +++ b/make/lib/Lib-jdk.jdi.gmk @@ -29,22 +29,13 @@ include LibCommon.gmk ifeq ($(OPENJDK_TARGET_OS), windows) - LIBDT_SHMEM_SRC := $(TOPDIR)/src/jdk.jdi/share/native/libdt_shmem \ - $(TOPDIR)/src/jdk.jdi/$(OPENJDK_TARGET_OS_TYPE)/native/libdt_shmem \ - # - LIBDT_SHMEM_CPPFLAGS := -I$(INCLUDEDIR) -I$(JDK_OUTPUTDIR)/include/$(OPENJDK_TARGET_OS) \ - $(addprefix -I, $(LIBDT_SHMEM_SRC)) \ - -I$(TOPDIR)/src/jdk.jdwp.agent/share/native/libjdwp/export \ - -I$(TOPDIR)/src/jdk.jdwp.agent/share/native/include \ - -I$(SUPPORT_OUTPUTDIR)/headers/jdk.jdi \ - # - $(eval $(call SetupJdkLibrary, BUILD_LIBDT_SHMEM, \ NAME := dt_shmem, \ - SRC := $(LIBDT_SHMEM_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) -DUSE_MMAP \ - $(LIBDT_SHMEM_CPPFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB) -DUSE_MMAP, \ + EXTRA_HEADER_DIRS := \ + jdk.jdwp.agent:include \ + jdk.jdwp.agent:libjdwp/export, \ LDFLAGS := $(LDFLAGS_JDKLIB), \ LIBS := $(JDKLIB_LIBS), \ )) diff --git a/make/lib/Lib-jdk.jdwp.agent.gmk b/make/lib/Lib-jdk.jdwp.agent.gmk index f0dc9f3d01c..0bc93e0d352 100644 --- a/make/lib/Lib-jdk.jdwp.agent.gmk +++ b/make/lib/Lib-jdk.jdwp.agent.gmk @@ -27,21 +27,14 @@ include LibCommon.gmk ################################################################################ -LIBDT_SOCKET_SRC := $(TOPDIR)/src/jdk.jdwp.agent/share/native/libdt_socket \ - $(TOPDIR)/src/jdk.jdwp.agent/$(OPENJDK_TARGET_OS_TYPE)/native/libdt_socket -LIBDT_SOCKET_CPPFLAGS := \ - $(addprefix -I, $(LIBDT_SOCKET_SRC)) \ - -I$(TOPDIR)/src/jdk.jdwp.agent/share/native/libjdwp/export \ - -I$(TOPDIR)/src/jdk.jdwp.agent/share/native/libjdwp \ - -I$(TOPDIR)/src/jdk.jdwp.agent/share/native/include \ - # - $(eval $(call SetupJdkLibrary, BUILD_LIBDT_SOCKET, \ NAME := dt_socket, \ - SRC := $(LIBDT_SOCKET_SRC), \ OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) -DUSE_MMAP \ $(LIBDT_SOCKET_CPPFLAGS), \ + EXTRA_HEADER_DIRS := \ + include \ + libjdwp/export, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS_linux := -lpthread, \ @@ -56,21 +49,14 @@ TARGETS += $(BUILD_LIBDT_SOCKET) ################################################################################ -LIBJDWP_SRC := $(TOPDIR)/src/jdk.jdwp.agent/share/native/libjdwp \ - $(TOPDIR)/src/jdk.jdwp.agent/$(OPENJDK_TARGET_OS_TYPE)/native/libjdwp -LIBJDWP_CPPFLAGS := \ - -I$(TOPDIR)/src/jdk.jdwp.agent/share/native/libjdwp/export \ - -I$(TOPDIR)/src/jdk.jdwp.agent/share/native/include \ - $(addprefix -I, $(LIBJDWP_SRC)) - # JDWP_LOGGING causes log messages to be compiled into the library. $(eval $(call SetupJdkLibrary, BUILD_LIBJDWP, \ NAME := jdwp, \ - SRC := $(LIBJDWP_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) -DJDWP_LOGGING \ - $(LIBJDWP_CPPFLAGS) \ - -I$(SUPPORT_OUTPUTDIR)/headers/jdk.jdwp.agent, \ + CFLAGS := $(CFLAGS_JDKLIB) -DJDWP_LOGGING, \ + EXTRA_HEADER_DIRS := \ + include \ + libjdwp/export, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS := $(JDKLIB_LIBS), \ diff --git a/make/lib/Lib-jdk.management.agent.gmk b/make/lib/Lib-jdk.management.agent.gmk index 426e84d30d3..35bf7ea21c8 100644 --- a/make/lib/Lib-jdk.management.agent.gmk +++ b/make/lib/Lib-jdk.management.agent.gmk @@ -27,17 +27,10 @@ include LibCommon.gmk ################################################################################ -LIBMANAGEMENT_AGENT_SRC += $(TOPDIR)/src/jdk.management.agent/$(OPENJDK_TARGET_OS_TYPE)/native/libmanagement_agent -LIBMANAGEMENT_AGENT_CFLAGS := $(addprefix -I,$(LIBMANAGEMENT_AGENT_SRC)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/jdk.management.agent \ - $(LIBJAVA_HEADER_FLAGS) \ - # - $(eval $(call SetupJdkLibrary, BUILD_LIBMANAGEMENT_AGENT, \ NAME := management_agent, \ - SRC := $(LIBMANAGEMENT_AGENT_SRC), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) $(LIBMANAGEMENT_AGENT_CFLAGS), \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS := $(JDKLIB_LIBS), \ diff --git a/make/lib/Lib-jdk.management.gmk b/make/lib/Lib-jdk.management.gmk index 22a167e23b5..29bfc7a5aa2 100644 --- a/make/lib/Lib-jdk.management.gmk +++ b/make/lib/Lib-jdk.management.gmk @@ -30,15 +30,6 @@ $(eval $(call IncludeCustomExtension, lib/Lib-jdk.management.gmk)) ################################################################################ -LIBMANAGEMENT_EXT_SRC += $(TOPDIR)/src/jdk.management/share/native/libmanagement_ext \ - $(TOPDIR)/src/jdk.management/$(OPENJDK_TARGET_OS_TYPE)/native/libmanagement_ext \ - $(TOPDIR)/src/jdk.management/$(OPENJDK_TARGET_OS)/native/libmanagement_ext -LIBMANAGEMENT_EXT_CFLAGS := -I$(TOPDIR)/src/java.management/share/native/include \ - $(addprefix -I,$(LIBMANAGEMENT_EXT_SRC)) \ - -I$(SUPPORT_OUTPUTDIR)/headers/jdk.management \ - $(LIBJAVA_HEADER_FLAGS) \ - # - ifeq ($(OPENJDK_TARGET_OS), windows) # In (at least) VS2013 and later, -DPSAPI_VERSION=1 is needed to generate # a binary that is compatible with windows versions older than 7/2008R2. @@ -55,8 +46,6 @@ endif $(eval $(call SetupJdkLibrary, BUILD_LIBMANAGEMENT_EXT, \ NAME := management_ext, \ - SRC := $(LIBMANAGEMENT_EXT_SRC), \ - LANG := C, \ OPTIMIZATION := $(LIBMANAGEMENT_EXT_OPTIMIZATION), \ CFLAGS := $(CFLAGS_JDKLIB) $(LIBMANAGEMENT_EXT_CFLAGS), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ diff --git a/make/lib/Lib-jdk.net.gmk b/make/lib/Lib-jdk.net.gmk index 642d29809e0..b202c6373f7 100644 --- a/make/lib/Lib-jdk.net.gmk +++ b/make/lib/Lib-jdk.net.gmk @@ -31,9 +31,8 @@ ifneq ($(filter $(OPENJDK_TARGET_OS), solaris linux macosx), ) $(eval $(call SetupJdkLibrary, BUILD_LIBEXTNET, \ NAME := extnet, \ - SRC := $(TOPDIR)/src/jdk.net/$(OPENJDK_TARGET_OS)/native/libextnet, \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/jdk.net, \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS := -ljava, \ diff --git a/make/lib/Lib-jdk.pack.gmk b/make/lib/Lib-jdk.pack.gmk index 9884818852c..f401e03e7c0 100644 --- a/make/lib/Lib-jdk.pack.gmk +++ b/make/lib/Lib-jdk.pack.gmk @@ -29,16 +29,13 @@ include LibCommon.gmk $(eval $(call SetupJdkLibrary, BUILD_LIBUNPACK, \ NAME := unpack, \ - SRC := $(TOPDIR)/src/jdk.pack/share/native/libunpack \ - $(TOPDIR)/src/jdk.pack/share/native/common-unpack, \ + EXTRA_SRC := common-unpack, \ TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ OPTIMIZATION := LOW, \ CFLAGS := $(CXXFLAGS_JDKLIB) \ - -DNO_ZLIB -DUNPACK_JNI -DFULL \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.base \ - -I$(TOPDIR)/src/jdk.pack/share/native/common-unpack \ - $(LIBJAVA_HEADER_FLAGS), \ + -DNO_ZLIB -DUNPACK_JNI -DFULL, \ CFLAGS_release := -DPRODUCT, \ + EXTRA_HEADER_DIRS := $(call GetJavaHeaderDir, java.base), \ DISABLED_WARNINGS_gcc := implicit-fallthrough, \ LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ diff --git a/make/lib/Lib-jdk.sctp.gmk b/make/lib/Lib-jdk.sctp.gmk index c1d2e468e86..2676102021e 100644 --- a/make/lib/Lib-jdk.sctp.gmk +++ b/make/lib/Lib-jdk.sctp.gmk @@ -29,18 +29,15 @@ include LibCommon.gmk ifeq ($(OPENJDK_TARGET_OS_TYPE), unix) - ifeq (, $(filter $(OPENJDK_TARGET_OS), macosx aix)) + ifeq ($(filter $(OPENJDK_TARGET_OS), macosx aix), ) $(eval $(call SetupJdkLibrary, BUILD_LIBSCTP, \ NAME := sctp, \ - SRC := $(TOPDIR)/src/jdk.sctp/$(OPENJDK_TARGET_OS_TYPE)/native/libsctp, \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - -I $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libnio/ch \ - -I $(TOPDIR)/src/java.base/share/native/libnio/ch \ - $(addprefix -I, $(call FindSrcDirsForLib, java.base, net)) \ - $(LIBJAVA_HEADER_FLAGS) \ - -I$(SUPPORT_OUTPUTDIR)/headers/jdk.sctp \ - -I$(SUPPORT_OUTPUTDIR)/headers/java.base, \ + CFLAGS := $(CFLAGS_JDKLIB), \ + EXTRA_HEADER_DIRS := \ + $(call GetJavaHeaderDir, java.base) \ + java.base:libnet \ + java.base:libnio/ch, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS_unix := -lnio -lnet -ljava -ljvm, \ diff --git a/make/lib/Lib-jdk.security.auth.gmk b/make/lib/Lib-jdk.security.auth.gmk index de3332f1522..12c26ca3758 100644 --- a/make/lib/Lib-jdk.security.auth.gmk +++ b/make/lib/Lib-jdk.security.auth.gmk @@ -29,9 +29,8 @@ include LibCommon.gmk $(eval $(call SetupJdkLibrary, BUILD_LIBJAAS, \ NAME := jaas, \ - SRC := $(call FindSrcDirsForLib, jdk.security.auth, jaas), \ OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/jdk.security.auth, \ + CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LIBS_windows := netapi32.lib user32.lib mpr.lib advapi32.lib $(JDKLIB_LIBS), \ diff --git a/make/lib/LibCommon.gmk b/make/lib/LibCommon.gmk index 57993303829..7e25925c7d1 100644 --- a/make/lib/LibCommon.gmk +++ b/make/lib/LibCommon.gmk @@ -25,9 +25,6 @@ include JdkNativeCompilation.gmk -# Hook to include the corresponding custom file, if present. -$(eval $(call IncludeCustomExtension, lib/LibCommon.gmk)) - ################################################################################ GLOBAL_VERSION_INFO_RESOURCE := $(TOPDIR)/src/java.base/windows/native/common/version.rc @@ -66,16 +63,6 @@ else ifeq ($(TOOLCHAIN_TYPE), xlc) endif endif -################################################################################ -# Find the default set of src dirs for a native library. -# Param 1 - module name -# Param 2 - library name -FindSrcDirsForLib += \ - $(call uniq, $(wildcard \ - $(TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS)/native/lib$(strip $2) \ - $(TOPDIR)/src/$(strip $1)/$(OPENJDK_TARGET_OS_TYPE)/native/lib$(strip $2) \ - $(TOPDIR)/src/$(strip $1)/share/native/lib$(strip $2))) - ################################################################################ # Find a library # Param 1 - module name @@ -94,10 +81,6 @@ FindStaticLib = \ $(addprefix $(SUPPORT_OUTPUTDIR)/native/, \ $(strip $1)$(strip $3)/$(LIBRARY_PREFIX)$(strip $2)$(STATIC_LIBRARY_SUFFIX)) -################################################################################ -# Define the header include flags needed to compile against it. -LIBJAVA_HEADER_FLAGS := $(addprefix -I, $(call FindSrcDirsForLib, java.base, java)) - # Put the libraries here. INSTALL_LIBRARIES_HERE := $(call FindLibDirForModule, $(MODULE)) diff --git a/src/java.desktop/macosx/native/libsplashscreen/libpng/zlib.h b/src/java.desktop/macosx/native/libsplashscreen/libpng/zlibwrapper/zlib.h similarity index 100% rename from src/java.desktop/macosx/native/libsplashscreen/libpng/zlib.h rename to src/java.desktop/macosx/native/libsplashscreen/libpng/zlibwrapper/zlib.h diff --git a/src/java.desktop/share/native/libsplashscreen/java_awt_SplashScreen.c b/src/java.desktop/share/native/libsplashscreen/java_awt_SplashScreen.c index 02c4a164fc1..d71e261decd 100644 --- a/src/java.desktop/share/native/libsplashscreen/java_awt_SplashScreen.c +++ b/src/java.desktop/share/native/libsplashscreen/java_awt_SplashScreen.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -28,6 +28,7 @@ #include #include #include +#include "java_awt_SplashScreen.h" JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM * vm, void *reserved) diff --git a/src/java.prefs/macosx/native/libprefs/MacOSXPreferencesFile.m b/src/java.prefs/macosx/native/libprefs/MacOSXPreferencesFile.m index 269981aecd5..8a17427af8d 100644 --- a/src/java.prefs/macosx/native/libprefs/MacOSXPreferencesFile.m +++ b/src/java.prefs/macosx/native/libprefs/MacOSXPreferencesFile.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,6 +63,7 @@ #include "jni_util.h" #include "jlong.h" #include "jvm.h" +#include "java_util_prefs_MacOSXPreferencesFile.h" /* * Declare library specific JNI_Onload entry if static build diff --git a/src/java.prefs/unix/native/libprefs/FileSystemPreferences.c b/src/java.prefs/unix/native/libprefs/FileSystemPreferences.c index 05dc673ae6d..c591f04d30a 100644 --- a/src/java.prefs/unix/native/libprefs/FileSystemPreferences.c +++ b/src/java.prefs/unix/native/libprefs/FileSystemPreferences.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -34,6 +34,7 @@ #include #include #include "jni_util.h" +#include "java_util_prefs_FileSystemPreferences.h" /* * Declare library specific JNI_Onload entry if static build diff --git a/src/java.prefs/windows/native/libprefs/WindowsPreferences.c b/src/java.prefs/windows/native/libprefs/WindowsPreferences.c index 0512b69b45c..0d512a36527 100644 --- a/src/java.prefs/windows/native/libprefs/WindowsPreferences.c +++ b/src/java.prefs/windows/native/libprefs/WindowsPreferences.c @@ -28,6 +28,8 @@ #include "jni.h" #include "jni_util.h" #include "jvm.h" +#include "java_util_prefs_WindowsPreferences.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/src/java.security.jgss/windows/native/libw2k_lsa_auth/NativeCreds.c b/src/java.security.jgss/windows/native/libw2k_lsa_auth/NativeCreds.c index d5424cf4f5f..a973eea330e 100644 --- a/src/java.security.jgss/windows/native/libw2k_lsa_auth/NativeCreds.c +++ b/src/java.security.jgss/windows/native/libw2k_lsa_auth/NativeCreds.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,7 @@ #include #include "jni_util.h" #include +#include "sun_security_krb5_Credentials.h" #undef LSA_SUCCESS #define LSA_SUCCESS(Status) ((Status) >= 0) diff --git a/src/java.security.jgss/windows/native/libw2k_lsa_auth/WindowsDirectory.c b/src/java.security.jgss/windows/native/libw2k_lsa_auth/WindowsDirectory.c index 7466022f752..0edf6ec8bad 100644 --- a/src/java.security.jgss/windows/native/libw2k_lsa_auth/WindowsDirectory.c +++ b/src/java.security.jgss/windows/native/libw2k_lsa_auth/WindowsDirectory.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -27,6 +27,7 @@ #include #include #include +#include "sun_security_krb5_Config.h" /* * Class: sun_security_krb5_Config diff --git a/src/jdk.crypto.ec/share/native/libsunec/ECC_JNI.cpp b/src/jdk.crypto.ec/share/native/libsunec/ECC_JNI.cpp index c093b75a490..eeae66e7cde 100644 --- a/src/jdk.crypto.ec/share/native/libsunec/ECC_JNI.cpp +++ b/src/jdk.crypto.ec/share/native/libsunec/ECC_JNI.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -26,6 +26,9 @@ #include #include "jni_util.h" #include "impl/ecc_impl.h" +#include "sun_security_ec_ECDHKeyAgreement.h" +#include "sun_security_ec_ECKeyPairGenerator.h" +#include "sun_security_ec_ECDSASignature.h" #define ILLEGAL_STATE_EXCEPTION "java/lang/IllegalStateException" #define INVALID_ALGORITHM_PARAMETER_EXCEPTION \ diff --git a/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp b/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp index 223002661f2..8bf3f441532 100644 --- a/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp +++ b/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp @@ -37,7 +37,13 @@ #include #include #include - +#include "sun_security_mscapi_Key.h" +#include "sun_security_mscapi_KeyStore.h" +#include "sun_security_mscapi_PRNG.h" +#include "sun_security_mscapi_RSACipher.h" +#include "sun_security_mscapi_RSAKeyPairGenerator.h" +#include "sun_security_mscapi_RSAPublicKey.h" +#include "sun_security_mscapi_RSASignature.h" #define OID_EKU_ANY "2.5.29.37.0" @@ -1313,7 +1319,7 @@ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_removeCertificate * Signature: (Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_sun_security_mscapi_KeyStore_destroyKeyContainer - (JNIEnv *env, jclass clazz, jstring keyContainerName) + (JNIEnv *env, jobject clazz, jstring keyContainerName) { HCRYPTPROV hCryptProv = NULL; const char* pszKeyContainerName = NULL; @@ -1435,7 +1441,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSACipher_encryptDecrypt * Signature: (J)[B */ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getPublicKeyBlob - (JNIEnv *env, jclass clazz, jlong hCryptKey) { + (JNIEnv *env, jobject clazz, jlong hCryptKey) { jbyteArray blob = NULL; DWORD dwBlobLen; @@ -1486,7 +1492,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getPublicKeyB * Signature: ([B)[B */ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getExponent - (JNIEnv *env, jclass clazz, jbyteArray jKeyBlob) { + (JNIEnv *env, jobject clazz, jbyteArray jKeyBlob) { jbyteArray exponent = NULL; jbyte* exponentBytes = NULL; @@ -1542,7 +1548,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getExponent * Signature: ([B)[B */ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSAPublicKey_getModulus - (JNIEnv *env, jclass clazz, jbyteArray jKeyBlob) { + (JNIEnv *env, jobject clazz, jbyteArray jKeyBlob) { jbyteArray modulus = NULL; jbyte* modulusBytes = NULL; @@ -1815,7 +1821,7 @@ jbyteArray generateKeyBlob( * Signature: (I[B[B[B[B[B[B[B[B)[B */ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_KeyStore_generatePrivateKeyBlob - (JNIEnv *env, jclass clazz, + (JNIEnv *env, jobject clazz, jint jKeyBitLength, jbyteArray jModulus, jbyteArray jPublicExponent, @@ -1852,7 +1858,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSASignature_generatePubli * Signature: ([BLjava/lang/String;I)Lsun/security/mscapi/RSAPrivateKey; */ JNIEXPORT jobject JNICALL Java_sun_security_mscapi_KeyStore_storePrivateKey - (JNIEnv *env, jclass clazz, jbyteArray keyBlob, jstring keyContainerName, + (JNIEnv *env, jobject clazz, jbyteArray keyBlob, jstring keyContainerName, jint keySize) { HCRYPTPROV hCryptProv = NULL; diff --git a/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c b/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c index b23910b5469..064ad2f9933 100644 --- a/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c +++ b/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c @@ -30,6 +30,13 @@ #include "jni_util.h" #include "nativeCrypto.h" #include "nativeFunc.h" +#include "com_oracle_security_ucrypto_NativeCipher.h" +#include "com_oracle_security_ucrypto_NativeDigest.h" +#include "com_oracle_security_ucrypto_NativeKey.h" +#include "com_oracle_security_ucrypto_NativeKey.h" +#include "com_oracle_security_ucrypto_NativeRSACipher.h" +#include "com_oracle_security_ucrypto_NativeRSASignature.h" +#include "com_oracle_security_ucrypto_UcryptoProvider.h" /* * Dumps out byte array in hex with and name and length info diff --git a/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCryptoMD.c b/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCryptoMD.c index bac407d3f72..6bc951fa3ba 100644 --- a/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCryptoMD.c +++ b/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCryptoMD.c @@ -30,7 +30,7 @@ #include "jni_util.h" #include "nativeCrypto.h" #include "nativeFunc.h" - +#include "com_oracle_security_ucrypto_NativeDigestMD.h" extern void throwOutOfMemoryError(JNIEnv *env, const char *msg); extern jbyte* getBytes(JNIEnv *env, jbyteArray bytes, int offset, int len); diff --git a/src/jdk.net/linux/native/libextnet/LinuxSocketOptions.c b/src/jdk.net/linux/native/libextnet/LinuxSocketOptions.c index 72d80ae1ecc..241133c813f 100644 --- a/src/jdk.net/linux/native/libextnet/LinuxSocketOptions.c +++ b/src/jdk.net/linux/native/libextnet/LinuxSocketOptions.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ #include #include #include "jni_util.h" +#include "jdk_net_LinuxSocketOptions.h" /* * Class: jdk_net_LinuxSocketOptions From 749c4a054bbea5184a38e4cbcce28ce3f103f10e Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Fri, 8 Jun 2018 18:15:58 +0200 Subject: [PATCH 41/46] 8204602: Add devkit for linux-arm32 Reviewed-by: erikj --- make/conf/jib-profiles.js | 22 ++++++++++++++++++++-- make/devkit/Makefile | 2 ++ make/devkit/Tools.gmk | 18 +++++++++++++++++- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 90bb74f470f..dc7b2f9ad0a 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -233,7 +233,7 @@ var getJibProfilesCommon = function (input, data) { common.main_profile_names = [ "linux-x64", "linux-x86", "macosx-x64", "solaris-x64", "solaris-sparcv9", "windows-x64", "windows-x86", - "linux-aarch64", "linux-arm64", "linux-arm-vfp-hflt", + "linux-aarch64", "linux-arm32", "linux-arm64", "linux-arm-vfp-hflt", "linux-arm-vfp-hflt-dyn" ]; @@ -490,6 +490,17 @@ var getJibProfilesProfiles = function (input, common, data) { ], }, + "linux-arm32": { + target_os: "linux", + target_cpu: "arm", + build_cpu: "x64", + dependencies: ["devkit", "autoconf", "build_devkit", "cups"], + configure_args: [ + "--openjdk-target=arm-linux-gnueabihf", "--with-freetype=bundled", + "--with-abi-profile=arm-vfp-hflt", "--disable-warnings-as-errors" + ], + }, + "linux-arm-vfp-hflt": { target_os: "linux", target_cpu: "arm", @@ -625,6 +636,9 @@ var getJibProfilesProfiles = function (input, common, data) { "linux-aarch64": { platform: "linux-aarch64", }, + "linux-arm32": { + platform: "linux-arm32", + }, "linux-arm64": { platform: "linux-arm64-vfp-hflt", }, @@ -829,7 +843,11 @@ 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" - : "arm-linaro-4.7+1.0") + : (input.profile.indexOf("arm32") >= 0 + ? "gcc7.3.0-Fedora27+1.0" + : "arm-linaro-4.7+1.0" + ) + ) }; var devkit_platform = (input.target_cpu == "x86" diff --git a/make/devkit/Makefile b/make/devkit/Makefile index 1bd37951fd3..d0464fbecd9 100644 --- a/make/devkit/Makefile +++ b/make/devkit/Makefile @@ -42,6 +42,8 @@ # line looking like this: # # make cross_compile_target="aarch64-linux-gnu" BASE_OS=Fedora27 +# or +# make cross_compile_target="arm-linux-gnueabihf" BASE_OS=Fedora27 # # This is the makefile which iterates over all host and target platforms. # diff --git a/make/devkit/Tools.gmk b/make/devkit/Tools.gmk index 5bc63448111..5e87a848e68 100644 --- a/make/devkit/Tools.gmk +++ b/make/devkit/Tools.gmk @@ -44,13 +44,23 @@ $(info HOST=$(HOST)) $(info BUILD=$(BUILD)) ARCH := $(word 1,$(subst -, ,$(TARGET))) + +ifeq ($(TARGET), arm-linux-gnueabihf) + ARCH=armhfp +endif + $(info ARCH=$(ARCH)) ifeq ($(BASE_OS), OEL6) OEL_URL := http://yum.oracle.com/repo/OracleLinux/OL6/4/base/$(ARCH)/ LINUX_VERSION := OEL6.4 else ifeq ($(BASE_OS), Fedora27) - OEL_URL := https://dl.fedoraproject.org/pub/fedora-secondary/releases/27/Everything/$(ARCH)/os/Packages/ + ifeq ($(ARCH), aarch64) + FEDORA_TYPE=fedora-secondary + else + FEDORA_TYPE=fedora/linux + endif + OEL_URL := https://dl.fedoraproject.org/pub/$(FEDORA_TYPE)/releases/27/Everything/$(ARCH)/os/Packages/ LINUX_VERSION := Fedora 27 else $(error Unknown base OS $(BASE_OS)) @@ -189,6 +199,8 @@ ifeq ($(ARCH),x86_64) endif else ifeq ($(ARCH),i686) RPM_ARCHS := i386 i686 noarch +else ifeq ($(ARCH), armhfp) + RPM_ARCHS := $(ARCH) armv7hl noarch else RPM_ARCHS := $(ARCH) noarch endif @@ -410,6 +422,10 @@ ifneq (,$(findstring linux,$(TARGET))) $(BUILDDIR)/$(gcc_ver)/Makefile : CONFIG += --enable-__cxa_atexit endif +ifeq ($(ARCH), armhfp) + $(BUILDDIR)/$(gcc_ver)/Makefile : CONFIG += --with-float=hard +endif + # Want: # c,c++ # shared libs From 170d8a7fae0b3e120f445af22ad23530484adb02 Mon Sep 17 00:00:00 2001 From: Martin Buchholz Date: Fri, 8 Jun 2018 09:36:10 -0700 Subject: [PATCH 42/46] 8204444: java.time cleanup Reviewed-by: scolebourne, rriggs --- .../share/classes/java/time/Clock.java | 4 +- .../share/classes/java/time/Duration.java | 12 ++-- .../share/classes/java/time/Instant.java | 4 +- .../share/classes/java/time/LocalTime.java | 16 ++--- .../java/time/chrono/ChronoLocalDateImpl.java | 2 +- .../java/time/chrono/ChronoLocalDateTime.java | 2 +- .../classes/java/time/chrono/Chronology.java | 8 +-- .../java/time/chrono/IsoChronology.java | 6 +- .../java/time/chrono/JapaneseChronology.java | 64 +++++++++---------- .../time/format/DateTimeFormatterBuilder.java | 2 +- .../java/time/format/DecimalStyle.java | 1 - .../java/time/zone/ZoneRulesProvider.java | 2 +- 12 files changed, 62 insertions(+), 61 deletions(-) diff --git a/src/java.base/share/classes/java/time/Clock.java b/src/java.base/share/classes/java/time/Clock.java index a372251f983..37e723ec7bf 100644 --- a/src/java.base/share/classes/java/time/Clock.java +++ b/src/java.base/share/classes/java/time/Clock.java @@ -586,7 +586,7 @@ public abstract class Clock { * This is typically used for testing. */ static final class FixedClock extends Clock implements Serializable { - private static final long serialVersionUID = 7430389292664866958L; + private static final long serialVersionUID = 7430389292664866958L; private final Instant instant; private final ZoneId zone; @@ -636,7 +636,7 @@ public abstract class Clock { * Implementation of a clock that adds an offset to an underlying clock. */ static final class OffsetClock extends Clock implements Serializable { - private static final long serialVersionUID = 2007484719125426256L; + private static final long serialVersionUID = 2007484719125426256L; private final Clock baseClock; private final Duration offset; diff --git a/src/java.base/share/classes/java/time/Duration.java b/src/java.base/share/classes/java/time/Duration.java index cf44f93978d..c446bf338ac 100644 --- a/src/java.base/share/classes/java/time/Duration.java +++ b/src/java.base/share/classes/java/time/Duration.java @@ -231,7 +231,7 @@ public final class Duration * This method allows an arbitrary number of nanoseconds to be passed in. * The factory will alter the values of the second and nanosecond in order * to ensure that the stored nanosecond is in the range 0 to 999,999,999. - * For example, the following will result in the exactly the same duration: + * For example, the following will result in exactly the same duration: *

      *  Duration.ofSeconds(3, 1);
      *  Duration.ofSeconds(4, -999_999_999);
@@ -1357,12 +1357,14 @@ public final class Duration
      * Truncating the duration returns a copy of the original with conceptual fields
      * smaller than the specified unit set to zero.
      * For example, truncating with the {@link ChronoUnit#MINUTES MINUTES} unit will
-     * round down to the nearest minute, setting the seconds and nanoseconds to zero.
+     * round down towards zero to the nearest minute, setting the seconds and
+     * nanoseconds to zero.
      * 

* The unit must have a {@linkplain TemporalUnit#getDuration() duration} * that divides into the length of a standard day without remainder. - * This includes all supplied time units on {@link ChronoUnit} and - * {@link ChronoUnit#DAYS DAYS}. Other ChronoUnits throw an exception. + * This includes all + * {@linkplain ChronoUnit#isTimeBased() time-based units on {@code ChronoUnit}} + * and {@link ChronoUnit#DAYS DAYS}. Other ChronoUnits throw an exception. *

* This instance is immutable and unaffected by this method call. * @@ -1388,7 +1390,7 @@ public final class Duration throw new UnsupportedTemporalTypeException("Unit must divide into a standard day without remainder"); } long nod = (seconds % LocalTime.SECONDS_PER_DAY) * LocalTime.NANOS_PER_SECOND + nanos; - long result = (nod / dur) * dur ; + long result = (nod / dur) * dur; return plusNanos(result - nod); } diff --git a/src/java.base/share/classes/java/time/Instant.java b/src/java.base/share/classes/java/time/Instant.java index 1aefddfffce..0aafa49fd40 100644 --- a/src/java.base/share/classes/java/time/Instant.java +++ b/src/java.base/share/classes/java/time/Instant.java @@ -311,7 +311,7 @@ public final class Instant * This method allows an arbitrary number of nanoseconds to be passed in. * The factory will alter the values of the second and nanosecond in order * to ensure that the stored nanosecond is in the range 0 to 999,999,999. - * For example, the following will result in the exactly the same instant: + * For example, the following will result in exactly the same instant: *

      *  Instant.ofEpochSecond(3, 1);
      *  Instant.ofEpochSecond(4, -999_999_999);
@@ -757,7 +757,7 @@ public final class Instant
             throw new UnsupportedTemporalTypeException("Unit must divide into a standard day without remainder");
         }
         long nod = (seconds % LocalTime.SECONDS_PER_DAY) * LocalTime.NANOS_PER_SECOND + nanos;
-        long result = Math.floorDiv(nod, dur) * dur ;
+        long result = Math.floorDiv(nod, dur) * dur;
         return plusNanos(result - nod);
     }
 
diff --git a/src/java.base/share/classes/java/time/LocalTime.java b/src/java.base/share/classes/java/time/LocalTime.java
index 76b5fed0367..80241339c35 100644
--- a/src/java.base/share/classes/java/time/LocalTime.java
+++ b/src/java.base/share/classes/java/time/LocalTime.java
@@ -356,14 +356,14 @@ public final class LocalTime
      * @return the local time, not null
      * @since 9
      */
-     public static LocalTime ofInstant(Instant instant, ZoneId zone) {
-         Objects.requireNonNull(instant, "instant");
-         Objects.requireNonNull(zone, "zone");
-         ZoneOffset offset = zone.getRules().getOffset(instant);
-         long localSecond = instant.getEpochSecond() + offset.getTotalSeconds();
-         int secsOfDay = Math.floorMod(localSecond, SECONDS_PER_DAY);
-         return ofNanoOfDay(secsOfDay * NANOS_PER_SECOND + instant.getNano());
-     }
+    public static LocalTime ofInstant(Instant instant, ZoneId zone) {
+        Objects.requireNonNull(instant, "instant");
+        Objects.requireNonNull(zone, "zone");
+        ZoneOffset offset = zone.getRules().getOffset(instant);
+        long localSecond = instant.getEpochSecond() + offset.getTotalSeconds();
+        int secsOfDay = Math.floorMod(localSecond, SECONDS_PER_DAY);
+        return ofNanoOfDay(secsOfDay * NANOS_PER_SECOND + instant.getNano());
+    }
 
     //-----------------------------------------------------------------------
     /**
diff --git a/src/java.base/share/classes/java/time/chrono/ChronoLocalDateImpl.java b/src/java.base/share/classes/java/time/chrono/ChronoLocalDateImpl.java
index 26513379b43..3d236ff4ccd 100644
--- a/src/java.base/share/classes/java/time/chrono/ChronoLocalDateImpl.java
+++ b/src/java.base/share/classes/java/time/chrono/ChronoLocalDateImpl.java
@@ -110,7 +110,7 @@ import java.util.Objects;
  *        int year = date.get(ChronoField.YEAR);
  *        System.out.printf("  Today is %s %s %d-%s-%d%n", date.getChronology().getID(),
  *                dow, day, month, year);
-
+ *
  *        // Print today's date and the last day of the year
  *        ChronoLocalDate now1 = Chronology.of("Hijrah").dateNow();
  *        ChronoLocalDate first = now1.with(ChronoField.DAY_OF_MONTH, 1)
diff --git a/src/java.base/share/classes/java/time/chrono/ChronoLocalDateTime.java b/src/java.base/share/classes/java/time/chrono/ChronoLocalDateTime.java
index d8411961697..51637c2b5d8 100644
--- a/src/java.base/share/classes/java/time/chrono/ChronoLocalDateTime.java
+++ b/src/java.base/share/classes/java/time/chrono/ChronoLocalDateTime.java
@@ -201,7 +201,7 @@ public interface ChronoLocalDateTime
      *
      * @return the date part of this date-time, not null
      */
-    D toLocalDate() ;
+    D toLocalDate();
 
     /**
      * Gets the local time part of this date-time.
diff --git a/src/java.base/share/classes/java/time/chrono/Chronology.java b/src/java.base/share/classes/java/time/chrono/Chronology.java
index d1c3919cb63..f35f9b95c3e 100644
--- a/src/java.base/share/classes/java/time/chrono/Chronology.java
+++ b/src/java.base/share/classes/java/time/chrono/Chronology.java
@@ -736,8 +736,8 @@ public interface Chronology extends Comparable {
      * @throws DateTimeException if any of the values are out of range
      * @since 9
      */
-     public default long epochSecond(int prolepticYear, int month, int dayOfMonth,
-                                     int hour, int minute, int second, ZoneOffset zoneOffset) {
+    public default long epochSecond(int prolepticYear, int month, int dayOfMonth,
+                                    int hour, int minute, int second, ZoneOffset zoneOffset) {
         Objects.requireNonNull(zoneOffset, "zoneOffset");
         HOUR_OF_DAY.checkValidValue(hour);
         MINUTE_OF_HOUR.checkValidValue(minute);
@@ -765,8 +765,8 @@ public interface Chronology extends Comparable {
      * @throws DateTimeException if any of the values are out of range
      * @since 9
      */
-     public default long epochSecond(Era era, int yearOfEra, int month, int dayOfMonth,
-                                     int hour, int minute, int second, ZoneOffset zoneOffset) {
+    public default long epochSecond(Era era, int yearOfEra, int month, int dayOfMonth,
+                                    int hour, int minute, int second, ZoneOffset zoneOffset) {
         Objects.requireNonNull(era, "era");
         return epochSecond(prolepticYear(era, yearOfEra), month, dayOfMonth, hour, minute, second, zoneOffset);
     }
diff --git a/src/java.base/share/classes/java/time/chrono/IsoChronology.java b/src/java.base/share/classes/java/time/chrono/IsoChronology.java
index 4919b3d7d3a..18d73689569 100644
--- a/src/java.base/share/classes/java/time/chrono/IsoChronology.java
+++ b/src/java.base/share/classes/java/time/chrono/IsoChronology.java
@@ -287,9 +287,9 @@ public final class IsoChronology extends AbstractChronology implements Serializa
      *         or if the day-of-month is invalid for the month-of-year
      * @since 9
      */
-     @Override
-     public long epochSecond(int prolepticYear, int month, int dayOfMonth,
-                             int hour, int minute, int second, ZoneOffset zoneOffset) {
+    @Override
+    public long epochSecond(int prolepticYear, int month, int dayOfMonth,
+                            int hour, int minute, int second, ZoneOffset zoneOffset) {
         YEAR.checkValidValue(prolepticYear);
         MONTH_OF_YEAR.checkValidValue(month);
         DAY_OF_MONTH.checkValidValue(dayOfMonth);
diff --git a/src/java.base/share/classes/java/time/chrono/JapaneseChronology.java b/src/java.base/share/classes/java/time/chrono/JapaneseChronology.java
index 4478c4c7de1..8cd67a05908 100644
--- a/src/java.base/share/classes/java/time/chrono/JapaneseChronology.java
+++ b/src/java.base/share/classes/java/time/chrono/JapaneseChronology.java
@@ -459,38 +459,38 @@ public final class JapaneseChronology extends AbstractChronology implements Seri
         return era.getPrivateEra().getSinceDate().getYear() + yearOfEra - 1;
     }
 
-     private ChronoLocalDate resolveYMD(JapaneseEra era, int yoe, Map fieldValues, ResolverStyle resolverStyle) {
-         fieldValues.remove(ERA);
-         fieldValues.remove(YEAR_OF_ERA);
-         if (resolverStyle == ResolverStyle.LENIENT) {
-             int y = prolepticYearLenient(era, yoe);
-             long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1);
-             long days = Math.subtractExact(fieldValues.remove(DAY_OF_MONTH), 1);
-             return date(y, 1, 1).plus(months, MONTHS).plus(days, DAYS);
-         }
-         int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR);
-         int dom = range(DAY_OF_MONTH).checkValidIntValue(fieldValues.remove(DAY_OF_MONTH), DAY_OF_MONTH);
-         if (resolverStyle == ResolverStyle.SMART) {  // previous valid
-             if (yoe < 1) {
-                 throw new DateTimeException("Invalid YearOfEra: " + yoe);
-             }
-             int y = prolepticYearLenient(era, yoe);
-             JapaneseDate result;
-             try {
-                 result = date(y, moy, dom);
-             } catch (DateTimeException ex) {
-                 result = date(y, moy, 1).with(TemporalAdjusters.lastDayOfMonth());
-             }
-             // handle the era being changed
-             // only allow if the new date is in the same Jan-Dec as the era change
-             // determine by ensuring either original yoe or result yoe is 1
-             if (result.getEra() != era && result.get(YEAR_OF_ERA) > 1 && yoe > 1) {
-                 throw new DateTimeException("Invalid YearOfEra for Era: " + era + " " + yoe);
-             }
-             return result;
-         }
-         return date(era, yoe, moy, dom);
-     }
+    private ChronoLocalDate resolveYMD(JapaneseEra era, int yoe, Map fieldValues, ResolverStyle resolverStyle) {
+        fieldValues.remove(ERA);
+        fieldValues.remove(YEAR_OF_ERA);
+        if (resolverStyle == ResolverStyle.LENIENT) {
+            int y = prolepticYearLenient(era, yoe);
+            long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1);
+            long days = Math.subtractExact(fieldValues.remove(DAY_OF_MONTH), 1);
+            return date(y, 1, 1).plus(months, MONTHS).plus(days, DAYS);
+        }
+        int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR);
+        int dom = range(DAY_OF_MONTH).checkValidIntValue(fieldValues.remove(DAY_OF_MONTH), DAY_OF_MONTH);
+        if (resolverStyle == ResolverStyle.SMART) {  // previous valid
+            if (yoe < 1) {
+                throw new DateTimeException("Invalid YearOfEra: " + yoe);
+            }
+            int y = prolepticYearLenient(era, yoe);
+            JapaneseDate result;
+            try {
+                result = date(y, moy, dom);
+            } catch (DateTimeException ex) {
+                result = date(y, moy, 1).with(TemporalAdjusters.lastDayOfMonth());
+            }
+            // handle the era being changed
+            // only allow if the new date is in the same Jan-Dec as the era change
+            // determine by ensuring either original yoe or result yoe is 1
+            if (result.getEra() != era && result.get(YEAR_OF_ERA) > 1 && yoe > 1) {
+                throw new DateTimeException("Invalid YearOfEra for Era: " + era + " " + yoe);
+            }
+            return result;
+        }
+        return date(era, yoe, moy, dom);
+    }
 
     private ChronoLocalDate resolveYD(JapaneseEra era, int yoe, Map  fieldValues, ResolverStyle resolverStyle) {
         fieldValues.remove(ERA);
diff --git a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
index 8e9437f2184..589792c18e2 100644
--- a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
+++ b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
@@ -3049,7 +3049,7 @@ public final class DateTimeFormatterBuilder {
      * Prints and parses a numeric date-time field with optional padding.
      */
     static final class FractionPrinterParser extends NumberPrinterParser {
-       private final boolean decimalPoint;
+        private final boolean decimalPoint;
 
         /**
          * Constructor.
diff --git a/src/java.base/share/classes/java/time/format/DecimalStyle.java b/src/java.base/share/classes/java/time/format/DecimalStyle.java
index 73f3cb23160..989c1c19e48 100644
--- a/src/java.base/share/classes/java/time/format/DecimalStyle.java
+++ b/src/java.base/share/classes/java/time/format/DecimalStyle.java
@@ -216,7 +216,6 @@ public final class DecimalStyle {
      *
      * @param zeroDigit  the character for zero
      * @return  a copy with a new character that represents zero, not null
-
      */
     public DecimalStyle withZeroDigit(char zeroDigit) {
         if (zeroDigit == this.zeroDigit) {
diff --git a/src/java.base/share/classes/java/time/zone/ZoneRulesProvider.java b/src/java.base/share/classes/java/time/zone/ZoneRulesProvider.java
index 4014c23c083..03e618731fc 100644
--- a/src/java.base/share/classes/java/time/zone/ZoneRulesProvider.java
+++ b/src/java.base/share/classes/java/time/zone/ZoneRulesProvider.java
@@ -119,7 +119,7 @@ import java.util.Collections;
  * Providers must ensure that once a rule has been seen by the application, the
  * rule must continue to be available.
  * 

-* Providers are encouraged to implement a meaningful {@code toString} method. + * Providers are encouraged to implement a meaningful {@code toString} method. *

* Many systems would like to update time-zone rules dynamically without stopping the JVM. * When examined in detail, this is a complex problem. From acdef788f07d9fcd5317e1b285ca991dc1a9d56a Mon Sep 17 00:00:00 2001 From: Martin Buchholz Date: Fri, 8 Jun 2018 09:37:52 -0700 Subject: [PATCH 43/46] 8204377: Rename Object#wait parameter name from "timeout" to "timeoutMillis" Reviewed-by: dholmes, scolebourne, alanb, rriggs --- .../share/classes/java/lang/Object.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Object.java b/src/java.base/share/classes/java/lang/Object.java index 2e031553d5b..0ccdc6b738c 100644 --- a/src/java.base/share/classes/java/lang/Object.java +++ b/src/java.base/share/classes/java/lang/Object.java @@ -333,12 +333,12 @@ public class Object { * by being notified or interrupted, or until a * certain amount of real time has elapsed. *

- * In all respects, this method behaves as if {@code wait(timeout, 0)} + * In all respects, this method behaves as if {@code wait(timeoutMillis, 0)} * had been called. See the specification of the {@link #wait(long, int)} method * for details. * - * @param timeout the maximum time to wait, in milliseconds - * @throws IllegalArgumentException if the value of {@code timeout} is negative + * @param timeoutMillis the maximum time to wait, in milliseconds + * @throws IllegalArgumentException if {@code timeoutMillis} is negative * @throws IllegalMonitorStateException if the current thread is not * the owner of the object's monitor * @throws InterruptedException if any thread interrupted the current thread before or @@ -349,7 +349,7 @@ public class Object { * @see #wait() * @see #wait(long, int) */ - public final native void wait(long timeout) throws InterruptedException; + public final native void wait(long timeoutMillis) throws InterruptedException; /** * Causes the current thread to wait until it is awakened, typically @@ -378,7 +378,7 @@ public class Object { * thread T. *

  • The specified amount of real time has elapsed, more or less. * The amount of real time, in nanoseconds, is given by the expression - * {@code 1000000 * timeout + nanos}. If {@code timeout} and {@code nanos} + * {@code 1000000 * timeoutMillis + nanos}. If {@code timeoutMillis} and {@code nanos} * are both zero, then real time is not taken into consideration and the * thread waits until awakened by one of the other causes. *
  • Thread T is awakened spuriously. (See below.) @@ -423,17 +423,17 @@ public class Object { *
    {@code
          *     synchronized (obj) {
          *         while ( and ) {
    -     *             long timeout = ... ; // recompute timeout values
    +     *             long timeoutMillis = ... ; // recompute timeout values
          *             int nanos = ... ;
    -     *             obj.wait(timeout, nanos);
    +     *             obj.wait(timeoutMillis, nanos);
          *         }
          *         ... // Perform action appropriate to condition or timeout
          *     }
          * }
    * - * @param timeout the maximum time to wait, in milliseconds + * @param timeoutMillis the maximum time to wait, in milliseconds * @param nanos additional time, in nanoseconds, in the range range 0-999999 inclusive - * @throws IllegalArgumentException if the value of {@code timeout} is negative, + * @throws IllegalArgumentException if {@code timeoutMillis} is negative, * or if the value of {@code nanos} is out of range * @throws IllegalMonitorStateException if the current thread is not * the owner of the object's monitor @@ -445,9 +445,9 @@ public class Object { * @see #wait() * @see #wait(long) */ - public final void wait(long timeout, int nanos) throws InterruptedException { - if (timeout < 0) { - throw new IllegalArgumentException("timeout value is negative"); + public final void wait(long timeoutMillis, int nanos) throws InterruptedException { + if (timeoutMillis < 0) { + throw new IllegalArgumentException("timeoutMillis value is negative"); } if (nanos < 0 || nanos > 999999) { @@ -456,10 +456,10 @@ public class Object { } if (nanos > 0) { - timeout++; + timeoutMillis++; } - wait(timeout); + wait(timeoutMillis); } /** From f56c0b79d86eefcca61de1830b380464023be718 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Fri, 8 Jun 2018 10:09:40 -0700 Subject: [PATCH 44/46] 8204229: Formatter and String.format ignore the width with the percent modifier (%5%) Reviewed-by: jlaskey --- src/java.base/share/classes/java/util/Formatter.java | 2 +- test/jdk/java/util/Formatter/Basic-X.java.template | 9 +++++++++ test/jdk/java/util/Formatter/Basic.java | 2 +- test/jdk/java/util/Formatter/BasicBigDecimal.java | 9 +++++++++ test/jdk/java/util/Formatter/BasicBigInteger.java | 9 +++++++++ test/jdk/java/util/Formatter/BasicBoolean.java | 9 +++++++++ test/jdk/java/util/Formatter/BasicBooleanObject.java | 9 +++++++++ test/jdk/java/util/Formatter/BasicByte.java | 9 +++++++++ test/jdk/java/util/Formatter/BasicByteObject.java | 9 +++++++++ test/jdk/java/util/Formatter/BasicChar.java | 9 +++++++++ test/jdk/java/util/Formatter/BasicCharObject.java | 9 +++++++++ test/jdk/java/util/Formatter/BasicDateTime.java | 9 +++++++++ test/jdk/java/util/Formatter/BasicDouble.java | 9 +++++++++ test/jdk/java/util/Formatter/BasicDoubleObject.java | 9 +++++++++ test/jdk/java/util/Formatter/BasicFloat.java | 9 +++++++++ test/jdk/java/util/Formatter/BasicFloatObject.java | 9 +++++++++ test/jdk/java/util/Formatter/BasicInt.java | 9 +++++++++ test/jdk/java/util/Formatter/BasicIntObject.java | 9 +++++++++ test/jdk/java/util/Formatter/BasicLong.java | 9 +++++++++ test/jdk/java/util/Formatter/BasicLongObject.java | 9 +++++++++ test/jdk/java/util/Formatter/BasicShort.java | 9 +++++++++ test/jdk/java/util/Formatter/BasicShortObject.java | 9 +++++++++ test/jdk/java/util/Formatter/genBasic.sh | 2 +- 23 files changed, 183 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/java/util/Formatter.java b/src/java.base/share/classes/java/util/Formatter.java index d61f2774df1..0fd1176b970 100644 --- a/src/java.base/share/classes/java/util/Formatter.java +++ b/src/java.base/share/classes/java/util/Formatter.java @@ -2914,7 +2914,7 @@ public final class Formatter implements Closeable, Flushable { a.append(System.lineSeparator()); break; case Conversion.PERCENT_SIGN: - a.append('%'); + print("%", l); break; default: assert false; diff --git a/test/jdk/java/util/Formatter/Basic-X.java.template b/test/jdk/java/util/Formatter/Basic-X.java.template index d885ac404ed..5dbd9abc0f8 100644 --- a/test/jdk/java/util/Formatter/Basic-X.java.template +++ b/test/jdk/java/util/Formatter/Basic-X.java.template @@ -1792,6 +1792,15 @@ public class Basic$Type$ extends Basic { //--------------------------------------------------------------------- test("%%", "%", (Object)null); test("%%", "%", ""); + + test("%5%", " %", (Object)null); + test("%5%", " %", ""); + test("%-5%", "% ", (Object)null); + test("%-5%", "% ", ""); + + tryCatch("%.5%", IllegalFormatPrecisionException.class); + tryCatch("%5.5%", IllegalFormatPrecisionException.class); + tryCatch("%%%", UnknownFormatConversionException.class); // perhaps an IllegalFormatArgumentIndexException should be defined? tryCatch("%<%", IllegalFormatFlagsException.class); diff --git a/test/jdk/java/util/Formatter/Basic.java b/test/jdk/java/util/Formatter/Basic.java index 4d5f5b58d69..935c5d107af 100644 --- a/test/jdk/java/util/Formatter/Basic.java +++ b/test/jdk/java/util/Formatter/Basic.java @@ -26,7 +26,7 @@ * @bug 4906370 4962433 4973103 4989961 5005818 5031150 4970931 4989491 5002937 * 5005104 5007745 5061412 5055180 5066788 5088703 6317248 6318369 6320122 * 6344623 6369500 6534606 6282094 6286592 6476425 5063507 6469160 6476168 - * 8059175 + * 8059175 8204229 * * @modules java.base * @run shell/timeout=240 Basic.sh diff --git a/test/jdk/java/util/Formatter/BasicBigDecimal.java b/test/jdk/java/util/Formatter/BasicBigDecimal.java index c485da4077b..206c0fe5015 100644 --- a/test/jdk/java/util/Formatter/BasicBigDecimal.java +++ b/test/jdk/java/util/Formatter/BasicBigDecimal.java @@ -1792,6 +1792,15 @@ public class BasicBigDecimal extends Basic { //--------------------------------------------------------------------- test("%%", "%", (Object)null); test("%%", "%", ""); + + test("%5%", " %", (Object)null); + test("%5%", " %", ""); + test("%-5%", "% ", (Object)null); + test("%-5%", "% ", ""); + + tryCatch("%.5%", IllegalFormatPrecisionException.class); + tryCatch("%5.5%", IllegalFormatPrecisionException.class); + tryCatch("%%%", UnknownFormatConversionException.class); // perhaps an IllegalFormatArgumentIndexException should be defined? tryCatch("%<%", IllegalFormatFlagsException.class); diff --git a/test/jdk/java/util/Formatter/BasicBigInteger.java b/test/jdk/java/util/Formatter/BasicBigInteger.java index 65e938b4d4d..30ffcf3c8a0 100644 --- a/test/jdk/java/util/Formatter/BasicBigInteger.java +++ b/test/jdk/java/util/Formatter/BasicBigInteger.java @@ -1792,6 +1792,15 @@ public class BasicBigInteger extends Basic { //--------------------------------------------------------------------- test("%%", "%", (Object)null); test("%%", "%", ""); + + test("%5%", " %", (Object)null); + test("%5%", " %", ""); + test("%-5%", "% ", (Object)null); + test("%-5%", "% ", ""); + + tryCatch("%.5%", IllegalFormatPrecisionException.class); + tryCatch("%5.5%", IllegalFormatPrecisionException.class); + tryCatch("%%%", UnknownFormatConversionException.class); // perhaps an IllegalFormatArgumentIndexException should be defined? tryCatch("%<%", IllegalFormatFlagsException.class); diff --git a/test/jdk/java/util/Formatter/BasicBoolean.java b/test/jdk/java/util/Formatter/BasicBoolean.java index 3ea99cb1886..f3db99331b3 100644 --- a/test/jdk/java/util/Formatter/BasicBoolean.java +++ b/test/jdk/java/util/Formatter/BasicBoolean.java @@ -1792,6 +1792,15 @@ public class BasicBoolean extends Basic { //--------------------------------------------------------------------- test("%%", "%", (Object)null); test("%%", "%", ""); + + test("%5%", " %", (Object)null); + test("%5%", " %", ""); + test("%-5%", "% ", (Object)null); + test("%-5%", "% ", ""); + + tryCatch("%.5%", IllegalFormatPrecisionException.class); + tryCatch("%5.5%", IllegalFormatPrecisionException.class); + tryCatch("%%%", UnknownFormatConversionException.class); // perhaps an IllegalFormatArgumentIndexException should be defined? tryCatch("%<%", IllegalFormatFlagsException.class); diff --git a/test/jdk/java/util/Formatter/BasicBooleanObject.java b/test/jdk/java/util/Formatter/BasicBooleanObject.java index 3d2b3dd61c8..a928b9f74ce 100644 --- a/test/jdk/java/util/Formatter/BasicBooleanObject.java +++ b/test/jdk/java/util/Formatter/BasicBooleanObject.java @@ -1792,6 +1792,15 @@ public class BasicBooleanObject extends Basic { //--------------------------------------------------------------------- test("%%", "%", (Object)null); test("%%", "%", ""); + + test("%5%", " %", (Object)null); + test("%5%", " %", ""); + test("%-5%", "% ", (Object)null); + test("%-5%", "% ", ""); + + tryCatch("%.5%", IllegalFormatPrecisionException.class); + tryCatch("%5.5%", IllegalFormatPrecisionException.class); + tryCatch("%%%", UnknownFormatConversionException.class); // perhaps an IllegalFormatArgumentIndexException should be defined? tryCatch("%<%", IllegalFormatFlagsException.class); diff --git a/test/jdk/java/util/Formatter/BasicByte.java b/test/jdk/java/util/Formatter/BasicByte.java index 6c6ca04c4b0..2fd80a4c8cc 100644 --- a/test/jdk/java/util/Formatter/BasicByte.java +++ b/test/jdk/java/util/Formatter/BasicByte.java @@ -1792,6 +1792,15 @@ public class BasicByte extends Basic { //--------------------------------------------------------------------- test("%%", "%", (Object)null); test("%%", "%", ""); + + test("%5%", " %", (Object)null); + test("%5%", " %", ""); + test("%-5%", "% ", (Object)null); + test("%-5%", "% ", ""); + + tryCatch("%.5%", IllegalFormatPrecisionException.class); + tryCatch("%5.5%", IllegalFormatPrecisionException.class); + tryCatch("%%%", UnknownFormatConversionException.class); // perhaps an IllegalFormatArgumentIndexException should be defined? tryCatch("%<%", IllegalFormatFlagsException.class); diff --git a/test/jdk/java/util/Formatter/BasicByteObject.java b/test/jdk/java/util/Formatter/BasicByteObject.java index 70e2e927fc7..f1d615f0888 100644 --- a/test/jdk/java/util/Formatter/BasicByteObject.java +++ b/test/jdk/java/util/Formatter/BasicByteObject.java @@ -1792,6 +1792,15 @@ public class BasicByteObject extends Basic { //--------------------------------------------------------------------- test("%%", "%", (Object)null); test("%%", "%", ""); + + test("%5%", " %", (Object)null); + test("%5%", " %", ""); + test("%-5%", "% ", (Object)null); + test("%-5%", "% ", ""); + + tryCatch("%.5%", IllegalFormatPrecisionException.class); + tryCatch("%5.5%", IllegalFormatPrecisionException.class); + tryCatch("%%%", UnknownFormatConversionException.class); // perhaps an IllegalFormatArgumentIndexException should be defined? tryCatch("%<%", IllegalFormatFlagsException.class); diff --git a/test/jdk/java/util/Formatter/BasicChar.java b/test/jdk/java/util/Formatter/BasicChar.java index 2a996d4e9bd..06865c24a63 100644 --- a/test/jdk/java/util/Formatter/BasicChar.java +++ b/test/jdk/java/util/Formatter/BasicChar.java @@ -1792,6 +1792,15 @@ public class BasicChar extends Basic { //--------------------------------------------------------------------- test("%%", "%", (Object)null); test("%%", "%", ""); + + test("%5%", " %", (Object)null); + test("%5%", " %", ""); + test("%-5%", "% ", (Object)null); + test("%-5%", "% ", ""); + + tryCatch("%.5%", IllegalFormatPrecisionException.class); + tryCatch("%5.5%", IllegalFormatPrecisionException.class); + tryCatch("%%%", UnknownFormatConversionException.class); // perhaps an IllegalFormatArgumentIndexException should be defined? tryCatch("%<%", IllegalFormatFlagsException.class); diff --git a/test/jdk/java/util/Formatter/BasicCharObject.java b/test/jdk/java/util/Formatter/BasicCharObject.java index 485a517447e..0bafba726a9 100644 --- a/test/jdk/java/util/Formatter/BasicCharObject.java +++ b/test/jdk/java/util/Formatter/BasicCharObject.java @@ -1792,6 +1792,15 @@ public class BasicCharObject extends Basic { //--------------------------------------------------------------------- test("%%", "%", (Object)null); test("%%", "%", ""); + + test("%5%", " %", (Object)null); + test("%5%", " %", ""); + test("%-5%", "% ", (Object)null); + test("%-5%", "% ", ""); + + tryCatch("%.5%", IllegalFormatPrecisionException.class); + tryCatch("%5.5%", IllegalFormatPrecisionException.class); + tryCatch("%%%", UnknownFormatConversionException.class); // perhaps an IllegalFormatArgumentIndexException should be defined? tryCatch("%<%", IllegalFormatFlagsException.class); diff --git a/test/jdk/java/util/Formatter/BasicDateTime.java b/test/jdk/java/util/Formatter/BasicDateTime.java index bb4611d2806..72f446625b2 100644 --- a/test/jdk/java/util/Formatter/BasicDateTime.java +++ b/test/jdk/java/util/Formatter/BasicDateTime.java @@ -1792,6 +1792,15 @@ public class BasicDateTime extends Basic { //--------------------------------------------------------------------- test("%%", "%", (Object)null); test("%%", "%", ""); + + test("%5%", " %", (Object)null); + test("%5%", " %", ""); + test("%-5%", "% ", (Object)null); + test("%-5%", "% ", ""); + + tryCatch("%.5%", IllegalFormatPrecisionException.class); + tryCatch("%5.5%", IllegalFormatPrecisionException.class); + tryCatch("%%%", UnknownFormatConversionException.class); // perhaps an IllegalFormatArgumentIndexException should be defined? tryCatch("%<%", IllegalFormatFlagsException.class); diff --git a/test/jdk/java/util/Formatter/BasicDouble.java b/test/jdk/java/util/Formatter/BasicDouble.java index e4b1de20683..4489a5c1f29 100644 --- a/test/jdk/java/util/Formatter/BasicDouble.java +++ b/test/jdk/java/util/Formatter/BasicDouble.java @@ -1792,6 +1792,15 @@ public class BasicDouble extends Basic { //--------------------------------------------------------------------- test("%%", "%", (Object)null); test("%%", "%", ""); + + test("%5%", " %", (Object)null); + test("%5%", " %", ""); + test("%-5%", "% ", (Object)null); + test("%-5%", "% ", ""); + + tryCatch("%.5%", IllegalFormatPrecisionException.class); + tryCatch("%5.5%", IllegalFormatPrecisionException.class); + tryCatch("%%%", UnknownFormatConversionException.class); // perhaps an IllegalFormatArgumentIndexException should be defined? tryCatch("%<%", IllegalFormatFlagsException.class); diff --git a/test/jdk/java/util/Formatter/BasicDoubleObject.java b/test/jdk/java/util/Formatter/BasicDoubleObject.java index 228b6e3eca3..4c26b794679 100644 --- a/test/jdk/java/util/Formatter/BasicDoubleObject.java +++ b/test/jdk/java/util/Formatter/BasicDoubleObject.java @@ -1792,6 +1792,15 @@ public class BasicDoubleObject extends Basic { //--------------------------------------------------------------------- test("%%", "%", (Object)null); test("%%", "%", ""); + + test("%5%", " %", (Object)null); + test("%5%", " %", ""); + test("%-5%", "% ", (Object)null); + test("%-5%", "% ", ""); + + tryCatch("%.5%", IllegalFormatPrecisionException.class); + tryCatch("%5.5%", IllegalFormatPrecisionException.class); + tryCatch("%%%", UnknownFormatConversionException.class); // perhaps an IllegalFormatArgumentIndexException should be defined? tryCatch("%<%", IllegalFormatFlagsException.class); diff --git a/test/jdk/java/util/Formatter/BasicFloat.java b/test/jdk/java/util/Formatter/BasicFloat.java index afdcea003c7..79eedf37dc7 100644 --- a/test/jdk/java/util/Formatter/BasicFloat.java +++ b/test/jdk/java/util/Formatter/BasicFloat.java @@ -1792,6 +1792,15 @@ public class BasicFloat extends Basic { //--------------------------------------------------------------------- test("%%", "%", (Object)null); test("%%", "%", ""); + + test("%5%", " %", (Object)null); + test("%5%", " %", ""); + test("%-5%", "% ", (Object)null); + test("%-5%", "% ", ""); + + tryCatch("%.5%", IllegalFormatPrecisionException.class); + tryCatch("%5.5%", IllegalFormatPrecisionException.class); + tryCatch("%%%", UnknownFormatConversionException.class); // perhaps an IllegalFormatArgumentIndexException should be defined? tryCatch("%<%", IllegalFormatFlagsException.class); diff --git a/test/jdk/java/util/Formatter/BasicFloatObject.java b/test/jdk/java/util/Formatter/BasicFloatObject.java index 4d94d8919df..91faf4ad37b 100644 --- a/test/jdk/java/util/Formatter/BasicFloatObject.java +++ b/test/jdk/java/util/Formatter/BasicFloatObject.java @@ -1792,6 +1792,15 @@ public class BasicFloatObject extends Basic { //--------------------------------------------------------------------- test("%%", "%", (Object)null); test("%%", "%", ""); + + test("%5%", " %", (Object)null); + test("%5%", " %", ""); + test("%-5%", "% ", (Object)null); + test("%-5%", "% ", ""); + + tryCatch("%.5%", IllegalFormatPrecisionException.class); + tryCatch("%5.5%", IllegalFormatPrecisionException.class); + tryCatch("%%%", UnknownFormatConversionException.class); // perhaps an IllegalFormatArgumentIndexException should be defined? tryCatch("%<%", IllegalFormatFlagsException.class); diff --git a/test/jdk/java/util/Formatter/BasicInt.java b/test/jdk/java/util/Formatter/BasicInt.java index a933a8ccc82..2ebf11f1433 100644 --- a/test/jdk/java/util/Formatter/BasicInt.java +++ b/test/jdk/java/util/Formatter/BasicInt.java @@ -1792,6 +1792,15 @@ public class BasicInt extends Basic { //--------------------------------------------------------------------- test("%%", "%", (Object)null); test("%%", "%", ""); + + test("%5%", " %", (Object)null); + test("%5%", " %", ""); + test("%-5%", "% ", (Object)null); + test("%-5%", "% ", ""); + + tryCatch("%.5%", IllegalFormatPrecisionException.class); + tryCatch("%5.5%", IllegalFormatPrecisionException.class); + tryCatch("%%%", UnknownFormatConversionException.class); // perhaps an IllegalFormatArgumentIndexException should be defined? tryCatch("%<%", IllegalFormatFlagsException.class); diff --git a/test/jdk/java/util/Formatter/BasicIntObject.java b/test/jdk/java/util/Formatter/BasicIntObject.java index d5f68bed668..808b40e7832 100644 --- a/test/jdk/java/util/Formatter/BasicIntObject.java +++ b/test/jdk/java/util/Formatter/BasicIntObject.java @@ -1792,6 +1792,15 @@ public class BasicIntObject extends Basic { //--------------------------------------------------------------------- test("%%", "%", (Object)null); test("%%", "%", ""); + + test("%5%", " %", (Object)null); + test("%5%", " %", ""); + test("%-5%", "% ", (Object)null); + test("%-5%", "% ", ""); + + tryCatch("%.5%", IllegalFormatPrecisionException.class); + tryCatch("%5.5%", IllegalFormatPrecisionException.class); + tryCatch("%%%", UnknownFormatConversionException.class); // perhaps an IllegalFormatArgumentIndexException should be defined? tryCatch("%<%", IllegalFormatFlagsException.class); diff --git a/test/jdk/java/util/Formatter/BasicLong.java b/test/jdk/java/util/Formatter/BasicLong.java index 1ffb9847afd..4afbe5730c6 100644 --- a/test/jdk/java/util/Formatter/BasicLong.java +++ b/test/jdk/java/util/Formatter/BasicLong.java @@ -1792,6 +1792,15 @@ public class BasicLong extends Basic { //--------------------------------------------------------------------- test("%%", "%", (Object)null); test("%%", "%", ""); + + test("%5%", " %", (Object)null); + test("%5%", " %", ""); + test("%-5%", "% ", (Object)null); + test("%-5%", "% ", ""); + + tryCatch("%.5%", IllegalFormatPrecisionException.class); + tryCatch("%5.5%", IllegalFormatPrecisionException.class); + tryCatch("%%%", UnknownFormatConversionException.class); // perhaps an IllegalFormatArgumentIndexException should be defined? tryCatch("%<%", IllegalFormatFlagsException.class); diff --git a/test/jdk/java/util/Formatter/BasicLongObject.java b/test/jdk/java/util/Formatter/BasicLongObject.java index fee981c2bc0..606d725d365 100644 --- a/test/jdk/java/util/Formatter/BasicLongObject.java +++ b/test/jdk/java/util/Formatter/BasicLongObject.java @@ -1792,6 +1792,15 @@ public class BasicLongObject extends Basic { //--------------------------------------------------------------------- test("%%", "%", (Object)null); test("%%", "%", ""); + + test("%5%", " %", (Object)null); + test("%5%", " %", ""); + test("%-5%", "% ", (Object)null); + test("%-5%", "% ", ""); + + tryCatch("%.5%", IllegalFormatPrecisionException.class); + tryCatch("%5.5%", IllegalFormatPrecisionException.class); + tryCatch("%%%", UnknownFormatConversionException.class); // perhaps an IllegalFormatArgumentIndexException should be defined? tryCatch("%<%", IllegalFormatFlagsException.class); diff --git a/test/jdk/java/util/Formatter/BasicShort.java b/test/jdk/java/util/Formatter/BasicShort.java index 5cea5b07216..37d4b97f948 100644 --- a/test/jdk/java/util/Formatter/BasicShort.java +++ b/test/jdk/java/util/Formatter/BasicShort.java @@ -1792,6 +1792,15 @@ public class BasicShort extends Basic { //--------------------------------------------------------------------- test("%%", "%", (Object)null); test("%%", "%", ""); + + test("%5%", " %", (Object)null); + test("%5%", " %", ""); + test("%-5%", "% ", (Object)null); + test("%-5%", "% ", ""); + + tryCatch("%.5%", IllegalFormatPrecisionException.class); + tryCatch("%5.5%", IllegalFormatPrecisionException.class); + tryCatch("%%%", UnknownFormatConversionException.class); // perhaps an IllegalFormatArgumentIndexException should be defined? tryCatch("%<%", IllegalFormatFlagsException.class); diff --git a/test/jdk/java/util/Formatter/BasicShortObject.java b/test/jdk/java/util/Formatter/BasicShortObject.java index 88c437392d5..d522a163944 100644 --- a/test/jdk/java/util/Formatter/BasicShortObject.java +++ b/test/jdk/java/util/Formatter/BasicShortObject.java @@ -1792,6 +1792,15 @@ public class BasicShortObject extends Basic { //--------------------------------------------------------------------- test("%%", "%", (Object)null); test("%%", "%", ""); + + test("%5%", " %", (Object)null); + test("%5%", " %", ""); + test("%-5%", "% ", (Object)null); + test("%-5%", "% ", ""); + + tryCatch("%.5%", IllegalFormatPrecisionException.class); + tryCatch("%5.5%", IllegalFormatPrecisionException.class); + tryCatch("%%%", UnknownFormatConversionException.class); // perhaps an IllegalFormatArgumentIndexException should be defined? tryCatch("%<%", IllegalFormatFlagsException.class); diff --git a/test/jdk/java/util/Formatter/genBasic.sh b/test/jdk/java/util/Formatter/genBasic.sh index 24bd5f786e0..de7f4662f0d 100644 --- a/test/jdk/java/util/Formatter/genBasic.sh +++ b/test/jdk/java/util/Formatter/genBasic.sh @@ -23,7 +23,7 @@ # questions. # -javac -d . ../../../../make/src/classes/build/tools/spp/Spp.java +javac -d . ../../../../../make/jdk/src/classes/build/tools/spp/Spp.java gen() { # if [ $3 = "true" ] From cc4dcf32d39f36af3b95ca279ea078e9d3eda306 Mon Sep 17 00:00:00 2001 From: Calvin Cheung Date: Fri, 8 Jun 2018 11:04:58 -0700 Subject: [PATCH 45/46] 8204110: serviceability/sa/ClhsdbSymbol.java and ClhsdbInspect.java failed when running in CDS mode ClhsdbSymbol - added printing of symbols from shared table. ClhsdbInspect - find type via FileMapInfo if guessTypeForAddress returns null and sharing is enabled. Reviewed-by: jgeorge, sspitsyn, iklam --- .../sun/jvm/hotspot/CommandProcessor.java | 23 +++++++++++- .../sun/jvm/hotspot/memory/SymbolTable.java | 6 ++- .../hotspot/utilities/CompactHashTable.java | 37 ++++++++++++++++++- 3 files changed, 63 insertions(+), 3 deletions(-) diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java index c227c4d82c4..c642da22f2b 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java @@ -49,6 +49,7 @@ import sun.jvm.hotspot.code.NMethod; import sun.jvm.hotspot.debugger.Address; import sun.jvm.hotspot.debugger.OopHandle; import sun.jvm.hotspot.classfile.ClassLoaderDataGraph; +import sun.jvm.hotspot.memory.FileMapInfo; import sun.jvm.hotspot.memory.SymbolTable; import sun.jvm.hotspot.memory.SystemDictionary; import sun.jvm.hotspot.memory.Universe; @@ -89,6 +90,7 @@ import sun.jvm.hotspot.ui.tree.OopTreeNodeAdapter; import sun.jvm.hotspot.ui.tree.SimpleTreeNode; import sun.jvm.hotspot.utilities.AddressOps; import sun.jvm.hotspot.utilities.Assert; +import sun.jvm.hotspot.utilities.CompactHashTable; import sun.jvm.hotspot.utilities.HeapProgressThunk; import sun.jvm.hotspot.utilities.LivenessPathElement; import sun.jvm.hotspot.utilities.MethodArray; @@ -637,12 +639,22 @@ public class CommandProcessor { }, new Command("symboldump", "symboldump", false) { public void doit(Tokens t) { - SymbolTable.getTheTable().symbolsDo(new SymbolTable.SymbolVisitor() { + SymbolTable theTable = SymbolTable.getTheTable(); + theTable.symbolsDo(new SymbolTable.SymbolVisitor() { public void visit(Symbol sym) { sym.printValueOn(out); out.println(); } }); + CompactHashTable sharedTable = theTable.getSharedTable(); + if (sharedTable != null) { + sharedTable.symbolsDo(new CompactHashTable.SymbolVisitor() { + public void visit(Symbol sym) { + sym.printValueOn(out); + out.println(); + } + }); + } } }, new Command("flags", "flags [ flag | -nd ]", false) { @@ -1048,6 +1060,15 @@ public class CommandProcessor { } if (node == null) { Type type = VM.getVM().getTypeDataBase().guessTypeForAddress(a); + if (type == null && VM.getVM().isSharingEnabled()) { + // Check if the value falls in the _md_region + Address loc1 = a.getAddressAt(0); + FileMapInfo cdsFileMapInfo = VM.getVM().getFileMapInfo(); + if (cdsFileMapInfo.inCopiedVtableSpace(loc1)) { + type = cdsFileMapInfo.getTypeForVptrAddress(loc1); + } + + } if (type != null) { out.println("Type is " + type.getName() + " (size of " + type.getSize() + ")"); node = new CTypeTreeNodeAdapter(a, type, null); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/SymbolTable.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/SymbolTable.java index e2231b53ecb..f1082d5538f 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/SymbolTable.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/SymbolTable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,6 +65,10 @@ public class SymbolTable extends sun.jvm.hotspot.utilities.Hashtable { return table; } + public CompactHashTable getSharedTable() { + return sharedTable; + } + public static long getSeed() { return (long) seedField.getValue(); } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/CompactHashTable.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/CompactHashTable.java index e03a85531fe..a136a3cf35f 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/CompactHashTable.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/CompactHashTable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -119,4 +119,39 @@ public class CompactHashTable extends VMObject { } return null; } + + public interface SymbolVisitor { + public void visit(Symbol sym); + } + + public void symbolsDo(SymbolVisitor visitor) { + long symOffset; + Symbol sym; + Address baseAddress = baseAddressField.getValue(addr); + Address bucket = bucketsField.getValue(addr); + for (long index = 0; index < bucketCount(); index++) { + int bucketInfo = (int)bucket.getCIntegerAt(index * uintSize, uintSize, true); + int bucketOffset = bucketOffset(bucketInfo); + int nextBucketInfo = (int)bucket.getCIntegerAt((index+1) * uintSize, uintSize, true); + int nextBucketOffset = bucketOffset(nextBucketInfo); + + Address entry = entriesField.getValue(addr).addOffsetTo(bucketOffset * uintSize); + + if (isValueOnlyBucket(bucketInfo)) { + symOffset = entry.getCIntegerAt(0, uintSize, true); + sym = Symbol.create(baseAddress.addOffsetTo(symOffset)); + visitor.visit(sym); + } else { + Address entryMax = entriesField.getValue(addr).addOffsetTo(nextBucketOffset * uintSize); + while (entry.lessThan(entryMax)) { + symOffset = entry.getCIntegerAt(uintSize, uintSize, true); + Address symAddr = baseAddress.addOffsetTo(symOffset); + sym = Symbol.create(symAddr); + visitor.visit(sym); + entry = entry.addOffsetTo(2 * uintSize); + } + } + } + } } + From 307f2c45508fbf2c359700726bddcb60a51f71c0 Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Fri, 8 Jun 2018 11:38:40 -0700 Subject: [PATCH 46/46] 8204375: Add TimeUnit#convert(Duration) Reviewed-by: martin, scolebourne, plevart, rriggs --- .../java/util/concurrent/TimeUnit.java | 63 +++++++++++--- .../util/concurrent/tck/TimeUnit8Test.java | 85 +++++++++++++++++++ 2 files changed, 136 insertions(+), 12 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/TimeUnit.java b/src/java.base/share/classes/java/util/concurrent/TimeUnit.java index cbddf59c337..7942fb55816 100644 --- a/src/java.base/share/classes/java/util/concurrent/TimeUnit.java +++ b/src/java.base/share/classes/java/util/concurrent/TimeUnit.java @@ -35,6 +35,7 @@ package java.util.concurrent; +import java.time.Duration; import java.time.temporal.ChronoUnit; import java.util.Objects; @@ -191,6 +192,50 @@ public enum TimeUnit { } } + /** + * Converts the given time duration to this unit. + * + *

    For any TimeUnit {@code unit}, + * {@code unit.convert(Duration.ofNanos(n))} + * is equivalent to + * {@code unit.convert(n, NANOSECONDS)}, and + * {@code unit.convert(Duration.of(n, unit.toChronoUnit()))} + * is equivalent to {@code n} (in the absence of overflow). + * + * @param duration the time duration + * @return the converted duration in this unit, + * or {@code Long.MIN_VALUE} if conversion would negatively overflow, + * or {@code Long.MAX_VALUE} if it would positively overflow. + * @throws NullPointerException if {@code duration} is null + * @see Duration#of(long,TemporalUnit) + * @since 11 + */ + public long convert(Duration duration) { + long secs = duration.getSeconds(); + int nano = duration.getNano(); + if (secs < 0 && nano > 0) { + // use representation compatible with integer division + secs++; + nano -= SECOND_SCALE; + } + final long s, nanoVal; + // Optimize for the common case - NANOSECONDS without overflow + if (this == NANOSECONDS) + nanoVal = nano; + else if ((s = scale) < SECOND_SCALE) + nanoVal = nano / s; + else if (this == SECONDS) + return secs; + else + return secs / secRatio; + long val = secs * secRatio + nanoVal; + return ((secs < maxSecs && secs > -maxSecs) || + (secs == maxSecs && val > 0) || + (secs == -maxSecs && val < 0)) + ? val + : (secs > 0) ? Long.MAX_VALUE : Long.MIN_VALUE; + } + /** * Equivalent to * {@link #convert(long, TimeUnit) NANOSECONDS.convert(duration, this)}. @@ -221,10 +266,8 @@ public enum TimeUnit { */ public long toMicros(long duration) { long s, m; - if ((s = scale) == MICRO_SCALE) - return duration; - else if (s < MICRO_SCALE) - return duration / microRatio; + if ((s = scale) <= MICRO_SCALE) + return (s == MICRO_SCALE) ? duration : duration / microRatio; else if (duration > (m = maxMicros)) return Long.MAX_VALUE; else if (duration < -m) @@ -243,10 +286,8 @@ public enum TimeUnit { */ public long toMillis(long duration) { long s, m; - if ((s = scale) == MILLI_SCALE) - return duration; - else if (s < MILLI_SCALE) - return duration / milliRatio; + if ((s = scale) <= MILLI_SCALE) + return (s == MILLI_SCALE) ? duration : duration / milliRatio; else if (duration > (m = maxMillis)) return Long.MAX_VALUE; else if (duration < -m) @@ -265,10 +306,8 @@ public enum TimeUnit { */ public long toSeconds(long duration) { long s, m; - if ((s = scale) == SECOND_SCALE) - return duration; - else if (s < SECOND_SCALE) - return duration / secRatio; + if ((s = scale) <= SECOND_SCALE) + return (s == SECOND_SCALE) ? duration : duration / secRatio; else if (duration > (m = maxSecs)) return Long.MAX_VALUE; else if (duration < -m) diff --git a/test/jdk/java/util/concurrent/tck/TimeUnit8Test.java b/test/jdk/java/util/concurrent/tck/TimeUnit8Test.java index b5fa1813cb2..acca0b0943d 100644 --- a/test/jdk/java/util/concurrent/tck/TimeUnit8Test.java +++ b/test/jdk/java/util/concurrent/tck/TimeUnit8Test.java @@ -40,8 +40,12 @@ import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.SECONDS; +import java.time.Duration; import java.time.temporal.ChronoUnit; +import java.util.Arrays; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; +import java.util.stream.LongStream; import junit.framework.Test; import junit.framework.TestSuite; @@ -100,4 +104,85 @@ public class TimeUnit8Test extends JSR166TestCase { } } + /** + * convert(Duration) roundtrips with Duration.ofXXXX and Duration.of(long, ChronoUnit) + */ + public void testConvertDuration_roundtripDurationOf() { + long n = ThreadLocalRandom.current().nextLong(); + + assertEquals(n, NANOSECONDS.convert(Duration.ofNanos(n))); + assertEquals(n, NANOSECONDS.convert(Duration.of(n, ChronoUnit.NANOS))); + assertEquals(n, MILLISECONDS.convert(Duration.ofMillis(n))); + assertEquals(n, MILLISECONDS.convert(Duration.of(n, ChronoUnit.MILLIS))); + assertEquals(n, SECONDS.convert(Duration.ofSeconds(n))); + assertEquals(n, SECONDS.convert(Duration.of(n, ChronoUnit.SECONDS))); + n /= 60; + assertEquals(n, MINUTES.convert(Duration.ofMinutes(n))); + assertEquals(n, MINUTES.convert(Duration.of(n, ChronoUnit.MINUTES))); + n /= 60; + assertEquals(n, HOURS.convert(Duration.ofHours(n))); + assertEquals(n, HOURS.convert(Duration.of(n, ChronoUnit.HOURS))); + n /= 24; + assertEquals(n, DAYS.convert(Duration.ofDays(n))); + assertEquals(n, DAYS.convert(Duration.of(n, ChronoUnit.DAYS))); + } + + /** + * convert(Duration.ofNanos(n)) agrees with convert(n, NANOSECONDS) + */ + public void testConvertDuration_roundtripDurationOfNanos() { + // Test values near unit transitions and near overflow. + LongStream.concat( + Arrays.stream(TimeUnit.values()).mapToLong(u -> u.toNanos(1)), + LongStream.of(Long.MAX_VALUE, Long.MIN_VALUE)) + .flatMap(n -> LongStream.of(n, n + 1, n - 1)) + .flatMap(n -> LongStream.of(n, n + 1_000_000_000, n - 1_000_000_000)) + .flatMap(n -> LongStream.of(n, -n)) + // .peek(System.err::println) + .forEach(n -> Arrays.stream(TimeUnit.values()).forEach( + u -> assertEquals(u.convert(n, NANOSECONDS), + u.convert(Duration.ofNanos(n))))); + } + + /** + * convert(Duration) doesn't misbehave near Long.MAX_VALUE and Long.MIN_VALUE. + */ + public void testConvertDuration_nearOverflow() { + ChronoUnit NANOS = ChronoUnit.NANOS; + Duration maxDuration = Duration.ofSeconds(Long.MAX_VALUE, 999_999_999); + Duration minDuration = Duration.ofSeconds(Long.MIN_VALUE, 0); + + for (TimeUnit u : TimeUnit.values()) { + ChronoUnit cu = u.toChronoUnit(); + long r; + if (u.toNanos(1) > SECONDS.toNanos(1)) { + r = u.toNanos(1) / SECONDS.toNanos(1); + + assertThrows(ArithmeticException.class, + () -> Duration.of(Long.MAX_VALUE, cu), + () -> Duration.of(Long.MIN_VALUE, cu)); + } else { + r = 1; + + Duration max = Duration.of(Long.MAX_VALUE, cu); + Duration min = Duration.of(Long.MIN_VALUE, cu); + assertEquals(Long.MAX_VALUE, u.convert(max)); + assertEquals(Long.MAX_VALUE - 1, u.convert(max.minus(1, NANOS))); + assertEquals(Long.MAX_VALUE - 1, u.convert(max.minus(1, cu))); + assertEquals(Long.MIN_VALUE, u.convert(min)); + assertEquals(Long.MIN_VALUE + 1, u.convert(min.plus(1, NANOS))); + assertEquals(Long.MIN_VALUE + 1, u.convert(min.plus(1, cu))); + assertEquals(Long.MAX_VALUE, u.convert(max.plus(1, NANOS))); + if (u != SECONDS) { + assertEquals(Long.MAX_VALUE, u.convert(max.plus(1, cu))); + assertEquals(Long.MIN_VALUE, u.convert(min.minus(1, NANOS))); + assertEquals(Long.MIN_VALUE, u.convert(min.minus(1, cu))); + } + } + + assertEquals(Long.MAX_VALUE / r, u.convert(maxDuration)); + assertEquals(Long.MIN_VALUE / r, u.convert(minDuration)); + } + } + }