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