ObjectArray* Java_java_lang_Thread_internalGetStackTrace(Env* env, Class* cls, JavaThread* threadObj) { Thread* thread = (Thread*) LONG_TO_PTR(threadObj->threadPtr); CallStack* callStack = NULL; if (thread) { callStack = rvmCaptureCallStackForThread(env, thread); } return rvmCallStackToStackTraceElements(env, callStack, 0); }
ObjectArray* Java_java_lang_Throwable_nativeGetStackTrace(Env* env, Object* thiz, jlong stackState) { CallStack* callStack = (CallStack*) LONG_TO_PTR(stackState); if (!callStack) { return rvmCallStackToStackTraceElements(env, NULL, 0); } jint index = 0; jint first = 0; Method* m = rvmGetNextCallStackMethod(env, callStack, &index); if (m && m->clazz == java_lang_Throwable && !strcmp(m->name, "nativeFillInStackTrace")) { // Skip Throwable.nativeFillInStackTrace() rvmGetNextCallStackMethod(env, callStack, &index); // Skip Throwable.fillInStackTrace() m = rvmGetNextCallStackMethod(env, callStack, &index); first = index; if (m) { Class* clazz = m->clazz; if (clazz == java_lang_Throwable && METHOD_IS_CONSTRUCTOR(m)) { // fillInStackTrace() was called from the constructor of Throwable // Skip all constructors until the constructor of thiz->clazz Class* superclass = java_lang_Object; while (m && METHOD_IS_CONSTRUCTOR(m) && clazz != thiz->clazz && clazz->superclass == superclass) { m = rvmGetNextCallStackMethod(env, callStack, &index); if (m && m->clazz != clazz) { superclass = clazz; clazz = m->clazz; } first = index - 1; } // We're now at the constructor of thiz->clazz which called super(). // Skip all constructors belonging to thiz->clazz to get to the method which created the throwable while (m && METHOD_IS_CONSTRUCTOR(m) && clazz == thiz->clazz) { m = rvmGetNextCallStackMethod(env, callStack, &index); if (m) clazz = m->clazz; first = index - 1; } } } } return rvmCallStackToStackTraceElements(env, callStack, first); }