• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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