diff options
| author | 2017-01-12 23:26:55 +0000 | |
|---|---|---|
| committer | 2017-01-12 23:26:56 +0000 | |
| commit | 31ace5c873b8c4b595aaeb5bd8e99ceb7679aedf (patch) | |
| tree | ce7c299ae318ae38ea5ea4bac0acf139c6b892d5 | |
| parent | 20e9474df95e099f58b5310188fea3631e9f7c36 (diff) | |
| parent | a1a27c603009a7b9101c6f672845e415f58571d7 (diff) | |
Merge "ART: Add GetAllStackTraces"
| -rw-r--r-- | runtime/openjdkjvmti/OpenjdkJvmTi.cc | 2 | ||||
| -rw-r--r-- | runtime/openjdkjvmti/ti_stack.cc | 236 | ||||
| -rw-r--r-- | runtime/openjdkjvmti/ti_stack.h | 9 | ||||
| -rw-r--r-- | test/911-get-stack-trace/expected.txt | 737 | ||||
| -rw-r--r-- | test/911-get-stack-trace/src/Main.java | 98 | ||||
| -rw-r--r-- | test/911-get-stack-trace/stack_trace.cc | 72 |
6 files changed, 933 insertions, 221 deletions
diff --git a/runtime/openjdkjvmti/OpenjdkJvmTi.cc b/runtime/openjdkjvmti/OpenjdkJvmTi.cc index 48f2793ff5..b3c56a1a05 100644 --- a/runtime/openjdkjvmti/OpenjdkJvmTi.cc +++ b/runtime/openjdkjvmti/OpenjdkJvmTi.cc @@ -238,7 +238,7 @@ class JvmtiFunctions { jint max_frame_count, jvmtiStackInfo** stack_info_ptr, jint* thread_count_ptr) { - return ERR(NOT_IMPLEMENTED); + return StackUtil::GetAllStackTraces(env, max_frame_count, stack_info_ptr, thread_count_ptr); } static jvmtiError GetThreadListStackTraces(jvmtiEnv* env, diff --git a/runtime/openjdkjvmti/ti_stack.cc b/runtime/openjdkjvmti/ti_stack.cc index 579fb50ecc..e33ea5f341 100644 --- a/runtime/openjdkjvmti/ti_stack.cc +++ b/runtime/openjdkjvmti/ti_stack.cc @@ -31,9 +31,15 @@ #include "ti_stack.h" +#include <list> +#include <unordered_map> +#include <vector> + #include "art_jvmti.h" #include "art_method-inl.h" +#include "base/bit_utils.h" #include "base/enums.h" +#include "base/mutex.h" #include "dex_file.h" #include "dex_file_annotations.h" #include "jni_env_ext.h" @@ -41,19 +47,19 @@ #include "mirror/class.h" #include "mirror/dex_cache.h" #include "scoped_thread_state_change-inl.h" +#include "ScopedLocalRef.h" #include "stack.h" -#include "thread.h" +#include "thread-inl.h" +#include "thread_list.h" #include "thread_pool.h" namespace openjdkjvmti { struct GetStackTraceVisitor : public art::StackVisitor { GetStackTraceVisitor(art::Thread* thread_in, - art::ScopedObjectAccessAlreadyRunnable& soa_, size_t start_, size_t stop_) : StackVisitor(thread_in, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames), - soa(soa_), start(start_), stop(stop_) {} @@ -85,7 +91,6 @@ struct GetStackTraceVisitor : public art::StackVisitor { return true; } - art::ScopedObjectAccessAlreadyRunnable& soa; std::vector<jvmtiFrameInfo> frames; size_t start; size_t stop; @@ -99,10 +104,8 @@ struct GetStackTraceClosure : public art::Closure { start_result(0), stop_result(0) {} - void Run(art::Thread* self) OVERRIDE { - art::ScopedObjectAccess soa(art::Thread::Current()); - - GetStackTraceVisitor visitor(self, soa, start_input, stop_input); + void Run(art::Thread* self) OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) { + GetStackTraceVisitor visitor(self, start_input, stop_input); visitor.WalkStack(false); frames.swap(visitor.frames); @@ -118,6 +121,44 @@ struct GetStackTraceClosure : public art::Closure { size_t stop_result; }; +static jvmtiError TranslateFrameVector(const std::vector<jvmtiFrameInfo>& frames, + jint start_depth, + size_t start_result, + jint max_frame_count, + jvmtiFrameInfo* frame_buffer, + jint* count_ptr) { + size_t collected_frames = frames.size(); + + // Assume we're here having collected something. + DCHECK_GT(max_frame_count, 0); + + // Frames from the top. + if (start_depth >= 0) { + if (start_result != 0) { + // Not enough frames. + return ERR(ILLEGAL_ARGUMENT); + } + DCHECK_LE(collected_frames, static_cast<size_t>(max_frame_count)); + if (frames.size() > 0) { + memcpy(frame_buffer, frames.data(), collected_frames * sizeof(jvmtiFrameInfo)); + } + *count_ptr = static_cast<jint>(frames.size()); + return ERR(NONE); + } + + // Frames from the bottom. + if (collected_frames < static_cast<size_t>(-start_depth)) { + return ERR(ILLEGAL_ARGUMENT); + } + + size_t count = std::min(static_cast<size_t>(-start_depth), static_cast<size_t>(max_frame_count)); + memcpy(frame_buffer, + &frames.data()[collected_frames + start_depth], + count * sizeof(jvmtiFrameInfo)); + *count_ptr = static_cast<jint>(count); + return ERR(NONE); +} + jvmtiError StackUtil::GetStackTrace(jvmtiEnv* jvmti_env ATTRIBUTE_UNUSED, jthread java_thread, jint start_depth, @@ -157,35 +198,174 @@ jvmtiError StackUtil::GetStackTrace(jvmtiEnv* jvmti_env ATTRIBUTE_UNUSED, } GetStackTraceClosure closure(start_depth >= 0 ? static_cast<size_t>(start_depth) : 0, - start_depth >= 0 ?static_cast<size_t>(max_frame_count) : 0); + start_depth >= 0 ? static_cast<size_t>(max_frame_count) : 0); thread->RequestSynchronousCheckpoint(&closure); - size_t collected_frames = closure.frames.size(); + return TranslateFrameVector(closure.frames, + start_depth, + closure.start_result, + max_frame_count, + frame_buffer, + count_ptr); +} - // Frames from the top. - if (start_depth >= 0) { - if (closure.start_result != 0) { - // Not enough frames. - return ERR(ILLEGAL_ARGUMENT); +struct GetAllStackTraceClosure : public art::Closure { + public: + explicit GetAllStackTraceClosure(size_t stop) + : start_input(0), + stop_input(stop), + frames_lock("GetAllStackTraceGuard", art::LockLevel::kAbortLock), + start_result(0), + stop_result(0) {} + + void Run(art::Thread* self) + OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) REQUIRES(!frames_lock) { + // self should be live here (so it could be suspended). No need to filter. + + art::Thread* current = art::Thread::Current(); + std::vector<jvmtiFrameInfo> self_frames; + + GetStackTraceVisitor visitor(self, start_input, stop_input); + visitor.WalkStack(false); + + self_frames.swap(visitor.frames); + + art::MutexLock mu(current, frames_lock); + frames.emplace(self, self_frames); + } + + const size_t start_input; + const size_t stop_input; + + art::Mutex frames_lock; + std::unordered_map<art::Thread*, std::vector<jvmtiFrameInfo>> frames GUARDED_BY(frames_lock); + size_t start_result; + size_t stop_result; +}; + + + +jvmtiError StackUtil::GetAllStackTraces(jvmtiEnv* env, + jint max_frame_count, + jvmtiStackInfo** stack_info_ptr, + jint* thread_count_ptr) { + if (max_frame_count < 0) { + return ERR(ILLEGAL_ARGUMENT); + } + if (stack_info_ptr == nullptr || thread_count_ptr == nullptr) { + return ERR(NULL_POINTER); + } + + + art::Thread* current = art::Thread::Current(); + art::ScopedObjectAccess soa(current); // Now we know we have the shared lock. + art::ScopedThreadSuspension sts(current, art::kWaitingForDebuggerSuspension); + art::ScopedSuspendAll ssa("GetAllStackTraces"); + + std::vector<art::Thread*> threads; + std::vector<std::vector<jvmtiFrameInfo>> frames; + { + std::list<art::Thread*> thread_list; + { + art::MutexLock mu(current, *art::Locks::thread_list_lock_); + thread_list = art::Runtime::Current()->GetThreadList()->GetList(); } - DCHECK_LE(collected_frames, static_cast<size_t>(max_frame_count)); - if (closure.frames.size() > 0) { - memcpy(frame_buffer, closure.frames.data(), collected_frames * sizeof(jvmtiFrameInfo)); + + for (art::Thread* thread : thread_list) { + GetStackTraceClosure closure(0u, static_cast<size_t>(max_frame_count)); + thread->RequestSynchronousCheckpoint(&closure); + + threads.push_back(thread); + frames.emplace_back(); + frames.back().swap(closure.frames); } - *count_ptr = static_cast<jint>(closure.frames.size()); - return ERR(NONE); } - // Frames from the bottom. - if (collected_frames < static_cast<size_t>(-start_depth)) { - return ERR(ILLEGAL_ARGUMENT); + // Convert the data into our output format. Note: we need to keep the threads suspended, + // as we need to access them for their peers. + + // Note: we use an array of jvmtiStackInfo for convenience. The spec says we need to + // allocate one big chunk for this and the actual frames, which means we need + // to either be conservative or rearrange things later (the latter is implemented). + std::unique_ptr<jvmtiStackInfo[]> stack_info_array(new jvmtiStackInfo[frames.size()]); + std::vector<std::unique_ptr<jvmtiFrameInfo[]>> frame_infos; + frame_infos.reserve(frames.size()); + + // Now run through and add data for each thread. + size_t sum_frames = 0; + for (size_t index = 0; index < frames.size(); ++index) { + jvmtiStackInfo& stack_info = stack_info_array.get()[index]; + memset(&stack_info, 0, sizeof(jvmtiStackInfo)); + + art::Thread* self = threads[index]; + const std::vector<jvmtiFrameInfo>& thread_frames = frames[index]; + + // For the time being, set the thread to null. We don't have good ScopedLocalRef + // infrastructure. + DCHECK(self->GetPeer() != nullptr); + stack_info.thread = nullptr; + stack_info.state = JVMTI_THREAD_STATE_SUSPENDED; + + size_t collected_frames = thread_frames.size(); + if (max_frame_count == 0 || collected_frames == 0) { + stack_info.frame_count = 0; + stack_info.frame_buffer = nullptr; + continue; + } + DCHECK_LE(collected_frames, static_cast<size_t>(max_frame_count)); + + jvmtiFrameInfo* frame_info = new jvmtiFrameInfo[collected_frames]; + frame_infos.emplace_back(frame_info); + + jint count; + jvmtiError translate_result = TranslateFrameVector(thread_frames, + 0, + 0, + static_cast<jint>(collected_frames), + frame_info, + &count); + DCHECK(translate_result == JVMTI_ERROR_NONE); + stack_info.frame_count = static_cast<jint>(collected_frames); + stack_info.frame_buffer = frame_info; + sum_frames += static_cast<size_t>(count); } - size_t count = std::min(static_cast<size_t>(-start_depth), static_cast<size_t>(max_frame_count)); - memcpy(frame_buffer, - &closure.frames.data()[collected_frames + start_depth], - count * sizeof(jvmtiFrameInfo)); - *count_ptr = static_cast<jint>(count); + // No errors, yet. Now put it all into an output buffer. + size_t rounded_stack_info_size = art::RoundUp(sizeof(jvmtiStackInfo) * frames.size(), + alignof(jvmtiFrameInfo)); + size_t chunk_size = rounded_stack_info_size + sum_frames * sizeof(jvmtiFrameInfo); + unsigned char* chunk_data; + jvmtiError alloc_result = env->Allocate(chunk_size, &chunk_data); + if (alloc_result != ERR(NONE)) { + return alloc_result; + } + + jvmtiStackInfo* stack_info = reinterpret_cast<jvmtiStackInfo*>(chunk_data); + // First copy in all the basic data. + memcpy(stack_info, stack_info_array.get(), sizeof(jvmtiStackInfo) * frames.size()); + + // Now copy the frames and fix up the pointers. + jvmtiFrameInfo* frame_info = reinterpret_cast<jvmtiFrameInfo*>( + chunk_data + rounded_stack_info_size); + for (size_t i = 0; i < frames.size(); ++i) { + jvmtiStackInfo& old_stack_info = stack_info_array.get()[i]; + jvmtiStackInfo& new_stack_info = stack_info[i]; + + jthread thread_peer = current->GetJniEnv()->AddLocalReference<jthread>(threads[i]->GetPeer()); + new_stack_info.thread = thread_peer; + + if (old_stack_info.frame_count > 0) { + // Only copy when there's data - leave the nullptr alone. + size_t frames_size = static_cast<size_t>(old_stack_info.frame_count) * sizeof(jvmtiFrameInfo); + memcpy(frame_info, old_stack_info.frame_buffer, frames_size); + new_stack_info.frame_buffer = frame_info; + frame_info += old_stack_info.frame_count; + } + } + + *stack_info_ptr = stack_info; + *thread_count_ptr = static_cast<jint>(frames.size()); + return ERR(NONE); } diff --git a/runtime/openjdkjvmti/ti_stack.h b/runtime/openjdkjvmti/ti_stack.h index 1931ed3113..7619f98daf 100644 --- a/runtime/openjdkjvmti/ti_stack.h +++ b/runtime/openjdkjvmti/ti_stack.h @@ -32,12 +32,21 @@ #ifndef ART_RUNTIME_OPENJDKJVMTI_TI_STACK_H_ #define ART_RUNTIME_OPENJDKJVMTI_TI_STACK_H_ +#include "jni.h" #include "jvmti.h" +#include "base/mutex.h" + namespace openjdkjvmti { class StackUtil { public: + static jvmtiError GetAllStackTraces(jvmtiEnv* env, + jint max_frame_count, + jvmtiStackInfo** stack_info_ptr, + jint* thread_count_ptr) + REQUIRES(!art::Locks::thread_list_lock_); + static jvmtiError GetStackTrace(jvmtiEnv* env, jthread thread, jint start_depth, diff --git a/test/911-get-stack-trace/expected.txt b/test/911-get-stack-trace/expected.txt index f8c97ce475..284a071f48 100644 --- a/test/911-get-stack-trace/expected.txt +++ b/test/911-get-stack-trace/expected.txt @@ -4,72 +4,72 @@ From top --------- getStackTrace (Ljava/lang/Thread;II)[[Ljava/lang/String; -1 -2 - print (Ljava/lang/Thread;II)V 0 124 - printOrWait (IILMain$ControlData;)V 6 151 - baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - doTest ()V 38 34 - main ([Ljava/lang/String;)V 6 24 ---------- - print (Ljava/lang/Thread;II)V 0 124 - printOrWait (IILMain$ControlData;)V 6 151 - baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - doTest ()V 42 35 - main ([Ljava/lang/String;)V 6 24 + print (Ljava/lang/Thread;II)V 0 172 + printOrWait (IILMain$ControlData;)V 6 235 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + doTest ()V 38 41 + main ([Ljava/lang/String;)V 6 27 +--------- + print (Ljava/lang/Thread;II)V 0 172 + printOrWait (IILMain$ControlData;)V 6 235 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + doTest ()V 42 42 + main ([Ljava/lang/String;)V 6 27 --------- getStackTrace (Ljava/lang/Thread;II)[[Ljava/lang/String; -1 -2 - print (Ljava/lang/Thread;II)V 0 124 - printOrWait (IILMain$ControlData;)V 6 151 - baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142 - bar (IIILMain$ControlData;)J 0 136 ---------- - printOrWait (IILMain$ControlData;)V 6 151 - baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 + print (Ljava/lang/Thread;II)V 0 172 + printOrWait (IILMain$ControlData;)V 6 235 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 +--------- + printOrWait (IILMain$ControlData;)V 6 235 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 From bottom --------- - main ([Ljava/lang/String;)V 6 24 + main ([Ljava/lang/String;)V 6 27 --------- - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - doTest ()V 65 41 - main ([Ljava/lang/String;)V 6 24 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + doTest ()V 65 48 + main ([Ljava/lang/String;)V 6 27 --------- - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 ################################ ### Other thread (suspended) ### @@ -77,132 +77,519 @@ From bottom From top --------- wait ()V -1 -2 - printOrWait (IILMain$ControlData;)V 24 157 - baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - run ()V 4 54 ---------- - printOrWait (IILMain$ControlData;)V 24 157 - baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - run ()V 4 54 ---------- - wait ()V -1 -2 - printOrWait (IILMain$ControlData;)V 24 157 - baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 ---------- - baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 + printOrWait (IILMain$ControlData;)V 24 241 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + run ()V 4 61 +--------- + printOrWait (IILMain$ControlData;)V 24 241 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + run ()V 4 61 +--------- + wait ()V -1 -2 + printOrWait (IILMain$ControlData;)V 24 241 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 +--------- + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 From bottom --------- - run ()V 4 54 + run ()V 4 61 --------- - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - run ()V 4 54 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + run ()V 4 61 --------- - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 ########################### ### Other thread (live) ### ########################### From top --------- - printOrWait (IILMain$ControlData;)V 44 164 - baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - run ()V 4 88 ---------- - baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - run ()V 4 88 ---------- - printOrWait (IILMain$ControlData;)V 44 164 - baz (IIILMain$ControlData;)Ljava/lang/Object; 2 142 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 ---------- - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 + printOrWait (IILMain$ControlData;)V 44 248 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + run ()V 4 95 +--------- + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + run ()V 4 95 +--------- + printOrWait (IILMain$ControlData;)V 44 248 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 +--------- + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 From bottom --------- - run ()V 4 88 + run ()V 4 95 +--------- + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + run ()V 4 95 +--------- + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + +################################ +### Other threads (suspended) ### +################################ +--------- +FinalizerDaemon +<not printed> +--------- +FinalizerWatchdogDaemon +<not printed> +--------- +HeapTaskDaemon +<not printed> +--------- +ReferenceQueueDaemon +<not printed> +--------- +Signal Catcher + +--------- +Thread-10 + +--------- +Thread-11 + +--------- +Thread-2 + +--------- +Thread-3 + +--------- +Thread-4 + +--------- +Thread-5 + +--------- +Thread-6 + +--------- +Thread-7 + +--------- +Thread-8 + +--------- +Thread-9 + +--------- +main + +--------- +FinalizerDaemon +<not printed> +--------- +FinalizerWatchdogDaemon +<not printed> +--------- +HeapTaskDaemon +<not printed> +--------- +ReferenceQueueDaemon +<not printed> +--------- +Signal Catcher + +--------- +Thread-10 + wait ()V -1 -2 + printOrWait (IILMain$ControlData;)V 24 241 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + +--------- +Thread-11 + wait ()V -1 -2 + printOrWait (IILMain$ControlData;)V 24 241 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + +--------- +Thread-2 + wait ()V -1 -2 + printOrWait (IILMain$ControlData;)V 24 241 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + +--------- +Thread-3 + wait ()V -1 -2 + printOrWait (IILMain$ControlData;)V 24 241 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + +--------- +Thread-4 + wait ()V -1 -2 + printOrWait (IILMain$ControlData;)V 24 241 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + +--------- +Thread-5 + wait ()V -1 -2 + printOrWait (IILMain$ControlData;)V 24 241 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + +--------- +Thread-6 + wait ()V -1 -2 + printOrWait (IILMain$ControlData;)V 24 241 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + +--------- +Thread-7 + wait ()V -1 -2 + printOrWait (IILMain$ControlData;)V 24 241 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + +--------- +Thread-8 + wait ()V -1 -2 + printOrWait (IILMain$ControlData;)V 24 241 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + +--------- +Thread-9 + wait ()V -1 -2 + printOrWait (IILMain$ControlData;)V 24 241 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + +--------- +main + getAllStackTraces (I)[[Ljava/lang/Object; -1 -2 + printAll (I)V 0 208 + doTestAllStackTraces ()V 81 147 + main ([Ljava/lang/String;)V 15 31 + +--------- +FinalizerDaemon +<not printed> +--------- +FinalizerWatchdogDaemon +<not printed> +--------- +HeapTaskDaemon +<not printed> +--------- +ReferenceQueueDaemon +<not printed> +--------- +Signal Catcher + +--------- +Thread-10 + wait ()V -1 -2 + printOrWait (IILMain$ControlData;)V 24 241 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + run ()V 4 135 + +--------- +Thread-11 + wait ()V -1 -2 + printOrWait (IILMain$ControlData;)V 24 241 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + run ()V 4 135 + --------- - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - run ()V 4 88 +Thread-2 + wait ()V -1 -2 + printOrWait (IILMain$ControlData;)V 24 241 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + run ()V 4 135 + --------- - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 - foo (IIILMain$ControlData;)I 0 131 - baz (IIILMain$ControlData;)Ljava/lang/Object; 9 144 - bar (IIILMain$ControlData;)J 0 136 +Thread-3 + wait ()V -1 -2 + printOrWait (IILMain$ControlData;)V 24 241 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + run ()V 4 135 + +--------- +Thread-4 + wait ()V -1 -2 + printOrWait (IILMain$ControlData;)V 24 241 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + run ()V 4 135 + +--------- +Thread-5 + wait ()V -1 -2 + printOrWait (IILMain$ControlData;)V 24 241 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + run ()V 4 135 + +--------- +Thread-6 + wait ()V -1 -2 + printOrWait (IILMain$ControlData;)V 24 241 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + run ()V 4 135 + +--------- +Thread-7 + wait ()V -1 -2 + printOrWait (IILMain$ControlData;)V 24 241 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + run ()V 4 135 + +--------- +Thread-8 + wait ()V -1 -2 + printOrWait (IILMain$ControlData;)V 24 241 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + run ()V 4 135 + +--------- +Thread-9 + wait ()V -1 -2 + printOrWait (IILMain$ControlData;)V 24 241 + baz (IIILMain$ControlData;)Ljava/lang/Object; 2 226 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + baz (IIILMain$ControlData;)Ljava/lang/Object; 9 228 + bar (IIILMain$ControlData;)J 0 220 + foo (IIILMain$ControlData;)I 0 215 + run ()V 4 135 + +--------- +main + getAllStackTraces (I)[[Ljava/lang/Object; -1 -2 + printAll (I)V 0 208 + doTestAllStackTraces ()V 86 149 + main ([Ljava/lang/String;)V 15 31 + +Done diff --git a/test/911-get-stack-trace/src/Main.java b/test/911-get-stack-trace/src/Main.java index 722bee8056..500e945ddd 100644 --- a/test/911-get-stack-trace/src/Main.java +++ b/test/911-get-stack-trace/src/Main.java @@ -14,7 +14,10 @@ * limitations under the License. */ +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.concurrent.CountDownLatch; public class Main { @@ -24,6 +27,10 @@ public class Main { doTest(); doTestOtherThreadWait(); doTestOtherThreadBusyLoop(); + + doTestAllStackTraces(); + + System.out.println("Done"); } public static void doTest() throws Exception { @@ -109,6 +116,47 @@ public class Main { t.join(); } + public static void doTestAllStackTraces() throws Exception { + System.out.println(); + System.out.println("################################"); + System.out.println("### Other threads (suspended) ###"); + System.out.println("################################"); + + final int N = 10; + + final ControlData data = new ControlData(N); + data.waitFor = new Object(); + + Thread threads[] = new Thread[N]; + + for (int i = 0; i < N; i++) { + Thread t = new Thread() { + public void run() { + Recurse.foo(4, 0, 0, data); + } + }; + t.start(); + threads[i] = t; + } + data.reached.await(); + Thread.yield(); + Thread.sleep(500); // A little bit of time... + + printAll(0); + + printAll(5); + + printAll(25); + + // Let the thread make progress and die. + synchronized(data.waitFor) { + data.waitFor.notifyAll(); + } + for (int i = 0; i < N; i++) { + threads[i].join(); + } + } + public static void print(String[][] stack) { System.out.println("---------"); for (String[] stackElement : stack) { @@ -124,6 +172,42 @@ public class Main { print(getStackTrace(t, start, max)); } + public static void printAll(Object[][] stacks) { + List<String> stringified = new ArrayList<String>(stacks.length); + + for (Object[] stackInfo : stacks) { + Thread t = (Thread)stackInfo[0]; + String name = (t != null) ? t.getName() : "null"; + String stackSerialization; + if (name.contains("Daemon")) { + // Do not print daemon stacks, as they're non-deterministic. + stackSerialization = "<not printed>"; + } else { + StringBuilder sb = new StringBuilder(); + for (String[] stackElement : (String[][])stackInfo[1]) { + for (String part : stackElement) { + sb.append(' '); + sb.append(part); + } + sb.append('\n'); + } + stackSerialization = sb.toString(); + } + stringified.add(name + "\n" + stackSerialization); + } + + Collections.sort(stringified); + + for (String s : stringified) { + System.out.println("---------"); + System.out.println(s); + } + } + + public static void printAll(int max) { + printAll(getAllStackTraces(max)); + } + // Wrap generated stack traces into a class to separate them nicely. public static class Recurse { @@ -170,10 +254,22 @@ public class Main { } public static class ControlData { - CountDownLatch reached = new CountDownLatch(1); + CountDownLatch reached; Object waitFor = null; volatile boolean stop = false; + + public ControlData() { + this(1); + } + + public ControlData(int latchCount) { + reached = new CountDownLatch(latchCount); + } } public static native String[][] getStackTrace(Thread thread, int start, int max); + // Get all stack traces. This will return an array with an element for each thread. The element + // is an array itself with the first element being the thread, and the second element a nested + // String array as in getStackTrace. + public static native Object[][] getAllStackTraces(int max); } diff --git a/test/911-get-stack-trace/stack_trace.cc b/test/911-get-stack-trace/stack_trace.cc index cca163b79b..57d4f6d2ee 100644 --- a/test/911-get-stack-trace/stack_trace.cc +++ b/test/911-get-stack-trace/stack_trace.cc @@ -50,22 +50,9 @@ static jint FindLineNumber(jint line_number_count, return line_number; } -extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getStackTrace( - JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jthread thread, jint start, jint max) { - std::unique_ptr<jvmtiFrameInfo[]> frames(new jvmtiFrameInfo[max]); - - jint count; - { - jvmtiError result = jvmti_env->GetStackTrace(thread, start, max, frames.get(), &count); - if (result != JVMTI_ERROR_NONE) { - char* err; - jvmti_env->GetErrorName(result, &err); - printf("Failure running GetStackTrace: %s\n", err); - jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err)); - return nullptr; - } - } - +static jobjectArray TranslateJvmtiFrameInfoArray(JNIEnv* env, + jvmtiFrameInfo* frames, + jint count) { auto callback = [&](jint method_index) -> jobjectArray { char* name; char* sig; @@ -140,5 +127,58 @@ extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getStackTrace( return CreateObjectArray(env, count, "[Ljava/lang/String;", callback); } +extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getStackTrace( + JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jthread thread, jint start, jint max) { + std::unique_ptr<jvmtiFrameInfo[]> frames(new jvmtiFrameInfo[max]); + + jint count; + { + jvmtiError result = jvmti_env->GetStackTrace(thread, start, max, frames.get(), &count); + if (result != JVMTI_ERROR_NONE) { + char* err; + jvmti_env->GetErrorName(result, &err); + printf("Failure running GetStackTrace: %s\n", err); + jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err)); + return nullptr; + } + } + + return TranslateJvmtiFrameInfoArray(env, frames.get(), count); +} + +extern "C" JNIEXPORT jobjectArray JNICALL Java_Main_getAllStackTraces( + JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jint max) { + std::unique_ptr<jvmtiFrameInfo[]> frames(new jvmtiFrameInfo[max]); + + jint thread_count; + jvmtiStackInfo* stack_infos; + { + jvmtiError result = jvmti_env->GetAllStackTraces(max, &stack_infos, &thread_count); + if (result != JVMTI_ERROR_NONE) { + char* err; + jvmti_env->GetErrorName(result, &err); + printf("Failure running GetAllStackTraces: %s\n", err); + jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err)); + return nullptr; + } + } + + auto callback = [&](jint thread_index) -> jobject { + auto inner_callback = [&](jint index) -> jobject { + if (index == 0) { + return stack_infos[thread_index].thread; + } else { + return TranslateJvmtiFrameInfoArray(env, + stack_infos[thread_index].frame_buffer, + stack_infos[thread_index].frame_count); + } + }; + return CreateObjectArray(env, 2, "java/lang/Object", inner_callback); + }; + jobjectArray ret = CreateObjectArray(env, thread_count, "[Ljava/lang/Object;", callback); + jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(stack_infos)); + return ret; +} + } // namespace Test911GetStackTrace } // namespace art |