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(); + } +}