blob: 2bcdd8cda1b02c974957ee137a9acaf50e25fc7c [file] [log] [blame]
Andreas Gampeaf13ab92017-01-11 20:57:40 -08001/* 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 "art_field.h"
35#include "art_jvmti.h"
36#include "base/logging.h"
37#include "base/mutex.h"
Andreas Gampef26bf2d2017-01-13 16:47:14 -080038#include "gc/system_weak.h"
39#include "gc_root-inl.h"
Andreas Gampeaf13ab92017-01-11 20:57:40 -080040#include "jni_internal.h"
41#include "mirror/class.h"
42#include "mirror/object-inl.h"
43#include "mirror/string.h"
44#include "obj_ptr.h"
Andreas Gampef26bf2d2017-01-13 16:47:14 -080045#include "runtime.h"
Andreas Gampeaf13ab92017-01-11 20:57:40 -080046#include "scoped_thread_state_change-inl.h"
47#include "thread-inl.h"
Andreas Gampe85807442017-01-13 14:40:58 -080048#include "thread_list.h"
Andreas Gampeaf13ab92017-01-11 20:57:40 -080049#include "well_known_classes.h"
50
51namespace openjdkjvmti {
52
53jvmtiError ThreadUtil::GetCurrentThread(jvmtiEnv* env ATTRIBUTE_UNUSED, jthread* thread_ptr) {
54 art::Thread* self = art::Thread::Current();
55
56 art::ScopedObjectAccess soa(self);
57
58 jthread thread_peer;
59 if (self->IsStillStarting()) {
60 thread_peer = nullptr;
61 } else {
62 thread_peer = soa.AddLocalReference<jthread>(self->GetPeer());
63 }
64
65 *thread_ptr = thread_peer;
66 return ERR(NONE);
67}
68
69// Read the context classloader from a Java thread object. This is a lazy implementation
70// that assumes GetThreadInfo isn't called too often. If we instead cache the ArtField,
71// we will have to add synchronization as this can't be cached on startup (which is
72// potentially runtime startup).
73static art::ObjPtr<art::mirror::Object> GetContextClassLoader(art::ObjPtr<art::mirror::Object> peer)
74 REQUIRES_SHARED(art::Locks::mutator_lock_) {
75 if (peer == nullptr) {
76 return nullptr;
77 }
78 art::ObjPtr<art::mirror::Class> klass = peer->GetClass();
79 art::ArtField* cc_field = klass->FindDeclaredInstanceField("contextClassLoader",
80 "Ljava/lang/ClassLoader;");
81 CHECK(cc_field != nullptr);
82 return cc_field->GetObject(peer);
83}
84
85// Get the native thread. The spec says a null object denotes the current thread.
86static art::Thread* GetNativeThread(jthread thread,
87 const art::ScopedObjectAccessAlreadyRunnable& soa)
88 REQUIRES_SHARED(art::Locks::mutator_lock_) {
89 if (thread == nullptr) {
90 return art::Thread::Current();
91 }
92
93 art::MutexLock mu(soa.Self(), *art::Locks::thread_list_lock_);
94 return art::Thread::FromManagedThread(soa, thread);
95}
96
97jvmtiError ThreadUtil::GetThreadInfo(jvmtiEnv* env, jthread thread, jvmtiThreadInfo* info_ptr) {
98 if (info_ptr == nullptr) {
99 return ERR(NULL_POINTER);
100 }
101
102 art::ScopedObjectAccess soa(art::Thread::Current());
103
104 art::Thread* self = GetNativeThread(thread, soa);
105 if (self == nullptr && thread == nullptr) {
106 return ERR(INVALID_THREAD);
107 }
108
109 JvmtiUniquePtr name_uptr;
110 if (self != nullptr) {
111 // Have a native thread object, this thread is alive.
112 std::string name;
113 self->GetThreadName(name);
114 jvmtiError name_result = CopyString(
115 env, name.c_str(), reinterpret_cast<unsigned char**>(&info_ptr->name));
116 if (name_result != ERR(NONE)) {
117 return name_result;
118 }
119 name_uptr = MakeJvmtiUniquePtr(env, info_ptr->name);
120
121 info_ptr->priority = self->GetNativePriority();
122
123 info_ptr->is_daemon = self->IsDaemon();
124
125 art::ObjPtr<art::mirror::Object> peer = self->GetPeer();
126
127 // ThreadGroup.
128 if (peer != nullptr) {
129 art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_group);
130 CHECK(f != nullptr);
131 art::ObjPtr<art::mirror::Object> group = f->GetObject(peer);
132 info_ptr->thread_group = group == nullptr
133 ? nullptr
134 : soa.AddLocalReference<jthreadGroup>(group);
135 } else {
136 info_ptr->thread_group = nullptr;
137 }
138
139 // Context classloader.
140 art::ObjPtr<art::mirror::Object> ccl = GetContextClassLoader(peer);
141 info_ptr->context_class_loader = ccl == nullptr
142 ? nullptr
143 : soa.AddLocalReference<jobject>(ccl);
144 } else {
145 // Only the peer. This thread has either not been started, or is dead. Read things from
146 // the Java side.
147 art::ObjPtr<art::mirror::Object> peer = soa.Decode<art::mirror::Object>(thread);
148
149 // Name.
150 {
151 art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_name);
152 CHECK(f != nullptr);
153 art::ObjPtr<art::mirror::Object> name = f->GetObject(peer);
154 std::string name_cpp;
155 const char* name_cstr;
156 if (name != nullptr) {
157 name_cpp = name->AsString()->ToModifiedUtf8();
158 name_cstr = name_cpp.c_str();
159 } else {
160 name_cstr = "";
161 }
162 jvmtiError name_result = CopyString(
163 env, name_cstr, reinterpret_cast<unsigned char**>(&info_ptr->name));
164 if (name_result != ERR(NONE)) {
165 return name_result;
166 }
167 name_uptr = MakeJvmtiUniquePtr(env, info_ptr->name);
168 }
169
170 // Priority.
171 {
172 art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_priority);
173 CHECK(f != nullptr);
174 info_ptr->priority = static_cast<jint>(f->GetInt(peer));
175 }
176
177 // Daemon.
178 {
179 art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_daemon);
180 CHECK(f != nullptr);
181 info_ptr->is_daemon = f->GetBoolean(peer) == 0 ? JNI_FALSE : JNI_TRUE;
182 }
183
184 // ThreadGroup.
185 {
186 art::ArtField* f = art::jni::DecodeArtField(art::WellKnownClasses::java_lang_Thread_group);
187 CHECK(f != nullptr);
188 art::ObjPtr<art::mirror::Object> group = f->GetObject(peer);
189 info_ptr->thread_group = group == nullptr
190 ? nullptr
191 : soa.AddLocalReference<jthreadGroup>(group);
192 }
193
194 // Context classloader.
195 art::ObjPtr<art::mirror::Object> ccl = GetContextClassLoader(peer);
196 info_ptr->context_class_loader = ccl == nullptr
197 ? nullptr
198 : soa.AddLocalReference<jobject>(ccl);
199 }
200
201 name_uptr.release();
202
203 return ERR(NONE);
204}
205
Andreas Gampe72c19832017-01-12 13:22:16 -0800206// Return the thread's (or current thread, if null) thread state. Return kStarting in case
207// there's no native counterpart (thread hasn't been started, yet, or is dead).
208static art::ThreadState GetNativeThreadState(jthread thread,
209 const art::ScopedObjectAccessAlreadyRunnable& soa,
210 art::Thread** native_thread)
211 REQUIRES_SHARED(art::Locks::mutator_lock_) {
212 art::Thread* self = nullptr;
213 art::MutexLock mu(soa.Self(), *art::Locks::thread_list_lock_);
214 if (thread == nullptr) {
215 self = art::Thread::Current();
216 } else {
217 self = art::Thread::FromManagedThread(soa, thread);
218 }
219 *native_thread = self;
220 if (self == nullptr || self->IsStillStarting()) {
221 return art::ThreadState::kStarting;
222 }
223 return self->GetState();
224}
225
226static jint GetJvmtiThreadStateFromInternal(art::ThreadState internal_thread_state) {
227 jint jvmti_state = JVMTI_THREAD_STATE_ALIVE;
228
229 if (internal_thread_state == art::ThreadState::kSuspended) {
230 jvmti_state |= JVMTI_THREAD_STATE_SUSPENDED;
231 // Note: We do not have data about the previous state. Otherwise we should load the previous
232 // state here.
233 }
234
235 if (internal_thread_state == art::ThreadState::kNative) {
236 jvmti_state |= JVMTI_THREAD_STATE_IN_NATIVE;
237 }
238
239 if (internal_thread_state == art::ThreadState::kRunnable ||
240 internal_thread_state == art::ThreadState::kWaitingWeakGcRootRead ||
241 internal_thread_state == art::ThreadState::kSuspended) {
242 jvmti_state |= JVMTI_THREAD_STATE_RUNNABLE;
243 } else if (internal_thread_state == art::ThreadState::kBlocked) {
244 jvmti_state |= JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER;
245 } else {
246 // Should be in waiting state.
247 jvmti_state |= JVMTI_THREAD_STATE_WAITING;
248
249 if (internal_thread_state == art::ThreadState::kTimedWaiting ||
250 internal_thread_state == art::ThreadState::kSleeping) {
251 jvmti_state |= JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT;
252 } else {
253 jvmti_state |= JVMTI_THREAD_STATE_WAITING_INDEFINITELY;
254 }
255
256 if (internal_thread_state == art::ThreadState::kSleeping) {
257 jvmti_state |= JVMTI_THREAD_STATE_SLEEPING;
258 }
259
260 if (internal_thread_state == art::ThreadState::kTimedWaiting ||
261 internal_thread_state == art::ThreadState::kWaiting) {
262 jvmti_state |= JVMTI_THREAD_STATE_IN_OBJECT_WAIT;
263 }
264
265 // TODO: PARKED. We'll have to inspect the stack.
266 }
267
268 return jvmti_state;
269}
270
271static jint GetJavaStateFromInternal(art::ThreadState internal_thread_state) {
272 switch (internal_thread_state) {
273 case art::ThreadState::kTerminated:
274 return JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED;
275
276 case art::ThreadState::kRunnable:
277 case art::ThreadState::kNative:
278 case art::ThreadState::kWaitingWeakGcRootRead:
279 case art::ThreadState::kSuspended:
280 return JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE;
281
282 case art::ThreadState::kTimedWaiting:
283 case art::ThreadState::kSleeping:
284 return JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING;
285
286 case art::ThreadState::kBlocked:
287 return JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED;
288
289 case art::ThreadState::kStarting:
290 return JVMTI_JAVA_LANG_THREAD_STATE_NEW;
291
292 case art::ThreadState::kWaiting:
293 case art::ThreadState::kWaitingForGcToComplete:
294 case art::ThreadState::kWaitingPerformingGc:
295 case art::ThreadState::kWaitingForCheckPointsToRun:
296 case art::ThreadState::kWaitingForDebuggerSend:
297 case art::ThreadState::kWaitingForDebuggerToAttach:
298 case art::ThreadState::kWaitingInMainDebuggerLoop:
299 case art::ThreadState::kWaitingForDebuggerSuspension:
300 case art::ThreadState::kWaitingForDeoptimization:
301 case art::ThreadState::kWaitingForGetObjectsAllocated:
302 case art::ThreadState::kWaitingForJniOnLoad:
303 case art::ThreadState::kWaitingForSignalCatcherOutput:
304 case art::ThreadState::kWaitingInMainSignalCatcherLoop:
305 case art::ThreadState::kWaitingForMethodTracingStart:
306 case art::ThreadState::kWaitingForVisitObjects:
307 case art::ThreadState::kWaitingForGcThreadFlip:
308 return JVMTI_JAVA_LANG_THREAD_STATE_WAITING;
309 }
310 LOG(FATAL) << "Unreachable";
311 UNREACHABLE();
312}
313
314jvmtiError ThreadUtil::GetThreadState(jvmtiEnv* env ATTRIBUTE_UNUSED,
315 jthread thread,
316 jint* thread_state_ptr) {
317 if (thread_state_ptr == nullptr) {
318 return ERR(NULL_POINTER);
319 }
320
321 art::ScopedObjectAccess soa(art::Thread::Current());
322 art::Thread* native_thread = nullptr;
323 art::ThreadState internal_thread_state = GetNativeThreadState(thread, soa, &native_thread);
324
325 if (internal_thread_state == art::ThreadState::kStarting) {
326 if (thread == nullptr) {
327 // No native thread, and no Java thread? We must be starting up. Report as wrong phase.
328 return ERR(WRONG_PHASE);
329 }
330
331 // Need to read the Java "started" field to know whether this is starting or terminated.
332 art::ObjPtr<art::mirror::Object> peer = soa.Decode<art::mirror::Object>(thread);
333 art::ObjPtr<art::mirror::Class> klass = peer->GetClass();
334 art::ArtField* started_field = klass->FindDeclaredInstanceField("started", "Z");
335 CHECK(started_field != nullptr);
336 bool started = started_field->GetBoolean(peer) != 0;
337 constexpr jint kStartedState = JVMTI_JAVA_LANG_THREAD_STATE_NEW;
338 constexpr jint kTerminatedState = JVMTI_THREAD_STATE_TERMINATED |
339 JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED;
340 *thread_state_ptr = started ? kTerminatedState : kStartedState;
341 return ERR(NONE);
342 }
343 DCHECK(native_thread != nullptr);
344
345 // Translate internal thread state to JVMTI and Java state.
346 jint jvmti_state = GetJvmtiThreadStateFromInternal(internal_thread_state);
347 if (native_thread->IsInterrupted()) {
348 jvmti_state |= JVMTI_THREAD_STATE_INTERRUPTED;
349 }
350
351 // Java state is derived from nativeGetState.
352 // Note: Our implementation assigns "runnable" to suspended. As such, we will have slightly
353 // different mask. However, this is for consistency with the Java view.
354 jint java_state = GetJavaStateFromInternal(internal_thread_state);
355
356 *thread_state_ptr = jvmti_state | java_state;
357
358 return ERR(NONE);
359}
360
Andreas Gampe85807442017-01-13 14:40:58 -0800361jvmtiError ThreadUtil::GetAllThreads(jvmtiEnv* env,
362 jint* threads_count_ptr,
363 jthread** threads_ptr) {
364 if (threads_count_ptr == nullptr || threads_ptr == nullptr) {
365 return ERR(NULL_POINTER);
366 }
367
368 art::Thread* current = art::Thread::Current();
369
370 art::ScopedObjectAccess soa(current);
371
372 art::MutexLock mu(current, *art::Locks::thread_list_lock_);
373 std::list<art::Thread*> thread_list = art::Runtime::Current()->GetThreadList()->GetList();
374
375 std::vector<art::ObjPtr<art::mirror::Object>> peers;
376
377 for (art::Thread* thread : thread_list) {
378 // Skip threads that are still starting.
379 if (thread->IsStillStarting()) {
380 continue;
381 }
382
383 art::ObjPtr<art::mirror::Object> peer = thread->GetPeer();
384 if (peer != nullptr) {
385 peers.push_back(peer);
386 }
387 }
388
389 if (peers.empty()) {
390 *threads_count_ptr = 0;
391 *threads_ptr = nullptr;
392 } else {
393 unsigned char* data;
394 jvmtiError data_result = env->Allocate(peers.size() * sizeof(jthread), &data);
395 if (data_result != ERR(NONE)) {
396 return data_result;
397 }
398 jthread* threads = reinterpret_cast<jthread*>(data);
399 for (size_t i = 0; i != peers.size(); ++i) {
400 threads[i] = soa.AddLocalReference<jthread>(peers[i]);
401 }
402
403 *threads_count_ptr = static_cast<jint>(peers.size());
404 *threads_ptr = threads;
405 }
Andreas Gampef26bf2d2017-01-13 16:47:14 -0800406 return ERR(NONE);
407}
Andreas Gampe85807442017-01-13 14:40:58 -0800408
Andreas Gampef26bf2d2017-01-13 16:47:14 -0800409jvmtiError ThreadUtil::SetThreadLocalStorage(jvmtiEnv* env ATTRIBUTE_UNUSED,
410 jthread thread,
411 const void* data) {
412 art::ScopedObjectAccess soa(art::Thread::Current());
413 art::Thread* self = GetNativeThread(thread, soa);
414 if (self == nullptr && thread == nullptr) {
415 return ERR(INVALID_THREAD);
416 }
417 if (self == nullptr) {
418 return ERR(THREAD_NOT_ALIVE);
419 }
420
421 self->SetCustomTLS(data);
422
423 return ERR(NONE);
424}
425
426jvmtiError ThreadUtil::GetThreadLocalStorage(jvmtiEnv* env ATTRIBUTE_UNUSED,
427 jthread thread,
428 void** data_ptr) {
429 if (data_ptr == nullptr) {
430 return ERR(NULL_POINTER);
431 }
432
433 art::ScopedObjectAccess soa(art::Thread::Current());
434 art::Thread* self = GetNativeThread(thread, soa);
435 if (self == nullptr && thread == nullptr) {
436 return ERR(INVALID_THREAD);
437 }
438 if (self == nullptr) {
439 return ERR(THREAD_NOT_ALIVE);
440 }
441
442 *data_ptr = const_cast<void*>(self->GetCustomTLS());
Andreas Gampe85807442017-01-13 14:40:58 -0800443 return ERR(NONE);
444}
445
Andreas Gampeaf13ab92017-01-11 20:57:40 -0800446} // namespace openjdkjvmti