From 554b8da9e1931353fec84907a2ff34774090dd7d Mon Sep 17 00:00:00 2001 From: Takakuri Date: Thu, 25 Jan 2024 20:38:43 +0900 Subject: [PATCH 1/2] d6a75a0f86d4c84132a3794c432b34068163fa60 --- .../classes/sun/jvm/hotspot/runtime/VM.java | 80 +++++++++- hotspot/src/share/vm/runtime/globals.hpp | 4 +- .../test/serviceability/sa/ClhsdbFlags.java | 141 ++++++++++++++++++ 3 files changed, 220 insertions(+), 5 deletions(-) create mode 100644 hotspot/test/serviceability/sa/ClhsdbFlags.java diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java index 29bf9efea7d..91a84001512 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -124,6 +124,7 @@ public class VM { private static Type intxType; private static Type uintxType; + private static Type uint64tType; private static CIntegerType boolType; private Boolean sharingEnabled; private Boolean compressedOopsEnabled; @@ -192,15 +193,87 @@ public long getUIntx() { return addr.getCIntegerAt(0, uintxType.getSize(), true); } + public boolean isCcstr() { + return type.equals("ccstr"); + } + + public String getCcstr() { + if (Assert.ASSERTS_ENABLED) { + Assert.that(isCcstr(), "not a ccstr flag!"); + } + return CStringUtilities.getString(addr.getAddressAt(0)); + } + + public boolean isCcstrlist() { + return type.equals("ccstrlist"); + } + + public String getCcstrlist() { + if (Assert.ASSERTS_ENABLED) { + Assert.that(isCcstrlist(), "not a ccstrlist flag!"); + } + return CStringUtilities.getString(addr.getAddressAt(0)); + } + + public boolean isDouble() { + return type.equals("double"); + } + + public double getDouble() { + if (Assert.ASSERTS_ENABLED) { + Assert.that(isDouble(), "not a double flag!"); + } + return addr.getJDoubleAt(0); + } + + public boolean isUint64t() { + return type.equals("uint64_t"); + } + + public long getUint64t() { + if (Assert.ASSERTS_ENABLED) { + Assert.that(isUint64t(), "not an uint64_t flag!"); + } + return addr.getCIntegerAt(0, uint64tType.getSize(), true); + } + public String getValue() { if (isBool()) { return new Boolean(getBool()).toString(); } else if (isIntx()) { return new Long(getIntx()).toString(); } else if (isUIntx()) { - return new Long(getUIntx()).toString(); + return longToUnsignedString(getUIntx()); + } else if (isCcstr()) { + String str = getCcstr(); + if (str != null) { + str = "\"" + str + "\""; + } + return str; + } else if (isCcstrlist()) { + String str = getCcstrlist(); + if (str != null) { + str = "\"" + str + "\""; + } + return str; + } else if (isDouble()) { + return new Double(getDouble()).toString(); + } else if (isUint64t()) { + return longToUnsignedString(getUint64t()); + } else { + throw new WrongTypeException("Unknown type: " + type + " (" + name + ")"); + } + } + + /** This is an alternative to Long.toUnsignedString(long i) + Required to build with the boot JDK7. */ + private String longToUnsignedString(long i) { + if (i >= 0) { + return Long.toString(i); } else { - return null; + long quot = (i >>> 1) / 5; + long rem = i - quot * 10; + return Long.toString(quot) + rem; } } }; @@ -325,6 +398,7 @@ private VM(TypeDataBase db, JVMDebugger debugger, boolean isBigEndian) { intxType = db.lookupType("intx"); uintxType = db.lookupType("uintx"); + uint64tType = db.lookupType("uint64_t"); boolType = (CIntegerType) db.lookupType("bool"); minObjAlignmentInBytes = getObjectAlignmentInBytes(); diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 23ce8af5696..46e1505b371 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -453,8 +453,8 @@ class CommandLineFlags { // notproduct flags are settable / visible only during development and are not declared in the PRODUCT version // A flag must be declared with one of the following types: -// bool, intx, uintx, ccstr. -// The type "ccstr" is an alias for "const char*" and is used +// bool, intx, uintx, ccstr, ccstrlist, double, or uint64_t. +// The type "ccstr" and "ccstrlist" are an alias for "const char*" and is used // only in this file, because the macrology requires single-token type names. // Note: Diagnostic options not meant for VM tuning or for product modes. diff --git a/hotspot/test/serviceability/sa/ClhsdbFlags.java b/hotspot/test/serviceability/sa/ClhsdbFlags.java new file mode 100644 index 00000000000..77eefc0c6c2 --- /dev/null +++ b/hotspot/test/serviceability/sa/ClhsdbFlags.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import jdk.test.lib.apps.LingeredApp; +import jdk.test.lib.Platform; +import jdk.test.lib.Utils; + +/** + * @bug 8190198 + * @bug 8217612 + * @summary Test clhsdb flags command + * @requires vm.hasSA + * @library /test/lib + * @run main/othervm ClhsdbFlags + */ + +public class ClhsdbFlags { + + public static void runBasicTest() throws Exception { + System.out.println("Starting ClhsdbFlags basic test"); + + LingeredApp theApp = null; + try { + ClhsdbLauncher test = new ClhsdbLauncher(); + List vmArgs = new ArrayList(); + vmArgs.add("-XX:+UnlockExperimentalVMOptions"); + vmArgs.add("-XX:+UnlockDiagnosticVMOptions"); + vmArgs.add("-XX:-MaxFDLimit"); + vmArgs.addAll(Utils.getVmOptions()); + theApp = LingeredApp.startApp(vmArgs); + System.out.println("Started LingeredApp with pid " + theApp.getPid()); + + List cmds = List.of( + "flags", "flags -nd", + "flags UnlockDiagnosticVMOptions", "flags MaxFDLimit", + "flags MaxJavaStackTraceDepth"); + + Map> expStrMap = new HashMap<>(); + expStrMap.put("flags", List.of( + "UnlockDiagnosticVMOptions = true", + "MaxFDLimit = false", + "MaxJavaStackTraceDepth = 1024", + "VerifyMergedCPBytecodes", + "ConcGCThreads", "UseThreadPriorities", + "ShowHiddenFrames")); + expStrMap.put("flags -nd", List.of( + "UnlockDiagnosticVMOptions = true", + "MaxFDLimit = false", + "InitialHeapSize", + "MaxHeapSize")); + expStrMap.put("flags UnlockDiagnosticVMOptions", List.of( + "UnlockDiagnosticVMOptions = true")); + expStrMap.put("flags MaxFDLimit", List.of( + "MaxFDLimit = false")); + expStrMap.put("flags MaxJavaStackTraceDepth", List.of( + "MaxJavaStackTraceDepth = 1024")); + + test.run(theApp.getPid(), cmds, expStrMap, null); + } catch (Exception ex) { + throw new RuntimeException("Test ERROR " + ex, ex); + } finally { + LingeredApp.stopApp(theApp); + } + System.out.println("Test PASSED"); + } + + public static void runAllTypesTest() throws Exception { + System.out.println("Starting ClhsdbFlags all types test"); + + LingeredApp theApp = null; + try { + ClhsdbLauncher test = new ClhsdbLauncher(); + List vmArgs = new ArrayList(); + vmArgs.add("-XX:+UnlockDiagnosticVMOptions"); // bool + vmArgs.add("-XX:ActiveProcessorCount=1"); // int + vmArgs.add("-XX:ParallelGCThreads=1"); // uint + vmArgs.add("-XX:MaxJavaStackTraceDepth=1024"); // intx + vmArgs.add("-XX:LogEventsBufferEntries=10"); // uintx + vmArgs.add("-XX:HeapSizePerGCThread=32m"); // size_t + vmArgs.add("-XX:NativeMemoryTracking=off"); // ccstr + vmArgs.add("-XX:OnError='echo error'"); // ccstrlist + vmArgs.add("-XX:CompileThresholdScaling=1.0"); // double + vmArgs.add("-XX:ErrorLogTimeout=120"); // uint64_t + vmArgs.addAll(Utils.getVmOptions()); + theApp = LingeredApp.startApp(vmArgs); + System.out.println("Started LingeredApp with pid " + theApp.getPid()); + + List cmds = List.of("flags"); + + Map> expStrMap = new HashMap<>(); + expStrMap.put("flags", List.of( + "UnlockDiagnosticVMOptions = true", + "ActiveProcessorCount = 1", + "ParallelGCThreads = 1", + "MaxJavaStackTraceDepth = 1024", + "LogEventsBufferEntries = 10", + "HeapSizePerGCThread = 3", + "NativeMemoryTracking = \"off\"", + "OnError = \"'echo error'\"", + "CompileThresholdScaling = 1.0", + "ErrorLogTimeout = 120")); + + test.run(theApp.getPid(), cmds, expStrMap, null); + } catch (Exception ex) { + throw new RuntimeException("Test ERROR " + ex, ex); + } finally { + LingeredApp.stopApp(theApp); + } + System.out.println("Test PASSED"); + } + + public static void main(String[] args) throws Exception { + runBasicTest(); + runAllTypesTest(); + } +} From ccb8463a09dc09a6df363017a350c8bc00fcbd60 Mon Sep 17 00:00:00 2001 From: Takakuri Date: Fri, 26 Jan 2024 13:20:43 +0900 Subject: [PATCH 2/2] Backport 49c91b7f9522a991bcac789b9fcccfee8bf08b5d --- .../sun/jvm/hotspot/tools/HeapSummary.java | 61 ++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java index afe4d2a50b5..9cc4ec2234d 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -255,6 +255,8 @@ private long getFlagValue(String name, Map flagMap) { if (f != null) { if (f.isBool()) { return f.getBool()? 1L : 0L; + } else if (f.isUIntx() || f.isUint64t()) { + return parseUnsignedLong(f.getValue(), 10); } else { return Long.parseLong(f.getValue()); } @@ -299,4 +301,61 @@ public void print() { strTable.stringsDo(stat); stat.print(); } + + /** This is an alternative to Long.parseUnsignedLong(String s, int radix) + Required to build with the boot JDK7. + Backporting JDK-8217850 requires this method. */ + private long parseUnsignedLong(String s, int radix) + throws NumberFormatException { + if (s == null) { + throw new NumberFormatException("null"); + } + + int len = s.length(); + if (len > 0) { + char firstChar = s.charAt(0); + if (firstChar == '-') { + throw new + NumberFormatException(String.format("Illegal leading minus sign " + + "on unsigned string %s.", s)); + } else { + if (len <= 12 || // Long.MAX_VALUE in Character.MAX_RADIX is 13 digits + (radix == 10 && len <= 18) ) { // Long.MAX_VALUE in base 10 is 19 digits + return Long.parseLong(s, radix); + } + + // No need for range checks on len due to testing above. + long first = Long.parseLong(s.substring(0, len - 1), radix); + int second = Character.digit(s.charAt(len - 1), radix); + if (second < 0) { + throw new NumberFormatException("Bad digit at end of " + s); + } + long result = first * radix + second; + /* Replace compareUnsigned(long x, long y) with its implementation */ + if (Long.compare(result + Long.MIN_VALUE, first + Long.MIN_VALUE) < 0) { + /* + * The maximum unsigned value, (2^64)-1, takes at + * most one more digit to represent than the + * maximum signed value, (2^63)-1. Therefore, + * parsing (len - 1) digits will be appropriately + * in-range of the signed parsing. In other + * words, if parsing (len -1) digits overflows + * signed parsing, parsing len digits will + * certainly overflow unsigned parsing. + * + * The compareUnsigned check above catches + * situations where an unsigned overflow occurs + * incorporating the contribution of the final + * digit. + */ + throw new NumberFormatException(String.format("String value %s exceeds " + + "range of unsigned long.", s)); + } + return result; + } + } else { + /* Replace NumberFormatException.forInputString(s) with its implementation */ + throw new NumberFormatException("For input string: \"" + s + "\""); + } + } }