From 392731311776d30b0910e51a5bc2aef070a9fc8b Mon Sep 17 00:00:00 2001 From: Kyle Galloway Date: Mon, 29 Jan 2007 22:05:56 +0000 Subject: [PATCH] java-interp.h: Added _Jv_Frame class and its two subclasses _Jv_InterpFrame and _Jv_NativeFrame. 2007-01-29 Kyle Galloway * include/java-interp.h: Added _Jv_Frame class and its two subclasses _Jv_InterpFrame and _Jv_NativeFrame. Also moved _Jv_FrameType from java-stack.h. * include/java-stack.h: Removed _Jv_FrameType. * java/lang/Thread.java: Added frame member to hold new composite frame stack. * java/lang/Thread.h: Regenerated. * java/lang/Thread.class: Rebuilt. * jni.cc (_Jv_JNIMethod::call): Push a frame onto the stack when calling a JNI method. * jvmti.cc (_Jv_JVMTI_GetStackTrace): New Method. (_Jv_JVMTI_GetFrameCount): New method. * stacktrace.cc (UnwindTraceFn): Modified to use new _Jv_Frame classes. * testsuite/libjava.jvmti/interp/getstacktrace.jar: New test. * testsuite/libjava.jvmti/interp/natgetstacktrace.cc: New test. * testsuite/libjava.jvmti/interp/getstacktrace.h: New test. * testsuite/libjava.jvmti/interp/getstacktrace.jar: New test. * testsuite/libjava.jvmti/interp/getstacktrace.out: Output file for test. From-SVN: r121314 --- libjava/ChangeLog | 23 +++ .../lib/java/lang/Thread$State.class | Bin 1242 -> 1242 bytes libjava/classpath/lib/java/lang/Thread.class | Bin 9327 -> 9343 bytes libjava/include/java-interp.h | 79 ++++++++-- libjava/include/java-stack.h | 7 - libjava/java/lang/Thread.h | 3 +- libjava/java/lang/Thread.java | 3 + libjava/jni.cc | 4 + libjava/jvmti.cc | 108 ++++++++++++- libjava/stacktrace.cc | 8 +- .../libjava.jvmti/interp/getstacktrace.h | 21 +++ .../libjava.jvmti/interp/getstacktrace.jar | Bin 0 -> 1237 bytes .../libjava.jvmti/interp/getstacktrace.java | 88 +++++++++++ .../libjava.jvmti/interp/getstacktrace.out | 76 +++++++++ .../libjava.jvmti/interp/natgetstacktrace.cc | 144 ++++++++++++++++++ 15 files changed, 537 insertions(+), 27 deletions(-) create mode 100644 libjava/testsuite/libjava.jvmti/interp/getstacktrace.h create mode 100644 libjava/testsuite/libjava.jvmti/interp/getstacktrace.jar create mode 100644 libjava/testsuite/libjava.jvmti/interp/getstacktrace.java create mode 100644 libjava/testsuite/libjava.jvmti/interp/getstacktrace.out create mode 100644 libjava/testsuite/libjava.jvmti/interp/natgetstacktrace.cc diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 20e91fdb1fd..037b1bb650d 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,26 @@ +2007-01-29 Kyle Galloway + + * include/java-interp.h: Added _Jv_Frame class and its two + subclasses _Jv_InterpFrame and _Jv_NativeFrame. Also moved + _Jv_FrameType from java-stack.h. + * include/java-stack.h: Removed _Jv_FrameType. + * java/lang/Thread.java: Added frame member to hold new + composite frame stack. + * java/lang/Thread.h: Regenerated. + * java/lang/Thread.class: Rebuilt. + * jni.cc (_Jv_JNIMethod::call): Push a frame onto the stack when + calling a JNI method. + * jvmti.cc (_Jv_JVMTI_GetStackTrace): New Method. + (_Jv_JVMTI_GetFrameCount): New method. + * stacktrace.cc (UnwindTraceFn): Modified to use new _Jv_Frame + classes. + * testsuite/libjava.jvmti/interp/getstacktrace.jar: New test. + * testsuite/libjava.jvmti/interp/natgetstacktrace.cc: New test. + * testsuite/libjava.jvmti/interp/getstacktrace.h: New test. + * testsuite/libjava.jvmti/interp/getstacktrace.jar: New test. + * testsuite/libjava.jvmti/interp/getstacktrace.out: Output file + for test. + 2007-01-29 Tom Tromey * interpret.cc (run_debug): Remove comment. diff --git a/libjava/classpath/lib/java/lang/Thread$State.class b/libjava/classpath/lib/java/lang/Thread$State.class index a7d5a333f22395a74b272ab11d3ed6608424990a..3ce018edd9c8b3d245b8578bcaff6d63be38e2de 100644 GIT binary patch delta 23 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 T)^VJps5e!_CC_JZZR7s}j^@nz literal 9327 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 + thr->frame = (gnu::gcj::RawData *) this; + thread = thr; + } + + ~_Jv_Frame () + { + thread->frame = (gnu::gcj::RawData *) next; + } +}; + +// An interpreted frame in the call stack +class _Jv_InterpFrame : public _Jv_Frame +{ +public: + + // Keep the purely interpreted list around so as not to break backtraces + _Jv_InterpFrame *next_interp; + union { pc_t pc; jclass proxyClass; }; - - _Jv_InterpFrame (void *meth, java::lang::Thread *thr, jclass proxyClass = NULL) + + //Debug info for local variables. + _Jv_word *locals; + char *locals_type; + + _Jv_InterpFrame (void *meth, java::lang::Thread *thr, jclass proxyCls = NULL) + : _Jv_Frame (reinterpret_cast<_Jv_MethodBase *> (meth), thr, + frame_interpreter) { - this->meth = meth; - thread = thr; - next = (_Jv_InterpFrame *) thr->interp_frame; + next_interp = (_Jv_InterpFrame *) thr->interp_frame; + proxyClass = proxyCls; thr->interp_frame = (gnu::gcj::RawData *) this; - this->proxyClass = proxyClass; } ~_Jv_InterpFrame () { - thread->interp_frame = (gnu::gcj::RawData *) next; + thread->interp_frame = (gnu::gcj::RawData *) next_interp; + } +}; + +// A native frame in the call stack really just a placeholder +class _Jv_NativeFrame : public _Jv_Frame +{ +public: + + _Jv_NativeFrame (_Jv_JNIMethod *s, java::lang::Thread *thr) + : _Jv_Frame (s, thr, frame_native) + { } }; diff --git a/libjava/include/java-stack.h b/libjava/include/java-stack.h index d4d63d74342..49e68412be6 100644 --- a/libjava/include/java-stack.h +++ b/libjava/include/java-stack.h @@ -41,13 +41,6 @@ extern "Java" } } -enum _Jv_FrameType -{ - frame_native, - frame_interpreter, - frame_proxy -}; - #ifdef INTERPRETER struct _Jv_InterpFrameInfo { diff --git a/libjava/java/lang/Thread.h b/libjava/java/lang/Thread.h index 74e149030f7..d5fce863877 100644 --- a/libjava/java/lang/Thread.h +++ b/libjava/java/lang/Thread.h @@ -144,7 +144,8 @@ public: // actually package-private static const jbyte THREAD_PARK_DEAD = 3; ::java::lang::Object * accessControlState; ::gnu::gcj::RawData * interp_frame; - jint volatile state; + ::gnu::gcj::RawData * frame; + volatile jint state; ::gnu::gcj::RawDataManaged * data; public: static ::java::lang::Class class$; diff --git a/libjava/java/lang/Thread.java b/libjava/java/lang/Thread.java index 9666482040a..7216512530d 100644 --- a/libjava/java/lang/Thread.java +++ b/libjava/java/lang/Thread.java @@ -182,6 +182,9 @@ public class Thread implements Runnable // This describes the top-most interpreter frame for this thread. RawData interp_frame; + + // This describes the top most frame in the composite (interp + JNI) stack + RawData frame; // Current state. volatile int state; diff --git a/libjava/jni.cc b/libjava/jni.cc index 59c1e5fd03e..07ef7134540 100644 --- a/libjava/jni.cc +++ b/libjava/jni.cc @@ -2339,6 +2339,10 @@ _Jv_JNIMethod::call (ffi_cif *, void *ret, ffi_raw *args, void *__this) // Copy over passed-in arguments. memcpy (&real_args[offset], args, _this->args_raw_size); + + // Add a frame to the composite (interpreted + JNI) call stack + java::lang::Thread *thread = java::lang::Thread::currentThread(); + _Jv_NativeFrame nat_frame (_this, thread); // The actual call to the JNI function. #if FFI_NATIVE_RAW_API diff --git a/libjava/jvmti.cc b/libjava/jvmti.cc index 03eec74b4c1..c9c7e7ba731 100644 --- a/libjava/jvmti.cc +++ b/libjava/jvmti.cc @@ -236,6 +236,34 @@ _Jv_JVMTI_GetAllThreads(MAYBE_UNUSED jvmtiEnv *env, jint *thread_cnt, return JVMTI_ERROR_NONE; } +static jvmtiError JNICALL +_Jv_JVMTI_GetFrameCount (MAYBE_UNUSED jvmtiEnv *env, jthread thread, + jint* frame_count) +{ + REQUIRE_PHASE (env, JVMTI_PHASE_LIVE); + + NULL_CHECK (frame_count); + + using namespace java::lang; + + THREAD_DEFAULT_TO_CURRENT (thread); + + Thread *thr = reinterpret_cast (thread); + THREAD_CHECK_VALID (thr); + THREAD_CHECK_IS_ALIVE (thr); + + _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thr->frame); + (*frame_count) = 0; + + while (frame != NULL) + { + (*frame_count)++; + frame = frame->next; + } + + return JVMTI_ERROR_NONE; +} + static jvmtiError JNICALL _Jv_JVMTI_CreateRawMonitor (MAYBE_UNUSED jvmtiEnv *env, const char *name, jrawMonitorID *result) @@ -747,6 +775,82 @@ _Jv_JVMTI_GetClassLoaderClasses (MAYBE_UNUSED jvmtiEnv *env, return JVMTI_ERROR_NONE; } +static jvmtiError JNICALL +_Jv_JVMTI_GetStackTrace (MAYBE_UNUSED jvmtiEnv *env, jthread thread, + jint start_depth, jint max_frames, + jvmtiFrameInfo *frames, jint *frame_count) +{ + REQUIRE_PHASE (env, JVMTI_PHASE_LIVE); + + ILLEGAL_ARGUMENT (max_frames < 0); + + NULL_CHECK (frames); + NULL_CHECK (frame_count); + + using namespace java::lang; + + THREAD_DEFAULT_TO_CURRENT (thread); + + Thread *thr = reinterpret_cast (thread); + THREAD_CHECK_VALID (thr); + THREAD_CHECK_IS_ALIVE (thr); + + jvmtiError jerr = env->GetFrameCount (thread, frame_count); + if (jerr != JVMTI_ERROR_NONE) + return jerr; + + // start_depth can be either a positive number, indicating the depth of the + // stack at which to begin the trace, or a negative number indicating the + // number of frames at the bottom of the stack to exclude. These checks + // ensure that it is a valid value in either case + + ILLEGAL_ARGUMENT (start_depth >= (*frame_count)); + ILLEGAL_ARGUMENT (start_depth < (-(*frame_count))); + + _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thr->frame); + + // If start_depth is negative use this to determine at what depth to start + // the trace by adding it to the length of the call stack. This allows the + // use of the same frame "discarding" mechanism as for a positive start_depth + if (start_depth < 0) + start_depth = *frame_count + start_depth; + + // If start_depth > 0 "remove" start_depth frames from the beginning + // of the stack before beginning the trace by moving along the frame list. + while (start_depth > 0) + { + frame = frame->next; + start_depth--; + (*frame_count)--; + } + + // Now check to see if the array supplied by the agent is large enough to + // hold frame_count frames, after adjustment for start_depth. + if ((*frame_count) > max_frames) + (*frame_count) = max_frames; + + for (int i = 0; i < (*frame_count); i++) + { + frames[i].method = frame->self->get_method (); + + // Set the location in the frame, native frames have location = -1 + if (frame->frame_type == frame_interpreter) + { + _Jv_InterpMethod *imeth + = static_cast<_Jv_InterpMethod *> (frame->self); + _Jv_InterpFrame *interp_frame + = static_cast<_Jv_InterpFrame *> (frame); + frames[i].location = imeth->insn_index (interp_frame->pc); + } + else + frames[i].location = -1; + + frame = frame->next; + } + + return JVMTI_ERROR_NONE; +} + static jvmtiError JNICALL _Jv_JVMTI_ForceGarbageCollection (MAYBE_UNUSED jvmtiEnv *env) { @@ -1484,7 +1588,7 @@ struct _Jv_jvmtiEnv _Jv_JVMTI_Interface = UNIMPLEMENTED, // GetTopThreadGroups UNIMPLEMENTED, // GetThreadGroupInfo UNIMPLEMENTED, // GetThreadGroupChildren - UNIMPLEMENTED, // GetFrameCount + _Jv_JVMTI_GetFrameCount, // GetFrameCount UNIMPLEMENTED, // GetThreadState RESERVED, // reserved18 UNIMPLEMENTED, // GetFrameLocation @@ -1572,7 +1676,7 @@ struct _Jv_jvmtiEnv _Jv_JVMTI_Interface = UNIMPLEMENTED, // GetThreadListStackTraces UNIMPLEMENTED, // GetThreadLocalStorage UNIMPLEMENTED, // SetThreadLocalStorage - UNIMPLEMENTED, // GetStackTrace + _Jv_JVMTI_GetStackTrace, // GetStackTrace RESERVED, // reserved105 UNIMPLEMENTED, // GetTag UNIMPLEMENTED, // SetTag diff --git a/libjava/stacktrace.cc b/libjava/stacktrace.cc index 5751e29b5f1..c3fbdf4e6a4 100644 --- a/libjava/stacktrace.cc +++ b/libjava/stacktrace.cc @@ -131,9 +131,11 @@ _Jv_StackTrace::UnwindTraceFn (struct _Unwind_Context *context, void *state_ptr) if (func_addr == UNWRAP_FUNCTION_DESCRIPTOR (interp_run)) { state->frames[pos].type = frame_interpreter; - state->frames[pos].interp.meth = state->interp_frame->self; + _Jv_Frame *frame = static_cast<_Jv_Frame *> (state->interp_frame); + state->frames[pos].interp.meth + = static_cast<_Jv_InterpMethod *> (frame->self); state->frames[pos].interp.pc = state->interp_frame->pc; - state->interp_frame = state->interp_frame->next; + state->interp_frame = state->interp_frame->next_interp; } else #endif @@ -143,7 +145,7 @@ _Jv_StackTrace::UnwindTraceFn (struct _Unwind_Context *context, void *state_ptr) state->frames[pos].type = frame_proxy; state->frames[pos].proxyClass = state->interp_frame->proxyClass; state->frames[pos].proxyMethod = state->interp_frame->proxyMethod; - state->interp_frame = state->interp_frame->next; + state->interp_frame = state->interp_frame->next_interp; } else { diff --git a/libjava/testsuite/libjava.jvmti/interp/getstacktrace.h b/libjava/testsuite/libjava.jvmti/interp/getstacktrace.h new file mode 100644 index 00000000000..6e5e8774e25 --- /dev/null +++ b/libjava/testsuite/libjava.jvmti/interp/getstacktrace.h @@ -0,0 +1,21 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ + +#ifndef __getstacktrace__ +#define __getstacktrace__ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +JNIEXPORT void JNICALL Java_getstacktrace_natPlaceholder (JNIEnv *env, jobject); +JNIEXPORT void JNICALL Java_getstacktrace_natRunner (JNIEnv *env, jobject); +JNIEXPORT jint JNICALL Java_getstacktrace_do_1getstacktrace_1tests (JNIEnv *env, jclass, jobjectArray); + +#ifdef __cplusplus +} +#endif + +#endif /* __getstacktrace__ */ diff --git a/libjava/testsuite/libjava.jvmti/interp/getstacktrace.jar b/libjava/testsuite/libjava.jvmti/interp/getstacktrace.jar new file mode 100644 index 0000000000000000000000000000000000000000..14b084a4de11b88f063a3ecea605f2d7e8705be4 GIT binary patch literal 1237 zcmWIWW@h1H0D%K(wq{@kl;8x?zOEsTx}JV+`T;1)cIf6N>HwudSOi&_ucM!*n`>~0 zp0As4VqRuiYH^8fSZYymW`3TPf}x%Pmvd2SVo7R>u2ZFzf`Oi;k#2f&G8Y%jbPk4X zKu2_~{;1;5%)pSv%D^BDG(A1Fq_`w8IlH7NF*#K)IVZ8WxHUL7TsU0h?sOg%Nj-U9 zrnN4-KUjrX_utBDTC~+GxY^tHNUPlghjkXSd?F4X(YyCo`0Gk}ew%RC$X&1aU&OyS z|H3&u-s}6!D+v*?tBteo7C)a;eEwegeCz#x|9-P=xU6yH;=&7?lMZdY5L+k3_HI+> z;h-1wkL-$<^5t5!qq7+0DJN&%i5cN&Ld-MZWBZ zJ6}Fs^}PC_YU_<3M{HiltPS@O;;NN06XL9KvbfKC+vA4BfdrY~w`NSacHJrXvcw^S zz*VK&gT72-GLHzCkkPN3BF;8%|0MAZ`xZT)J-heTB+gUsf~Nl2y-eB6EJ@EGNUnb~&=-IoDV}Tj1Dm(9G{@BNPq&g-!X3yR)_f}2%`M7H9 zB_2zuNY2vr+kX3J`E>2q&Iq+!YRR+9>bh<4(reCBes}biz4FMU3{W$ z!MOTa)xUcc-W@7W{{%g@(c5smN_k1bS(Ej4rQMc_#=X&})hDDczJKogRPLFP&iWru zH_g}lv5+&2S$LM$G9NuNy(Be0ztRWxT$wS`B#(w44gI?Gs9@x}tQy&`C(ktn*jzU~ z_dq8MejLW7@n&0W^RcCr@NlahHlIKbij6XV=y8nFE|LCfpQlWsV4ZT=E=urnU;o6W2353Pivp&LvRv;5gK@i~0$_7%z41~LYG%E{; F2LNfB@h|`Y literal 0 HcmV?d00001 diff --git a/libjava/testsuite/libjava.jvmti/interp/getstacktrace.java b/libjava/testsuite/libjava.jvmti/interp/getstacktrace.java new file mode 100644 index 00000000000..21a21f0fbb1 --- /dev/null +++ b/libjava/testsuite/libjava.jvmti/interp/getstacktrace.java @@ -0,0 +1,88 @@ +public class getstacktrace + extends Thread +{ + public boolean done = false; + + // num_frames is the number of frames > the original run () call so if + // num_frames = 1, the thread will have 2 frames, the original Thread.run + // call, plus one additional + public int num_frames, thread_num; + + public static int num_threads = 1; + + static + { + System.loadLibrary("natgetstacktrace"); + } + + public void run () + { + thread_num = num_threads++; + num_frames = thread_num; + + if (num_frames <= 1) + { + natRunner (); + } + else + { + if (thread_num % 2 == 0) + natPlaceholder (); + else + placeholder (); + } + } + + public void placeholder () + { + num_frames--; + if (num_frames <= 1) + { + if (thread_num % 2 == 1) + natRunner (); + else + runner (); + } + else + { + if (thread_num % 2 == 0) + natPlaceholder (); + else + placeholder (); + } + } + + public void runner () + { + done = true; + while (done) + yield (); + } + + public native void natPlaceholder (); + public native void natRunner (); + + public static native int do_getstacktrace_tests (Thread[] threads); + + public static void main (String[] args) + { + System.out.println ("JVMTI GetStackTrace Interpreted Test"); + + getstacktrace[] threads = new getstacktrace[10]; + + for (int i = 0; i < threads.length; i++) + { + threads[i] = new getstacktrace (); + threads[i].start (); + while (!threads[i].done) + yield (); + } + + do_getstacktrace_tests (threads); + + for (int i = 0; i < threads.length; i++) + { + threads[i].done = false; + } + } +} diff --git a/libjava/testsuite/libjava.jvmti/interp/getstacktrace.out b/libjava/testsuite/libjava.jvmti/interp/getstacktrace.out new file mode 100644 index 00000000000..5134e6eab78 --- /dev/null +++ b/libjava/testsuite/libjava.jvmti/interp/getstacktrace.out @@ -0,0 +1,76 @@ +JVMTI GetStackTrace Interpreted Test +Thread has 2 frames +Frame 0 is native +Frame 1 is interpreted +Thread has 3 frames +Frame 0 is interpreted +Frame 1 is native +Frame 2 is interpreted +Thread has 4 frames +Frame 0 is native +Frame 1 is interpreted +Frame 2 is interpreted +Frame 3 is interpreted +Thread has 5 frames +Frame 0 is interpreted +Frame 1 is native +Frame 2 is native +Frame 3 is native +Frame 4 is interpreted +Thread has 6 frames +Frame 0 is native +Frame 1 is interpreted +Frame 2 is interpreted +Frame 3 is interpreted +Frame 4 is interpreted +Frame 5 is interpreted +Thread has 7 frames +Frame 0 is interpreted +Frame 1 is native +Frame 2 is native +Frame 3 is native +Frame 4 is native +Frame 5 is native +Frame 6 is interpreted +Thread has 8 frames +Frame 0 is native +Frame 1 is interpreted +Frame 2 is interpreted +Frame 3 is interpreted +Frame 4 is interpreted +Frame 5 is interpreted +Frame 6 is interpreted +Frame 7 is interpreted +Thread has 9 frames +Frame 0 is interpreted +Frame 1 is native +Frame 2 is native +Frame 3 is native +Frame 4 is native +Frame 5 is native +Frame 6 is native +Frame 7 is native +Frame 8 is interpreted +Thread has 10 frames +Frame 0 is native +Frame 1 is interpreted +Frame 2 is interpreted +Frame 3 is interpreted +Frame 4 is interpreted +Frame 5 is interpreted +Frame 6 is interpreted +Frame 7 is interpreted +Frame 8 is interpreted +Frame 9 is interpreted +Thread has 11 frames +Frame 0 is interpreted +Frame 1 is native +Frame 2 is native +Frame 3 is native +Frame 4 is native +Frame 5 is native +Frame 6 is native +Frame 7 is native +Frame 8 is native +Frame 9 is native +Frame 10 is interpreted diff --git a/libjava/testsuite/libjava.jvmti/interp/natgetstacktrace.cc b/libjava/testsuite/libjava.jvmti/interp/natgetstacktrace.cc new file mode 100644 index 00000000000..e2c88ada40c --- /dev/null +++ b/libjava/testsuite/libjava.jvmti/interp/natgetstacktrace.cc @@ -0,0 +1,144 @@ +#include + +#include +#include +#include + +#include + +#include "getstacktrace.h" + +void +printStackTrace (jvmtiFrameInfo *frames, jint frame_cnt) +{ + printf ("Thread has %d frames\n", static_cast (frame_cnt)); + + for (int i = 0; i < frame_cnt; i++) + { + jmethodID method = frames[i].method; + jlocation location = frames[i].location; + + if (location == -1) + { + printf ("Frame %d is native\n", i); + } + else + { + printf ("Frame %d is interpreted\n", i); + } + } +} + + +JNIEXPORT void JNICALL Java_getstacktrace_natPlaceholder (JNIEnv *env, jobject obj) +{ + jclass klass = env->GetObjectClass (obj); + jfieldID done_id = env->GetFieldID (klass, "done", "Z"); + jfieldID num_frames_id = env->GetFieldID (klass, "num_frames", "I"); + jfieldID thread_num_id = env->GetFieldID (klass, "thread_num", "I"); + + // num_frames-- + jint n_frames = env->GetIntField (obj, num_frames_id); + n_frames--; + env->SetIntField (obj, num_frames_id, n_frames); + + jint t_num = env->GetIntField (obj, thread_num_id); + + if (n_frames <= 1) + { + if (t_num % 2 == 1) + { + jmethodID natRunner_id = env->GetMethodID (klass, "natRunner", "()V"); + env->CallVoidMethod (obj, natRunner_id); + } + else + { + jmethodID runner_id = env->GetMethodID (klass, "runner", "()V"); + env->CallVoidMethod (obj, runner_id); + } + } + else + { + if (t_num % 2 == 0) + { + jmethodID natPlaceholder_id = env->GetMethodID (klass, + "natPlaceholder", + "()V"); + env->CallVoidMethod (obj, natPlaceholder_id); + } + else + { + jmethodID placeholder_id = env->GetMethodID (klass, "placeholder", + "()V"); + env->CallVoidMethod (obj, placeholder_id); + } + } +} + +JNIEXPORT void JNICALL Java_getstacktrace_natRunner (JNIEnv *env, jobject obj) +{ + jclass klass = env->GetObjectClass (obj); + jfieldID done_id = env->GetFieldID (klass, "done", "Z"); + + + jboolean done; + done = true; + env->SetBooleanField (obj, done_id, done); + + do + { + done = env->GetBooleanField (obj, done_id); + if (done == false) + break; + usleep (10); + } + while (done != false); +} + +JNIEXPORT jint JNICALL Java_getstacktrace_do_1getstacktrace_1tests +(JNIEnv *env, jclass klass, jobjectArray thr_arr) +{ + JavaVM *vm; + jint err = env->GetJavaVM (&vm); + if (err < 0) + { + fprintf (stderr, "error getting VM\n"); + exit (1); + } + + jvmtiEnv *jvmti = NULL; + vm->GetEnv ((void **) &jvmti, JVMTI_VERSION_1_0); + + if (jvmti == NULL) + { + fprintf (stderr, "error getting jvmti environment\n"); + exit (1); + } + + jint frame_cnt; + jvmtiFrameInfo frames[30]; + + jvmtiError jerr; + jthread thr; + + jsize num_threads = env->GetArrayLength (thr_arr); + + for (int i = 0; i < num_threads; i++) + { + thr = reinterpret_cast + (env->GetObjectArrayElement (thr_arr, static_cast (i))); + fflush (stdout); + jerr = jvmti->GetStackTrace (thr, 0, 30, frames, &frame_cnt); + if (jerr != JVMTI_ERROR_NONE) + { + char *error_name; + jvmti->GetErrorName (jerr, &error_name); + fprintf (stderr, "JVMTI Error: %s\n", error_name); + jvmti->Deallocate (reinterpret_cast (error_name)); + } + else + { + printStackTrace (frames, frame_cnt); + } + } +}