Home | History | Annotate | Download | only in native
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "jni_internal.h"
     18 #include "nth_caller_visitor.h"
     19 #include "mirror/art_method-inl.h"
     20 #include "mirror/class-inl.h"
     21 #include "mirror/class_loader.h"
     22 #include "mirror/object-inl.h"
     23 #include "scoped_thread_state_change.h"
     24 #include "thread_list.h"
     25 
     26 namespace art {
     27 
     28 static jobject GetThreadStack(JNIEnv* env, jobject peer) {
     29   {
     30     ScopedObjectAccess soa(env);
     31     if (soa.Decode<mirror::Object*>(peer) == soa.Self()->GetPeer()) {
     32       return soa.Self()->CreateInternalStackTrace(soa);
     33     }
     34   }
     35   // Suspend thread to build stack trace.
     36   bool timed_out;
     37   Thread* thread = Thread::SuspendForDebugger(peer, true, &timed_out);
     38   if (thread != NULL) {
     39     jobject trace;
     40     {
     41       ScopedObjectAccess soa(env);
     42       trace = thread->CreateInternalStackTrace(soa);
     43     }
     44     // Restart suspended thread.
     45     Runtime::Current()->GetThreadList()->Resume(thread, true);
     46     return trace;
     47   } else {
     48     if (timed_out) {
     49       LOG(ERROR) << "Trying to get thread's stack failed as the thread failed to suspend within a "
     50           "generous timeout.";
     51     }
     52     return NULL;
     53   }
     54 }
     55 
     56 static jint VMStack_fillStackTraceElements(JNIEnv* env, jclass, jobject javaThread,
     57                                            jobjectArray javaSteArray) {
     58   jobject trace = GetThreadStack(env, javaThread);
     59   if (trace == NULL) {
     60     return 0;
     61   }
     62   int32_t depth;
     63   Thread::InternalStackTraceToStackTraceElementArray(env, trace, javaSteArray, &depth);
     64   return depth;
     65 }
     66 
     67 // Returns the defining class loader of the caller's caller.
     68 static jobject VMStack_getCallingClassLoader(JNIEnv* env, jclass) {
     69   ScopedObjectAccess soa(env);
     70   NthCallerVisitor visitor(soa.Self(), 2);
     71   visitor.WalkStack();
     72   return soa.AddLocalReference<jobject>(visitor.caller->GetDeclaringClass()->GetClassLoader());
     73 }
     74 
     75 static jobject VMStack_getClosestUserClassLoader(JNIEnv* env, jclass, jobject javaBootstrap,
     76                                                  jobject javaSystem) {
     77   struct ClosestUserClassLoaderVisitor : public StackVisitor {
     78     ClosestUserClassLoaderVisitor(Thread* thread, mirror::Object* bootstrap, mirror::Object* system)
     79       : StackVisitor(thread, NULL), bootstrap(bootstrap), system(system), class_loader(NULL) {}
     80 
     81     bool VisitFrame() {
     82       DCHECK(class_loader == NULL);
     83       mirror::Class* c = GetMethod()->GetDeclaringClass();
     84       mirror::Object* cl = c->GetClassLoader();
     85       if (cl != NULL && cl != bootstrap && cl != system) {
     86         class_loader = cl;
     87         return false;
     88       }
     89       return true;
     90     }
     91 
     92     mirror::Object* bootstrap;
     93     mirror::Object* system;
     94     mirror::Object* class_loader;
     95   };
     96   ScopedObjectAccess soa(env);
     97   mirror::Object* bootstrap = soa.Decode<mirror::Object*>(javaBootstrap);
     98   mirror::Object* system = soa.Decode<mirror::Object*>(javaSystem);
     99   ClosestUserClassLoaderVisitor visitor(soa.Self(), bootstrap, system);
    100   visitor.WalkStack();
    101   return soa.AddLocalReference<jobject>(visitor.class_loader);
    102 }
    103 
    104 // Returns the class of the caller's caller's caller.
    105 static jclass VMStack_getStackClass2(JNIEnv* env, jclass) {
    106   ScopedObjectAccess soa(env);
    107   NthCallerVisitor visitor(soa.Self(), 3);
    108   visitor.WalkStack();
    109   return soa.AddLocalReference<jclass>(visitor.caller->GetDeclaringClass());
    110 }
    111 
    112 static jobjectArray VMStack_getThreadStackTrace(JNIEnv* env, jclass, jobject javaThread) {
    113   jobject trace = GetThreadStack(env, javaThread);
    114   if (trace == NULL) {
    115     return NULL;
    116   }
    117   return Thread::InternalStackTraceToStackTraceElementArray(env, trace);
    118 }
    119 
    120 static JNINativeMethod gMethods[] = {
    121   NATIVE_METHOD(VMStack, fillStackTraceElements, "(Ljava/lang/Thread;[Ljava/lang/StackTraceElement;)I"),
    122   NATIVE_METHOD(VMStack, getCallingClassLoader, "()Ljava/lang/ClassLoader;"),
    123   NATIVE_METHOD(VMStack, getClosestUserClassLoader, "(Ljava/lang/ClassLoader;Ljava/lang/ClassLoader;)Ljava/lang/ClassLoader;"),
    124   NATIVE_METHOD(VMStack, getStackClass2, "()Ljava/lang/Class;"),
    125   NATIVE_METHOD(VMStack, getThreadStackTrace, "(Ljava/lang/Thread;)[Ljava/lang/StackTraceElement;"),
    126 };
    127 
    128 void register_dalvik_system_VMStack(JNIEnv* env) {
    129   REGISTER_NATIVE_METHODS("dalvik/system/VMStack");
    130 }
    131 
    132 }  // namespace art
    133