1 /* 2 * Copyright (C) 2017 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 "common_helper.h" 18 19 #include "jni.h" 20 #include "jvmti.h" 21 22 #include "jvmti_helper.h" 23 #include "scoped_local_ref.h" 24 #include "test_env.h" 25 26 namespace art { 27 28 namespace common_trace { 29 30 static bool IsInCallback(JNIEnv* env, jvmtiEnv *jvmti, jthread thr) { 31 void* data; 32 ScopedLocalRef<jthrowable> exc(env, env->ExceptionOccurred()); 33 env->ExceptionClear(); 34 jvmti->GetThreadLocalStorage(thr, &data); 35 if (exc.get() != nullptr) { 36 env->Throw(exc.get()); 37 } 38 if (data == nullptr) { 39 return false; 40 } else { 41 return true; 42 } 43 } 44 45 static void SetInCallback(JNIEnv* env, jvmtiEnv *jvmti, jthread thr, bool val) { 46 ScopedLocalRef<jthrowable> exc(env, env->ExceptionOccurred()); 47 env->ExceptionClear(); 48 jvmti->SetThreadLocalStorage(thr, (val ? reinterpret_cast<void*>(0x1) 49 : reinterpret_cast<void*>(0x0))); 50 if (exc.get() != nullptr) { 51 env->Throw(exc.get()); 52 } 53 } 54 55 class ScopedCallbackState { 56 public: 57 ScopedCallbackState(JNIEnv* jnienv, jvmtiEnv* env, jthread thr) 58 : jnienv_(jnienv), env_(env), thr_(thr) { 59 CHECK(!IsInCallback(jnienv_, env_, thr_)); 60 SetInCallback(jnienv_, env_, thr_, true); 61 } 62 ~ScopedCallbackState() { 63 CHECK(IsInCallback(jnienv_, env_, thr_)); 64 SetInCallback(jnienv_, env_, thr_, false); 65 } 66 67 private: 68 JNIEnv* jnienv_; 69 jvmtiEnv* env_; 70 jthread thr_; 71 }; 72 73 struct TraceData { 74 jclass test_klass; 75 jmethodID enter_method; 76 jmethodID exit_method; 77 jmethodID field_access; 78 jmethodID field_modify; 79 jmethodID single_step; 80 jmethodID thread_start; 81 jmethodID thread_end; 82 bool access_watch_on_load; 83 bool modify_watch_on_load; 84 jrawMonitorID trace_mon; 85 86 jclass GetTestClass(jvmtiEnv* jvmti, JNIEnv* env) { 87 if (JvmtiErrorToException(env, jvmti, jvmti->RawMonitorEnter(trace_mon))) { 88 return nullptr; 89 } 90 jclass out = reinterpret_cast<jclass>(env->NewLocalRef(test_klass)); 91 if (JvmtiErrorToException(env, jvmti, jvmti->RawMonitorExit(trace_mon))) { 92 return nullptr; 93 } 94 return out; 95 } 96 }; 97 98 static void threadStartCB(jvmtiEnv* jvmti, 99 JNIEnv* jnienv, 100 jthread thread) { 101 TraceData* data = nullptr; 102 if (JvmtiErrorToException(jnienv, jvmti, 103 jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)))) { 104 return; 105 } 106 ScopedLocalRef<jclass> klass(jnienv, data->GetTestClass(jvmti, jnienv)); 107 if (klass.get() == nullptr) { 108 return; 109 } 110 CHECK(data->thread_start != nullptr); 111 jnienv->CallStaticVoidMethod(klass.get(), data->thread_start, thread); 112 } 113 static void threadEndCB(jvmtiEnv* jvmti, 114 JNIEnv* jnienv, 115 jthread thread) { 116 TraceData* data = nullptr; 117 if (JvmtiErrorToException(jnienv, jvmti, 118 jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)))) { 119 return; 120 } 121 ScopedLocalRef<jclass> klass(jnienv, data->GetTestClass(jvmti, jnienv)); 122 if (klass.get() == nullptr) { 123 return; 124 } 125 CHECK(data->thread_end != nullptr); 126 jnienv->CallStaticVoidMethod(klass.get(), data->thread_end, thread); 127 } 128 129 static void singleStepCB(jvmtiEnv* jvmti, 130 JNIEnv* jnienv, 131 jthread thread, 132 jmethodID method, 133 jlocation location) { 134 TraceData* data = nullptr; 135 if (JvmtiErrorToException(jnienv, jvmti, 136 jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)))) { 137 return; 138 } 139 if (IsInCallback(jnienv, jvmti, thread)) { 140 return; 141 } 142 ScopedLocalRef<jclass> klass(jnienv, data->GetTestClass(jvmti, jnienv)); 143 if (klass.get() == nullptr) { 144 return; 145 } 146 CHECK(data->single_step != nullptr); 147 ScopedCallbackState st(jnienv, jvmti, thread); 148 jobject method_arg = GetJavaMethod(jvmti, jnienv, method); 149 jnienv->CallStaticVoidMethod(klass.get(), 150 data->single_step, 151 thread, 152 method_arg, 153 static_cast<jlong>(location)); 154 jnienv->DeleteLocalRef(method_arg); 155 } 156 157 static void fieldAccessCB(jvmtiEnv* jvmti, 158 JNIEnv* jnienv, 159 jthread thr, 160 jmethodID method, 161 jlocation location, 162 jclass field_klass, 163 jobject object, 164 jfieldID field) { 165 TraceData* data = nullptr; 166 if (JvmtiErrorToException(jnienv, jvmti, 167 jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)))) { 168 return; 169 } 170 if (IsInCallback(jnienv, jvmti, thr)) { 171 // Don't do callback for either of these to prevent an infinite loop. 172 return; 173 } 174 ScopedLocalRef<jclass> klass(jnienv, data->GetTestClass(jvmti, jnienv)); 175 if (klass.get() == nullptr) { 176 return; 177 } 178 CHECK(data->field_access != nullptr); 179 ScopedCallbackState st(jnienv, jvmti, thr); 180 jobject method_arg = GetJavaMethod(jvmti, jnienv, method); 181 jobject field_arg = GetJavaField(jvmti, jnienv, field_klass, field); 182 jnienv->CallStaticVoidMethod(klass.get(), 183 data->field_access, 184 method_arg, 185 static_cast<jlong>(location), 186 field_klass, 187 object, 188 field_arg); 189 jnienv->DeleteLocalRef(method_arg); 190 jnienv->DeleteLocalRef(field_arg); 191 } 192 193 static void fieldModificationCB(jvmtiEnv* jvmti, 194 JNIEnv* jnienv, 195 jthread thr, 196 jmethodID method, 197 jlocation location, 198 jclass field_klass, 199 jobject object, 200 jfieldID field, 201 char type_char, 202 jvalue new_value) { 203 TraceData* data = nullptr; 204 if (JvmtiErrorToException(jnienv, jvmti, 205 jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)))) { 206 return; 207 } 208 if (IsInCallback(jnienv, jvmti, thr)) { 209 // Don't do callback recursively to prevent an infinite loop. 210 return; 211 } 212 ScopedLocalRef<jclass> klass(jnienv, data->GetTestClass(jvmti, jnienv)); 213 if (klass.get() == nullptr) { 214 return; 215 } 216 CHECK(data->field_modify != nullptr); 217 ScopedCallbackState st(jnienv, jvmti, thr); 218 jobject method_arg = GetJavaMethod(jvmti, jnienv, method); 219 jobject field_arg = GetJavaField(jvmti, jnienv, field_klass, field); 220 jobject value = GetJavaValueByType(jnienv, type_char, new_value); 221 if (jnienv->ExceptionCheck()) { 222 jnienv->DeleteLocalRef(method_arg); 223 jnienv->DeleteLocalRef(field_arg); 224 return; 225 } 226 jnienv->CallStaticVoidMethod(klass.get(), 227 data->field_modify, 228 method_arg, 229 static_cast<jlong>(location), 230 field_klass, 231 object, 232 field_arg, 233 value); 234 jnienv->DeleteLocalRef(method_arg); 235 jnienv->DeleteLocalRef(field_arg); 236 } 237 238 static void methodExitCB(jvmtiEnv* jvmti, 239 JNIEnv* jnienv, 240 jthread thr, 241 jmethodID method, 242 jboolean was_popped_by_exception, 243 jvalue return_value) { 244 TraceData* data = nullptr; 245 if (JvmtiErrorToException(jnienv, jvmti, 246 jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)))) { 247 return; 248 } 249 if (method == data->exit_method || 250 method == data->enter_method || 251 IsInCallback(jnienv, jvmti, thr)) { 252 // Don't do callback for either of these to prevent an infinite loop. 253 return; 254 } 255 ScopedLocalRef<jclass> klass(jnienv, data->GetTestClass(jvmti, jnienv)); 256 if (klass.get() == nullptr) { 257 return; 258 } 259 CHECK(data->exit_method != nullptr); 260 ScopedCallbackState st(jnienv, jvmti, thr); 261 jobject method_arg = GetJavaMethod(jvmti, jnienv, method); 262 jobject result = 263 was_popped_by_exception ? nullptr : GetJavaValue(jvmti, jnienv, method, return_value); 264 if (jnienv->ExceptionCheck()) { 265 return; 266 } 267 jnienv->CallStaticVoidMethod(klass.get(), 268 data->exit_method, 269 method_arg, 270 was_popped_by_exception, 271 result); 272 jnienv->DeleteLocalRef(method_arg); 273 } 274 275 static void methodEntryCB(jvmtiEnv* jvmti, 276 JNIEnv* jnienv, 277 jthread thr, 278 jmethodID method) { 279 TraceData* data = nullptr; 280 if (JvmtiErrorToException(jnienv, jvmti, 281 jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)))) { 282 return; 283 } 284 CHECK(data->enter_method != nullptr); 285 if (method == data->exit_method || 286 method == data->enter_method || 287 IsInCallback(jnienv, jvmti, thr)) { 288 // Don't do callback for either of these to prevent an infinite loop. 289 return; 290 } 291 ScopedLocalRef<jclass> klass(jnienv, data->GetTestClass(jvmti, jnienv)); 292 if (klass.get() == nullptr) { 293 return; 294 } 295 ScopedCallbackState st(jnienv, jvmti, thr); 296 jobject method_arg = GetJavaMethod(jvmti, jnienv, method); 297 if (jnienv->ExceptionCheck()) { 298 return; 299 } 300 jnienv->CallStaticVoidMethod(klass.get(), data->enter_method, method_arg); 301 jnienv->DeleteLocalRef(method_arg); 302 } 303 304 static void classPrepareCB(jvmtiEnv* jvmti, 305 JNIEnv* jnienv, 306 jthread thr ATTRIBUTE_UNUSED, 307 jclass klass) { 308 TraceData* data = nullptr; 309 if (JvmtiErrorToException(jnienv, jvmti, 310 jvmti->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)))) { 311 return; 312 } 313 if (data->access_watch_on_load || data->modify_watch_on_load) { 314 jint nfields; 315 jfieldID* fields; 316 if (JvmtiErrorToException(jnienv, jvmti, jvmti->GetClassFields(klass, &nfields, &fields))) { 317 return; 318 } 319 for (jint i = 0; i < nfields; i++) { 320 jfieldID f = fields[i]; 321 // Ignore errors 322 if (data->access_watch_on_load) { 323 jvmti->SetFieldAccessWatch(klass, f); 324 } 325 326 if (data->modify_watch_on_load) { 327 jvmti->SetFieldModificationWatch(klass, f); 328 } 329 } 330 jvmti->Deallocate(reinterpret_cast<unsigned char*>(fields)); 331 } 332 } 333 334 extern "C" JNIEXPORT void JNICALL Java_art_Trace_watchAllFieldAccesses(JNIEnv* env) { 335 TraceData* data = nullptr; 336 if (JvmtiErrorToException( 337 env, jvmti_env, jvmti_env->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)))) { 338 return; 339 } 340 data->access_watch_on_load = true; 341 // We need the classPrepareCB to watch new fields as the classes are loaded/prepared. 342 if (JvmtiErrorToException(env, 343 jvmti_env, 344 jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, 345 JVMTI_EVENT_CLASS_PREPARE, 346 nullptr))) { 347 return; 348 } 349 jint nklasses; 350 jclass* klasses; 351 if (JvmtiErrorToException(env, jvmti_env, jvmti_env->GetLoadedClasses(&nklasses, &klasses))) { 352 return; 353 } 354 for (jint i = 0; i < nklasses; i++) { 355 jclass k = klasses[i]; 356 357 jint nfields; 358 jfieldID* fields; 359 jvmtiError err = jvmti_env->GetClassFields(k, &nfields, &fields); 360 if (err == JVMTI_ERROR_CLASS_NOT_PREPARED) { 361 continue; 362 } else if (JvmtiErrorToException(env, jvmti_env, err)) { 363 jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(klasses)); 364 return; 365 } 366 for (jint j = 0; j < nfields; j++) { 367 jvmti_env->SetFieldAccessWatch(k, fields[j]); 368 } 369 jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(fields)); 370 } 371 jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(klasses)); 372 } 373 374 extern "C" JNIEXPORT void JNICALL Java_art_Trace_watchAllFieldModifications(JNIEnv* env) { 375 TraceData* data = nullptr; 376 if (JvmtiErrorToException( 377 env, jvmti_env, jvmti_env->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)))) { 378 return; 379 } 380 data->modify_watch_on_load = true; 381 // We need the classPrepareCB to watch new fields as the classes are loaded/prepared. 382 if (JvmtiErrorToException(env, 383 jvmti_env, 384 jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, 385 JVMTI_EVENT_CLASS_PREPARE, 386 nullptr))) { 387 return; 388 } 389 jint nklasses; 390 jclass* klasses; 391 if (JvmtiErrorToException(env, jvmti_env, jvmti_env->GetLoadedClasses(&nklasses, &klasses))) { 392 return; 393 } 394 for (jint i = 0; i < nklasses; i++) { 395 jclass k = klasses[i]; 396 397 jint nfields; 398 jfieldID* fields; 399 jvmtiError err = jvmti_env->GetClassFields(k, &nfields, &fields); 400 if (err == JVMTI_ERROR_CLASS_NOT_PREPARED) { 401 continue; 402 } else if (JvmtiErrorToException(env, jvmti_env, err)) { 403 jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(klasses)); 404 return; 405 } 406 for (jint j = 0; j < nfields; j++) { 407 jvmti_env->SetFieldModificationWatch(k, fields[j]); 408 } 409 jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(fields)); 410 } 411 jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(klasses)); 412 } 413 414 static bool GetFieldAndClass(JNIEnv* env, 415 jobject ref_field, 416 jclass* out_klass, 417 jfieldID* out_field) { 418 *out_field = env->FromReflectedField(ref_field); 419 if (env->ExceptionCheck()) { 420 return false; 421 } 422 jclass field_klass = env->FindClass("java/lang/reflect/Field"); 423 if (env->ExceptionCheck()) { 424 return false; 425 } 426 jmethodID get_declaring_class_method = 427 env->GetMethodID(field_klass, "getDeclaringClass", "()Ljava/lang/Class;"); 428 if (env->ExceptionCheck()) { 429 env->DeleteLocalRef(field_klass); 430 return false; 431 } 432 *out_klass = static_cast<jclass>(env->CallObjectMethod(ref_field, get_declaring_class_method)); 433 if (env->ExceptionCheck()) { 434 *out_klass = nullptr; 435 env->DeleteLocalRef(field_klass); 436 return false; 437 } 438 env->DeleteLocalRef(field_klass); 439 return true; 440 } 441 442 extern "C" JNIEXPORT void JNICALL Java_art_Trace_watchFieldModification( 443 JNIEnv* env, 444 jclass trace ATTRIBUTE_UNUSED, 445 jobject field_obj) { 446 jfieldID field; 447 jclass klass; 448 if (!GetFieldAndClass(env, field_obj, &klass, &field)) { 449 return; 450 } 451 452 JvmtiErrorToException(env, jvmti_env, jvmti_env->SetFieldModificationWatch(klass, field)); 453 env->DeleteLocalRef(klass); 454 } 455 456 extern "C" JNIEXPORT void JNICALL Java_art_Trace_watchFieldAccess( 457 JNIEnv* env, 458 jclass trace ATTRIBUTE_UNUSED, 459 jobject field_obj) { 460 jfieldID field; 461 jclass klass; 462 if (!GetFieldAndClass(env, field_obj, &klass, &field)) { 463 return; 464 } 465 JvmtiErrorToException(env, jvmti_env, jvmti_env->SetFieldAccessWatch(klass, field)); 466 env->DeleteLocalRef(klass); 467 } 468 469 extern "C" JNIEXPORT void JNICALL Java_art_Trace_enableTracing2( 470 JNIEnv* env, 471 jclass trace ATTRIBUTE_UNUSED, 472 jclass klass, 473 jobject enter, 474 jobject exit, 475 jobject field_access, 476 jobject field_modify, 477 jobject single_step, 478 jobject thread_start, 479 jobject thread_end, 480 jthread thr) { 481 TraceData* data = nullptr; 482 if (JvmtiErrorToException(env, 483 jvmti_env, 484 jvmti_env->Allocate(sizeof(TraceData), 485 reinterpret_cast<unsigned char**>(&data)))) { 486 return; 487 } 488 memset(data, 0, sizeof(TraceData)); 489 if (JvmtiErrorToException(env, jvmti_env, 490 jvmti_env->CreateRawMonitor("Trace monitor", &data->trace_mon))) { 491 return; 492 } 493 data->test_klass = reinterpret_cast<jclass>(env->NewGlobalRef(klass)); 494 data->enter_method = enter != nullptr ? env->FromReflectedMethod(enter) : nullptr; 495 data->exit_method = exit != nullptr ? env->FromReflectedMethod(exit) : nullptr; 496 data->field_access = field_access != nullptr ? env->FromReflectedMethod(field_access) : nullptr; 497 data->field_modify = field_modify != nullptr ? env->FromReflectedMethod(field_modify) : nullptr; 498 data->single_step = single_step != nullptr ? env->FromReflectedMethod(single_step) : nullptr; 499 data->thread_start = thread_start != nullptr ? env->FromReflectedMethod(thread_start) : nullptr; 500 data->thread_end = thread_end != nullptr ? env->FromReflectedMethod(thread_end) : nullptr; 501 502 TraceData* old_data = nullptr; 503 if (JvmtiErrorToException(env, jvmti_env, 504 jvmti_env->GetEnvironmentLocalStorage( 505 reinterpret_cast<void**>(&old_data)))) { 506 return; 507 } else if (old_data != nullptr && old_data->test_klass != nullptr) { 508 ScopedLocalRef<jclass> rt_exception(env, env->FindClass("java/lang/RuntimeException")); 509 env->ThrowNew(rt_exception.get(), "Environment already has local storage set!"); 510 return; 511 } 512 if (JvmtiErrorToException(env, jvmti_env, jvmti_env->SetEnvironmentLocalStorage(data))) { 513 return; 514 } 515 516 current_callbacks.MethodEntry = methodEntryCB; 517 current_callbacks.MethodExit = methodExitCB; 518 current_callbacks.FieldAccess = fieldAccessCB; 519 current_callbacks.FieldModification = fieldModificationCB; 520 current_callbacks.ClassPrepare = classPrepareCB; 521 current_callbacks.SingleStep = singleStepCB; 522 current_callbacks.ThreadStart = threadStartCB; 523 current_callbacks.ThreadEnd = threadEndCB; 524 if (JvmtiErrorToException(env, 525 jvmti_env, 526 jvmti_env->SetEventCallbacks(¤t_callbacks, 527 sizeof(current_callbacks)))) { 528 return; 529 } 530 if (enter != nullptr && 531 JvmtiErrorToException(env, 532 jvmti_env, 533 jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, 534 JVMTI_EVENT_METHOD_ENTRY, 535 thr))) { 536 return; 537 } 538 if (exit != nullptr && 539 JvmtiErrorToException(env, 540 jvmti_env, 541 jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, 542 JVMTI_EVENT_METHOD_EXIT, 543 thr))) { 544 return; 545 } 546 if (field_access != nullptr && 547 JvmtiErrorToException(env, 548 jvmti_env, 549 jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, 550 JVMTI_EVENT_FIELD_ACCESS, 551 thr))) { 552 return; 553 } 554 if (field_modify != nullptr && 555 JvmtiErrorToException(env, 556 jvmti_env, 557 jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, 558 JVMTI_EVENT_FIELD_MODIFICATION, 559 thr))) { 560 return; 561 } 562 if (single_step != nullptr && 563 JvmtiErrorToException(env, 564 jvmti_env, 565 jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, 566 JVMTI_EVENT_SINGLE_STEP, 567 thr))) { 568 return; 569 } 570 if (thread_start != nullptr && 571 JvmtiErrorToException(env, 572 jvmti_env, 573 jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, 574 JVMTI_EVENT_THREAD_START, 575 thr))) { 576 return; 577 } 578 if (thread_end != nullptr && 579 JvmtiErrorToException(env, 580 jvmti_env, 581 jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, 582 JVMTI_EVENT_THREAD_END, 583 thr))) { 584 return; 585 } 586 } 587 588 extern "C" JNIEXPORT void JNICALL Java_art_Trace_enableTracing( 589 JNIEnv* env, 590 jclass trace, 591 jclass klass, 592 jobject enter, 593 jobject exit, 594 jobject field_access, 595 jobject field_modify, 596 jobject single_step, 597 jthread thr) { 598 Java_art_Trace_enableTracing2(env, 599 trace, 600 klass, 601 enter, 602 exit, 603 field_access, 604 field_modify, 605 single_step, 606 /* thread_start */ nullptr, 607 /* thread_end */ nullptr, 608 thr); 609 return; 610 } 611 612 extern "C" JNIEXPORT void JNICALL Java_art_Trace_disableTracing( 613 JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jthread thr) { 614 TraceData* data = nullptr; 615 if (JvmtiErrorToException( 616 env, jvmti_env, jvmti_env->GetEnvironmentLocalStorage(reinterpret_cast<void**>(&data)))) { 617 return; 618 } 619 // If data is null then we haven't ever enabled tracing so we don't need to do anything. 620 if (data == nullptr || data->test_klass == nullptr) { 621 return; 622 } 623 ScopedLocalRef<jthrowable> err(env, nullptr); 624 // First disable all the events. 625 if (JvmtiErrorToException(env, jvmti_env, 626 jvmti_env->SetEventNotificationMode(JVMTI_DISABLE, 627 JVMTI_EVENT_FIELD_ACCESS, 628 thr))) { 629 env->ExceptionDescribe(); 630 err.reset(env->ExceptionOccurred()); 631 env->ExceptionClear(); 632 } 633 if (JvmtiErrorToException(env, jvmti_env, 634 jvmti_env->SetEventNotificationMode(JVMTI_DISABLE, 635 JVMTI_EVENT_FIELD_MODIFICATION, 636 thr))) { 637 env->ExceptionDescribe(); 638 err.reset(env->ExceptionOccurred()); 639 env->ExceptionClear(); 640 } 641 if (JvmtiErrorToException(env, jvmti_env, 642 jvmti_env->SetEventNotificationMode(JVMTI_DISABLE, 643 JVMTI_EVENT_METHOD_ENTRY, 644 thr))) { 645 env->ExceptionDescribe(); 646 err.reset(env->ExceptionOccurred()); 647 env->ExceptionClear(); 648 } 649 if (JvmtiErrorToException(env, jvmti_env, 650 jvmti_env->SetEventNotificationMode(JVMTI_DISABLE, 651 JVMTI_EVENT_METHOD_EXIT, 652 thr))) { 653 env->ExceptionDescribe(); 654 err.reset(env->ExceptionOccurred()); 655 env->ExceptionClear(); 656 } 657 if (JvmtiErrorToException(env, jvmti_env, 658 jvmti_env->SetEventNotificationMode(JVMTI_DISABLE, 659 JVMTI_EVENT_SINGLE_STEP, 660 thr))) { 661 env->ExceptionDescribe(); 662 err.reset(env->ExceptionOccurred()); 663 env->ExceptionClear(); 664 } 665 if (JvmtiErrorToException(env, jvmti_env, 666 jvmti_env->RawMonitorEnter(data->trace_mon))) { 667 return; 668 } 669 // Clear test_klass so we know this isn't being used 670 env->DeleteGlobalRef(data->test_klass); 671 data->test_klass = nullptr; 672 if (JvmtiErrorToException(env, 673 jvmti_env, 674 jvmti_env->RawMonitorExit(data->trace_mon))) { 675 return; 676 } 677 if (err.get() != nullptr) { 678 env->Throw(err.get()); 679 } 680 } 681 682 } // namespace common_trace 683 684 685 } // namespace art 686