8316778: test hprof lib: invalid array element type from JavaValueArray.elementSize

Reviewed-by: cjplummer, lmesnik, sspitsyn
This commit is contained in:
Alex Menkov 2023-10-03 19:35:51 +00:00
parent 8ff10a0d35
commit f7deaf4bef
3 changed files with 196 additions and 11 deletions

View File

@ -0,0 +1,171 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.File;
import java.lang.ref.Reference;
import java.util.Enumeration;
import java.util.concurrent.TimeUnit;
import jdk.test.lib.Asserts;
import jdk.test.lib.JDKToolLauncher;
import jdk.test.lib.apps.LingeredApp;
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.hprof.model.JavaClass;
import jdk.test.lib.hprof.model.JavaHeapObject;
import jdk.test.lib.hprof.model.JavaObject;
import jdk.test.lib.hprof.model.JavaValueArray;
import jdk.test.lib.hprof.model.JavaThing;
import jdk.test.lib.hprof.model.Snapshot;
import jdk.test.lib.hprof.parser.Reader;
/**
* @test
* @bug 8316778
* @library /test/lib
* @run main HprofTest
*/
class HprofTestTarg extends LingeredApp {
// Array of primitive types
int[] intArray = new int[2];
// String
String str = "test_string";
public static void main(String[] args) {
HprofTestTarg testObj = new HprofTestTarg();
LingeredApp.main(args);
Reference.reachabilityFence(testObj);
}
}
public class HprofTest {
public static void main(String[] args) throws Exception {
File dumpFile = new File("Myheapdump.hprof");
createDump(dumpFile);
test(dumpFile);
}
private static void createDump(File dumpFile) throws Exception {
LingeredApp theApp = null;
try {
theApp = new HprofTestTarg();
LingeredApp.startApp(theApp);
//jcmd <pid> GC.heap_dump <file_path>
JDKToolLauncher launcher = JDKToolLauncher
.createUsingTestJDK("jcmd")
.addToolArg(Long.toString(theApp.getPid()))
.addToolArg("GC.heap_dump")
.addToolArg(dumpFile.getAbsolutePath());
Process p = ProcessTools.startProcess("jcmd", new ProcessBuilder(launcher.getCommand()));
while (!p.waitFor(5, TimeUnit.SECONDS)) {
if (!theApp.getProcess().isAlive()) {
log("ERROR: target VM died, killing jcmd...");
p.destroyForcibly();
throw new Exception("Target VM died");
}
}
if (p.exitValue() != 0) {
throw new Exception("Jcmd exited with code " + p.exitValue());
}
} finally {
LingeredApp.stopApp(theApp);
}
}
private static void test(File dumpFile) throws Exception {
Asserts.assertTrue(dumpFile.exists(), "Heap dump file not found.");
log("Reading " + dumpFile + "...");
try (Snapshot snapshot = Reader.readFile(dumpFile.getPath(), true, 0)) {
log("Resolving snapshot...");
snapshot.resolve(true);
log("Snapshot resolved.");
JavaObject testObj = getTestObject(snapshot);
testPrimitiveArray(testObj);
testString(testObj);
}
}
// verifies JavaValueArray.valueString does not throw
// "invalid array element type" exception
private static void testPrimitiveArray(JavaObject obj) {
JavaHeapObject field = getObjectField(obj, "intArray");
Asserts.assertTrue(field instanceof JavaValueArray);
log("int array: " + ((JavaValueArray)field).valueString());
}
// verifies JavaObject.toString returns String value
private static void testString(JavaObject obj) {
JavaHeapObject field = getObjectField(obj, "str");
Asserts.assertTrue(field instanceof JavaObject);
JavaObject javaObj = (JavaObject)field;
Asserts.assertTrue(javaObj.getClazz().isString());
log("string: " + javaObj.toString());
assert(javaObj.toString().contains(new HprofTestTarg().str));
}
private static JavaHeapObject getObjectField(JavaObject obj, String fieldName) {
JavaThing thing = obj.getField(fieldName);
// only non-primitive types are supported
return (JavaHeapObject)thing;
}
// gets test HprofTestTarg
private static JavaObject getTestObject(Snapshot snapshot) {
String testClassName = HprofTestTarg.class.getName();
JavaHeapObject testObject = getObjects(snapshot, testClassName).nextElement();
Asserts.assertTrue(testObject instanceof JavaObject);
return (JavaObject)testObject;
}
// finds all objects of the specified type
private static Enumeration<JavaHeapObject> getObjects(Snapshot snapshot, String className) {
log("Looking for '" + className + "' objects...");
JavaClass jClass = snapshot.findClass(className);
if (jClass == null) {
throw new RuntimeException("Class '" + className + "' not found");
}
int instanceCount = jClass.getInstancesCount(false);
if (instanceCount < 1) {
throw new RuntimeException("Not instances of '" + className + "' found");
}
log("Found " + instanceCount + " instance(s).");
return jClass.getInstances(false);
}
private static void log(Object s) {
System.out.println(s);
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -190,7 +190,7 @@ public class JavaObject extends JavaLazyReadObject {
if (getClazz().isString()) { if (getClazz().isString()) {
JavaThing value = getField("value"); JavaThing value = getField("value");
if (value instanceof JavaValueArray) { if (value instanceof JavaValueArray) {
return ((JavaValueArray)value).valueString(); return ((JavaValueArray)value).valueAsString();
} else { } else {
return "null"; return "null";
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -66,17 +66,17 @@ public class JavaValueArray extends JavaLazyReadObject
private static int elementSize(byte type) { private static int elementSize(byte type) {
switch (type) { switch (type) {
case T_BYTE: case 'B':
case T_BOOLEAN: case 'Z':
return 1; return 1;
case T_CHAR: case 'C':
case T_SHORT: case 'S':
return 2; return 2;
case T_INT: case 'I':
case T_FLOAT: case 'F':
return 4; return 4;
case T_LONG: case 'J':
case T_DOUBLE: case 'D':
return 8; return 8;
default: default:
throw new RuntimeException("invalid array element type: " + type); throw new RuntimeException("invalid array element type: " + type);
@ -347,4 +347,18 @@ public class JavaValueArray extends JavaLazyReadObject
} }
return result.toString(); return result.toString();
} }
// Tries to represent the value as string (used by JavaObject.toString).
public String valueAsString() {
if (getElementType() == 'B') {
JavaThing[] things = getValue();
byte[] bytes = new byte[things.length];
for (int i = 0; i < things.length; i++) {
bytes[i] = ((JavaByte)things[i]).value;
}
return new String(bytes);
}
// fallback
return valueString();
}
} }