1 /* 2 * Copyright (C) 2016 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 #ifndef ART_OPENJDKJVMTI_EVENTS_H_ 18 #define ART_OPENJDKJVMTI_EVENTS_H_ 19 20 #include <bitset> 21 #include <vector> 22 23 #include <android-base/logging.h> 24 #include <android-base/thread_annotations.h> 25 26 #include "base/macros.h" 27 #include "base/mutex.h" 28 #include "jvmti.h" 29 #include "thread.h" 30 31 namespace openjdkjvmti { 32 33 struct ArtJvmTiEnv; 34 class JvmtiAllocationListener; 35 class JvmtiDdmChunkListener; 36 class JvmtiGcPauseListener; 37 class JvmtiMethodTraceListener; 38 class JvmtiMonitorListener; 39 class JvmtiParkListener; 40 41 // an enum for ArtEvents. This differs from the JVMTI events only in that we distinguish between 42 // retransformation capable and incapable loading 43 enum class ArtJvmtiEvent : jint { 44 kMinEventTypeVal = JVMTI_MIN_EVENT_TYPE_VAL, 45 kVmInit = JVMTI_EVENT_VM_INIT, 46 kVmDeath = JVMTI_EVENT_VM_DEATH, 47 kThreadStart = JVMTI_EVENT_THREAD_START, 48 kThreadEnd = JVMTI_EVENT_THREAD_END, 49 kClassFileLoadHookNonRetransformable = JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, 50 kClassLoad = JVMTI_EVENT_CLASS_LOAD, 51 kClassPrepare = JVMTI_EVENT_CLASS_PREPARE, 52 kVmStart = JVMTI_EVENT_VM_START, 53 kException = JVMTI_EVENT_EXCEPTION, 54 kExceptionCatch = JVMTI_EVENT_EXCEPTION_CATCH, 55 kSingleStep = JVMTI_EVENT_SINGLE_STEP, 56 kFramePop = JVMTI_EVENT_FRAME_POP, 57 kBreakpoint = JVMTI_EVENT_BREAKPOINT, 58 kFieldAccess = JVMTI_EVENT_FIELD_ACCESS, 59 kFieldModification = JVMTI_EVENT_FIELD_MODIFICATION, 60 kMethodEntry = JVMTI_EVENT_METHOD_ENTRY, 61 kMethodExit = JVMTI_EVENT_METHOD_EXIT, 62 kNativeMethodBind = JVMTI_EVENT_NATIVE_METHOD_BIND, 63 kCompiledMethodLoad = JVMTI_EVENT_COMPILED_METHOD_LOAD, 64 kCompiledMethodUnload = JVMTI_EVENT_COMPILED_METHOD_UNLOAD, 65 kDynamicCodeGenerated = JVMTI_EVENT_DYNAMIC_CODE_GENERATED, 66 kDataDumpRequest = JVMTI_EVENT_DATA_DUMP_REQUEST, 67 kMonitorWait = JVMTI_EVENT_MONITOR_WAIT, 68 kMonitorWaited = JVMTI_EVENT_MONITOR_WAITED, 69 kMonitorContendedEnter = JVMTI_EVENT_MONITOR_CONTENDED_ENTER, 70 kMonitorContendedEntered = JVMTI_EVENT_MONITOR_CONTENDED_ENTERED, 71 kResourceExhausted = JVMTI_EVENT_RESOURCE_EXHAUSTED, 72 kGarbageCollectionStart = JVMTI_EVENT_GARBAGE_COLLECTION_START, 73 kGarbageCollectionFinish = JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, 74 kObjectFree = JVMTI_EVENT_OBJECT_FREE, 75 kVmObjectAlloc = JVMTI_EVENT_VM_OBJECT_ALLOC, 76 kClassFileLoadHookRetransformable = JVMTI_MAX_EVENT_TYPE_VAL + 1, 77 kDdmPublishChunk = JVMTI_MAX_EVENT_TYPE_VAL + 2, 78 kMaxEventTypeVal = kDdmPublishChunk, 79 }; 80 81 using ArtJvmtiEventDdmPublishChunk = void (*)(jvmtiEnv *jvmti_env, 82 JNIEnv* jni_env, 83 jint data_type, 84 jint data_len, 85 const jbyte* data); 86 87 struct ArtJvmtiEventCallbacks : jvmtiEventCallbacks { ArtJvmtiEventCallbacksArtJvmtiEventCallbacks88 ArtJvmtiEventCallbacks() : DdmPublishChunk(nullptr) { 89 memset(this, 0, sizeof(jvmtiEventCallbacks)); 90 } 91 92 // Copies extension functions from other callback struct if it exists. There must not have been 93 // any modifications to this struct when it is called. 94 void CopyExtensionsFrom(const ArtJvmtiEventCallbacks* cb); 95 96 jvmtiError Set(jint index, jvmtiExtensionEvent cb); 97 98 ArtJvmtiEventDdmPublishChunk DdmPublishChunk; 99 }; 100 101 bool IsExtensionEvent(jint e); 102 bool IsExtensionEvent(ArtJvmtiEvent e); 103 104 // Convert a jvmtiEvent into a ArtJvmtiEvent 105 ALWAYS_INLINE static inline ArtJvmtiEvent GetArtJvmtiEvent(ArtJvmTiEnv* env, jvmtiEvent e); 106 GetJvmtiEvent(ArtJvmtiEvent e)107 static inline jvmtiEvent GetJvmtiEvent(ArtJvmtiEvent e) { 108 if (UNLIKELY(e == ArtJvmtiEvent::kClassFileLoadHookRetransformable)) { 109 return JVMTI_EVENT_CLASS_FILE_LOAD_HOOK; 110 } else { 111 return static_cast<jvmtiEvent>(e); 112 } 113 } 114 115 struct EventMask { 116 static constexpr size_t kEventsSize = 117 static_cast<size_t>(ArtJvmtiEvent::kMaxEventTypeVal) - 118 static_cast<size_t>(ArtJvmtiEvent::kMinEventTypeVal) + 1; 119 std::bitset<kEventsSize> bit_set; 120 EventIsInRangeEventMask121 static bool EventIsInRange(ArtJvmtiEvent event) { 122 return event >= ArtJvmtiEvent::kMinEventTypeVal && event <= ArtJvmtiEvent::kMaxEventTypeVal; 123 } 124 125 void Set(ArtJvmtiEvent event, bool value = true) { 126 DCHECK(EventIsInRange(event)); 127 bit_set.set(static_cast<size_t>(event) - static_cast<size_t>(ArtJvmtiEvent::kMinEventTypeVal), 128 value); 129 } 130 TestEventMask131 bool Test(ArtJvmtiEvent event) const { 132 DCHECK(EventIsInRange(event)); 133 return bit_set.test( 134 static_cast<size_t>(event) - static_cast<size_t>(ArtJvmtiEvent::kMinEventTypeVal)); 135 } 136 }; 137 138 struct EventMasks { 139 // The globally enabled events. 140 EventMask global_event_mask; 141 142 // The per-thread enabled events. 143 144 // It is not enough to store a Thread pointer, as these may be reused. Use the pointer and the 145 // thread id. 146 // Note: We could just use the tid like tracing does. 147 using UniqueThread = std::pair<art::Thread*, uint32_t>; 148 // TODO: Native thread objects are immovable, so we can use them as keys in an (unordered) map, 149 // if necessary. 150 std::vector<std::pair<UniqueThread, EventMask>> thread_event_masks; 151 152 // A union of the per-thread events, for fast-pathing. 153 EventMask unioned_thread_event_mask; 154 155 EventMask& GetEventMask(art::Thread* thread); 156 EventMask* GetEventMaskOrNull(art::Thread* thread); 157 // Circular dependencies mean we cannot see the definition of ArtJvmTiEnv so the mutex is simply 158 // asserted in the function. 159 // Note that the 'env' passed in must be the same env this EventMasks is associated with. 160 void EnableEvent(ArtJvmTiEnv* env, art::Thread* thread, ArtJvmtiEvent event); 161 // REQUIRES(env->event_info_mutex_); 162 // Circular dependencies mean we cannot see the definition of ArtJvmTiEnv so the mutex is simply 163 // asserted in the function. 164 // Note that the 'env' passed in must be the same env this EventMasks is associated with. 165 void DisableEvent(ArtJvmTiEnv* env, art::Thread* thread, ArtJvmtiEvent event); 166 // REQUIRES(env->event_info_mutex_); 167 bool IsEnabledAnywhere(ArtJvmtiEvent event); 168 // Make any changes to event masks needed for the given capability changes. If caps_added is true 169 // then caps is all the newly set capabilities of the jvmtiEnv. If it is false then caps is the 170 // set of all capabilities that were removed from the jvmtiEnv. 171 void HandleChangedCapabilities(const jvmtiCapabilities& caps, bool caps_added); 172 }; 173 174 namespace impl { 175 template <ArtJvmtiEvent kEvent> struct EventHandlerFunc { }; 176 } // namespace impl 177 178 // Helper class for event handling. 179 class EventHandler { 180 public: 181 EventHandler(); 182 ~EventHandler(); 183 184 // do cleanup for the event handler. 185 void Shutdown(); 186 187 // Register an env. It is assumed that this happens on env creation, that is, no events are 188 // enabled, yet. 189 void RegisterArtJvmTiEnv(ArtJvmTiEnv* env) REQUIRES(!envs_lock_); 190 191 // Remove an env. 192 void RemoveArtJvmTiEnv(ArtJvmTiEnv* env) REQUIRES(!envs_lock_); 193 IsEventEnabledAnywhere(ArtJvmtiEvent event)194 bool IsEventEnabledAnywhere(ArtJvmtiEvent event) const { 195 if (!EventMask::EventIsInRange(event)) { 196 return false; 197 } 198 return global_mask.Test(event); 199 } 200 201 jvmtiError SetEvent(ArtJvmTiEnv* env, 202 jthread thread, 203 ArtJvmtiEvent event, 204 jvmtiEventMode mode) 205 REQUIRES(!envs_lock_); 206 207 // Dispatch event to all registered environments. Since this one doesn't have a JNIEnv* it doesn't 208 // matter if it has the mutator_lock. 209 template <ArtJvmtiEvent kEvent, typename ...Args> 210 ALWAYS_INLINE 211 inline void DispatchEvent(art::Thread* thread, Args... args) const 212 REQUIRES(!envs_lock_); 213 214 // Dispatch event to all registered environments stashing exceptions as needed. This works since 215 // JNIEnv* is always the second argument if it is passed to an event. Needed since C++ does not 216 // allow partial template function specialization. 217 // 218 // We need both of these since we want to make sure to push a stack frame when it is possible for 219 // the event to allocate local references. 220 template <ArtJvmtiEvent kEvent, typename ...Args> 221 ALWAYS_INLINE 222 inline void DispatchEvent(art::Thread* thread, JNIEnv* jnienv, Args... args) const 223 REQUIRES(!envs_lock_); 224 225 // Tell the event handler capabilities were added/lost so it can adjust the sent events.If 226 // caps_added is true then caps is all the newly set capabilities of the jvmtiEnv. If it is false 227 // then caps is the set of all capabilities that were removed from the jvmtiEnv. 228 ALWAYS_INLINE 229 inline void HandleChangedCapabilities(ArtJvmTiEnv* env, 230 const jvmtiCapabilities& caps, 231 bool added) 232 REQUIRES(!envs_lock_); 233 234 // Dispatch event to the given environment, only. 235 template <ArtJvmtiEvent kEvent, typename ...Args> 236 ALWAYS_INLINE 237 inline void DispatchEventOnEnv(ArtJvmTiEnv* env, 238 art::Thread* thread, 239 JNIEnv* jnienv, 240 Args... args) const 241 REQUIRES(!envs_lock_); 242 243 // Dispatch event to the given environment, only. 244 template <ArtJvmtiEvent kEvent, typename ...Args> 245 ALWAYS_INLINE 246 inline void DispatchEventOnEnv(ArtJvmTiEnv* env, art::Thread* thread, Args... args) const 247 REQUIRES(!envs_lock_); 248 249 private: 250 void SetupTraceListener(JvmtiMethodTraceListener* listener, ArtJvmtiEvent event, bool enable); 251 252 // Specifically handle the FramePop event which it might not always be possible to turn off. 253 void SetupFramePopTraceListener(bool enable); 254 255 template <ArtJvmtiEvent kEvent, typename ...Args> 256 ALWAYS_INLINE 257 inline std::vector<impl::EventHandlerFunc<kEvent>> CollectEvents(art::Thread* thread, 258 Args... args) const 259 REQUIRES(!envs_lock_); 260 261 template <ArtJvmtiEvent kEvent> 262 ALWAYS_INLINE 263 inline bool ShouldDispatchOnThread(ArtJvmTiEnv* env, art::Thread* thread) const; 264 265 template <ArtJvmtiEvent kEvent, typename ...Args> 266 ALWAYS_INLINE 267 static inline void ExecuteCallback(impl::EventHandlerFunc<kEvent> handler, 268 JNIEnv* env, 269 Args... args) 270 REQUIRES(!envs_lock_); 271 272 template <ArtJvmtiEvent kEvent, typename ...Args> 273 ALWAYS_INLINE 274 static inline void ExecuteCallback(impl::EventHandlerFunc<kEvent> handler, Args... args) 275 REQUIRES(!envs_lock_); 276 277 // Public for use to collect dispatches 278 template <ArtJvmtiEvent kEvent, typename ...Args> 279 ALWAYS_INLINE 280 inline bool ShouldDispatch(ArtJvmTiEnv* env, art::Thread* thread, Args... args) const; 281 282 ALWAYS_INLINE 283 inline bool NeedsEventUpdate(ArtJvmTiEnv* env, 284 const jvmtiCapabilities& caps, 285 bool added); 286 287 // Recalculates the event mask for the given event. 288 ALWAYS_INLINE 289 inline void RecalculateGlobalEventMask(ArtJvmtiEvent event) REQUIRES(!envs_lock_); 290 ALWAYS_INLINE 291 inline void RecalculateGlobalEventMaskLocked(ArtJvmtiEvent event) REQUIRES_SHARED(envs_lock_); 292 293 // Returns whether there are any active requests for the given event on the given thread. This 294 // should only be used while modifying the events for a thread. 295 bool GetThreadEventState(ArtJvmtiEvent event, art::Thread* thread) 296 REQUIRES(envs_lock_, art::Locks::thread_list_lock_); 297 298 template <ArtJvmtiEvent kEvent> 299 ALWAYS_INLINE inline void DispatchClassFileLoadHookEvent(art::Thread* thread, 300 JNIEnv* jnienv, 301 jclass class_being_redefined, 302 jobject loader, 303 const char* name, 304 jobject protection_domain, 305 jint class_data_len, 306 const unsigned char* class_data, 307 jint* new_class_data_len, 308 unsigned char** new_class_data) const 309 REQUIRES(!envs_lock_); 310 311 template <ArtJvmtiEvent kEvent> 312 ALWAYS_INLINE inline void DispatchClassLoadOrPrepareEvent(art::Thread* thread, 313 JNIEnv* jnienv, 314 jthread jni_thread, 315 jclass klass) const 316 REQUIRES(!envs_lock_); 317 318 // Sets up the global state needed for the first/last enable of an event across all threads 319 void HandleEventType(ArtJvmtiEvent event, bool enable); 320 // Perform deopts required for enabling the event on the given thread. Null thread indicates 321 // global event enabled. 322 jvmtiError HandleEventDeopt(ArtJvmtiEvent event, jthread thread, bool enable); 323 void HandleLocalAccessCapabilityAdded(); 324 void HandleBreakpointEventsChanged(bool enable); 325 326 bool OtherMonitorEventsEnabledAnywhere(ArtJvmtiEvent event); 327 328 // List of all JvmTiEnv objects that have been created, in their creation order. It is a std::list 329 // since we mostly access it by iterating over the entire thing, only ever append to the end, and 330 // need to be able to remove arbitrary elements from it. 331 std::list<ArtJvmTiEnv*> envs GUARDED_BY(envs_lock_); 332 333 // Close to top level lock. Nothing should be held when we lock this (except for mutator_lock_ 334 // which is needed when setting new events). 335 mutable art::ReaderWriterMutex envs_lock_ ACQUIRED_AFTER(art::Locks::mutator_lock_); 336 337 // A union of all enabled events, anywhere. 338 EventMask global_mask; 339 340 std::unique_ptr<JvmtiAllocationListener> alloc_listener_; 341 std::unique_ptr<JvmtiDdmChunkListener> ddm_listener_; 342 std::unique_ptr<JvmtiGcPauseListener> gc_pause_listener_; 343 std::unique_ptr<JvmtiMethodTraceListener> method_trace_listener_; 344 std::unique_ptr<JvmtiMonitorListener> monitor_listener_; 345 std::unique_ptr<JvmtiParkListener> park_listener_; 346 347 // True if frame pop has ever been enabled. Since we store pointers to stack frames we need to 348 // continue to listen to this event even if it has been disabled. 349 // TODO We could remove the listeners once all jvmtiEnvs have drained their shadow-frame vectors. 350 bool frame_pop_enabled; 351 }; 352 353 } // namespace openjdkjvmti 354 355 #endif // ART_OPENJDKJVMTI_EVENTS_H_ 356