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