1/* Copyright (C) 2017 The Android Open Source Project 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This file implements interfaces from the file jvmti.h. This implementation 5 * is licensed under the same terms as the file jvmti.h. The 6 * copyright and license information for the file jvmti.h follows. 7 * 8 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. 9 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 10 * 11 * This code is free software; you can redistribute it and/or modify it 12 * under the terms of the GNU General Public License version 2 only, as 13 * published by the Free Software Foundation. Oracle designates this 14 * particular file as subject to the "Classpath" exception as provided 15 * by Oracle in the LICENSE file that accompanied this code. 16 * 17 * This code is distributed in the hope that it will be useful, but WITHOUT 18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 20 * version 2 for more details (a copy is included in the LICENSE file that 21 * accompanied this code). 22 * 23 * You should have received a copy of the GNU General Public License version 24 * 2 along with this work; if not, write to the Free Software Foundation, 25 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 26 * 27 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 28 * or visit www.oracle.com if you need additional information or have any 29 * questions. 30 */ 31 32#include "ti_thread.h" 33 34#include "android-base/strings.h" 35#include "art_field-inl.h" 36#include "art_jvmti.h" 37#include "base/logging.h" 38#include "base/mutex.h" 39#include "events-inl.h" 40#include "gc/system_weak.h" 41#include "gc_root-inl.h" 42#include "jni_internal.h" 43#include "mirror/class.h" 44#include "mirror/object-inl.h" 45#include "mirror/string.h" 46#include "obj_ptr.h" 47#include "ti_phase.h" 48#include "runtime.h" 49#include "runtime_callbacks.h" 50#include "ScopedLocalRef.h" 51#include "scoped_thread_state_change-inl.h" 52#include "thread-inl.h" 53#include "thread_list.h" 54#include "well_known_classes.h" 55 56namespace openjdkjvmti { 57 58art::ArtField* ThreadUtil::context_class_loader_ = nullptr; 59 60struct ThreadCallback : public art::ThreadLifecycleCallback, public art::RuntimePhaseCallback { 61 jthread GetThreadObject(art::Thread* self) REQUIRES_SHARED(art::Locks::mutator_lock_) { 62 if (self->GetPeer() == nullptr) { 63 return nullptr; 64 } 65 return self->GetJniEnv()->AddLocalReference<jthread>(self->GetPeer()); 66 } 67 template <ArtJvmtiEvent kEvent> 68 void Post(art::Thread* self) REQUIRES_SHARED(art::Locks::mutator_lock_) { 69 DCHECK_EQ(self, art::Thread::Current()); 70 ScopedLocalRef<jthread> thread(self->GetJniEnv(), GetThreadObject(self)); 71 art::ScopedThreadSuspension sts(self, art::ThreadState::kNative); 72 event_handler->DispatchEvent<kEvent>(self, 73 reinterpret_cast<JNIEnv*>(self->GetJniEnv()), 74 thread.get()); 75 } 76 77 void ThreadStart(art::Thread* self) OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) { 78 if (!started) { 79 // Runtime isn't started. We only expect at most the signal handler or JIT threads to be 80 // started here. 81 if (art::kIsDebugBuild) { 82 std::string name; 83 self->GetThreadName(name); 84 if (name != "JDWP" && 85 name != "Signal Catcher" && 86 !android::base::StartsWith(name, "Jit thread pool")) { 87 LOG(FATAL) << "Unexpected thread before start: " << name; 88 } 89 } 90 return; 91 } 92 Post<ArtJvmtiEvent::kThreadStart>(self); 93 } 94 95 void ThreadDeath(art::Thread* self) OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) { 96 Post<ArtJvmtiEvent::kThreadEnd>(self); 97 } 98 99 void NextRuntimePhase(RuntimePhase phase) OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) { 100 if (phase == RuntimePhase::kInit) { 101 // We moved to VMInit. Report the main thread as started (it was attached early, and must 102 // not be reported until Init. 103 started = true; 104 Post<ArtJvmtiEvent::kThreadStart>(art::Thread::Current()); 105 } 106 } 107 108 EventHandler* event_handler = nullptr; 109 bool started = false; 110}; 111 112ThreadCallback gThreadCallback; 113 114void ThreadUtil::Register(EventHandler* handler) { 115 art::Runtime* runtime = art::Runtime::Current(); 116 117 gThreadCallback.started = runtime->IsStarted(); 118 gThreadCallback.event_handler = handler; 119 120 art::ScopedThreadStateChange stsc(art::Thread::Current(), 121 art::ThreadState::kWaitingForDebuggerToAttach); 122 art::ScopedSuspendAll ssa("Add thread callback"); 123 runtime->GetRuntimeCallbacks()->AddThreadLifecycleCallback(&gThreadCallback); 124 runtime->GetRuntimeCallbacks()->AddRuntimePhaseCallback(&gThreadCallback); 125} 126 127void ThreadUtil::CacheData() { 128 art::ScopedObjectAccess soa(art::Thread::Current()); 129 art::ObjPtr<art::mirror::Class> thread_class = 130 soa.Decode<art::mirror::Class>(art::WellKnownClasses::java_lang_Thread); 131 CHECK(thread_class != nullptr); 132 context_class_loader_ = thread_class->FindDeclaredInstanceField("contextClassLoader", 133 "Ljava/lang/ClassLoader;"); 134 CHECK(context_class_loader_ != nullptr); 135} 136 137void ThreadUtil::Unregister() { 138 art::ScopedThreadStateChange stsc(art::Thread::Current(), 139 art::ThreadState::kWaitingForDebuggerToAttach); 140 art::ScopedSuspendAll ssa("Remove thread callback"); 141 art::Runtime* runtime = art::Runtime::Current(); 142 runtime->GetRuntimeCallbacks()->RemoveThreadLifecycleCallback(&gThreadCallback); 143 runtime->GetRuntimeCallbacks()->RemoveRuntimePhaseCallback(&gThreadCallback); 144} 145 146jvmtiError ThreadUtil::GetCurrentThread(jvmtiEnv* env ATTRIBUTE_UNUSED, jthread* thread_ptr) { 147 art::Thread* self = art::Thread::Current(); 148 149 art::ScopedObjectAccess soa(self); 150 151 jthread thread_peer; 152 if (self->IsStillStarting()) { 153 thread_peer = nullptr; 154 } else { 155 thread_peer = soa.AddLocalReference<jthread>(self->GetPeer()); 156 } 157 158 *thread_ptr = thread_peer; 159 return ERR(NONE); 160} 161 162// Get the native thread. The spec says a null object denotes the current thread. 163static art::Thread* GetNativeThread(jthread thread, 164 const art::ScopedObjectAccessAlreadyRunnable& soa) 165 REQUIRES_SHARED(art::Locks::mutator_lock_) { 166 if (thread == nullptr) { 167 return art::Thread::Current(); 168 } 169 170 art::MutexLock mu(soa.Self(), *art::Locks::thread_list_lock_); 171 return art::Thread::FromManagedThread(soa, thread); 172} 173 174jvmtiError ThreadUtil::GetThreadInfo(jvmtiEnv* env, jthread thread, jvmtiThreadInfo* info_ptr) { 175 if (info_ptr == nullptr) { 176 return ERR(NULL_POINTER); 177 } 178 if (!PhaseUtil::IsLivePhase()) { 179 return JVMTI_ERROR_WRONG_PHASE; 180 } 181 182 art::ScopedObjectAccess soa(art::Thread::Current()); 183 184 art::Thread* self = GetNativeThread(thread, soa); 185 if (self == nullptr && thread == nullptr) { 186 return ERR(INVALID_THREAD); 187 } 188 189 JvmtiUniquePtr<char[]> name_uptr; 190 if (self != nullptr) { 191 // Have a native thread object, this thread is alive. 192 std::string name; 193 self->GetThreadName(name); 194 jvmtiError name_result; 195 name_uptr = CopyString(env, name.c_str(), &name_result); 196 if (name_uptr == nullptr) { 197 return name_result; 198 } 199 info_ptr->name = name_uptr.get(); 200 201 info_ptr->priority = self->GetNativePriority(); 202 203 info_ptr->is_daemon = self->IsDaemon(); 204 205 art::ObjPtr<art::mirror::Object> peer = self->GetPeerFromOtherThread(); 206 207 // ThreadGroup. 208 if (peer != nullptr) { 209 art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_group); 210 CHECK(f != nullptr); 211 art::ObjPtr<art::mirror::Object> group = f->GetObject(peer); 212 info_ptr->thread_group = group == nullptr 213 ? nullptr 214 : soa.AddLocalReference<jthreadGroup>(group); 215 } else { 216 info_ptr->thread_group = nullptr; 217 } 218 219 // Context classloader. 220 DCHECK(context_class_loader_ != nullptr); 221 art::ObjPtr<art::mirror::Object> ccl = peer != nullptr 222 ? context_class_loader_->GetObject(peer) 223 : nullptr; 224 info_ptr->context_class_loader = ccl == nullptr 225 ? nullptr 226 : soa.AddLocalReference<jobject>(ccl); 227 } else { 228 // Only the peer. This thread has either not been started, or is dead. Read things from 229 // the Java side. 230 art::ObjPtr<art::mirror::Object> peer = soa.Decode<art::mirror::Object>(thread); 231 232 // Name. 233 { 234 art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_name); 235 CHECK(f != nullptr); 236 art::ObjPtr<art::mirror::Object> name = f->GetObject(peer); 237 std::string name_cpp; 238 const char* name_cstr; 239 if (name != nullptr) { 240 name_cpp = name->AsString()->ToModifiedUtf8(); 241 name_cstr = name_cpp.c_str(); 242 } else { 243 name_cstr = ""; 244 } 245 jvmtiError name_result; 246 name_uptr = CopyString(env, name_cstr, &name_result); 247 if (name_uptr == nullptr) { 248 return name_result; 249 } 250 info_ptr->name = name_uptr.get(); 251 } 252 253 // Priority. 254 { 255 art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_priority); 256 CHECK(f != nullptr); 257 info_ptr->priority = static_cast<jint>(f->GetInt(peer)); 258 } 259 260 // Daemon. 261 { 262 art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_daemon); 263 CHECK(f != nullptr); 264 info_ptr->is_daemon = f->GetBoolean(peer) == 0 ? JNI_FALSE : JNI_TRUE; 265 } 266 267 // ThreadGroup. 268 { 269 art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_group); 270 CHECK(f != nullptr); 271 art::ObjPtr<art::mirror::Object> group = f->GetObject(peer); 272 info_ptr->thread_group = group == nullptr 273 ? nullptr 274 : soa.AddLocalReference<jthreadGroup>(group); 275 } 276 277 // Context classloader. 278 DCHECK(context_class_loader_ != nullptr); 279 art::ObjPtr<art::mirror::Object> ccl = peer != nullptr 280 ? context_class_loader_->GetObject(peer) 281 : nullptr; 282 info_ptr->context_class_loader = ccl == nullptr 283 ? nullptr 284 : soa.AddLocalReference<jobject>(ccl); 285 } 286 287 name_uptr.release(); 288 289 return ERR(NONE); 290} 291 292// Return the thread's (or current thread, if null) thread state. Return kStarting in case 293// there's no native counterpart (thread hasn't been started, yet, or is dead). 294static art::ThreadState GetNativeThreadState(jthread thread, 295 const art::ScopedObjectAccessAlreadyRunnable& soa, 296 art::Thread** native_thread) 297 REQUIRES_SHARED(art::Locks::mutator_lock_) { 298 art::Thread* self = nullptr; 299 art::MutexLock mu(soa.Self(), *art::Locks::thread_list_lock_); 300 if (thread == nullptr) { 301 self = art::Thread::Current(); 302 } else { 303 self = art::Thread::FromManagedThread(soa, thread); 304 } 305 *native_thread = self; 306 if (self == nullptr || self->IsStillStarting()) { 307 return art::ThreadState::kStarting; 308 } 309 return self->GetState(); 310} 311 312static jint GetJvmtiThreadStateFromInternal(art::ThreadState internal_thread_state) { 313 jint jvmti_state = JVMTI_THREAD_STATE_ALIVE; 314 315 if (internal_thread_state == art::ThreadState::kSuspended) { 316 jvmti_state |= JVMTI_THREAD_STATE_SUSPENDED; 317 // Note: We do not have data about the previous state. Otherwise we should load the previous 318 // state here. 319 } 320 321 if (internal_thread_state == art::ThreadState::kNative) { 322 jvmti_state |= JVMTI_THREAD_STATE_IN_NATIVE; 323 } 324 325 if (internal_thread_state == art::ThreadState::kRunnable || 326 internal_thread_state == art::ThreadState::kWaitingWeakGcRootRead || 327 internal_thread_state == art::ThreadState::kSuspended) { 328 jvmti_state |= JVMTI_THREAD_STATE_RUNNABLE; 329 } else if (internal_thread_state == art::ThreadState::kBlocked) { 330 jvmti_state |= JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER; 331 } else { 332 // Should be in waiting state. 333 jvmti_state |= JVMTI_THREAD_STATE_WAITING; 334 335 if (internal_thread_state == art::ThreadState::kTimedWaiting || 336 internal_thread_state == art::ThreadState::kSleeping) { 337 jvmti_state |= JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT; 338 } else { 339 jvmti_state |= JVMTI_THREAD_STATE_WAITING_INDEFINITELY; 340 } 341 342 if (internal_thread_state == art::ThreadState::kSleeping) { 343 jvmti_state |= JVMTI_THREAD_STATE_SLEEPING; 344 } 345 346 if (internal_thread_state == art::ThreadState::kTimedWaiting || 347 internal_thread_state == art::ThreadState::kWaiting) { 348 jvmti_state |= JVMTI_THREAD_STATE_IN_OBJECT_WAIT; 349 } 350 351 // TODO: PARKED. We'll have to inspect the stack. 352 } 353 354 return jvmti_state; 355} 356 357static jint GetJavaStateFromInternal(art::ThreadState internal_thread_state) { 358 switch (internal_thread_state) { 359 case art::ThreadState::kTerminated: 360 return JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED; 361 362 case art::ThreadState::kRunnable: 363 case art::ThreadState::kNative: 364 case art::ThreadState::kWaitingWeakGcRootRead: 365 case art::ThreadState::kSuspended: 366 return JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE; 367 368 case art::ThreadState::kTimedWaiting: 369 case art::ThreadState::kSleeping: 370 return JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING; 371 372 case art::ThreadState::kBlocked: 373 return JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED; 374 375 case art::ThreadState::kStarting: 376 return JVMTI_JAVA_LANG_THREAD_STATE_NEW; 377 378 case art::ThreadState::kWaiting: 379 case art::ThreadState::kWaitingForGcToComplete: 380 case art::ThreadState::kWaitingPerformingGc: 381 case art::ThreadState::kWaitingForCheckPointsToRun: 382 case art::ThreadState::kWaitingForDebuggerSend: 383 case art::ThreadState::kWaitingForDebuggerToAttach: 384 case art::ThreadState::kWaitingInMainDebuggerLoop: 385 case art::ThreadState::kWaitingForDebuggerSuspension: 386 case art::ThreadState::kWaitingForDeoptimization: 387 case art::ThreadState::kWaitingForGetObjectsAllocated: 388 case art::ThreadState::kWaitingForJniOnLoad: 389 case art::ThreadState::kWaitingForSignalCatcherOutput: 390 case art::ThreadState::kWaitingInMainSignalCatcherLoop: 391 case art::ThreadState::kWaitingForMethodTracingStart: 392 case art::ThreadState::kWaitingForVisitObjects: 393 case art::ThreadState::kWaitingForGcThreadFlip: 394 return JVMTI_JAVA_LANG_THREAD_STATE_WAITING; 395 } 396 LOG(FATAL) << "Unreachable"; 397 UNREACHABLE(); 398} 399 400jvmtiError ThreadUtil::GetThreadState(jvmtiEnv* env ATTRIBUTE_UNUSED, 401 jthread thread, 402 jint* thread_state_ptr) { 403 if (thread_state_ptr == nullptr) { 404 return ERR(NULL_POINTER); 405 } 406 407 art::ScopedObjectAccess soa(art::Thread::Current()); 408 art::Thread* native_thread = nullptr; 409 art::ThreadState internal_thread_state = GetNativeThreadState(thread, soa, &native_thread); 410 411 if (internal_thread_state == art::ThreadState::kStarting) { 412 if (thread == nullptr) { 413 // No native thread, and no Java thread? We must be starting up. Report as wrong phase. 414 return ERR(WRONG_PHASE); 415 } 416 417 // Need to read the Java "started" field to know whether this is starting or terminated. 418 art::ObjPtr<art::mirror::Object> peer = soa.Decode<art::mirror::Object>(thread); 419 art::ObjPtr<art::mirror::Class> klass = peer->GetClass(); 420 art::ArtField* started_field = klass->FindDeclaredInstanceField("started", "Z"); 421 CHECK(started_field != nullptr); 422 bool started = started_field->GetBoolean(peer) != 0; 423 constexpr jint kStartedState = JVMTI_JAVA_LANG_THREAD_STATE_NEW; 424 constexpr jint kTerminatedState = JVMTI_THREAD_STATE_TERMINATED | 425 JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED; 426 *thread_state_ptr = started ? kTerminatedState : kStartedState; 427 return ERR(NONE); 428 } 429 DCHECK(native_thread != nullptr); 430 431 // Translate internal thread state to JVMTI and Java state. 432 jint jvmti_state = GetJvmtiThreadStateFromInternal(internal_thread_state); 433 if (native_thread->IsInterrupted()) { 434 jvmti_state |= JVMTI_THREAD_STATE_INTERRUPTED; 435 } 436 437 // Java state is derived from nativeGetState. 438 // Note: Our implementation assigns "runnable" to suspended. As such, we will have slightly 439 // different mask. However, this is for consistency with the Java view. 440 jint java_state = GetJavaStateFromInternal(internal_thread_state); 441 442 *thread_state_ptr = jvmti_state | java_state; 443 444 return ERR(NONE); 445} 446 447jvmtiError ThreadUtil::GetAllThreads(jvmtiEnv* env, 448 jint* threads_count_ptr, 449 jthread** threads_ptr) { 450 if (threads_count_ptr == nullptr || threads_ptr == nullptr) { 451 return ERR(NULL_POINTER); 452 } 453 454 art::Thread* current = art::Thread::Current(); 455 456 art::ScopedObjectAccess soa(current); 457 458 art::MutexLock mu(current, *art::Locks::thread_list_lock_); 459 std::list<art::Thread*> thread_list = art::Runtime::Current()->GetThreadList()->GetList(); 460 461 std::vector<art::ObjPtr<art::mirror::Object>> peers; 462 463 for (art::Thread* thread : thread_list) { 464 // Skip threads that are still starting. 465 if (thread->IsStillStarting()) { 466 continue; 467 } 468 469 art::ObjPtr<art::mirror::Object> peer = thread->GetPeerFromOtherThread(); 470 if (peer != nullptr) { 471 peers.push_back(peer); 472 } 473 } 474 475 if (peers.empty()) { 476 *threads_count_ptr = 0; 477 *threads_ptr = nullptr; 478 } else { 479 unsigned char* data; 480 jvmtiError data_result = env->Allocate(peers.size() * sizeof(jthread), &data); 481 if (data_result != ERR(NONE)) { 482 return data_result; 483 } 484 jthread* threads = reinterpret_cast<jthread*>(data); 485 for (size_t i = 0; i != peers.size(); ++i) { 486 threads[i] = soa.AddLocalReference<jthread>(peers[i]); 487 } 488 489 *threads_count_ptr = static_cast<jint>(peers.size()); 490 *threads_ptr = threads; 491 } 492 return ERR(NONE); 493} 494 495jvmtiError ThreadUtil::SetThreadLocalStorage(jvmtiEnv* env ATTRIBUTE_UNUSED, 496 jthread thread, 497 const void* data) { 498 art::ScopedObjectAccess soa(art::Thread::Current()); 499 art::Thread* self = GetNativeThread(thread, soa); 500 if (self == nullptr && thread == nullptr) { 501 return ERR(INVALID_THREAD); 502 } 503 if (self == nullptr) { 504 return ERR(THREAD_NOT_ALIVE); 505 } 506 507 self->SetCustomTLS(data); 508 509 return ERR(NONE); 510} 511 512jvmtiError ThreadUtil::GetThreadLocalStorage(jvmtiEnv* env ATTRIBUTE_UNUSED, 513 jthread thread, 514 void** data_ptr) { 515 if (data_ptr == nullptr) { 516 return ERR(NULL_POINTER); 517 } 518 519 art::ScopedObjectAccess soa(art::Thread::Current()); 520 art::Thread* self = GetNativeThread(thread, soa); 521 if (self == nullptr && thread == nullptr) { 522 return ERR(INVALID_THREAD); 523 } 524 if (self == nullptr) { 525 return ERR(THREAD_NOT_ALIVE); 526 } 527 528 *data_ptr = const_cast<void*>(self->GetCustomTLS()); 529 return ERR(NONE); 530} 531 532struct AgentData { 533 const void* arg; 534 jvmtiStartFunction proc; 535 jthread thread; 536 JavaVM* java_vm; 537 jvmtiEnv* jvmti_env; 538 jint priority; 539}; 540 541static void* AgentCallback(void* arg) { 542 std::unique_ptr<AgentData> data(reinterpret_cast<AgentData*>(arg)); 543 CHECK(data->thread != nullptr); 544 545 // We already have a peer. So call our special Attach function. 546 art::Thread* self = art::Thread::Attach("JVMTI Agent thread", true, data->thread); 547 CHECK(self != nullptr); 548 // The name in Attach() is only for logging. Set the thread name. This is important so 549 // that the thread is no longer seen as starting up. 550 { 551 art::ScopedObjectAccess soa(self); 552 self->SetThreadName("JVMTI Agent thread"); 553 } 554 555 // Release the peer. 556 JNIEnv* env = self->GetJniEnv(); 557 env->DeleteGlobalRef(data->thread); 558 data->thread = nullptr; 559 560 // Run the agent code. 561 data->proc(data->jvmti_env, env, const_cast<void*>(data->arg)); 562 563 // Detach the thread. 564 int detach_result = data->java_vm->DetachCurrentThread(); 565 CHECK_EQ(detach_result, 0); 566 567 return nullptr; 568} 569 570jvmtiError ThreadUtil::RunAgentThread(jvmtiEnv* jvmti_env, 571 jthread thread, 572 jvmtiStartFunction proc, 573 const void* arg, 574 jint priority) { 575 if (priority < JVMTI_THREAD_MIN_PRIORITY || priority > JVMTI_THREAD_MAX_PRIORITY) { 576 return ERR(INVALID_PRIORITY); 577 } 578 JNIEnv* env = art::Thread::Current()->GetJniEnv(); 579 if (thread == nullptr || !env->IsInstanceOf(thread, art::WellKnownClasses::java_lang_Thread)) { 580 return ERR(INVALID_THREAD); 581 } 582 if (proc == nullptr) { 583 return ERR(NULL_POINTER); 584 } 585 586 std::unique_ptr<AgentData> data(new AgentData); 587 data->arg = arg; 588 data->proc = proc; 589 // We need a global ref for Java objects, as local refs will be invalid. 590 data->thread = env->NewGlobalRef(thread); 591 data->java_vm = art::Runtime::Current()->GetJavaVM(); 592 data->jvmti_env = jvmti_env; 593 data->priority = priority; 594 595 pthread_t pthread; 596 int pthread_create_result = pthread_create(&pthread, 597 nullptr, 598 &AgentCallback, 599 reinterpret_cast<void*>(data.get())); 600 if (pthread_create_result != 0) { 601 return ERR(INTERNAL); 602 } 603 data.release(); 604 605 return ERR(NONE); 606} 607 608} // namespace openjdkjvmti 609