• Home
  • History
  • Annotate
  • 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