1 /* Copyright (C) 2016 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 "events-inl.h" 33 34 #include "art_jvmti.h" 35 #include "base/logging.h" 36 #include "gc/allocation_listener.h" 37 #include "gc/gc_pause_listener.h" 38 #include "gc/heap.h" 39 #include "handle_scope-inl.h" 40 #include "instrumentation.h" 41 #include "jni_env_ext-inl.h" 42 #include "mirror/class.h" 43 #include "mirror/object-inl.h" 44 #include "runtime.h" 45 #include "ScopedLocalRef.h" 46 #include "scoped_thread_state_change-inl.h" 47 #include "thread-inl.h" 48 49 namespace openjdkjvmti { 50 51 bool EventMasks::IsEnabledAnywhere(ArtJvmtiEvent event) { 52 return global_event_mask.Test(event) || unioned_thread_event_mask.Test(event); 53 } 54 55 EventMask& EventMasks::GetEventMask(art::Thread* thread) { 56 if (thread == nullptr) { 57 return global_event_mask; 58 } 59 60 for (auto& pair : thread_event_masks) { 61 const UniqueThread& unique_thread = pair.first; 62 if (unique_thread.first == thread && 63 unique_thread.second == static_cast<uint32_t>(thread->GetTid())) { 64 return pair.second; 65 } 66 } 67 68 // TODO: Remove old UniqueThread with the same pointer, if exists. 69 70 thread_event_masks.emplace_back(UniqueThread(thread, thread->GetTid()), EventMask()); 71 return thread_event_masks.back().second; 72 } 73 74 EventMask* EventMasks::GetEventMaskOrNull(art::Thread* thread) { 75 if (thread == nullptr) { 76 return &global_event_mask; 77 } 78 79 for (auto& pair : thread_event_masks) { 80 const UniqueThread& unique_thread = pair.first; 81 if (unique_thread.first == thread && 82 unique_thread.second == static_cast<uint32_t>(thread->GetTid())) { 83 return &pair.second; 84 } 85 } 86 87 return nullptr; 88 } 89 90 91 void EventMasks::EnableEvent(art::Thread* thread, ArtJvmtiEvent event) { 92 DCHECK(EventMask::EventIsInRange(event)); 93 GetEventMask(thread).Set(event); 94 if (thread != nullptr) { 95 unioned_thread_event_mask.Set(event, true); 96 } 97 } 98 99 void EventMasks::DisableEvent(art::Thread* thread, ArtJvmtiEvent event) { 100 DCHECK(EventMask::EventIsInRange(event)); 101 GetEventMask(thread).Set(event, false); 102 if (thread != nullptr) { 103 // Regenerate union for the event. 104 bool union_value = false; 105 for (auto& pair : thread_event_masks) { 106 union_value |= pair.second.Test(event); 107 if (union_value) { 108 break; 109 } 110 } 111 unioned_thread_event_mask.Set(event, union_value); 112 } 113 } 114 115 void EventMasks::HandleChangedCapabilities(const jvmtiCapabilities& caps, bool caps_added) { 116 if (UNLIKELY(caps.can_retransform_classes == 1)) { 117 // If we are giving this env the retransform classes cap we need to switch all events of 118 // NonTransformable to Transformable and vice versa. 119 ArtJvmtiEvent to_remove = caps_added ? ArtJvmtiEvent::kClassFileLoadHookNonRetransformable 120 : ArtJvmtiEvent::kClassFileLoadHookRetransformable; 121 ArtJvmtiEvent to_add = caps_added ? ArtJvmtiEvent::kClassFileLoadHookRetransformable 122 : ArtJvmtiEvent::kClassFileLoadHookNonRetransformable; 123 if (global_event_mask.Test(to_remove)) { 124 CHECK(!global_event_mask.Test(to_add)); 125 global_event_mask.Set(to_remove, false); 126 global_event_mask.Set(to_add, true); 127 } 128 129 if (unioned_thread_event_mask.Test(to_remove)) { 130 CHECK(!unioned_thread_event_mask.Test(to_add)); 131 unioned_thread_event_mask.Set(to_remove, false); 132 unioned_thread_event_mask.Set(to_add, true); 133 } 134 for (auto thread_mask : thread_event_masks) { 135 if (thread_mask.second.Test(to_remove)) { 136 CHECK(!thread_mask.second.Test(to_add)); 137 thread_mask.second.Set(to_remove, false); 138 thread_mask.second.Set(to_add, true); 139 } 140 } 141 } 142 } 143 144 void EventHandler::RegisterArtJvmTiEnv(ArtJvmTiEnv* env) { 145 // Since we never shrink this array we might as well try to fill gaps. 146 auto it = std::find(envs.begin(), envs.end(), nullptr); 147 if (it != envs.end()) { 148 *it = env; 149 } else { 150 envs.push_back(env); 151 } 152 } 153 154 void EventHandler::RemoveArtJvmTiEnv(ArtJvmTiEnv* env) { 155 // Since we might be currently iterating over the envs list we cannot actually erase elements. 156 // Instead we will simply replace them with 'nullptr' and skip them manually. 157 auto it = std::find(envs.begin(), envs.end(), env); 158 if (it != envs.end()) { 159 *it = nullptr; 160 for (size_t i = static_cast<size_t>(ArtJvmtiEvent::kMinEventTypeVal); 161 i <= static_cast<size_t>(ArtJvmtiEvent::kMaxEventTypeVal); 162 ++i) { 163 RecalculateGlobalEventMask(static_cast<ArtJvmtiEvent>(i)); 164 } 165 } 166 } 167 168 static bool IsThreadControllable(ArtJvmtiEvent event) { 169 switch (event) { 170 case ArtJvmtiEvent::kVmInit: 171 case ArtJvmtiEvent::kVmStart: 172 case ArtJvmtiEvent::kVmDeath: 173 case ArtJvmtiEvent::kThreadStart: 174 case ArtJvmtiEvent::kCompiledMethodLoad: 175 case ArtJvmtiEvent::kCompiledMethodUnload: 176 case ArtJvmtiEvent::kDynamicCodeGenerated: 177 case ArtJvmtiEvent::kDataDumpRequest: 178 return false; 179 180 default: 181 return true; 182 } 183 } 184 185 class JvmtiAllocationListener : public art::gc::AllocationListener { 186 public: 187 explicit JvmtiAllocationListener(EventHandler* handler) : handler_(handler) {} 188 189 void ObjectAllocated(art::Thread* self, art::ObjPtr<art::mirror::Object>* obj, size_t byte_count) 190 OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) { 191 DCHECK_EQ(self, art::Thread::Current()); 192 193 if (handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kVmObjectAlloc)) { 194 art::StackHandleScope<1> hs(self); 195 auto h = hs.NewHandleWrapper(obj); 196 // jvmtiEventVMObjectAlloc parameters: 197 // jvmtiEnv *jvmti_env, 198 // JNIEnv* jni_env, 199 // jthread thread, 200 // jobject object, 201 // jclass object_klass, 202 // jlong size 203 art::JNIEnvExt* jni_env = self->GetJniEnv(); 204 205 jthread thread_peer; 206 if (self->IsStillStarting()) { 207 thread_peer = nullptr; 208 } else { 209 thread_peer = jni_env->AddLocalReference<jthread>(self->GetPeer()); 210 } 211 212 ScopedLocalRef<jthread> thread(jni_env, thread_peer); 213 ScopedLocalRef<jobject> object( 214 jni_env, jni_env->AddLocalReference<jobject>(*obj)); 215 ScopedLocalRef<jclass> klass( 216 jni_env, jni_env->AddLocalReference<jclass>(obj->Ptr()->GetClass())); 217 218 handler_->DispatchEvent<ArtJvmtiEvent::kVmObjectAlloc>(self, 219 reinterpret_cast<JNIEnv*>(jni_env), 220 thread.get(), 221 object.get(), 222 klass.get(), 223 static_cast<jlong>(byte_count)); 224 } 225 } 226 227 private: 228 EventHandler* handler_; 229 }; 230 231 static void SetupObjectAllocationTracking(art::gc::AllocationListener* listener, bool enable) { 232 // We must not hold the mutator lock here, but if we're in FastJNI, for example, we might. For 233 // now, do a workaround: (possibly) acquire and release. 234 art::ScopedObjectAccess soa(art::Thread::Current()); 235 art::ScopedThreadSuspension sts(soa.Self(), art::ThreadState::kSuspended); 236 if (enable) { 237 art::Runtime::Current()->GetHeap()->SetAllocationListener(listener); 238 } else { 239 art::Runtime::Current()->GetHeap()->RemoveAllocationListener(); 240 } 241 } 242 243 // Report GC pauses (see spec) as GARBAGE_COLLECTION_START and GARBAGE_COLLECTION_END. 244 class JvmtiGcPauseListener : public art::gc::GcPauseListener { 245 public: 246 explicit JvmtiGcPauseListener(EventHandler* handler) 247 : handler_(handler), 248 start_enabled_(false), 249 finish_enabled_(false) {} 250 251 void StartPause() OVERRIDE { 252 handler_->DispatchEvent<ArtJvmtiEvent::kGarbageCollectionStart>(nullptr); 253 } 254 255 void EndPause() OVERRIDE { 256 handler_->DispatchEvent<ArtJvmtiEvent::kGarbageCollectionFinish>(nullptr); 257 } 258 259 bool IsEnabled() { 260 return start_enabled_ || finish_enabled_; 261 } 262 263 void SetStartEnabled(bool e) { 264 start_enabled_ = e; 265 } 266 267 void SetFinishEnabled(bool e) { 268 finish_enabled_ = e; 269 } 270 271 private: 272 EventHandler* handler_; 273 bool start_enabled_; 274 bool finish_enabled_; 275 }; 276 277 static void SetupGcPauseTracking(JvmtiGcPauseListener* listener, ArtJvmtiEvent event, bool enable) { 278 bool old_state = listener->IsEnabled(); 279 280 if (event == ArtJvmtiEvent::kGarbageCollectionStart) { 281 listener->SetStartEnabled(enable); 282 } else { 283 listener->SetFinishEnabled(enable); 284 } 285 286 bool new_state = listener->IsEnabled(); 287 288 if (old_state != new_state) { 289 if (new_state) { 290 art::Runtime::Current()->GetHeap()->SetGcPauseListener(listener); 291 } else { 292 art::Runtime::Current()->GetHeap()->RemoveGcPauseListener(); 293 } 294 } 295 } 296 297 // Handle special work for the given event type, if necessary. 298 void EventHandler::HandleEventType(ArtJvmtiEvent event, bool enable) { 299 switch (event) { 300 case ArtJvmtiEvent::kVmObjectAlloc: 301 SetupObjectAllocationTracking(alloc_listener_.get(), enable); 302 return; 303 304 case ArtJvmtiEvent::kGarbageCollectionStart: 305 case ArtJvmtiEvent::kGarbageCollectionFinish: 306 SetupGcPauseTracking(gc_pause_listener_.get(), event, enable); 307 return; 308 309 default: 310 break; 311 } 312 } 313 314 // Checks to see if the env has the capabilities associated with the given event. 315 static bool HasAssociatedCapability(ArtJvmTiEnv* env, 316 ArtJvmtiEvent event) { 317 jvmtiCapabilities caps = env->capabilities; 318 switch (event) { 319 case ArtJvmtiEvent::kBreakpoint: 320 return caps.can_generate_breakpoint_events == 1; 321 322 case ArtJvmtiEvent::kCompiledMethodLoad: 323 case ArtJvmtiEvent::kCompiledMethodUnload: 324 return caps.can_generate_compiled_method_load_events == 1; 325 326 case ArtJvmtiEvent::kException: 327 case ArtJvmtiEvent::kExceptionCatch: 328 return caps.can_generate_exception_events == 1; 329 330 case ArtJvmtiEvent::kFieldAccess: 331 return caps.can_generate_field_access_events == 1; 332 333 case ArtJvmtiEvent::kFieldModification: 334 return caps.can_generate_field_modification_events == 1; 335 336 case ArtJvmtiEvent::kFramePop: 337 return caps.can_generate_frame_pop_events == 1; 338 339 case ArtJvmtiEvent::kGarbageCollectionStart: 340 case ArtJvmtiEvent::kGarbageCollectionFinish: 341 return caps.can_generate_garbage_collection_events == 1; 342 343 case ArtJvmtiEvent::kMethodEntry: 344 return caps.can_generate_method_entry_events == 1; 345 346 case ArtJvmtiEvent::kMethodExit: 347 return caps.can_generate_method_exit_events == 1; 348 349 case ArtJvmtiEvent::kMonitorContendedEnter: 350 case ArtJvmtiEvent::kMonitorContendedEntered: 351 case ArtJvmtiEvent::kMonitorWait: 352 case ArtJvmtiEvent::kMonitorWaited: 353 return caps.can_generate_monitor_events == 1; 354 355 case ArtJvmtiEvent::kNativeMethodBind: 356 return caps.can_generate_native_method_bind_events == 1; 357 358 case ArtJvmtiEvent::kObjectFree: 359 return caps.can_generate_object_free_events == 1; 360 361 case ArtJvmtiEvent::kSingleStep: 362 return caps.can_generate_single_step_events == 1; 363 364 case ArtJvmtiEvent::kVmObjectAlloc: 365 return caps.can_generate_vm_object_alloc_events == 1; 366 367 default: 368 return true; 369 } 370 } 371 372 jvmtiError EventHandler::SetEvent(ArtJvmTiEnv* env, 373 art::Thread* thread, 374 ArtJvmtiEvent event, 375 jvmtiEventMode mode) { 376 if (thread != nullptr) { 377 art::ThreadState state = thread->GetState(); 378 if (state == art::ThreadState::kStarting || 379 state == art::ThreadState::kTerminated || 380 thread->IsStillStarting()) { 381 return ERR(THREAD_NOT_ALIVE); 382 } 383 if (!IsThreadControllable(event)) { 384 return ERR(ILLEGAL_ARGUMENT); 385 } 386 } 387 388 if (mode != JVMTI_ENABLE && mode != JVMTI_DISABLE) { 389 return ERR(ILLEGAL_ARGUMENT); 390 } 391 392 if (!EventMask::EventIsInRange(event)) { 393 return ERR(INVALID_EVENT_TYPE); 394 } 395 396 if (!HasAssociatedCapability(env, event)) { 397 return ERR(MUST_POSSESS_CAPABILITY); 398 } 399 400 bool old_state = global_mask.Test(event); 401 402 if (mode == JVMTI_ENABLE) { 403 env->event_masks.EnableEvent(thread, event); 404 global_mask.Set(event); 405 } else { 406 DCHECK_EQ(mode, JVMTI_DISABLE); 407 408 env->event_masks.DisableEvent(thread, event); 409 RecalculateGlobalEventMask(event); 410 } 411 412 bool new_state = global_mask.Test(event); 413 414 // Handle any special work required for the event type. 415 if (new_state != old_state) { 416 HandleEventType(event, mode == JVMTI_ENABLE); 417 } 418 419 return ERR(NONE); 420 } 421 422 EventHandler::EventHandler() { 423 alloc_listener_.reset(new JvmtiAllocationListener(this)); 424 gc_pause_listener_.reset(new JvmtiGcPauseListener(this)); 425 } 426 427 EventHandler::~EventHandler() { 428 } 429 430 } // namespace openjdkjvmti 431