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 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 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