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_RUNTIME_OPENJDKJVMTI_EVENTS_H_ 18 #define ART_RUNTIME_OPENJDKJVMTI_EVENTS_H_ 19 20 #include <bitset> 21 #include <vector> 22 23 #include "base/logging.h" 24 #include "jvmti.h" 25 #include "thread.h" 26 27 namespace openjdkjvmti { 28 29 struct ArtJvmTiEnv; 30 class JvmtiAllocationListener; 31 class JvmtiGcPauseListener; 32 class JvmtiMethodTraceListener; 33 34 // an enum for ArtEvents. This differs from the JVMTI events only in that we distinguish between 35 // retransformation capable and incapable loading 36 enum class ArtJvmtiEvent { 37 kMinEventTypeVal = JVMTI_MIN_EVENT_TYPE_VAL, 38 kVmInit = JVMTI_EVENT_VM_INIT, 39 kVmDeath = JVMTI_EVENT_VM_DEATH, 40 kThreadStart = JVMTI_EVENT_THREAD_START, 41 kThreadEnd = JVMTI_EVENT_THREAD_END, 42 kClassFileLoadHookNonRetransformable = JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, 43 kClassLoad = JVMTI_EVENT_CLASS_LOAD, 44 kClassPrepare = JVMTI_EVENT_CLASS_PREPARE, 45 kVmStart = JVMTI_EVENT_VM_START, 46 kException = JVMTI_EVENT_EXCEPTION, 47 kExceptionCatch = JVMTI_EVENT_EXCEPTION_CATCH, 48 kSingleStep = JVMTI_EVENT_SINGLE_STEP, 49 kFramePop = JVMTI_EVENT_FRAME_POP, 50 kBreakpoint = JVMTI_EVENT_BREAKPOINT, 51 kFieldAccess = JVMTI_EVENT_FIELD_ACCESS, 52 kFieldModification = JVMTI_EVENT_FIELD_MODIFICATION, 53 kMethodEntry = JVMTI_EVENT_METHOD_ENTRY, 54 kMethodExit = JVMTI_EVENT_METHOD_EXIT, 55 kNativeMethodBind = JVMTI_EVENT_NATIVE_METHOD_BIND, 56 kCompiledMethodLoad = JVMTI_EVENT_COMPILED_METHOD_LOAD, 57 kCompiledMethodUnload = JVMTI_EVENT_COMPILED_METHOD_UNLOAD, 58 kDynamicCodeGenerated = JVMTI_EVENT_DYNAMIC_CODE_GENERATED, 59 kDataDumpRequest = JVMTI_EVENT_DATA_DUMP_REQUEST, 60 kMonitorWait = JVMTI_EVENT_MONITOR_WAIT, 61 kMonitorWaited = JVMTI_EVENT_MONITOR_WAITED, 62 kMonitorContendedEnter = JVMTI_EVENT_MONITOR_CONTENDED_ENTER, 63 kMonitorContendedEntered = JVMTI_EVENT_MONITOR_CONTENDED_ENTERED, 64 kResourceExhausted = JVMTI_EVENT_RESOURCE_EXHAUSTED, 65 kGarbageCollectionStart = JVMTI_EVENT_GARBAGE_COLLECTION_START, 66 kGarbageCollectionFinish = JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, 67 kObjectFree = JVMTI_EVENT_OBJECT_FREE, 68 kVmObjectAlloc = JVMTI_EVENT_VM_OBJECT_ALLOC, 69 kClassFileLoadHookRetransformable = JVMTI_MAX_EVENT_TYPE_VAL + 1, 70 kMaxEventTypeVal = kClassFileLoadHookRetransformable, 71 }; 72 73 // Convert a jvmtiEvent into a ArtJvmtiEvent 74 ALWAYS_INLINE static inline ArtJvmtiEvent GetArtJvmtiEvent(ArtJvmTiEnv* env, jvmtiEvent e); 75 76 static inline jvmtiEvent GetJvmtiEvent(ArtJvmtiEvent e) { 77 if (UNLIKELY(e == ArtJvmtiEvent::kClassFileLoadHookRetransformable)) { 78 return JVMTI_EVENT_CLASS_FILE_LOAD_HOOK; 79 } else { 80 return static_cast<jvmtiEvent>(e); 81 } 82 } 83 84 struct EventMask { 85 static constexpr size_t kEventsSize = 86 static_cast<size_t>(ArtJvmtiEvent::kMaxEventTypeVal) - 87 static_cast<size_t>(ArtJvmtiEvent::kMinEventTypeVal) + 1; 88 std::bitset<kEventsSize> bit_set; 89 90 static bool EventIsInRange(ArtJvmtiEvent event) { 91 return event >= ArtJvmtiEvent::kMinEventTypeVal && event <= ArtJvmtiEvent::kMaxEventTypeVal; 92 } 93 94 void Set(ArtJvmtiEvent event, bool value = true) { 95 DCHECK(EventIsInRange(event)); 96 bit_set.set(static_cast<size_t>(event) - static_cast<size_t>(ArtJvmtiEvent::kMinEventTypeVal), 97 value); 98 } 99 100 bool Test(ArtJvmtiEvent event) const { 101 DCHECK(EventIsInRange(event)); 102 return bit_set.test( 103 static_cast<size_t>(event) - static_cast<size_t>(ArtJvmtiEvent::kMinEventTypeVal)); 104 } 105 }; 106 107 struct EventMasks { 108 // The globally enabled events. 109 EventMask global_event_mask; 110 111 // The per-thread enabled events. 112 113 // It is not enough to store a Thread pointer, as these may be reused. Use the pointer and the 114 // thread id. 115 // Note: We could just use the tid like tracing does. 116 using UniqueThread = std::pair<art::Thread*, uint32_t>; 117 // TODO: Native thread objects are immovable, so we can use them as keys in an (unordered) map, 118 // if necessary. 119 std::vector<std::pair<UniqueThread, EventMask>> thread_event_masks; 120 121 // A union of the per-thread events, for fast-pathing. 122 EventMask unioned_thread_event_mask; 123 124 EventMask& GetEventMask(art::Thread* thread); 125 EventMask* GetEventMaskOrNull(art::Thread* thread); 126 void EnableEvent(art::Thread* thread, ArtJvmtiEvent event); 127 void DisableEvent(art::Thread* thread, ArtJvmtiEvent event); 128 bool IsEnabledAnywhere(ArtJvmtiEvent event); 129 // Make any changes to event masks needed for the given capability changes. If caps_added is true 130 // then caps is all the newly set capabilities of the jvmtiEnv. If it is false then caps is the 131 // set of all capabilities that were removed from the jvmtiEnv. 132 void HandleChangedCapabilities(const jvmtiCapabilities& caps, bool caps_added); 133 }; 134 135 // Helper class for event handling. 136 class EventHandler { 137 public: 138 EventHandler(); 139 ~EventHandler(); 140 141 // do cleanup for the event handler. 142 void Shutdown(); 143 144 // Register an env. It is assumed that this happens on env creation, that is, no events are 145 // enabled, yet. 146 void RegisterArtJvmTiEnv(ArtJvmTiEnv* env); 147 148 // Remove an env. 149 void RemoveArtJvmTiEnv(ArtJvmTiEnv* env); 150 151 bool IsEventEnabledAnywhere(ArtJvmtiEvent event) const { 152 if (!EventMask::EventIsInRange(event)) { 153 return false; 154 } 155 return global_mask.Test(event); 156 } 157 158 jvmtiError SetEvent(ArtJvmTiEnv* env, 159 art::Thread* thread, 160 ArtJvmtiEvent event, 161 jvmtiEventMode mode); 162 163 // Dispatch event to all registered environments. 164 template <ArtJvmtiEvent kEvent, typename ...Args> 165 ALWAYS_INLINE 166 inline void DispatchEvent(art::Thread* thread, Args... args) const; 167 // Dispatch event to all registered environments stashing exceptions as needed. This works since 168 // JNIEnv* is always the second argument if it is passed to an event. Needed since C++ does not 169 // allow partial template function specialization. 170 template <ArtJvmtiEvent kEvent, typename ...Args> 171 ALWAYS_INLINE 172 void DispatchEvent(art::Thread* thread, JNIEnv* jnienv, Args... args) const; 173 // Dispatch event to the given environment, only. 174 template <ArtJvmtiEvent kEvent, typename ...Args> 175 ALWAYS_INLINE 176 inline void DispatchEvent(ArtJvmTiEnv* env, art::Thread* thread, Args... args) const; 177 178 // Tell the event handler capabilities were added/lost so it can adjust the sent events.If 179 // caps_added is true then caps is all the newly set capabilities of the jvmtiEnv. If it is false 180 // then caps is the set of all capabilities that were removed from the jvmtiEnv. 181 ALWAYS_INLINE 182 inline void HandleChangedCapabilities(ArtJvmTiEnv* env, 183 const jvmtiCapabilities& caps, 184 bool added); 185 186 private: 187 template <ArtJvmtiEvent kEvent> 188 ALWAYS_INLINE 189 static inline bool ShouldDispatch(ArtJvmTiEnv* env, art::Thread* thread); 190 191 ALWAYS_INLINE 192 inline bool NeedsEventUpdate(ArtJvmTiEnv* env, 193 const jvmtiCapabilities& caps, 194 bool added); 195 196 // Recalculates the event mask for the given event. 197 ALWAYS_INLINE 198 inline void RecalculateGlobalEventMask(ArtJvmtiEvent event); 199 200 template <ArtJvmtiEvent kEvent> 201 ALWAYS_INLINE inline void DispatchClassFileLoadHookEvent(art::Thread* thread, 202 JNIEnv* jnienv, 203 jclass class_being_redefined, 204 jobject loader, 205 const char* name, 206 jobject protection_domain, 207 jint class_data_len, 208 const unsigned char* class_data, 209 jint* new_class_data_len, 210 unsigned char** new_class_data) const; 211 212 void HandleEventType(ArtJvmtiEvent event, bool enable); 213 214 // List of all JvmTiEnv objects that have been created, in their creation order. 215 // NB Some elements might be null representing envs that have been deleted. They should be skipped 216 // anytime this list is used. 217 std::vector<ArtJvmTiEnv*> envs; 218 219 // A union of all enabled events, anywhere. 220 EventMask global_mask; 221 222 std::unique_ptr<JvmtiAllocationListener> alloc_listener_; 223 std::unique_ptr<JvmtiGcPauseListener> gc_pause_listener_; 224 std::unique_ptr<JvmtiMethodTraceListener> method_trace_listener_; 225 }; 226 227 } // namespace openjdkjvmti 228 229 #endif // ART_RUNTIME_OPENJDKJVMTI_EVENTS_H_ 230