mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-03 11:38:44 +00:00
8171084: heapdump/JMapHeapCore fails with java.lang.RuntimeException: Heap segment size overflow
Create a new heapdump segment and truncate huge arrays if required, to avoid overflow of the 32 bit value representing the size. Reviewed-by: dholmes, dsamersoff
This commit is contained in:
parent
f798c318f8
commit
f02b7dfba7
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2017, 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
|
||||
@ -50,7 +50,7 @@ int pathmap_open(const char* name) {
|
||||
}
|
||||
|
||||
|
||||
if (strlen(alt_root) + strlen(name) < PATH_MAX) {
|
||||
if (strlen(alt_root) + strlen(name) > PATH_MAX) {
|
||||
// Buffer too small.
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2004, 2017, 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
|
||||
@ -114,6 +114,8 @@ public abstract class AbstractHeapGraphWriter implements HeapGraphWriter {
|
||||
}
|
||||
});
|
||||
|
||||
writeHeapRecordPrologue();
|
||||
|
||||
// write JavaThreads
|
||||
writeJavaThreads();
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2004, 2017, 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
|
||||
@ -45,8 +45,8 @@ import sun.jvm.hotspot.classfile.*;
|
||||
* WARNING: This format is still under development, and is subject to
|
||||
* change without notice.
|
||||
*
|
||||
* header "JAVA PROFILE 1.0.1" or "JAVA PROFILE 1.0.2" (0-terminated)
|
||||
* u4 size of identifiers. Identifiers are used to represent
|
||||
* header "JAVA PROFILE 1.0.2" (0-terminated)
|
||||
* u4 size of identifiers. Identifiers are used to represent
|
||||
* UTF8 strings, objects, stack traces, etc. They usually
|
||||
* have the same size as host pointers. For example, on
|
||||
* Solaris and Win32, the size is 4.
|
||||
@ -294,10 +294,9 @@ import sun.jvm.hotspot.classfile.*;
|
||||
* u2 stack trace depth
|
||||
*
|
||||
*
|
||||
* When the header is "JAVA PROFILE 1.0.2" a heap dump can optionally
|
||||
* be generated as a sequence of heap dump segments. This sequence is
|
||||
* terminated by an end record. The additional tags allowed by format
|
||||
* "JAVA PROFILE 1.0.2" are:
|
||||
* A heap dump can optionally be generated as a sequence of heap dump
|
||||
* segments. This sequence is terminated by an end record. The additional
|
||||
* tags allowed by format "JAVA PROFILE 1.0.2" are:
|
||||
*
|
||||
* HPROF_HEAP_DUMP_SEGMENT denote a heap dump segment
|
||||
*
|
||||
@ -310,8 +309,6 @@ import sun.jvm.hotspot.classfile.*;
|
||||
|
||||
public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||
|
||||
// The heap size threshold used to determine if segmented format
|
||||
// ("JAVA PROFILE 1.0.2") should be used.
|
||||
private static final long HPROF_SEGMENTED_HEAP_DUMP_THRESHOLD = 2L * 0x40000000;
|
||||
|
||||
// The approximate size of a heap segment. Used to calculate when to create
|
||||
@ -319,7 +316,6 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||
private static final long HPROF_SEGMENTED_HEAP_DUMP_SEGMENT_SIZE = 1L * 0x40000000;
|
||||
|
||||
// hprof binary file header
|
||||
private static final String HPROF_HEADER_1_0_1 = "JAVA PROFILE 1.0.1";
|
||||
private static final String HPROF_HEADER_1_0_2 = "JAVA PROFILE 1.0.2";
|
||||
|
||||
// constants in enum HprofTag
|
||||
@ -380,6 +376,7 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||
private static final int JVM_SIGNATURE_ARRAY = '[';
|
||||
private static final int JVM_SIGNATURE_CLASS = 'L';
|
||||
|
||||
private static final long MAX_U4_VALUE = 0xFFFFFFFFL;
|
||||
int serialNum = 1;
|
||||
|
||||
public synchronized void write(String fileName) throws IOException {
|
||||
@ -469,7 +466,6 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||
// length later - hprof format requires length.
|
||||
out.flush();
|
||||
currentSegmentStart = fos.getChannel().position();
|
||||
|
||||
// write dummy length of 0 and we'll fix it later.
|
||||
out.writeInt(0);
|
||||
}
|
||||
@ -479,7 +475,7 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||
protected void writeHeapRecordEpilogue() throws IOException {
|
||||
if (useSegmentedHeapDump) {
|
||||
out.flush();
|
||||
if ((fos.getChannel().position() - currentSegmentStart - 4) >= HPROF_SEGMENTED_HEAP_DUMP_SEGMENT_SIZE) {
|
||||
if ((fos.getChannel().position() - currentSegmentStart - 4L) >= HPROF_SEGMENTED_HEAP_DUMP_SEGMENT_SIZE) {
|
||||
fillInHeapRecordLength();
|
||||
currentSegmentStart = 0;
|
||||
}
|
||||
@ -488,14 +484,14 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||
|
||||
private void fillInHeapRecordLength() throws IOException {
|
||||
|
||||
// now get current position to calculate length
|
||||
// now get the current position to calculate length
|
||||
long dumpEnd = fos.getChannel().position();
|
||||
|
||||
// calculate length of heap data
|
||||
// calculate the length of heap data
|
||||
long dumpLenLong = (dumpEnd - currentSegmentStart - 4L);
|
||||
|
||||
// Check length boundary, overflow could happen but is _very_ unlikely
|
||||
if(dumpLenLong >= (4L * 0x40000000)){
|
||||
if (dumpLenLong >= (4L * 0x40000000)) {
|
||||
throw new RuntimeException("Heap segment size overflow.");
|
||||
}
|
||||
|
||||
@ -517,6 +513,71 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||
fos.getChannel().position(currentPosition);
|
||||
}
|
||||
|
||||
// get the size in bytes for the requested type
|
||||
private long getSizeForType(int type) throws IOException {
|
||||
switch (type) {
|
||||
case TypeArrayKlass.T_BOOLEAN:
|
||||
return BOOLEAN_SIZE;
|
||||
case TypeArrayKlass.T_INT:
|
||||
return INT_SIZE;
|
||||
case TypeArrayKlass.T_CHAR:
|
||||
return CHAR_SIZE;
|
||||
case TypeArrayKlass.T_SHORT:
|
||||
return SHORT_SIZE;
|
||||
case TypeArrayKlass.T_BYTE:
|
||||
return BYTE_SIZE;
|
||||
case TypeArrayKlass.T_LONG:
|
||||
return LONG_SIZE;
|
||||
case TypeArrayKlass.T_FLOAT:
|
||||
return FLOAT_SIZE;
|
||||
case TypeArrayKlass.T_DOUBLE:
|
||||
return DOUBLE_SIZE;
|
||||
default:
|
||||
throw new RuntimeException(
|
||||
"Should not reach here: Unknown type: " + type);
|
||||
}
|
||||
}
|
||||
|
||||
private int getArrayHeaderSize(boolean isObjectAarray) {
|
||||
return isObjectAarray?
|
||||
((int) BYTE_SIZE + 2 * (int) INT_SIZE + 2 * (int) OBJ_ID_SIZE):
|
||||
(2 * (int) BYTE_SIZE + 2 * (int) INT_SIZE + (int) OBJ_ID_SIZE);
|
||||
}
|
||||
|
||||
// Check if we need to truncate an array
|
||||
private int calculateArrayMaxLength(long originalArrayLength,
|
||||
int headerSize,
|
||||
long typeSize,
|
||||
String typeName) throws IOException {
|
||||
|
||||
long length = originalArrayLength;
|
||||
|
||||
// now get the current position to calculate length
|
||||
long dumpEnd = fos.getChannel().position();
|
||||
long originalLengthInBytes = originalArrayLength * typeSize;
|
||||
|
||||
// calculate the length of heap data
|
||||
long currentRecordLength = (dumpEnd - currentSegmentStart - 4L);
|
||||
if (currentRecordLength > 0 &&
|
||||
(currentRecordLength + headerSize + originalLengthInBytes) > MAX_U4_VALUE) {
|
||||
fillInHeapRecordLength();
|
||||
currentSegmentStart = 0;
|
||||
writeHeapRecordPrologue();
|
||||
currentRecordLength = 0;
|
||||
}
|
||||
|
||||
// Calculate the max bytes we can use.
|
||||
long maxBytes = (MAX_U4_VALUE - (headerSize + currentRecordLength));
|
||||
|
||||
if (originalLengthInBytes > maxBytes) {
|
||||
length = maxBytes/typeSize;
|
||||
System.err.println("WARNING: Cannot dump array of type " + typeName
|
||||
+ " with length " + originalArrayLength
|
||||
+ "; truncating to length " + length);
|
||||
}
|
||||
return (int) length;
|
||||
}
|
||||
|
||||
private void writeClassDumpRecords() throws IOException {
|
||||
SystemDictionary sysDict = VM.getVM().getSystemDictionary();
|
||||
ClassLoaderDataGraph cldGraph = VM.getVM().getClassLoaderDataGraph();
|
||||
@ -694,12 +755,16 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||
}
|
||||
|
||||
protected void writeObjectArray(ObjArray array) throws IOException {
|
||||
int headerSize = getArrayHeaderSize(true);
|
||||
final int length = calculateArrayMaxLength(array.getLength(),
|
||||
headerSize,
|
||||
OBJ_ID_SIZE,
|
||||
"Object");
|
||||
out.writeByte((byte) HPROF_GC_OBJ_ARRAY_DUMP);
|
||||
writeObjectID(array);
|
||||
out.writeInt(DUMMY_STACK_TRACE_ID);
|
||||
out.writeInt((int) array.getLength());
|
||||
out.writeInt(length);
|
||||
writeObjectID(array.getKlass().getJavaMirror());
|
||||
final int length = (int) array.getLength();
|
||||
for (int index = 0; index < length; index++) {
|
||||
OopHandle handle = array.getOopHandleAt(index);
|
||||
writeObjectID(getAddressValue(handle));
|
||||
@ -707,101 +772,101 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||
}
|
||||
|
||||
protected void writePrimitiveArray(TypeArray array) throws IOException {
|
||||
int headerSize = getArrayHeaderSize(false);
|
||||
TypeArrayKlass tak = (TypeArrayKlass) array.getKlass();
|
||||
final int type = (int) tak.getElementType();
|
||||
final String typeName = tak.getElementTypeName();
|
||||
final long typeSize = getSizeForType(type);
|
||||
final int length = calculateArrayMaxLength(array.getLength(),
|
||||
headerSize,
|
||||
typeSize,
|
||||
typeName);
|
||||
out.writeByte((byte) HPROF_GC_PRIM_ARRAY_DUMP);
|
||||
writeObjectID(array);
|
||||
out.writeInt(DUMMY_STACK_TRACE_ID);
|
||||
out.writeInt((int) array.getLength());
|
||||
TypeArrayKlass tak = (TypeArrayKlass) array.getKlass();
|
||||
final int type = (int) tak.getElementType();
|
||||
out.writeInt(length);
|
||||
out.writeByte((byte) type);
|
||||
switch (type) {
|
||||
case TypeArrayKlass.T_BOOLEAN:
|
||||
writeBooleanArray(array);
|
||||
writeBooleanArray(array, length);
|
||||
break;
|
||||
case TypeArrayKlass.T_CHAR:
|
||||
writeCharArray(array);
|
||||
writeCharArray(array, length);
|
||||
break;
|
||||
case TypeArrayKlass.T_FLOAT:
|
||||
writeFloatArray(array);
|
||||
writeFloatArray(array, length);
|
||||
break;
|
||||
case TypeArrayKlass.T_DOUBLE:
|
||||
writeDoubleArray(array);
|
||||
writeDoubleArray(array, length);
|
||||
break;
|
||||
case TypeArrayKlass.T_BYTE:
|
||||
writeByteArray(array);
|
||||
writeByteArray(array, length);
|
||||
break;
|
||||
case TypeArrayKlass.T_SHORT:
|
||||
writeShortArray(array);
|
||||
writeShortArray(array, length);
|
||||
break;
|
||||
case TypeArrayKlass.T_INT:
|
||||
writeIntArray(array);
|
||||
writeIntArray(array, length);
|
||||
break;
|
||||
case TypeArrayKlass.T_LONG:
|
||||
writeLongArray(array);
|
||||
writeLongArray(array, length);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("should not reach here");
|
||||
throw new RuntimeException(
|
||||
"Should not reach here: Unknown type: " + type);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeBooleanArray(TypeArray array) throws IOException {
|
||||
final int length = (int) array.getLength();
|
||||
private void writeBooleanArray(TypeArray array, int length) throws IOException {
|
||||
for (int index = 0; index < length; index++) {
|
||||
long offset = BOOLEAN_BASE_OFFSET + index * BOOLEAN_SIZE;
|
||||
out.writeBoolean(array.getHandle().getJBooleanAt(offset));
|
||||
}
|
||||
}
|
||||
|
||||
private void writeByteArray(TypeArray array) throws IOException {
|
||||
final int length = (int) array.getLength();
|
||||
private void writeByteArray(TypeArray array, int length) throws IOException {
|
||||
for (int index = 0; index < length; index++) {
|
||||
long offset = BYTE_BASE_OFFSET + index * BYTE_SIZE;
|
||||
out.writeByte(array.getHandle().getJByteAt(offset));
|
||||
}
|
||||
}
|
||||
|
||||
private void writeShortArray(TypeArray array) throws IOException {
|
||||
final int length = (int) array.getLength();
|
||||
private void writeShortArray(TypeArray array, int length) throws IOException {
|
||||
for (int index = 0; index < length; index++) {
|
||||
long offset = SHORT_BASE_OFFSET + index * SHORT_SIZE;
|
||||
out.writeShort(array.getHandle().getJShortAt(offset));
|
||||
}
|
||||
}
|
||||
|
||||
private void writeIntArray(TypeArray array) throws IOException {
|
||||
final int length = (int) array.getLength();
|
||||
private void writeIntArray(TypeArray array, int length) throws IOException {
|
||||
for (int index = 0; index < length; index++) {
|
||||
long offset = INT_BASE_OFFSET + index * INT_SIZE;
|
||||
out.writeInt(array.getHandle().getJIntAt(offset));
|
||||
}
|
||||
}
|
||||
|
||||
private void writeLongArray(TypeArray array) throws IOException {
|
||||
final int length = (int) array.getLength();
|
||||
private void writeLongArray(TypeArray array, int length) throws IOException {
|
||||
for (int index = 0; index < length; index++) {
|
||||
long offset = LONG_BASE_OFFSET + index * LONG_SIZE;
|
||||
out.writeLong(array.getHandle().getJLongAt(offset));
|
||||
}
|
||||
}
|
||||
|
||||
private void writeCharArray(TypeArray array) throws IOException {
|
||||
final int length = (int) array.getLength();
|
||||
private void writeCharArray(TypeArray array, int length) throws IOException {
|
||||
for (int index = 0; index < length; index++) {
|
||||
long offset = CHAR_BASE_OFFSET + index * CHAR_SIZE;
|
||||
out.writeChar(array.getHandle().getJCharAt(offset));
|
||||
}
|
||||
}
|
||||
|
||||
private void writeFloatArray(TypeArray array) throws IOException {
|
||||
final int length = (int) array.getLength();
|
||||
private void writeFloatArray(TypeArray array, int length) throws IOException {
|
||||
for (int index = 0; index < length; index++) {
|
||||
long offset = FLOAT_BASE_OFFSET + index * FLOAT_SIZE;
|
||||
out.writeFloat(array.getHandle().getJFloatAt(offset));
|
||||
}
|
||||
}
|
||||
|
||||
private void writeDoubleArray(TypeArray array) throws IOException {
|
||||
final int length = (int) array.getLength();
|
||||
private void writeDoubleArray(TypeArray array, int length) throws IOException {
|
||||
for (int index = 0; index < length; index++) {
|
||||
long offset = DOUBLE_BASE_OFFSET + index * DOUBLE_SIZE;
|
||||
out.writeDouble(array.getHandle().getJDoubleAt(offset));
|
||||
@ -996,12 +1061,7 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||
// writes hprof binary file header
|
||||
private void writeFileHeader() throws IOException {
|
||||
// version string
|
||||
if(useSegmentedHeapDump) {
|
||||
out.writeBytes(HPROF_HEADER_1_0_2);
|
||||
}
|
||||
else {
|
||||
out.writeBytes(HPROF_HEADER_1_0_1);
|
||||
}
|
||||
out.writeBytes(HPROF_HEADER_1_0_2);
|
||||
out.writeByte((byte)'\0');
|
||||
|
||||
// write identifier size. we use pointers as identifiers.
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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 jdk.test.lib.apps.LingeredApp;
|
||||
|
||||
public class LingeredAppWithLargeArray extends LingeredApp {
|
||||
public static void main(String args[]) {
|
||||
int[] hugeArray = new int[Integer.MAX_VALUE/2];
|
||||
LingeredApp.main(args);
|
||||
}
|
||||
}
|
||||
117
hotspot/test/serviceability/sa/TestHeapDumpForLargeArray.java
Normal file
117
hotspot/test/serviceability/sa/TestHeapDumpForLargeArray.java
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.List;
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.io.IOException;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.util.stream.Collectors;
|
||||
import java.io.FileInputStream;
|
||||
|
||||
import sun.jvm.hotspot.HotSpotAgent;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
|
||||
import jdk.test.lib.apps.LingeredApp;
|
||||
import jdk.test.lib.JDKToolLauncher;
|
||||
import jdk.test.lib.JDKToolFinder;
|
||||
import jdk.test.lib.Platform;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.Utils;
|
||||
import jdk.test.lib.Asserts;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @library /test/lib
|
||||
* @bug 8171084
|
||||
* @requires (vm.bits == "64" & os.maxMemory > 8g)
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* jdk.hotspot.agent/sun.jvm.hotspot
|
||||
* jdk.hotspot.agent/sun.jvm.hotspot.utilities
|
||||
* jdk.hotspot.agent/sun.jvm.hotspot.oops
|
||||
* jdk.hotspot.agent/sun.jvm.hotspot.debugger
|
||||
* @run main/timeout=1800/othervm -Xmx8g TestHeapDumpForLargeArray
|
||||
*/
|
||||
|
||||
public class TestHeapDumpForLargeArray {
|
||||
|
||||
private static LingeredAppWithLargeArray theApp = null;
|
||||
|
||||
private static void attachAndDump(String heapDumpFileName,
|
||||
long lingeredAppPid) throws Exception {
|
||||
|
||||
JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb");
|
||||
launcher.addToolArg("jmap");
|
||||
launcher.addToolArg("--binaryheap");
|
||||
launcher.addToolArg("--dumpfile");
|
||||
launcher.addToolArg(heapDumpFileName);
|
||||
launcher.addToolArg("--pid");
|
||||
launcher.addToolArg(Long.toString(lingeredAppPid));
|
||||
|
||||
ProcessBuilder processBuilder = new ProcessBuilder();
|
||||
processBuilder.command(launcher.getCommand());
|
||||
System.out.println(
|
||||
processBuilder.command().stream().collect(Collectors.joining(" ")));
|
||||
|
||||
OutputAnalyzer SAOutput = ProcessTools.executeProcess(processBuilder);
|
||||
SAOutput.shouldHaveExitValue(0);
|
||||
SAOutput.shouldNotContain("Heap segment size overflow");
|
||||
SAOutput.shouldContain("truncating to");
|
||||
SAOutput.shouldContain("heap written to");
|
||||
SAOutput.shouldContain(heapDumpFileName);
|
||||
System.out.println(SAOutput.getOutput());
|
||||
|
||||
}
|
||||
|
||||
public static void main (String... args) throws Exception {
|
||||
|
||||
String heapDumpFileName = "LargeArrayHeapDump.bin";
|
||||
|
||||
if (!Platform.shouldSAAttach()) {
|
||||
System.out.println(
|
||||
"SA attach not expected to work - test skipped.");
|
||||
return;
|
||||
}
|
||||
|
||||
File heapDumpFile = new File(heapDumpFileName);
|
||||
if (heapDumpFile.exists()) {
|
||||
heapDumpFile.delete();
|
||||
}
|
||||
|
||||
try {
|
||||
List<String> vmArgs = new ArrayList<String>();
|
||||
vmArgs.add("-XX:+UsePerfData");
|
||||
vmArgs.add("-Xmx8g");
|
||||
vmArgs.addAll(Utils.getVmOptions());
|
||||
|
||||
theApp = new LingeredAppWithLargeArray();
|
||||
LingeredApp.startApp(vmArgs, theApp);
|
||||
attachAndDump(heapDumpFileName, theApp.getPid());
|
||||
} finally {
|
||||
LingeredApp.stopApp(theApp);
|
||||
heapDumpFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -53,7 +53,6 @@ import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
public class JMapHProfLargeHeapTest {
|
||||
private static final String HEAP_DUMP_FILE_NAME = "heap.bin";
|
||||
private static final String HPROF_HEADER_1_0_1 = "JAVA PROFILE 1.0.1";
|
||||
private static final String HPROF_HEADER_1_0_2 = "JAVA PROFILE 1.0.2";
|
||||
private static final long M = 1024L;
|
||||
private static final long G = 1024L * M;
|
||||
@ -65,9 +64,7 @@ public class JMapHProfLargeHeapTest {
|
||||
}
|
||||
|
||||
// All heap dumps should create 1.0.2 file format
|
||||
// Hotspot internal heapdumper always use HPROF_HEADER_1_0_2 format,
|
||||
// but SA heapdumper still use HPROF_HEADER_1_0_1 for small heaps
|
||||
testHProfFileFormat("-Xmx1g", 22 * M, HPROF_HEADER_1_0_1);
|
||||
testHProfFileFormat("-Xmx1g", 22 * M, HPROF_HEADER_1_0_2);
|
||||
|
||||
/**
|
||||
* This test was deliberately commented out since the test system lacks
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user