6760477: Update SA to include stack traces in the heap dump
Update SA to include HPROF_TRACE and HPROF_FRAME records in the heap dump Reviewed-by: dsamersoff
This commit is contained in:
parent
a449b10079
commit
536c210f77
hotspot/src
jdk.hotspot.agent/share/classes/sun/jvm/hotspot
share/vm/runtime
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 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,6 +50,7 @@ public class JavaThread extends Thread {
|
||||
private static AddressField osThreadField;
|
||||
private static AddressField stackBaseField;
|
||||
private static CIntegerField stackSizeField;
|
||||
private static CIntegerField terminatedField;
|
||||
|
||||
private static JavaThreadPDAccess access;
|
||||
|
||||
@ -66,6 +67,9 @@ public class JavaThread extends Thread {
|
||||
private static int BLOCKED;
|
||||
private static int BLOCKED_TRANS;
|
||||
|
||||
private static int NOT_TERMINATED;
|
||||
private static int EXITING;
|
||||
|
||||
static {
|
||||
VM.registerVMInitializedObserver(new Observer() {
|
||||
public void update(Observable o, Object data) {
|
||||
@ -87,6 +91,7 @@ public class JavaThread extends Thread {
|
||||
osThreadField = type.getAddressField("_osthread");
|
||||
stackBaseField = type.getAddressField("_stack_base");
|
||||
stackSizeField = type.getCIntegerField("_stack_size");
|
||||
terminatedField = type.getCIntegerField("_terminated");
|
||||
|
||||
UNINITIALIZED = db.lookupIntConstant("_thread_uninitialized").intValue();
|
||||
NEW = db.lookupIntConstant("_thread_new").intValue();
|
||||
@ -99,6 +104,10 @@ public class JavaThread extends Thread {
|
||||
IN_JAVA_TRANS = db.lookupIntConstant("_thread_in_Java_trans").intValue();
|
||||
BLOCKED = db.lookupIntConstant("_thread_blocked").intValue();
|
||||
BLOCKED_TRANS = db.lookupIntConstant("_thread_blocked_trans").intValue();
|
||||
|
||||
NOT_TERMINATED = db.lookupIntConstant("JavaThread::_not_terminated").intValue();
|
||||
EXITING = db.lookupIntConstant("JavaThread::_thread_exiting").intValue();
|
||||
|
||||
}
|
||||
|
||||
public JavaThread(Address addr) {
|
||||
@ -128,6 +137,14 @@ public class JavaThread extends Thread {
|
||||
example, "SolarisSPARCCompilerThread".) */
|
||||
public boolean isJavaThread() { return true; }
|
||||
|
||||
public boolean isExiting () {
|
||||
return (getTerminated() == EXITING) || isTerminated();
|
||||
}
|
||||
|
||||
public boolean isTerminated() {
|
||||
return (getTerminated() != NOT_TERMINATED) && (getTerminated() != EXITING);
|
||||
}
|
||||
|
||||
public static AddressField getAnchorField() { return anchorField; }
|
||||
|
||||
/** Get the last Java stack pointer */
|
||||
@ -329,6 +346,10 @@ public class JavaThread extends Thread {
|
||||
return stackSizeField.getValue(addr);
|
||||
}
|
||||
|
||||
public int getTerminated() {
|
||||
return (int) terminatedField.getValue(addr);
|
||||
}
|
||||
|
||||
/** Gets the Java-side thread object for this JavaThread */
|
||||
public Oop getThreadObj() {
|
||||
Oop obj = null;
|
||||
|
46
hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/StackFrameInfo.java
Normal file
46
hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/StackFrameInfo.java
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.runtime;
|
||||
|
||||
import sun.jvm.hotspot.oops.*;
|
||||
|
||||
public class StackFrameInfo {
|
||||
private Method method;
|
||||
int bci;
|
||||
Oop classHolder;
|
||||
|
||||
public StackFrameInfo(JavaVFrame vf) {
|
||||
this.method = vf.getMethod();
|
||||
this.bci = vf.getBCI();
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public int getBCI() {
|
||||
return bci;
|
||||
}
|
||||
}
|
69
hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ThreadStackTrace.java
Normal file
69
hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ThreadStackTrace.java
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.runtime;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class ThreadStackTrace {
|
||||
private JavaThread thread;
|
||||
private int depth; // number of stack frames added
|
||||
private ArrayList<StackFrameInfo> frames;
|
||||
|
||||
public ThreadStackTrace(JavaThread t) {
|
||||
this.thread = t;
|
||||
this.depth = 0;
|
||||
this.frames = new ArrayList<StackFrameInfo>();
|
||||
}
|
||||
|
||||
public int getStackDepth() {
|
||||
return depth;
|
||||
}
|
||||
|
||||
public StackFrameInfo stackFrameAt(int index) {
|
||||
return frames.get(index);
|
||||
}
|
||||
|
||||
public void dumpStack(int maxDepth) {
|
||||
if (!thread.isJavaThread()) {
|
||||
System.out.println("dumpStack: not java Thread returning");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
for (JavaVFrame vf = thread.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) {
|
||||
StackFrameInfo frame = new StackFrameInfo(vf);
|
||||
frames.add(frame);
|
||||
depth++;
|
||||
|
||||
if (maxDepth > 0 && depth == maxDepth) {
|
||||
// Skip frames if more than maxDepth
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error occurred during stack walking:");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@ -379,6 +379,10 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||
private static final long MAX_U4_VALUE = 0xFFFFFFFFL;
|
||||
int serialNum = 1;
|
||||
|
||||
public HeapHprofBinWriter() {
|
||||
this.KlassMap = new ArrayList<Klass>();
|
||||
}
|
||||
|
||||
public synchronized void write(String fileName) throws IOException {
|
||||
// open file stream and create buffered data output stream
|
||||
fos = new FileOutputStream(fileName);
|
||||
@ -426,6 +430,9 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||
// HPROF_LOAD_CLASS records for all classes
|
||||
writeClasses();
|
||||
|
||||
// write HPROF_FRAME and HPROF_TRACE records
|
||||
dumpStackTraces();
|
||||
|
||||
// write CLASS_DUMP records
|
||||
writeClassDumpRecords();
|
||||
|
||||
@ -700,6 +707,67 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||
}
|
||||
}
|
||||
|
||||
private void dumpStackTraces() throws IOException {
|
||||
// write a HPROF_TRACE record without any frames to be referenced as object alloc sites
|
||||
writeHeader(HPROF_TRACE, 3 * (int)INT_SIZE );
|
||||
out.writeInt(DUMMY_STACK_TRACE_ID);
|
||||
out.writeInt(0); // thread number
|
||||
out.writeInt(0); // frame count
|
||||
|
||||
int frameSerialNum = 0;
|
||||
int numThreads = 0;
|
||||
Threads threads = VM.getVM().getThreads();
|
||||
|
||||
for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) {
|
||||
Oop threadObj = thread.getThreadObj();
|
||||
if (threadObj != null && !thread.isExiting() && !thread.isHiddenFromExternalView()) {
|
||||
|
||||
// dump thread stack trace
|
||||
ThreadStackTrace st = new ThreadStackTrace(thread);
|
||||
st.dumpStack(-1);
|
||||
numThreads++;
|
||||
|
||||
// write HPROF_FRAME records for this thread's stack trace
|
||||
int depth = st.getStackDepth();
|
||||
int threadFrameStart = frameSerialNum;
|
||||
for (int j=0; j < depth; j++) {
|
||||
StackFrameInfo frame = st.stackFrameAt(j);
|
||||
Method m = frame.getMethod();
|
||||
int classSerialNum = KlassMap.indexOf(m.getMethodHolder()) + 1;
|
||||
// the class serial number starts from 1
|
||||
assert classSerialNum > 0:"class not found";
|
||||
dumpStackFrame(++frameSerialNum, classSerialNum, m, frame.getBCI());
|
||||
}
|
||||
|
||||
// write HPROF_TRACE record for one thread
|
||||
writeHeader(HPROF_TRACE, 3 * (int)INT_SIZE + depth * (int)VM.getVM().getOopSize());
|
||||
int stackSerialNum = numThreads + DUMMY_STACK_TRACE_ID;
|
||||
out.writeInt(stackSerialNum); // stack trace serial number
|
||||
out.writeInt(numThreads); // thread serial number
|
||||
out.writeInt(depth); // frame count
|
||||
for (int j=1; j <= depth; j++) {
|
||||
writeObjectID(threadFrameStart + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void dumpStackFrame(int frameSN, int classSN, Method m, int bci) throws IOException {
|
||||
int lineNumber;
|
||||
if (m.isNative()) {
|
||||
lineNumber = -3; // native frame
|
||||
} else {
|
||||
lineNumber = m.getLineNumberFromBCI(bci);
|
||||
}
|
||||
writeHeader(HPROF_FRAME, 4 * (int)VM.getVM().getOopSize() + 2 * (int)INT_SIZE);
|
||||
writeObjectID(frameSN); // frame serial number
|
||||
writeSymbolID(m.getName()); // method's name
|
||||
writeSymbolID(m.getSignature()); // method's signature
|
||||
writeSymbolID(m.getMethodHolder().getSourceFileName()); // source file name
|
||||
out.writeInt(classSN); // class serial number
|
||||
out.writeInt(lineNumber); // line number
|
||||
}
|
||||
|
||||
protected void writeJavaThread(JavaThread jt, int index) throws IOException {
|
||||
out.writeByte((byte) HPROF_GC_ROOT_THREAD_OBJ);
|
||||
writeObjectID(jt.getThreadObj());
|
||||
@ -1030,6 +1098,7 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||
writeHeader(HPROF_LOAD_CLASS, 2 * (OBJ_ID_SIZE + 4));
|
||||
out.writeInt(serialNum);
|
||||
writeObjectID(clazz);
|
||||
KlassMap.add(serialNum - 1, k);
|
||||
out.writeInt(DUMMY_STACK_TRACE_ID);
|
||||
writeSymbolID(k.getName());
|
||||
serialNum++;
|
||||
@ -1045,6 +1114,7 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||
writeHeader(HPROF_LOAD_CLASS, 2 * (OBJ_ID_SIZE + 4));
|
||||
out.writeInt(serialNum);
|
||||
writeObjectID(clazz);
|
||||
KlassMap.add(serialNum - 1, k);
|
||||
out.writeInt(DUMMY_STACK_TRACE_ID);
|
||||
writeSymbolID(k.getName());
|
||||
serialNum++;
|
||||
@ -1157,6 +1227,7 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
|
||||
private Debugger dbg;
|
||||
private ObjectHeap objectHeap;
|
||||
private SymbolTable symTbl;
|
||||
private ArrayList<Klass> KlassMap;
|
||||
|
||||
// oopSize of the debuggee
|
||||
private int OBJ_ID_SIZE;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 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
|
||||
@ -971,6 +971,7 @@ typedef RehashableHashtable<Symbol*, mtSymbol> RehashableSymbolHashtable;
|
||||
nonstatic_field(JavaThread, _vframe_array_last, vframeArray*) \
|
||||
nonstatic_field(JavaThread, _satb_mark_queue, SATBMarkQueue) \
|
||||
nonstatic_field(JavaThread, _dirty_card_queue, DirtyCardQueue) \
|
||||
volatile_nonstatic_field(JavaThread, _terminated, JavaThread::TerminatedTypes) \
|
||||
nonstatic_field(Thread, _resource_area, ResourceArea*) \
|
||||
nonstatic_field(CompilerThread, _env, ciEnv*) \
|
||||
\
|
||||
@ -2213,6 +2214,7 @@ typedef RehashableHashtable<Symbol*, mtSymbol> RehashableSymbolHashtable;
|
||||
declare_toplevel_type(JavaThread*) \
|
||||
declare_toplevel_type(java_lang_Class) \
|
||||
declare_integer_type(JavaThread::AsyncRequests) \
|
||||
declare_integer_type(JavaThread::TerminatedTypes) \
|
||||
declare_toplevel_type(jbyte*) \
|
||||
declare_toplevel_type(jbyte**) \
|
||||
declare_toplevel_type(jint*) \
|
||||
@ -2435,6 +2437,8 @@ typedef RehashableHashtable<Symbol*, mtSymbol> RehashableSymbolHashtable;
|
||||
declare_constant(_thread_in_Java_trans) \
|
||||
declare_constant(_thread_blocked) \
|
||||
declare_constant(_thread_blocked_trans) \
|
||||
declare_constant(JavaThread::_not_terminated) \
|
||||
declare_constant(JavaThread::_thread_exiting) \
|
||||
\
|
||||
/******************************/ \
|
||||
/* Klass misc. enum constants */ \
|
||||
|
Loading…
x
Reference in New Issue
Block a user