1 | /* |
2 | * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. |
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | * |
5 | * This code is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 only, as |
7 | * published by the Free Software Foundation. |
8 | * |
9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
12 | * version 2 for more details (a copy is included in the LICENSE file that |
13 | * accompanied this code). |
14 | * |
15 | * You should have received a copy of the GNU General Public License version |
16 | * 2 along with this work; if not, write to the Free Software Foundation, |
17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
18 | * |
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 | * or visit www.oracle.com if you need additional information or have any |
21 | * questions. |
22 | * |
23 | */ |
24 | |
25 | #ifndef SHARE_PRIMS_JVMTIEXPORT_HPP |
26 | #define SHARE_PRIMS_JVMTIEXPORT_HPP |
27 | |
28 | #include "jvmtifiles/jvmti.h" |
29 | #include "memory/allocation.hpp" |
30 | #include "memory/iterator.hpp" |
31 | #include "oops/oop.hpp" |
32 | #include "oops/oopsHierarchy.hpp" |
33 | #include "runtime/frame.hpp" |
34 | #include "runtime/handles.hpp" |
35 | #include "utilities/globalDefinitions.hpp" |
36 | #include "utilities/growableArray.hpp" |
37 | #include "utilities/macros.hpp" |
38 | |
39 | // Must be included after jvmti.h. |
40 | #include "jvmticmlr.h" |
41 | |
42 | // Forward declarations |
43 | |
44 | class JvmtiEventControllerPrivate; |
45 | class JvmtiManageCapabilities; |
46 | class JvmtiEnv; |
47 | class JvmtiThreadState; |
48 | |
49 | #define JVMTI_SUPPORT_FLAG(key) \ |
50 | private: \ |
51 | static bool _##key; \ |
52 | public: \ |
53 | inline static void set_##key(bool on) { \ |
54 | JVMTI_ONLY(_##key = (on != 0)); \ |
55 | NOT_JVMTI(report_unsupported(on)); \ |
56 | } \ |
57 | inline static bool key() { \ |
58 | JVMTI_ONLY(return _##key); \ |
59 | NOT_JVMTI(return false); \ |
60 | } |
61 | |
62 | |
63 | // This class contains the JVMTI interface for the rest of hotspot. |
64 | // |
65 | class JvmtiExport : public AllStatic { |
66 | friend class VMStructs; |
67 | friend class CompileReplay; |
68 | |
69 | private: |
70 | |
71 | #if INCLUDE_JVMTI |
72 | static int _field_access_count; |
73 | static int _field_modification_count; |
74 | |
75 | static bool _can_access_local_variables; |
76 | static bool _can_hotswap_or_post_breakpoint; |
77 | static bool _can_modify_any_class; |
78 | static bool _can_walk_any_space; |
79 | #endif // INCLUDE_JVMTI |
80 | |
81 | JVMTI_SUPPORT_FLAG(can_get_source_debug_extension) |
82 | JVMTI_SUPPORT_FLAG(can_maintain_original_method_order) |
83 | JVMTI_SUPPORT_FLAG(can_post_interpreter_events) |
84 | JVMTI_SUPPORT_FLAG(can_post_on_exceptions) |
85 | JVMTI_SUPPORT_FLAG(can_post_breakpoint) |
86 | JVMTI_SUPPORT_FLAG(can_post_field_access) |
87 | JVMTI_SUPPORT_FLAG(can_post_field_modification) |
88 | JVMTI_SUPPORT_FLAG(can_post_method_entry) |
89 | JVMTI_SUPPORT_FLAG(can_post_method_exit) |
90 | JVMTI_SUPPORT_FLAG(can_pop_frame) |
91 | JVMTI_SUPPORT_FLAG(can_force_early_return) |
92 | |
93 | JVMTI_SUPPORT_FLAG(early_vmstart_recorded) |
94 | |
95 | friend class JvmtiEventControllerPrivate; // should only modify these flags |
96 | JVMTI_SUPPORT_FLAG(should_post_single_step) |
97 | JVMTI_SUPPORT_FLAG(should_post_field_access) |
98 | JVMTI_SUPPORT_FLAG(should_post_field_modification) |
99 | JVMTI_SUPPORT_FLAG(should_post_class_load) |
100 | JVMTI_SUPPORT_FLAG(should_post_class_prepare) |
101 | JVMTI_SUPPORT_FLAG(should_post_class_unload) |
102 | JVMTI_SUPPORT_FLAG(should_post_native_method_bind) |
103 | JVMTI_SUPPORT_FLAG(should_post_compiled_method_load) |
104 | JVMTI_SUPPORT_FLAG(should_post_compiled_method_unload) |
105 | JVMTI_SUPPORT_FLAG(should_post_dynamic_code_generated) |
106 | JVMTI_SUPPORT_FLAG(should_post_monitor_contended_enter) |
107 | JVMTI_SUPPORT_FLAG(should_post_monitor_contended_entered) |
108 | JVMTI_SUPPORT_FLAG(should_post_monitor_wait) |
109 | JVMTI_SUPPORT_FLAG(should_post_monitor_waited) |
110 | JVMTI_SUPPORT_FLAG(should_post_data_dump) |
111 | JVMTI_SUPPORT_FLAG(should_post_garbage_collection_start) |
112 | JVMTI_SUPPORT_FLAG(should_post_garbage_collection_finish) |
113 | JVMTI_SUPPORT_FLAG(should_post_on_exceptions) |
114 | |
115 | // ------ the below maybe don't have to be (but are for now) |
116 | // fixed conditions here ------------ |
117 | // any events can be enabled |
118 | JVMTI_SUPPORT_FLAG(should_post_thread_life) |
119 | JVMTI_SUPPORT_FLAG(should_post_object_free) |
120 | JVMTI_SUPPORT_FLAG(should_post_resource_exhausted) |
121 | |
122 | // we are holding objects on the heap - need to talk to GC - e.g. |
123 | // breakpoint info |
124 | JVMTI_SUPPORT_FLAG(should_clean_up_heap_objects) |
125 | JVMTI_SUPPORT_FLAG(should_post_vm_object_alloc) |
126 | JVMTI_SUPPORT_FLAG(should_post_sampled_object_alloc) |
127 | |
128 | // If flag cannot be implemented, give an error if on=true |
129 | static void report_unsupported(bool on); |
130 | |
131 | // these should only be called by the friend class |
132 | friend class JvmtiManageCapabilities; |
133 | inline static void set_can_modify_any_class(bool on) { |
134 | JVMTI_ONLY(_can_modify_any_class = (on != 0);) |
135 | } |
136 | inline static void set_can_access_local_variables(bool on) { |
137 | JVMTI_ONLY(_can_access_local_variables = (on != 0);) |
138 | } |
139 | inline static void set_can_hotswap_or_post_breakpoint(bool on) { |
140 | JVMTI_ONLY(_can_hotswap_or_post_breakpoint = (on != 0);) |
141 | } |
142 | inline static void set_can_walk_any_space(bool on) { |
143 | JVMTI_ONLY(_can_walk_any_space = (on != 0);) |
144 | } |
145 | |
146 | enum { |
147 | JVMTI_VERSION_MASK = 0x70000000, |
148 | JVMTI_VERSION_VALUE = 0x30000000, |
149 | JVMDI_VERSION_VALUE = 0x20000000 |
150 | }; |
151 | |
152 | static void post_field_modification(JavaThread *thread, Method* method, address location, |
153 | Klass* field_klass, Handle object, jfieldID field, |
154 | char sig_type, jvalue *value); |
155 | |
156 | |
157 | // posts a DynamicCodeGenerated event (internal/private implementation). |
158 | // The public post_dynamic_code_generated* functions make use of the |
159 | // internal implementation. Also called from JvmtiDeferredEvent::post() |
160 | static void post_dynamic_code_generated_internal(const char *name, const void *code_begin, const void *code_end) NOT_JVMTI_RETURN; |
161 | |
162 | private: |
163 | |
164 | // GenerateEvents support to allow posting of CompiledMethodLoad and |
165 | // DynamicCodeGenerated events for a given environment. |
166 | friend class JvmtiCodeBlobEvents; |
167 | |
168 | static void post_compiled_method_load(JvmtiEnv* env, nmethod *nm) NOT_JVMTI_RETURN; |
169 | static void post_dynamic_code_generated(JvmtiEnv* env, const char *name, const void *code_begin, |
170 | const void *code_end) NOT_JVMTI_RETURN; |
171 | |
172 | // This flag indicates whether RedefineClasses() has ever redefined |
173 | // one or more classes during the lifetime of the VM. The flag should |
174 | // only be set by the friend class and can be queried by other sub |
175 | // systems as needed to relax invariant checks. |
176 | static bool _has_redefined_a_class; |
177 | friend class VM_RedefineClasses; |
178 | inline static void set_has_redefined_a_class() { |
179 | JVMTI_ONLY(_has_redefined_a_class = true;) |
180 | } |
181 | // Flag to indicate if the compiler has recorded all dependencies. When the |
182 | // can_redefine_classes capability is enabled in the OnLoad phase then the compiler |
183 | // records all dependencies from startup. However if the capability is first |
184 | // enabled some time later then the dependencies recorded by the compiler |
185 | // are incomplete. This flag is used by RedefineClasses to know if the |
186 | // dependency information is complete or not. |
187 | static bool _all_dependencies_are_recorded; |
188 | |
189 | public: |
190 | inline static bool has_redefined_a_class() { |
191 | JVMTI_ONLY(return _has_redefined_a_class); |
192 | NOT_JVMTI(return false); |
193 | } |
194 | |
195 | inline static bool all_dependencies_are_recorded() { |
196 | return _all_dependencies_are_recorded; |
197 | } |
198 | |
199 | inline static void set_all_dependencies_are_recorded(bool on) { |
200 | _all_dependencies_are_recorded = (on != 0); |
201 | } |
202 | |
203 | // Add read edges to the unnamed modules of the bootstrap and app class loaders |
204 | static void add_default_read_edges(Handle h_module, TRAPS) NOT_JVMTI_RETURN; |
205 | |
206 | // Add a read edge to the module |
207 | static jvmtiError add_module_reads(Handle module, Handle to_module, TRAPS); |
208 | |
209 | // Updates a module to export a package |
210 | static jvmtiError add_module_exports(Handle module, Handle pkg_name, Handle to_module, TRAPS); |
211 | |
212 | // Updates a module to open a package |
213 | static jvmtiError add_module_opens(Handle module, Handle pkg_name, Handle to_module, TRAPS); |
214 | |
215 | // Add a used service to the module |
216 | static jvmtiError add_module_uses(Handle module, Handle service, TRAPS); |
217 | |
218 | // Add a service provider to the module |
219 | static jvmtiError add_module_provides(Handle module, Handle service, Handle impl_class, TRAPS); |
220 | |
221 | // let JVMTI know that the JVM_OnLoad code is running |
222 | static void enter_onload_phase() NOT_JVMTI_RETURN; |
223 | |
224 | // let JVMTI know that the VM isn't up yet (and JVM_OnLoad code isn't running) |
225 | static void enter_primordial_phase() NOT_JVMTI_RETURN; |
226 | |
227 | // let JVMTI know that the VM isn't up yet but JNI is live |
228 | static void enter_early_start_phase() NOT_JVMTI_RETURN; |
229 | static void enter_start_phase() NOT_JVMTI_RETURN; |
230 | |
231 | // let JVMTI know that the VM is fully up and running now |
232 | static void enter_live_phase() NOT_JVMTI_RETURN; |
233 | |
234 | // ------ can_* conditions (below) are set at OnLoad and never changed ------------ |
235 | inline static bool can_modify_any_class() { |
236 | JVMTI_ONLY(return _can_modify_any_class); |
237 | NOT_JVMTI(return false); |
238 | } |
239 | inline static bool can_access_local_variables() { |
240 | JVMTI_ONLY(return _can_access_local_variables); |
241 | NOT_JVMTI(return false); |
242 | } |
243 | inline static bool can_hotswap_or_post_breakpoint() { |
244 | JVMTI_ONLY(return _can_hotswap_or_post_breakpoint); |
245 | NOT_JVMTI(return false); |
246 | } |
247 | inline static bool can_walk_any_space() { |
248 | JVMTI_ONLY(return _can_walk_any_space); |
249 | NOT_JVMTI(return false); |
250 | } |
251 | |
252 | // field access management |
253 | static address get_field_access_count_addr() NOT_JVMTI_RETURN_(0); |
254 | |
255 | // field modification management |
256 | static address get_field_modification_count_addr() NOT_JVMTI_RETURN_(0); |
257 | |
258 | // ----------------- |
259 | |
260 | static bool is_jvmti_version(jint version) { |
261 | JVMTI_ONLY(return (version & JVMTI_VERSION_MASK) == JVMTI_VERSION_VALUE); |
262 | NOT_JVMTI(return false); |
263 | } |
264 | static bool is_jvmdi_version(jint version) { |
265 | JVMTI_ONLY(return (version & JVMTI_VERSION_MASK) == JVMDI_VERSION_VALUE); |
266 | NOT_JVMTI(return false); |
267 | } |
268 | static jint get_jvmti_interface(JavaVM *jvm, void **penv, jint version) NOT_JVMTI_RETURN_(0); |
269 | static void decode_version_values(jint version, int * major, int * minor, |
270 | int * micro) NOT_JVMTI_RETURN; |
271 | |
272 | // single stepping management methods |
273 | static void at_single_stepping_point(JavaThread *thread, Method* method, address location) NOT_JVMTI_RETURN; |
274 | static void expose_single_stepping(JavaThread *thread) NOT_JVMTI_RETURN; |
275 | static bool hide_single_stepping(JavaThread *thread) NOT_JVMTI_RETURN_(false); |
276 | |
277 | // Methods that notify the debugger that something interesting has happened in the VM. |
278 | static void post_early_vm_start () NOT_JVMTI_RETURN; |
279 | static void post_vm_start () NOT_JVMTI_RETURN; |
280 | static void post_vm_initialized () NOT_JVMTI_RETURN; |
281 | static void post_vm_death () NOT_JVMTI_RETURN; |
282 | |
283 | static void post_single_step (JavaThread *thread, Method* method, address location) NOT_JVMTI_RETURN; |
284 | static void post_raw_breakpoint (JavaThread *thread, Method* method, address location) NOT_JVMTI_RETURN; |
285 | |
286 | static void post_exception_throw (JavaThread *thread, Method* method, address location, oop exception) NOT_JVMTI_RETURN; |
287 | static void notice_unwind_due_to_exception (JavaThread *thread, Method* method, address location, oop exception, bool in_handler_frame) NOT_JVMTI_RETURN; |
288 | |
289 | static oop jni_GetField_probe (JavaThread *thread, jobject jobj, |
290 | oop obj, Klass* klass, jfieldID fieldID, bool is_static) |
291 | NOT_JVMTI_RETURN_(NULL); |
292 | static oop jni_GetField_probe_nh (JavaThread *thread, jobject jobj, |
293 | oop obj, Klass* klass, jfieldID fieldID, bool is_static) |
294 | NOT_JVMTI_RETURN_(NULL); |
295 | static void post_field_access_by_jni (JavaThread *thread, oop obj, |
296 | Klass* klass, jfieldID fieldID, bool is_static) NOT_JVMTI_RETURN; |
297 | static void post_field_access (JavaThread *thread, Method* method, |
298 | address location, Klass* field_klass, Handle object, jfieldID field) NOT_JVMTI_RETURN; |
299 | static oop jni_SetField_probe (JavaThread *thread, jobject jobj, |
300 | oop obj, Klass* klass, jfieldID fieldID, bool is_static, char sig_type, |
301 | jvalue *value) NOT_JVMTI_RETURN_(NULL); |
302 | static oop jni_SetField_probe_nh (JavaThread *thread, jobject jobj, |
303 | oop obj, Klass* klass, jfieldID fieldID, bool is_static, char sig_type, |
304 | jvalue *value) NOT_JVMTI_RETURN_(NULL); |
305 | static void post_field_modification_by_jni(JavaThread *thread, oop obj, |
306 | Klass* klass, jfieldID fieldID, bool is_static, char sig_type, |
307 | jvalue *value); |
308 | static void post_raw_field_modification(JavaThread *thread, Method* method, |
309 | address location, Klass* field_klass, Handle object, jfieldID field, |
310 | char sig_type, jvalue *value) NOT_JVMTI_RETURN; |
311 | |
312 | static void post_method_entry (JavaThread *thread, Method* method, frame current_frame) NOT_JVMTI_RETURN; |
313 | static void post_method_exit (JavaThread *thread, Method* method, frame current_frame) NOT_JVMTI_RETURN; |
314 | |
315 | static void post_class_load (JavaThread *thread, Klass* klass) NOT_JVMTI_RETURN; |
316 | static void post_class_unload (Klass* klass) NOT_JVMTI_RETURN; |
317 | static void post_class_prepare (JavaThread *thread, Klass* klass) NOT_JVMTI_RETURN; |
318 | |
319 | static void post_thread_start (JavaThread *thread) NOT_JVMTI_RETURN; |
320 | static void post_thread_end (JavaThread *thread) NOT_JVMTI_RETURN; |
321 | |
322 | // Support for java.lang.instrument agent loading. |
323 | static bool _should_post_class_file_load_hook; |
324 | inline static void set_should_post_class_file_load_hook(bool on) { _should_post_class_file_load_hook = on; } |
325 | inline static bool should_post_class_file_load_hook() { |
326 | JVMTI_ONLY(return _should_post_class_file_load_hook); |
327 | NOT_JVMTI(return false;) |
328 | } |
329 | static bool is_early_phase() NOT_JVMTI_RETURN_(false); |
330 | static bool has_early_class_hook_env() NOT_JVMTI_RETURN_(false); |
331 | // Return true if the class was modified by the hook. |
332 | static bool post_class_file_load_hook(Symbol* h_name, Handle class_loader, |
333 | Handle h_protection_domain, |
334 | unsigned char **data_ptr, unsigned char **end_ptr, |
335 | JvmtiCachedClassFileData **cache_ptr) NOT_JVMTI_RETURN_(false); |
336 | static void post_native_method_bind(Method* method, address* function_ptr) NOT_JVMTI_RETURN; |
337 | static void post_compiled_method_load(nmethod *nm) NOT_JVMTI_RETURN; |
338 | static void post_dynamic_code_generated(const char *name, const void *code_begin, const void *code_end) NOT_JVMTI_RETURN; |
339 | |
340 | // used to post a CompiledMethodUnload event |
341 | static void post_compiled_method_unload(jmethodID mid, const void *code_begin) NOT_JVMTI_RETURN; |
342 | |
343 | // similiar to post_dynamic_code_generated except that it can be used to |
344 | // post a DynamicCodeGenerated event while holding locks in the VM. Any event |
345 | // posted using this function is recorded by the enclosing event collector |
346 | // -- JvmtiDynamicCodeEventCollector. |
347 | static void post_dynamic_code_generated_while_holding_locks(const char* name, address code_begin, address code_end) NOT_JVMTI_RETURN; |
348 | |
349 | static void post_garbage_collection_finish() NOT_JVMTI_RETURN; |
350 | static void post_garbage_collection_start() NOT_JVMTI_RETURN; |
351 | static void post_data_dump() NOT_JVMTI_RETURN; |
352 | static void post_monitor_contended_enter(JavaThread *thread, ObjectMonitor *obj_mntr) NOT_JVMTI_RETURN; |
353 | static void post_monitor_contended_entered(JavaThread *thread, ObjectMonitor *obj_mntr) NOT_JVMTI_RETURN; |
354 | static void post_monitor_wait(JavaThread *thread, oop obj, jlong timeout) NOT_JVMTI_RETURN; |
355 | static void post_monitor_waited(JavaThread *thread, ObjectMonitor *obj_mntr, jboolean timed_out) NOT_JVMTI_RETURN; |
356 | static void post_object_free(JvmtiEnv* env, jlong tag) NOT_JVMTI_RETURN; |
357 | static void post_resource_exhausted(jint resource_exhausted_flags, const char* detail) NOT_JVMTI_RETURN; |
358 | static void record_vm_internal_object_allocation(oop object) NOT_JVMTI_RETURN; |
359 | // Post objects collected by vm_object_alloc_event_collector. |
360 | static void post_vm_object_alloc(JavaThread *thread, oop object) NOT_JVMTI_RETURN; |
361 | // Collects vm internal objects for later event posting. |
362 | inline static void vm_object_alloc_event_collector(oop object) { |
363 | if (should_post_vm_object_alloc()) { |
364 | record_vm_internal_object_allocation(object); |
365 | } |
366 | } |
367 | |
368 | static void record_sampled_internal_object_allocation(oop object) NOT_JVMTI_RETURN; |
369 | // Post objects collected by sampled_object_alloc_event_collector. |
370 | static void post_sampled_object_alloc(JavaThread *thread, oop object) NOT_JVMTI_RETURN; |
371 | |
372 | // Collects vm internal objects for later event posting. |
373 | inline static void sampled_object_alloc_event_collector(oop object) { |
374 | if (should_post_sampled_object_alloc()) { |
375 | record_sampled_internal_object_allocation(object); |
376 | } |
377 | } |
378 | |
379 | inline static void post_array_size_exhausted() { |
380 | if (should_post_resource_exhausted()) { |
381 | post_resource_exhausted(JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR, |
382 | "Requested array size exceeds VM limit" ); |
383 | } |
384 | } |
385 | |
386 | static void cleanup_thread (JavaThread* thread) NOT_JVMTI_RETURN; |
387 | static void clear_detected_exception (JavaThread* thread) NOT_JVMTI_RETURN; |
388 | |
389 | static void oops_do(OopClosure* f) NOT_JVMTI_RETURN; |
390 | static void weak_oops_do(BoolObjectClosure* b, OopClosure* f) NOT_JVMTI_RETURN; |
391 | static void gc_epilogue() NOT_JVMTI_RETURN; |
392 | |
393 | static void transition_pending_onload_raw_monitors() NOT_JVMTI_RETURN; |
394 | |
395 | #if INCLUDE_SERVICES |
396 | // attach support |
397 | static jint load_agent_library(const char *agent, const char *absParam, const char *options, outputStream* out) NOT_JVMTI_RETURN_(JNI_ERR); |
398 | #endif |
399 | |
400 | // SetNativeMethodPrefix support |
401 | static char** get_all_native_method_prefixes(int* count_ptr) NOT_JVMTI_RETURN_(NULL); |
402 | |
403 | // JavaThread lifecycle support: |
404 | static jvmtiError cv_external_thread_to_JavaThread(ThreadsList * t_list, |
405 | jthread thread, |
406 | JavaThread ** jt_pp, |
407 | oop * thread_oop_p); |
408 | static jvmtiError cv_oop_to_JavaThread(ThreadsList * t_list, oop thread_oop, |
409 | JavaThread ** jt_pp); |
410 | }; |
411 | |
412 | // Support class used by JvmtiDynamicCodeEventCollector and others. It |
413 | // describes a single code blob by name and address range. |
414 | class JvmtiCodeBlobDesc : public CHeapObj<mtInternal> { |
415 | private: |
416 | char _name[64]; |
417 | address _code_begin; |
418 | address _code_end; |
419 | |
420 | public: |
421 | JvmtiCodeBlobDesc(const char *name, address code_begin, address code_end) { |
422 | assert(name != NULL, "all code blobs must be named" ); |
423 | strncpy(_name, name, sizeof(_name) - 1); |
424 | _name[sizeof(_name)-1] = '\0'; |
425 | _code_begin = code_begin; |
426 | _code_end = code_end; |
427 | } |
428 | char* name() { return _name; } |
429 | address code_begin() { return _code_begin; } |
430 | address code_end() { return _code_end; } |
431 | }; |
432 | |
433 | // JvmtiEventCollector is a helper class to setup thread for |
434 | // event collection. |
435 | class JvmtiEventCollector : public StackObj { |
436 | private: |
437 | JvmtiEventCollector* _prev; // Save previous one to support nested event collector. |
438 | bool _unset_jvmti_thread_state; |
439 | |
440 | public: |
441 | JvmtiEventCollector() : _prev(NULL), _unset_jvmti_thread_state(false) {} |
442 | |
443 | void setup_jvmti_thread_state(); // Set this collector in current thread, returns if success. |
444 | void unset_jvmti_thread_state(); // Reset previous collector in current thread. |
445 | virtual bool is_dynamic_code_event() { return false; } |
446 | virtual bool is_vm_object_alloc_event(){ return false; } |
447 | virtual bool is_sampled_object_alloc_event(){ return false; } |
448 | JvmtiEventCollector *get_prev() { return _prev; } |
449 | }; |
450 | |
451 | // A JvmtiDynamicCodeEventCollector is a helper class for the JvmtiExport |
452 | // interface. It collects "dynamic code generated" events that are posted |
453 | // while holding locks. When the event collector goes out of scope the |
454 | // events will be posted. |
455 | // |
456 | // Usage :- |
457 | // |
458 | // { |
459 | // JvmtiDynamicCodeEventCollector event_collector; |
460 | // : |
461 | // { MutexLocker ml(...) |
462 | // : |
463 | // JvmtiExport::post_dynamic_code_generated_while_holding_locks(...) |
464 | // } |
465 | // // event collector goes out of scope => post events to profiler. |
466 | // } |
467 | |
468 | class JvmtiDynamicCodeEventCollector : public JvmtiEventCollector { |
469 | private: |
470 | GrowableArray<JvmtiCodeBlobDesc*>* _code_blobs; // collected code blob events |
471 | |
472 | friend class JvmtiExport; |
473 | void register_stub(const char* name, address start, address end); |
474 | |
475 | public: |
476 | JvmtiDynamicCodeEventCollector() NOT_JVMTI_RETURN; |
477 | ~JvmtiDynamicCodeEventCollector() NOT_JVMTI_RETURN; |
478 | bool is_dynamic_code_event() { return true; } |
479 | |
480 | }; |
481 | |
482 | // Used as a base class for object allocation collection and then posting |
483 | // the allocations to any event notification callbacks. |
484 | // |
485 | class JvmtiObjectAllocEventCollector : public JvmtiEventCollector { |
486 | protected: |
487 | GrowableArray<oop>* _allocated; // field to record collected allocated object oop. |
488 | bool _enable; // This flag is enabled in constructor if set up in the thread state |
489 | // and disabled in destructor before posting event. To avoid |
490 | // collection of objects allocated while running java code inside |
491 | // agent post_X_object_alloc() event handler. |
492 | void (*_post_callback)(JavaThread*, oop); // what callback to use when destroying the collector. |
493 | |
494 | //GC support |
495 | void oops_do(OopClosure* f); |
496 | |
497 | friend class JvmtiExport; |
498 | |
499 | // Record allocated object oop. |
500 | inline void record_allocation(oop obj); |
501 | |
502 | //GC support |
503 | static void oops_do_for_all_threads(OopClosure* f); |
504 | |
505 | public: |
506 | JvmtiObjectAllocEventCollector() NOT_JVMTI_RETURN; |
507 | |
508 | void generate_call_for_allocated(); |
509 | |
510 | bool is_enabled() { return _enable; } |
511 | void set_enabled(bool on) { _enable = on; } |
512 | }; |
513 | |
514 | // Used to record vm internally allocated object oops and post |
515 | // vm object alloc event for objects visible to java world. |
516 | // Constructor enables JvmtiThreadState flag and all vm allocated |
517 | // objects are recorded in a growable array. When destructor is |
518 | // called the vm object alloc event is posted for each object |
519 | // visible to java world. |
520 | // See jvm.cpp file for its usage. |
521 | // |
522 | class JvmtiVMObjectAllocEventCollector : public JvmtiObjectAllocEventCollector { |
523 | public: |
524 | JvmtiVMObjectAllocEventCollector() NOT_JVMTI_RETURN; |
525 | ~JvmtiVMObjectAllocEventCollector() NOT_JVMTI_RETURN; |
526 | virtual bool is_vm_object_alloc_event() { return true; } |
527 | }; |
528 | |
529 | // Used to record sampled allocated object oops and post |
530 | // sampled object alloc event. |
531 | // Constructor enables JvmtiThreadState flag and all sampled allocated |
532 | // objects are recorded in a growable array. When destructor is |
533 | // called the sampled object alloc event is posted for each sampled object. |
534 | // See jvm.cpp file for its usage. |
535 | // |
536 | class JvmtiSampledObjectAllocEventCollector : public JvmtiObjectAllocEventCollector { |
537 | public: |
538 | JvmtiSampledObjectAllocEventCollector() NOT_JVMTI_RETURN; |
539 | ~JvmtiSampledObjectAllocEventCollector() NOT_JVMTI_RETURN; |
540 | bool is_sampled_object_alloc_event() { return true; } |
541 | static bool object_alloc_is_safe_to_sample() NOT_JVMTI_RETURN_(false); |
542 | }; |
543 | |
544 | // Marker class to disable the posting of VMObjectAlloc events |
545 | // within its scope. |
546 | // |
547 | // Usage :- |
548 | // |
549 | // { |
550 | // NoJvmtiVMObjectAllocMark njm; |
551 | // : |
552 | // // VMObjAlloc event will not be posted |
553 | // JvmtiExport::vm_object_alloc_event_collector(obj); |
554 | // : |
555 | // } |
556 | |
557 | class NoJvmtiVMObjectAllocMark : public StackObj { |
558 | private: |
559 | // enclosing collector if enabled, NULL otherwise |
560 | JvmtiVMObjectAllocEventCollector *_collector; |
561 | |
562 | bool was_enabled() { return _collector != NULL; } |
563 | |
564 | public: |
565 | NoJvmtiVMObjectAllocMark() NOT_JVMTI_RETURN; |
566 | ~NoJvmtiVMObjectAllocMark() NOT_JVMTI_RETURN; |
567 | }; |
568 | |
569 | |
570 | // Base class for reporting GC events to JVMTI. |
571 | class JvmtiGCMarker : public StackObj { |
572 | public: |
573 | JvmtiGCMarker() NOT_JVMTI_RETURN; |
574 | ~JvmtiGCMarker() NOT_JVMTI_RETURN; |
575 | }; |
576 | |
577 | // JvmtiHideSingleStepping is a helper class for hiding |
578 | // internal single step events. |
579 | class JvmtiHideSingleStepping : public StackObj { |
580 | private: |
581 | bool _single_step_hidden; |
582 | JavaThread * _thread; |
583 | |
584 | public: |
585 | JvmtiHideSingleStepping(JavaThread * thread) { |
586 | assert(thread != NULL, "sanity check" ); |
587 | |
588 | _single_step_hidden = false; |
589 | _thread = thread; |
590 | if (JvmtiExport::should_post_single_step()) { |
591 | _single_step_hidden = JvmtiExport::hide_single_stepping(_thread); |
592 | } |
593 | } |
594 | |
595 | ~JvmtiHideSingleStepping() { |
596 | if (_single_step_hidden) { |
597 | JvmtiExport::expose_single_stepping(_thread); |
598 | } |
599 | } |
600 | }; |
601 | |
602 | #endif // SHARE_PRIMS_JVMTIEXPORT_HPP |
603 | |