Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8217850: CompressedClassSpaceSizeInJmapHeap fails after JDK-8217612 #433

Open
wants to merge 2 commits into
base: pr/431
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 77 additions & 3 deletions hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}
};
Expand Down Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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());
}
Expand Down Expand Up @@ -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 + "\"");
}
}
}
4 changes: 2 additions & 2 deletions hotspot/src/share/vm/runtime/globals.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
141 changes: 141 additions & 0 deletions hotspot/test/serviceability/sa/ClhsdbFlags.java
Original file line number Diff line number Diff line change
@@ -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<String> vmArgs = new ArrayList<String>();
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<String> cmds = List.of(
"flags", "flags -nd",
"flags UnlockDiagnosticVMOptions", "flags MaxFDLimit",
"flags MaxJavaStackTraceDepth");

Map<String, List<String>> 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<String> vmArgs = new ArrayList<String>();
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<String> cmds = List.of("flags");

Map<String, List<String>> 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();
}
}