dalvik_system_VMStack.cc revision 8e5bd18fc665d7ec5461ea068e98740a65da754c
18daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes/*
28daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * Copyright (C) 2008 The Android Open Source Project
38daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes *
48daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
58daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * you may not use this file except in compliance with the License.
68daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * You may obtain a copy of the License at
78daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes *
88daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
98daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes *
108daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * Unless required by applicable law or agreed to in writing, software
118daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
128daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * See the License for the specific language governing permissions and
148daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * limitations under the License.
158daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes */
168daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
17277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe#include "dalvik_system_VMStack.h"
18277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe
19eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include "jni_internal.h"
206a144338023bdc0ca6954fc71a1f9b4d94088ee4Elliott Hughes#include "nth_caller_visitor.h"
21ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method-inl.h"
224f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/class-inl.h"
232dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class_loader.h"
244f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/object-inl.h"
251eb512d33f94d1dd7ea38263307ba0f7a0dfa653Ian Rogers#include "scoped_fast_native_object_access.h"
2600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h"
2701158d7a57c8321370667a6045220237d16e0da8Elliott Hughes#include "thread_list.h"
288daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
298daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughesnamespace art {
308daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
3153b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogersstatic jobject GetThreadStack(const ScopedFastNativeObjectAccess& soa, jobject peer)
3253b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
3353b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  jobject trace = nullptr;
3453b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  if (soa.Decode<mirror::Object*>(peer) == soa.Self()->GetPeer()) {
35ee1d79a603c77c0667b27c075a983579d5c51f7eSebastien Hertz    trace = soa.Self()->CreateInternalStackTrace<false>(soa);
3600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  } else {
3753b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers    // Suspend thread to build stack trace.
3853b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers    soa.Self()->TransitionFromRunnableToSuspended(kNative);
39ba32de47e32f436d7c11cb4a2e78bdd4ad4dc5d2Brian Carlstrom    ThreadList* thread_list = Runtime::Current()->GetThreadList();
4053b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers    bool timed_out;
414ad5cd3e7d519484559ef778d96fb3f0be8919faIan Rogers    Thread* thread = thread_list->SuspendThreadByPeer(peer, true, false, &timed_out);
4253b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers    if (thread != nullptr) {
4353b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers      // Must be runnable to create returned array.
4453b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers      CHECK_EQ(soa.Self()->TransitionFromSuspendedToRunnable(), kNative);
45ee1d79a603c77c0667b27c075a983579d5c51f7eSebastien Hertz      trace = thread->CreateInternalStackTrace<false>(soa);
4653b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers      soa.Self()->TransitionFromRunnableToSuspended(kNative);
4753b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers      // Restart suspended thread.
48ba32de47e32f436d7c11cb4a2e78bdd4ad4dc5d2Brian Carlstrom      thread_list->Resume(thread, false);
4953b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers    } else {
5053b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers      if (timed_out) {
5153b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers        LOG(ERROR) << "Trying to get thread's stack failed as the thread failed to suspend within a "
5253b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers            "generous timeout.";
5353b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers      }
5415bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers    }
5553b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers    CHECK_EQ(soa.Self()->TransitionFromSuspendedToRunnable(), kNative);
5600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  }
5753b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  return trace;
5801158d7a57c8321370667a6045220237d16e0da8Elliott Hughes}
5901158d7a57c8321370667a6045220237d16e0da8Elliott Hughes
60306057fd278d75bf3794bd5243a3b6652c487d18Ian Rogersstatic jint VMStack_fillStackTraceElements(JNIEnv* env, jclass, jobject javaThread,
61306057fd278d75bf3794bd5243a3b6652c487d18Ian Rogers                                           jobjectArray javaSteArray) {
6253b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  ScopedFastNativeObjectAccess soa(env);
6353b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  jobject trace = GetThreadStack(soa, javaThread);
6453b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  if (trace == nullptr) {
6501158d7a57c8321370667a6045220237d16e0da8Elliott Hughes    return 0;
6601158d7a57c8321370667a6045220237d16e0da8Elliott Hughes  }
6701158d7a57c8321370667a6045220237d16e0da8Elliott Hughes  int32_t depth;
6853b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  Thread::InternalStackTraceToStackTraceElementArray(soa, trace, javaSteArray, &depth);
6901158d7a57c8321370667a6045220237d16e0da8Elliott Hughes  return depth;
708daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes}
718daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
726a144338023bdc0ca6954fc71a1f9b4d94088ee4Elliott Hughes// Returns the defining class loader of the caller's caller.
730512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic jobject VMStack_getCallingClassLoader(JNIEnv* env, jclass) {
741eb512d33f94d1dd7ea38263307ba0f7a0dfa653Ian Rogers  ScopedFastNativeObjectAccess soa(env);
757a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers  NthCallerVisitor visitor(soa.Self(), 2);
760399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  visitor.WalkStack();
77718ac65aa78403124c2269f0dcadd341a18b8efeAndreas Gampe  if (UNLIKELY(visitor.caller == nullptr)) {
78718ac65aa78403124c2269f0dcadd341a18b8efeAndreas Gampe    // The caller is an attached native thread.
79718ac65aa78403124c2269f0dcadd341a18b8efeAndreas Gampe    return nullptr;
80718ac65aa78403124c2269f0dcadd341a18b8efeAndreas Gampe  }
8100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  return soa.AddLocalReference<jobject>(visitor.caller->GetDeclaringClass()->GetClassLoader());
828daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes}
838daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
84598854726a5d50c18fa720af6b097279e5e01584Brian Carlstromstatic jobject VMStack_getClosestUserClassLoader(JNIEnv* env, jclass) {
850399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  struct ClosestUserClassLoaderVisitor : public StackVisitor {
86598854726a5d50c18fa720af6b097279e5e01584Brian Carlstrom    explicit ClosestUserClassLoaderVisitor(Thread* thread)
878e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray      : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
888e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray        class_loader(nullptr) {}
8908fc03ae5dded4adc9b45b7014a4b9dfedbe95a6Elliott Hughes
90ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
91598854726a5d50c18fa720af6b097279e5e01584Brian Carlstrom      DCHECK(class_loader == nullptr);
922dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      mirror::Class* c = GetMethod()->GetDeclaringClass();
932dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      mirror::Object* cl = c->GetClassLoader();
94598854726a5d50c18fa720af6b097279e5e01584Brian Carlstrom      if (cl != nullptr) {
955cb71bb4437db51f415e57e6002ba1ef023e7de1Brian Carlstrom        class_loader = cl;
96530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes        return false;
975cb71bb4437db51f415e57e6002ba1ef023e7de1Brian Carlstrom      }
98530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes      return true;
995cb71bb4437db51f415e57e6002ba1ef023e7de1Brian Carlstrom    }
10008fc03ae5dded4adc9b45b7014a4b9dfedbe95a6Elliott Hughes
1012dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::Object* class_loader;
1025cb71bb4437db51f415e57e6002ba1ef023e7de1Brian Carlstrom  };
1031eb512d33f94d1dd7ea38263307ba0f7a0dfa653Ian Rogers  ScopedFastNativeObjectAccess soa(env);
104598854726a5d50c18fa720af6b097279e5e01584Brian Carlstrom  ClosestUserClassLoaderVisitor visitor(soa.Self());
1050399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  visitor.WalkStack();
10600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  return soa.AddLocalReference<jobject>(visitor.class_loader);
1078daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes}
1088daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
1096a144338023bdc0ca6954fc71a1f9b4d94088ee4Elliott Hughes// Returns the class of the caller's caller's caller.
1100512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic jclass VMStack_getStackClass2(JNIEnv* env, jclass) {
1111eb512d33f94d1dd7ea38263307ba0f7a0dfa653Ian Rogers  ScopedFastNativeObjectAccess soa(env);
1127a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers  NthCallerVisitor visitor(soa.Self(), 3);
1130399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers  visitor.WalkStack();
1140d334ce54efd791da14536b6a16f61d9085b8785Andreas Gampe  if (UNLIKELY(visitor.caller == nullptr)) {
1150d334ce54efd791da14536b6a16f61d9085b8785Andreas Gampe    // The caller is an attached native thread.
1160d334ce54efd791da14536b6a16f61d9085b8785Andreas Gampe    return nullptr;
1170d334ce54efd791da14536b6a16f61d9085b8785Andreas Gampe  }
11800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  return soa.AddLocalReference<jclass>(visitor.caller->GetDeclaringClass());
1198daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes}
1208daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
1210512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic jobjectArray VMStack_getThreadStackTrace(JNIEnv* env, jclass, jobject javaThread) {
12253b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  ScopedFastNativeObjectAccess soa(env);
12353b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  jobject trace = GetThreadStack(soa, javaThread);
12453b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  if (trace == nullptr) {
12553b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers    return nullptr;
12601158d7a57c8321370667a6045220237d16e0da8Elliott Hughes  }
12753b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  return Thread::InternalStackTraceToStackTraceElementArray(soa, trace);
1288daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes}
1298daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
1308daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughesstatic JNINativeMethod gMethods[] = {
13153b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  NATIVE_METHOD(VMStack, fillStackTraceElements, "!(Ljava/lang/Thread;[Ljava/lang/StackTraceElement;)I"),
1321eb512d33f94d1dd7ea38263307ba0f7a0dfa653Ian Rogers  NATIVE_METHOD(VMStack, getCallingClassLoader, "!()Ljava/lang/ClassLoader;"),
133598854726a5d50c18fa720af6b097279e5e01584Brian Carlstrom  NATIVE_METHOD(VMStack, getClosestUserClassLoader, "!()Ljava/lang/ClassLoader;"),
1341eb512d33f94d1dd7ea38263307ba0f7a0dfa653Ian Rogers  NATIVE_METHOD(VMStack, getStackClass2, "!()Ljava/lang/Class;"),
13553b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  NATIVE_METHOD(VMStack, getThreadStackTrace, "!(Ljava/lang/Thread;)[Ljava/lang/StackTraceElement;"),
1368daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes};
1378daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
1388daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughesvoid register_dalvik_system_VMStack(JNIEnv* env) {
139eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes  REGISTER_NATIVE_METHODS("dalvik/system/VMStack");
1408daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes}
1418daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes
1428daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes}  // namespace art
143