• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright (C) 2017 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include "common_helper.h"
19 
20 #include "jni.h"
21 #include "jvmti.h"
22 
23 #include "jvmti_helper.h"
24 #include "scoped_local_ref.h"
25 #include "test_env.h"
26 
27 namespace art {
28 namespace common_stack_trace {
29 
Java_art_StackTrace_GetStackDepth(JNIEnv * env,jclass,jthread thr)30 extern "C" JNIEXPORT jint JNICALL Java_art_StackTrace_GetStackDepth(
31     JNIEnv* env, jclass, jthread thr) {
32   jint ret;
33   JvmtiErrorToException(env, jvmti_env, jvmti_env->GetFrameCount(thr, &ret));
34   return ret;
35 }
36 
Java_art_StackTrace_nativeGetStackTrace(JNIEnv * env,jclass,jthread thr)37 extern "C" JNIEXPORT jobjectArray Java_art_StackTrace_nativeGetStackTrace(JNIEnv* env,
38                                                                           jclass,
39                                                                           jthread thr) {
40   jint depth;
41   ScopedLocalRef<jclass> klass(env, env->FindClass("art/StackTrace$StackFrameData"));
42   if (env->ExceptionCheck()) {
43     return nullptr;
44   }
45   jmethodID constructor = env->GetMethodID(
46       klass.get(), "<init>", "(Ljava/lang/Thread;Ljava/lang/reflect/Executable;JI)V");
47   if (env->ExceptionCheck()) {
48     return nullptr;
49   }
50   if (JvmtiErrorToException(env, jvmti_env, jvmti_env->GetFrameCount(thr, &depth))) {
51     return nullptr;
52   }
53   // Just give some extra space.
54   depth += 10;
55   jvmtiFrameInfo* frames;
56   if (JvmtiErrorToException(
57       env, jvmti_env, jvmti_env->Allocate(depth * sizeof(jvmtiFrameInfo),
58                                           reinterpret_cast<unsigned char**>(&frames)))) {
59     return nullptr;
60   }
61   jint nframes = 0;
62   if (JvmtiErrorToException(
63       env, jvmti_env, jvmti_env->GetStackTrace(thr, 0, depth, frames, &nframes))) {
64     jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(frames));
65     return nullptr;
66   }
67   jobjectArray frames_array = env->NewObjectArray(nframes, klass.get(), nullptr);
68   if (env->ExceptionCheck()) {
69     jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(frames));
70     return nullptr;
71   }
72   for (jint i = 0; i < nframes; i++) {
73     jobject jmethod = GetJavaMethod(jvmti_env, env, frames[i].method);
74     if (env->ExceptionCheck()) {
75       jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(frames));
76       return nullptr;
77     }
78     jobject frame_obj = env->NewObject(klass.get(),
79                                        constructor,
80                                        thr,
81                                        jmethod,
82                                        frames[i].location,
83                                        i);
84     if (env->ExceptionCheck()) {
85       jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(frames));
86       return nullptr;
87     }
88     env->SetObjectArrayElement(frames_array, i, frame_obj);
89     if (env->ExceptionCheck()) {
90       jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(frames));
91       return nullptr;
92     }
93   }
94   jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(frames));
95   return frames_array;
96 }
97 
98 }  // namespace common_stack_trace
99 }  // namespace art
100