8316778: test hprof lib: invalid array element type from JavaValueArray.elementSize
Reviewed-by: cjplummer, lmesnik, sspitsyn
This commit is contained in:
parent
8ff10a0d35
commit
f7deaf4bef
171
test/lib-test/jdk/test/lib/hprof/HprofTest.java
Normal file
171
test/lib-test/jdk/test/lib/hprof/HprofTest.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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";
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user