0
|
1 /*
|
|
2 * Copyright 2003-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or
|
|
21 * have any questions.
|
|
22 *
|
|
23 */
|
|
24
|
|
25 # include "incls/_precompiled.incl"
|
|
26 # include "incls/_jvmtiExport.cpp.incl"
|
|
27
|
|
28 #ifdef JVMTI_TRACE
|
|
29 #define EVT_TRACE(evt,out) if ((JvmtiTrace::event_trace_flags(evt) & JvmtiTrace::SHOW_EVENT_SENT) != 0) { SafeResourceMark rm; tty->print_cr out; }
|
|
30 #define EVT_TRIG_TRACE(evt,out) if ((JvmtiTrace::event_trace_flags(evt) & JvmtiTrace::SHOW_EVENT_TRIGGER) != 0) { SafeResourceMark rm; tty->print_cr out; }
|
|
31 #else
|
|
32 #define EVT_TRIG_TRACE(evt,out)
|
|
33 #define EVT_TRACE(evt,out)
|
|
34 #endif
|
|
35
|
|
36 ///////////////////////////////////////////////////////////////
|
|
37 //
|
|
38 // JvmtiEventTransition
|
|
39 //
|
|
40 // TO DO --
|
|
41 // more handle purging
|
|
42
|
|
43 // Use this for JavaThreads and state is _thread_in_vm.
|
|
44 class JvmtiJavaThreadEventTransition : StackObj {
|
|
45 private:
|
|
46 ResourceMark _rm;
|
|
47 ThreadToNativeFromVM _transition;
|
|
48 HandleMark _hm;
|
|
49
|
|
50 public:
|
|
51 JvmtiJavaThreadEventTransition(JavaThread *thread) :
|
|
52 _rm(),
|
|
53 _transition(thread),
|
|
54 _hm(thread) {};
|
|
55 };
|
|
56
|
|
57 // For JavaThreads which are not in _thread_in_vm state
|
|
58 // and other system threads use this.
|
|
59 class JvmtiThreadEventTransition : StackObj {
|
|
60 private:
|
|
61 ResourceMark _rm;
|
|
62 HandleMark _hm;
|
|
63 JavaThreadState _saved_state;
|
|
64 JavaThread *_jthread;
|
|
65
|
|
66 public:
|
|
67 JvmtiThreadEventTransition(Thread *thread) : _rm(), _hm() {
|
|
68 if (thread->is_Java_thread()) {
|
|
69 _jthread = (JavaThread *)thread;
|
|
70 _saved_state = _jthread->thread_state();
|
|
71 if (_saved_state == _thread_in_Java) {
|
|
72 ThreadStateTransition::transition_from_java(_jthread, _thread_in_native);
|
|
73 } else {
|
|
74 ThreadStateTransition::transition(_jthread, _saved_state, _thread_in_native);
|
|
75 }
|
|
76 } else {
|
|
77 _jthread = NULL;
|
|
78 }
|
|
79 }
|
|
80
|
|
81 ~JvmtiThreadEventTransition() {
|
|
82 if (_jthread != NULL)
|
|
83 ThreadStateTransition::transition_from_native(_jthread, _saved_state);
|
|
84 }
|
|
85 };
|
|
86
|
|
87
|
|
88 ///////////////////////////////////////////////////////////////
|
|
89 //
|
|
90 // JvmtiEventMark
|
|
91 //
|
|
92
|
|
93 class JvmtiEventMark : public StackObj {
|
|
94 private:
|
|
95 JavaThread *_thread;
|
|
96 JNIEnv* _jni_env;
|
|
97 bool _exception_detected;
|
|
98 bool _exception_caught;
|
|
99 #if 0
|
|
100 JNIHandleBlock* _hblock;
|
|
101 #endif
|
|
102
|
|
103 public:
|
|
104 JvmtiEventMark(JavaThread *thread) : _thread(thread),
|
|
105 _jni_env(thread->jni_environment()) {
|
|
106 #if 0
|
|
107 _hblock = thread->active_handles();
|
|
108 _hblock->clear_thoroughly(); // so we can be safe
|
|
109 #else
|
|
110 // we want to use the code above - but that needs the JNIHandle changes - later...
|
|
111 // for now, steal JNI push local frame code
|
|
112 JvmtiThreadState *state = thread->jvmti_thread_state();
|
|
113 // we are before an event.
|
|
114 // Save current jvmti thread exception state.
|
|
115 if (state != NULL) {
|
|
116 _exception_detected = state->is_exception_detected();
|
|
117 _exception_caught = state->is_exception_caught();
|
|
118 } else {
|
|
119 _exception_detected = false;
|
|
120 _exception_caught = false;
|
|
121 }
|
|
122
|
|
123 JNIHandleBlock* old_handles = thread->active_handles();
|
|
124 JNIHandleBlock* new_handles = JNIHandleBlock::allocate_block(thread);
|
|
125 assert(new_handles != NULL, "should not be NULL");
|
|
126 new_handles->set_pop_frame_link(old_handles);
|
|
127 thread->set_active_handles(new_handles);
|
|
128 #endif
|
|
129 assert(thread == JavaThread::current(), "thread must be current!");
|
|
130 thread->frame_anchor()->make_walkable(thread);
|
|
131 };
|
|
132
|
|
133 ~JvmtiEventMark() {
|
|
134 #if 0
|
|
135 _hblock->clear(); // for consistency with future correct behavior
|
|
136 #else
|
|
137 // we want to use the code above - but that needs the JNIHandle changes - later...
|
|
138 // for now, steal JNI pop local frame code
|
|
139 JNIHandleBlock* old_handles = _thread->active_handles();
|
|
140 JNIHandleBlock* new_handles = old_handles->pop_frame_link();
|
|
141 assert(new_handles != NULL, "should not be NULL");
|
|
142 _thread->set_active_handles(new_handles);
|
|
143 // Note that we set the pop_frame_link to NULL explicitly, otherwise
|
|
144 // the release_block call will release the blocks.
|
|
145 old_handles->set_pop_frame_link(NULL);
|
|
146 JNIHandleBlock::release_block(old_handles, _thread); // may block
|
|
147 #endif
|
|
148
|
|
149 JvmtiThreadState* state = _thread->jvmti_thread_state();
|
|
150 // we are continuing after an event.
|
|
151 if (state != NULL) {
|
|
152 // Restore the jvmti thread exception state.
|
|
153 if (_exception_detected) {
|
|
154 state->set_exception_detected();
|
|
155 }
|
|
156 if (_exception_caught) {
|
|
157 state->set_exception_caught();
|
|
158 }
|
|
159 }
|
|
160 }
|
|
161
|
|
162 #if 0
|
|
163 jobject to_jobject(oop obj) { return obj == NULL? NULL : _hblock->allocate_handle_fast(obj); }
|
|
164 #else
|
|
165 // we want to use the code above - but that needs the JNIHandle changes - later...
|
|
166 // for now, use regular make_local
|
|
167 jobject to_jobject(oop obj) { return JNIHandles::make_local(_thread,obj); }
|
|
168 #endif
|
|
169
|
|
170 jclass to_jclass(klassOop klass) { return (klass == NULL ? NULL : (jclass)to_jobject(Klass::cast(klass)->java_mirror())); }
|
|
171
|
|
172 jmethodID to_jmethodID(methodHandle method) { return method->jmethod_id(); }
|
|
173
|
|
174 JNIEnv* jni_env() { return _jni_env; }
|
|
175 };
|
|
176
|
|
177 class JvmtiThreadEventMark : public JvmtiEventMark {
|
|
178 private:
|
|
179 jthread _jt;
|
|
180
|
|
181 public:
|
|
182 JvmtiThreadEventMark(JavaThread *thread) :
|
|
183 JvmtiEventMark(thread) {
|
|
184 _jt = (jthread)(to_jobject(thread->threadObj()));
|
|
185 };
|
|
186 jthread jni_thread() { return _jt; }
|
|
187 };
|
|
188
|
|
189 class JvmtiClassEventMark : public JvmtiThreadEventMark {
|
|
190 private:
|
|
191 jclass _jc;
|
|
192
|
|
193 public:
|
|
194 JvmtiClassEventMark(JavaThread *thread, klassOop klass) :
|
|
195 JvmtiThreadEventMark(thread) {
|
|
196 _jc = to_jclass(klass);
|
|
197 };
|
|
198 jclass jni_class() { return _jc; }
|
|
199 };
|
|
200
|
|
201 class JvmtiMethodEventMark : public JvmtiThreadEventMark {
|
|
202 private:
|
|
203 jmethodID _mid;
|
|
204
|
|
205 public:
|
|
206 JvmtiMethodEventMark(JavaThread *thread, methodHandle method) :
|
|
207 JvmtiThreadEventMark(thread),
|
|
208 _mid(to_jmethodID(method)) {};
|
|
209 jmethodID jni_methodID() { return _mid; }
|
|
210 };
|
|
211
|
|
212 class JvmtiLocationEventMark : public JvmtiMethodEventMark {
|
|
213 private:
|
|
214 jlocation _loc;
|
|
215
|
|
216 public:
|
|
217 JvmtiLocationEventMark(JavaThread *thread, methodHandle method, address location) :
|
|
218 JvmtiMethodEventMark(thread, method),
|
|
219 _loc(location - method->code_base()) {};
|
|
220 jlocation location() { return _loc; }
|
|
221 };
|
|
222
|
|
223 class JvmtiExceptionEventMark : public JvmtiLocationEventMark {
|
|
224 private:
|
|
225 jobject _exc;
|
|
226
|
|
227 public:
|
|
228 JvmtiExceptionEventMark(JavaThread *thread, methodHandle method, address location, Handle exception) :
|
|
229 JvmtiLocationEventMark(thread, method, location),
|
|
230 _exc(to_jobject(exception())) {};
|
|
231 jobject exception() { return _exc; }
|
|
232 };
|
|
233
|
|
234 class JvmtiClassFileLoadEventMark : public JvmtiThreadEventMark {
|
|
235 private:
|
|
236 const char *_class_name;
|
|
237 jobject _jloader;
|
|
238 jobject _protection_domain;
|
|
239 jclass _class_being_redefined;
|
|
240
|
|
241 public:
|
|
242 JvmtiClassFileLoadEventMark(JavaThread *thread, symbolHandle name,
|
|
243 Handle class_loader, Handle prot_domain, KlassHandle *class_being_redefined) : JvmtiThreadEventMark(thread) {
|
|
244 _class_name = name() != NULL? name->as_utf8() : NULL;
|
|
245 _jloader = (jobject)to_jobject(class_loader());
|
|
246 _protection_domain = (jobject)to_jobject(prot_domain());
|
|
247 if (class_being_redefined == NULL) {
|
|
248 _class_being_redefined = NULL;
|
|
249 } else {
|
|
250 _class_being_redefined = (jclass)to_jclass((*class_being_redefined)());
|
|
251 }
|
|
252 };
|
|
253 const char *class_name() {
|
|
254 return _class_name;
|
|
255 }
|
|
256 jobject jloader() {
|
|
257 return _jloader;
|
|
258 }
|
|
259 jobject protection_domain() {
|
|
260 return _protection_domain;
|
|
261 }
|
|
262 jclass class_being_redefined() {
|
|
263 return _class_being_redefined;
|
|
264 }
|
|
265 };
|
|
266
|
|
267 //////////////////////////////////////////////////////////////////////////////
|
|
268
|
|
269 int JvmtiExport::_field_access_count = 0;
|
|
270 int JvmtiExport::_field_modification_count = 0;
|
|
271
|
|
272 bool JvmtiExport::_can_access_local_variables = false;
|
|
273 bool JvmtiExport::_can_examine_or_deopt_anywhere = false;
|
|
274 bool JvmtiExport::_can_hotswap_or_post_breakpoint = false;
|
|
275 bool JvmtiExport::_can_modify_any_class = false;
|
|
276 bool JvmtiExport::_can_walk_any_space = false;
|
|
277
|
|
278 bool JvmtiExport::_has_redefined_a_class = false;
|
|
279 bool JvmtiExport::_all_dependencies_are_recorded = false;
|
|
280
|
|
281 //
|
|
282 // field access management
|
|
283 //
|
|
284
|
|
285 // interpreter generator needs the address of the counter
|
|
286 address JvmtiExport::get_field_access_count_addr() {
|
|
287 // We don't grab a lock because we don't want to
|
|
288 // serialize field access between all threads. This means that a
|
|
289 // thread on another processor can see the wrong count value and
|
|
290 // may either miss making a needed call into post_field_access()
|
|
291 // or will make an unneeded call into post_field_access(). We pay
|
|
292 // this price to avoid slowing down the VM when we aren't watching
|
|
293 // field accesses.
|
|
294 // Other access/mutation safe by virtue of being in VM state.
|
|
295 return (address)(&_field_access_count);
|
|
296 }
|
|
297
|
|
298 //
|
|
299 // field modification management
|
|
300 //
|
|
301
|
|
302 // interpreter generator needs the address of the counter
|
|
303 address JvmtiExport::get_field_modification_count_addr() {
|
|
304 // We don't grab a lock because we don't
|
|
305 // want to serialize field modification between all threads. This
|
|
306 // means that a thread on another processor can see the wrong
|
|
307 // count value and may either miss making a needed call into
|
|
308 // post_field_modification() or will make an unneeded call into
|
|
309 // post_field_modification(). We pay this price to avoid slowing
|
|
310 // down the VM when we aren't watching field modifications.
|
|
311 // Other access/mutation safe by virtue of being in VM state.
|
|
312 return (address)(&_field_modification_count);
|
|
313 }
|
|
314
|
|
315
|
|
316 ///////////////////////////////////////////////////////////////
|
|
317 // Functions needed by java.lang.instrument for starting up javaagent.
|
|
318 ///////////////////////////////////////////////////////////////
|
|
319
|
|
320 jint
|
|
321 JvmtiExport::get_jvmti_interface(JavaVM *jvm, void **penv, jint version) {
|
|
322 /* To Do: add version checks */
|
|
323
|
|
324 if (JvmtiEnv::get_phase() == JVMTI_PHASE_LIVE) {
|
|
325 JavaThread* current_thread = (JavaThread*) ThreadLocalStorage::thread();
|
|
326 // transition code: native to VM
|
|
327 ThreadInVMfromNative __tiv(current_thread);
|
|
328 __ENTRY(jvmtiEnv*, JvmtiExport::get_jvmti_interface, current_thread)
|
|
329 debug_only(VMNativeEntryWrapper __vew;)
|
|
330
|
|
331 JvmtiEnv *jvmti_env = JvmtiEnv::create_a_jvmti();
|
|
332 *penv = jvmti_env->jvmti_external(); // actual type is jvmtiEnv* -- not to be confused with JvmtiEnv*
|
|
333 return JNI_OK;
|
|
334
|
|
335 } else if (JvmtiEnv::get_phase() == JVMTI_PHASE_ONLOAD) {
|
|
336 // not live, no thread to transition
|
|
337 JvmtiEnv *jvmti_env = JvmtiEnv::create_a_jvmti();
|
|
338 *penv = jvmti_env->jvmti_external(); // actual type is jvmtiEnv* -- not to be confused with JvmtiEnv*
|
|
339 return JNI_OK;
|
|
340
|
|
341 } else {
|
|
342 // Called at the wrong time
|
|
343 *penv = NULL;
|
|
344 return JNI_EDETACHED;
|
|
345 }
|
|
346 }
|
|
347
|
|
348 void JvmtiExport::enter_primordial_phase() {
|
|
349 JvmtiEnvBase::set_phase(JVMTI_PHASE_PRIMORDIAL);
|
|
350 }
|
|
351
|
|
352 void JvmtiExport::enter_start_phase() {
|
|
353 JvmtiManageCapabilities::recompute_always_capabilities();
|
|
354 JvmtiEnvBase::set_phase(JVMTI_PHASE_START);
|
|
355 }
|
|
356
|
|
357 void JvmtiExport::enter_onload_phase() {
|
|
358 JvmtiEnvBase::set_phase(JVMTI_PHASE_ONLOAD);
|
|
359 }
|
|
360
|
|
361 void JvmtiExport::enter_live_phase() {
|
|
362 JvmtiEnvBase::set_phase(JVMTI_PHASE_LIVE);
|
|
363 }
|
|
364
|
|
365 //
|
|
366 // JVMTI events that the VM posts to the debugger and also startup agent
|
|
367 // and call the agent's premain() for java.lang.instrument.
|
|
368 //
|
|
369
|
|
370 void JvmtiExport::post_vm_start() {
|
|
371 EVT_TRIG_TRACE(JVMTI_EVENT_VM_START, ("JVMTI Trg VM start event triggered" ));
|
|
372
|
|
373 // can now enable some events
|
|
374 JvmtiEventController::vm_start();
|
|
375
|
|
376 JvmtiEnvIterator it;
|
|
377 for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
|
378 if (env->is_enabled(JVMTI_EVENT_VM_START)) {
|
|
379 EVT_TRACE(JVMTI_EVENT_VM_START, ("JVMTI Evt VM start event sent" ));
|
|
380
|
|
381 JavaThread *thread = JavaThread::current();
|
|
382 JvmtiThreadEventMark jem(thread);
|
|
383 JvmtiJavaThreadEventTransition jet(thread);
|
|
384 jvmtiEventVMStart callback = env->callbacks()->VMStart;
|
|
385 if (callback != NULL) {
|
|
386 (*callback)(env->jvmti_external(), jem.jni_env());
|
|
387 }
|
|
388 }
|
|
389 }
|
|
390 }
|
|
391
|
|
392
|
|
393 void JvmtiExport::post_vm_initialized() {
|
|
394 EVT_TRIG_TRACE(JVMTI_EVENT_VM_INIT, ("JVMTI Trg VM init event triggered" ));
|
|
395
|
|
396 // can now enable events
|
|
397 JvmtiEventController::vm_init();
|
|
398
|
|
399 JvmtiEnvIterator it;
|
|
400 for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
|
401 if (env->is_enabled(JVMTI_EVENT_VM_INIT)) {
|
|
402 EVT_TRACE(JVMTI_EVENT_VM_INIT, ("JVMTI Evt VM init event sent" ));
|
|
403
|
|
404 JavaThread *thread = JavaThread::current();
|
|
405 JvmtiThreadEventMark jem(thread);
|
|
406 JvmtiJavaThreadEventTransition jet(thread);
|
|
407 jvmtiEventVMInit callback = env->callbacks()->VMInit;
|
|
408 if (callback != NULL) {
|
|
409 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread());
|
|
410 }
|
|
411 }
|
|
412 }
|
|
413 }
|
|
414
|
|
415
|
|
416 void JvmtiExport::post_vm_death() {
|
|
417 EVT_TRIG_TRACE(JVMTI_EVENT_VM_DEATH, ("JVMTI Trg VM death event triggered" ));
|
|
418
|
|
419 JvmtiEnvIterator it;
|
|
420 for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
|
421 if (env->is_enabled(JVMTI_EVENT_VM_DEATH)) {
|
|
422 EVT_TRACE(JVMTI_EVENT_VM_DEATH, ("JVMTI Evt VM death event sent" ));
|
|
423
|
|
424 JavaThread *thread = JavaThread::current();
|
|
425 JvmtiEventMark jem(thread);
|
|
426 JvmtiJavaThreadEventTransition jet(thread);
|
|
427 jvmtiEventVMDeath callback = env->callbacks()->VMDeath;
|
|
428 if (callback != NULL) {
|
|
429 (*callback)(env->jvmti_external(), jem.jni_env());
|
|
430 }
|
|
431 }
|
|
432 }
|
|
433
|
|
434 JvmtiEnvBase::set_phase(JVMTI_PHASE_DEAD);
|
|
435 JvmtiEventController::vm_death();
|
|
436 }
|
|
437
|
|
438 char**
|
|
439 JvmtiExport::get_all_native_method_prefixes(int* count_ptr) {
|
|
440 // Have to grab JVMTI thread state lock to be sure environment doesn't
|
|
441 // go away while we iterate them. No locks during VM bring-up.
|
|
442 if (Threads::number_of_threads() == 0 || SafepointSynchronize::is_at_safepoint()) {
|
|
443 return JvmtiEnvBase::get_all_native_method_prefixes(count_ptr);
|
|
444 } else {
|
|
445 MutexLocker mu(JvmtiThreadState_lock);
|
|
446 return JvmtiEnvBase::get_all_native_method_prefixes(count_ptr);
|
|
447 }
|
|
448 }
|
|
449
|
|
450 class JvmtiClassFileLoadHookPoster : public StackObj {
|
|
451 private:
|
|
452 symbolHandle _h_name;
|
|
453 Handle _class_loader;
|
|
454 Handle _h_protection_domain;
|
|
455 unsigned char ** _data_ptr;
|
|
456 unsigned char ** _end_ptr;
|
|
457 JavaThread * _thread;
|
|
458 jint _curr_len;
|
|
459 unsigned char * _curr_data;
|
|
460 JvmtiEnv * _curr_env;
|
|
461 jint * _cached_length_ptr;
|
|
462 unsigned char ** _cached_data_ptr;
|
|
463 JvmtiThreadState * _state;
|
|
464 KlassHandle * _h_class_being_redefined;
|
|
465 JvmtiClassLoadKind _load_kind;
|
|
466
|
|
467 public:
|
|
468 inline JvmtiClassFileLoadHookPoster(symbolHandle h_name, Handle class_loader,
|
|
469 Handle h_protection_domain,
|
|
470 unsigned char **data_ptr, unsigned char **end_ptr,
|
|
471 unsigned char **cached_data_ptr,
|
|
472 jint *cached_length_ptr) {
|
|
473 _h_name = h_name;
|
|
474 _class_loader = class_loader;
|
|
475 _h_protection_domain = h_protection_domain;
|
|
476 _data_ptr = data_ptr;
|
|
477 _end_ptr = end_ptr;
|
|
478 _thread = JavaThread::current();
|
|
479 _curr_len = *end_ptr - *data_ptr;
|
|
480 _curr_data = *data_ptr;
|
|
481 _curr_env = NULL;
|
|
482 _cached_length_ptr = cached_length_ptr;
|
|
483 _cached_data_ptr = cached_data_ptr;
|
|
484 *_cached_length_ptr = 0;
|
|
485 *_cached_data_ptr = NULL;
|
|
486
|
|
487 _state = _thread->jvmti_thread_state();
|
|
488 if (_state != NULL) {
|
|
489 _h_class_being_redefined = _state->get_class_being_redefined();
|
|
490 _load_kind = _state->get_class_load_kind();
|
|
491 // Clear class_being_redefined flag here. The action
|
|
492 // from agent handler could generate a new class file load
|
|
493 // hook event and if it is not cleared the new event generated
|
|
494 // from regular class file load could have this stale redefined
|
|
495 // class handle info.
|
|
496 _state->clear_class_being_redefined();
|
|
497 } else {
|
|
498 // redefine and retransform will always set the thread state
|
|
499 _h_class_being_redefined = (KlassHandle *) NULL;
|
|
500 _load_kind = jvmti_class_load_kind_load;
|
|
501 }
|
|
502 }
|
|
503
|
|
504 void post() {
|
|
505 // EVT_TRIG_TRACE(JVMTI_EVENT_CLASS_FILE_LOAD_HOOK,
|
|
506 // ("JVMTI [%s] class file load hook event triggered",
|
|
507 // JvmtiTrace::safe_get_thread_name(_thread)));
|
|
508 post_all_envs();
|
|
509 copy_modified_data();
|
|
510 }
|
|
511
|
|
512 private:
|
|
513 void post_all_envs() {
|
|
514 if (_load_kind != jvmti_class_load_kind_retransform) {
|
|
515 // for class load and redefine,
|
|
516 // call the non-retransformable agents
|
|
517 JvmtiEnvIterator it;
|
|
518 for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
|
519 if (!env->is_retransformable() && env->is_enabled(JVMTI_EVENT_CLASS_FILE_LOAD_HOOK)) {
|
|
520 // non-retransformable agents cannot retransform back,
|
|
521 // so no need to cache the original class file bytes
|
|
522 post_to_env(env, false);
|
|
523 }
|
|
524 }
|
|
525 }
|
|
526 JvmtiEnvIterator it;
|
|
527 for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
|
528 // retransformable agents get all events
|
|
529 if (env->is_retransformable() && env->is_enabled(JVMTI_EVENT_CLASS_FILE_LOAD_HOOK)) {
|
|
530 // retransformable agents need to cache the original class file
|
|
531 // bytes if changes are made via the ClassFileLoadHook
|
|
532 post_to_env(env, true);
|
|
533 }
|
|
534 }
|
|
535 }
|
|
536
|
|
537 void post_to_env(JvmtiEnv* env, bool caching_needed) {
|
|
538 unsigned char *new_data = NULL;
|
|
539 jint new_len = 0;
|
|
540 // EVT_TRACE(JVMTI_EVENT_CLASS_FILE_LOAD_HOOK,
|
|
541 // ("JVMTI [%s] class file load hook event sent %s data_ptr = %d, data_len = %d",
|
|
542 // JvmtiTrace::safe_get_thread_name(_thread),
|
|
543 // _h_name.is_null() ? "NULL" : _h_name->as_utf8(),
|
|
544 // _curr_data, _curr_len ));
|
|
545 JvmtiClassFileLoadEventMark jem(_thread, _h_name, _class_loader,
|
|
546 _h_protection_domain,
|
|
547 _h_class_being_redefined);
|
|
548 JvmtiJavaThreadEventTransition jet(_thread);
|
|
549 JNIEnv* jni_env = (JvmtiEnv::get_phase() == JVMTI_PHASE_PRIMORDIAL)?
|
|
550 NULL : jem.jni_env();
|
|
551 jvmtiEventClassFileLoadHook callback = env->callbacks()->ClassFileLoadHook;
|
|
552 if (callback != NULL) {
|
|
553 (*callback)(env->jvmti_external(), jni_env,
|
|
554 jem.class_being_redefined(),
|
|
555 jem.jloader(), jem.class_name(),
|
|
556 jem.protection_domain(),
|
|
557 _curr_len, _curr_data,
|
|
558 &new_len, &new_data);
|
|
559 }
|
|
560 if (new_data != NULL) {
|
|
561 // this agent has modified class data.
|
|
562 if (caching_needed && *_cached_data_ptr == NULL) {
|
|
563 // data has been changed by the new retransformable agent
|
|
564 // and it hasn't already been cached, cache it
|
|
565 *_cached_data_ptr = (unsigned char *)os::malloc(_curr_len);
|
|
566 memcpy(*_cached_data_ptr, _curr_data, _curr_len);
|
|
567 *_cached_length_ptr = _curr_len;
|
|
568 }
|
|
569
|
|
570 if (_curr_data != *_data_ptr) {
|
|
571 // curr_data is previous agent modified class data.
|
|
572 // And this has been changed by the new agent so
|
|
573 // we can delete it now.
|
|
574 _curr_env->Deallocate(_curr_data);
|
|
575 }
|
|
576
|
|
577 // Class file data has changed by the current agent.
|
|
578 _curr_data = new_data;
|
|
579 _curr_len = new_len;
|
|
580 // Save the current agent env we need this to deallocate the
|
|
581 // memory allocated by this agent.
|
|
582 _curr_env = env;
|
|
583 }
|
|
584 }
|
|
585
|
|
586 void copy_modified_data() {
|
|
587 // if one of the agent has modified class file data.
|
|
588 // Copy modified class data to new resources array.
|
|
589 if (_curr_data != *_data_ptr) {
|
|
590 *_data_ptr = NEW_RESOURCE_ARRAY(u1, _curr_len);
|
|
591 memcpy(*_data_ptr, _curr_data, _curr_len);
|
|
592 *_end_ptr = *_data_ptr + _curr_len;
|
|
593 _curr_env->Deallocate(_curr_data);
|
|
594 }
|
|
595 }
|
|
596 };
|
|
597
|
|
598 bool JvmtiExport::_should_post_class_file_load_hook = false;
|
|
599
|
|
600 // this entry is for class file load hook on class load, redefine and retransform
|
|
601 void JvmtiExport::post_class_file_load_hook(symbolHandle h_name,
|
|
602 Handle class_loader,
|
|
603 Handle h_protection_domain,
|
|
604 unsigned char **data_ptr,
|
|
605 unsigned char **end_ptr,
|
|
606 unsigned char **cached_data_ptr,
|
|
607 jint *cached_length_ptr) {
|
|
608 JvmtiClassFileLoadHookPoster poster(h_name, class_loader,
|
|
609 h_protection_domain,
|
|
610 data_ptr, end_ptr,
|
|
611 cached_data_ptr,
|
|
612 cached_length_ptr);
|
|
613 poster.post();
|
|
614 }
|
|
615
|
|
616 void JvmtiExport::report_unsupported(bool on) {
|
|
617 // If any JVMTI service is turned on, we need to exit before native code
|
|
618 // tries to access nonexistant services.
|
|
619 if (on) {
|
|
620 vm_exit_during_initialization("Java Kernel does not support JVMTI.");
|
|
621 }
|
|
622 }
|
|
623
|
|
624
|
|
625 #ifndef JVMTI_KERNEL
|
|
626 static inline klassOop oop_to_klassOop(oop obj) {
|
|
627 klassOop k = obj->klass();
|
|
628
|
|
629 // if the object is a java.lang.Class then return the java mirror
|
|
630 if (k == SystemDictionary::class_klass()) {
|
|
631 if (!java_lang_Class::is_primitive(obj)) {
|
|
632 k = java_lang_Class::as_klassOop(obj);
|
|
633 assert(k != NULL, "class for non-primitive mirror must exist");
|
|
634 }
|
|
635 }
|
|
636 return k;
|
|
637 }
|
|
638
|
|
639 class JvmtiVMObjectAllocEventMark : public JvmtiClassEventMark {
|
|
640 private:
|
|
641 jobject _jobj;
|
|
642 jlong _size;
|
|
643 public:
|
|
644 JvmtiVMObjectAllocEventMark(JavaThread *thread, oop obj) : JvmtiClassEventMark(thread, oop_to_klassOop(obj)) {
|
|
645 _jobj = (jobject)to_jobject(obj);
|
|
646 _size = obj->size() * wordSize;
|
|
647 };
|
|
648 jobject jni_jobject() { return _jobj; }
|
|
649 jlong size() { return _size; }
|
|
650 };
|
|
651
|
|
652 class JvmtiCompiledMethodLoadEventMark : public JvmtiMethodEventMark {
|
|
653 private:
|
|
654 jint _code_size;
|
|
655 const void *_code_data;
|
|
656 jint _map_length;
|
|
657 jvmtiAddrLocationMap *_map;
|
|
658 const void *_compile_info;
|
|
659 public:
|
|
660 JvmtiCompiledMethodLoadEventMark(JavaThread *thread, nmethod *nm)
|
|
661 : JvmtiMethodEventMark(thread,methodHandle(thread, nm->method())) {
|
|
662 _code_data = nm->code_begin();
|
|
663 _code_size = nm->code_size();
|
|
664 _compile_info = NULL; /* no info for our VM. */
|
|
665 JvmtiCodeBlobEvents::build_jvmti_addr_location_map(nm, &_map, &_map_length);
|
|
666 }
|
|
667 ~JvmtiCompiledMethodLoadEventMark() {
|
|
668 FREE_C_HEAP_ARRAY(jvmtiAddrLocationMap, _map);
|
|
669 }
|
|
670
|
|
671 jint code_size() { return _code_size; }
|
|
672 const void *code_data() { return _code_data; }
|
|
673 jint map_length() { return _map_length; }
|
|
674 const jvmtiAddrLocationMap* map() { return _map; }
|
|
675 const void *compile_info() { return _compile_info; }
|
|
676 };
|
|
677
|
|
678
|
|
679
|
|
680 class JvmtiMonitorEventMark : public JvmtiThreadEventMark {
|
|
681 private:
|
|
682 jobject _jobj;
|
|
683 public:
|
|
684 JvmtiMonitorEventMark(JavaThread *thread, oop object)
|
|
685 : JvmtiThreadEventMark(thread){
|
|
686 _jobj = to_jobject(object);
|
|
687 }
|
|
688 jobject jni_object() { return _jobj; }
|
|
689 };
|
|
690
|
|
691 ///////////////////////////////////////////////////////////////
|
|
692 //
|
|
693 // pending CompiledMethodUnload support
|
|
694 //
|
|
695
|
|
696 bool JvmtiExport::_have_pending_compiled_method_unload_events;
|
|
697 GrowableArray<jmethodID>* JvmtiExport::_pending_compiled_method_unload_method_ids;
|
|
698 GrowableArray<const void *>* JvmtiExport::_pending_compiled_method_unload_code_begins;
|
|
699 JavaThread* JvmtiExport::_current_poster;
|
|
700
|
|
701 // post any pending CompiledMethodUnload events
|
|
702
|
|
703 void JvmtiExport::post_pending_compiled_method_unload_events() {
|
|
704 JavaThread* self = JavaThread::current();
|
|
705 assert(!self->owns_locks(), "can't hold locks");
|
|
706
|
|
707 // Indicates if this is the first activiation of this function.
|
|
708 // In theory the profiler's callback could call back into VM and provoke
|
|
709 // another CompiledMethodLoad event to be posted from this thread. As the
|
|
710 // stack rewinds we need to ensure that the original activation does the
|
|
711 // completion and notifies any waiters.
|
|
712 bool first_activation = false;
|
|
713
|
|
714 // the jmethodID (may not be valid) to be used for a single event
|
|
715 jmethodID method;
|
|
716 const void *code_begin;
|
|
717
|
|
718 // grab the monitor and check if another thread is already posting
|
|
719 // events. If there is another thread posting events then we wait
|
|
720 // until it completes. (In theory we could check the pending events to
|
|
721 // see if any of the addresses overlap with the event that we want to
|
|
722 // post but as it will happen so rarely we just block any thread waiting
|
|
723 // to post a CompiledMethodLoad or DynamicCodeGenerated event until all
|
|
724 // pending CompiledMethodUnload events have been posted).
|
|
725 //
|
|
726 // If another thread isn't posting we examine the list of pending jmethodIDs.
|
|
727 // If the list is empty then we are done. If it's not empty then this thread
|
|
728 // (self) becomes the pending event poster and we remove the top (last)
|
|
729 // event from the list. Note that this means we remove the newest event first
|
|
730 // but as they are all CompiledMethodUnload events the order doesn't matter.
|
|
731 // Once we have removed a jmethodID then we exit the monitor. Any other thread
|
|
732 // wanting to post a CompiledMethodLoad or DynamicCodeGenerated event will
|
|
733 // be forced to wait on the monitor.
|
|
734 {
|
|
735 MutexLocker mu(JvmtiPendingEvent_lock);
|
|
736 if (_current_poster != self) {
|
|
737 while (_current_poster != NULL) {
|
|
738 JvmtiPendingEvent_lock->wait();
|
|
739 }
|
|
740 }
|
|
741 if ((_pending_compiled_method_unload_method_ids == NULL) ||
|
|
742 (_pending_compiled_method_unload_method_ids->length() == 0)) {
|
|
743 return;
|
|
744 }
|
|
745 if (_current_poster == NULL) {
|
|
746 _current_poster = self;
|
|
747 first_activation = true;
|
|
748 } else {
|
|
749 // re-entrant
|
|
750 guarantee(_current_poster == self, "checking");
|
|
751 }
|
|
752 method = _pending_compiled_method_unload_method_ids->pop();
|
|
753 code_begin = _pending_compiled_method_unload_code_begins->pop();
|
|
754 }
|
|
755
|
|
756 // This thread is the pending event poster so it first posts the CompiledMethodUnload
|
|
757 // event for the jmethodID that has been removed from the list. Once posted it
|
|
758 // re-grabs the monitor and checks the list again. If the list is empty then and this
|
|
759 // is the first activation of the function then we reset the _have_pending_events
|
|
760 // flag, cleanup _current_poster to indicate that no thread is now servicing the
|
|
761 // pending events list, and finally notify any thread that might be waiting.
|
|
762 for (;;) {
|
|
763 EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD,
|
|
764 ("JVMTI [%s] method compile unload event triggered",
|
|
765 JvmtiTrace::safe_get_thread_name(self)));
|
|
766
|
|
767 // post the event for each environment that has this event enabled.
|
|
768 JvmtiEnvIterator it;
|
|
769 for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
|
770 if (env->is_enabled(JVMTI_EVENT_COMPILED_METHOD_UNLOAD)) {
|
|
771 EVT_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD,
|
|
772 ("JVMTI [%s] class compile method unload event sent jmethodID " PTR_FORMAT,
|
|
773 JvmtiTrace::safe_get_thread_name(self), method));
|
|
774
|
|
775 JvmtiEventMark jem(self);
|
|
776 JvmtiJavaThreadEventTransition jet(self);
|
|
777 jvmtiEventCompiledMethodUnload callback = env->callbacks()->CompiledMethodUnload;
|
|
778 if (callback != NULL) {
|
|
779 (*callback)(env->jvmti_external(), method, code_begin);
|
|
780 }
|
|
781 }
|
|
782 }
|
|
783
|
|
784 // event posted, now re-grab monitor and get the next event
|
|
785 // If there's no next event then we are done. If this is the first
|
|
786 // activiation of this function by this thread notify any waiters
|
|
787 // so that they can post.
|
|
788 {
|
|
789 MutexLocker ml(JvmtiPendingEvent_lock);
|
|
790 if (_pending_compiled_method_unload_method_ids->length() == 0) {
|
|
791 if (first_activation) {
|
|
792 _have_pending_compiled_method_unload_events = false;
|
|
793 _current_poster = NULL;
|
|
794 JvmtiPendingEvent_lock->notify_all();
|
|
795 }
|
|
796 return;
|
|
797 }
|
|
798 method = _pending_compiled_method_unload_method_ids->pop();
|
|
799 code_begin = _pending_compiled_method_unload_code_begins->pop();
|
|
800 }
|
|
801 }
|
|
802 }
|
|
803
|
|
804 ///////////////////////////////////////////////////////////////
|
|
805 //
|
|
806 // JvmtiExport
|
|
807 //
|
|
808
|
|
809 void JvmtiExport::post_raw_breakpoint(JavaThread *thread, methodOop method, address location) {
|
|
810 HandleMark hm(thread);
|
|
811 methodHandle mh(thread, method);
|
|
812
|
|
813 JvmtiThreadState *state = thread->jvmti_thread_state();
|
|
814 if (state == NULL) {
|
|
815 return;
|
|
816 }
|
|
817 EVT_TRIG_TRACE(JVMTI_EVENT_BREAKPOINT, ("JVMTI [%s] Trg Breakpoint triggered",
|
|
818 JvmtiTrace::safe_get_thread_name(thread)));
|
|
819 JvmtiEnvThreadStateIterator it(state);
|
|
820 for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
|
|
821 ets->compare_and_set_current_location(mh(), location, JVMTI_EVENT_BREAKPOINT);
|
|
822 if (!ets->breakpoint_posted() && ets->is_enabled(JVMTI_EVENT_BREAKPOINT)) {
|
|
823 ThreadState old_os_state = thread->osthread()->get_state();
|
|
824 thread->osthread()->set_state(BREAKPOINTED);
|
|
825 EVT_TRACE(JVMTI_EVENT_BREAKPOINT, ("JVMTI [%s] Evt Breakpoint sent %s.%s @ %d",
|
|
826 JvmtiTrace::safe_get_thread_name(thread),
|
|
827 (mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),
|
|
828 (mh() == NULL) ? "NULL" : mh()->name()->as_C_string(),
|
|
829 location - mh()->code_base() ));
|
|
830
|
|
831 JvmtiEnv *env = ets->get_env();
|
|
832 JvmtiLocationEventMark jem(thread, mh, location);
|
|
833 JvmtiJavaThreadEventTransition jet(thread);
|
|
834 jvmtiEventBreakpoint callback = env->callbacks()->Breakpoint;
|
|
835 if (callback != NULL) {
|
|
836 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(),
|
|
837 jem.jni_methodID(), jem.location());
|
|
838 }
|
|
839
|
|
840 ets->set_breakpoint_posted();
|
|
841 thread->osthread()->set_state(old_os_state);
|
|
842 }
|
|
843 }
|
|
844 }
|
|
845
|
|
846 //////////////////////////////////////////////////////////////////////////////
|
|
847
|
|
848 bool JvmtiExport::_can_get_source_debug_extension = false;
|
|
849 bool JvmtiExport::_can_maintain_original_method_order = false;
|
|
850 bool JvmtiExport::_can_post_interpreter_events = false;
|
|
851 bool JvmtiExport::_can_post_exceptions = false;
|
|
852 bool JvmtiExport::_can_post_breakpoint = false;
|
|
853 bool JvmtiExport::_can_post_field_access = false;
|
|
854 bool JvmtiExport::_can_post_field_modification = false;
|
|
855 bool JvmtiExport::_can_post_method_entry = false;
|
|
856 bool JvmtiExport::_can_post_method_exit = false;
|
|
857 bool JvmtiExport::_can_pop_frame = false;
|
|
858 bool JvmtiExport::_can_force_early_return = false;
|
|
859
|
|
860 bool JvmtiExport::_should_post_single_step = false;
|
|
861 bool JvmtiExport::_should_post_field_access = false;
|
|
862 bool JvmtiExport::_should_post_field_modification = false;
|
|
863 bool JvmtiExport::_should_post_class_load = false;
|
|
864 bool JvmtiExport::_should_post_class_prepare = false;
|
|
865 bool JvmtiExport::_should_post_class_unload = false;
|
|
866 bool JvmtiExport::_should_post_thread_life = false;
|
|
867 bool JvmtiExport::_should_clean_up_heap_objects = false;
|
|
868 bool JvmtiExport::_should_post_native_method_bind = false;
|
|
869 bool JvmtiExport::_should_post_dynamic_code_generated = false;
|
|
870 bool JvmtiExport::_should_post_data_dump = false;
|
|
871 bool JvmtiExport::_should_post_compiled_method_load = false;
|
|
872 bool JvmtiExport::_should_post_compiled_method_unload = false;
|
|
873 bool JvmtiExport::_should_post_monitor_contended_enter = false;
|
|
874 bool JvmtiExport::_should_post_monitor_contended_entered = false;
|
|
875 bool JvmtiExport::_should_post_monitor_wait = false;
|
|
876 bool JvmtiExport::_should_post_monitor_waited = false;
|
|
877 bool JvmtiExport::_should_post_garbage_collection_start = false;
|
|
878 bool JvmtiExport::_should_post_garbage_collection_finish = false;
|
|
879 bool JvmtiExport::_should_post_object_free = false;
|
|
880 bool JvmtiExport::_should_post_resource_exhausted = false;
|
|
881 bool JvmtiExport::_should_post_vm_object_alloc = false;
|
|
882
|
|
883 ////////////////////////////////////////////////////////////////////////////////////////////////
|
|
884
|
|
885
|
|
886 //
|
|
887 // JVMTI single step management
|
|
888 //
|
|
889 void JvmtiExport::at_single_stepping_point(JavaThread *thread, methodOop method, address location) {
|
|
890 assert(JvmtiExport::should_post_single_step(), "must be single stepping");
|
|
891
|
|
892 HandleMark hm(thread);
|
|
893 methodHandle mh(thread, method);
|
|
894
|
|
895 // update information about current location and post a step event
|
|
896 JvmtiThreadState *state = thread->jvmti_thread_state();
|
|
897 if (state == NULL) {
|
|
898 return;
|
|
899 }
|
|
900 EVT_TRIG_TRACE(JVMTI_EVENT_SINGLE_STEP, ("JVMTI [%s] Trg Single Step triggered",
|
|
901 JvmtiTrace::safe_get_thread_name(thread)));
|
|
902 if (!state->hide_single_stepping()) {
|
|
903 if (state->is_pending_step_for_popframe()) {
|
|
904 state->process_pending_step_for_popframe();
|
|
905 }
|
|
906 if (state->is_pending_step_for_earlyret()) {
|
|
907 state->process_pending_step_for_earlyret();
|
|
908 }
|
|
909 JvmtiExport::post_single_step(thread, mh(), location);
|
|
910 }
|
|
911 }
|
|
912
|
|
913
|
|
914 void JvmtiExport::expose_single_stepping(JavaThread *thread) {
|
|
915 JvmtiThreadState *state = thread->jvmti_thread_state();
|
|
916 if (state != NULL) {
|
|
917 state->clear_hide_single_stepping();
|
|
918 }
|
|
919 }
|
|
920
|
|
921
|
|
922 bool JvmtiExport::hide_single_stepping(JavaThread *thread) {
|
|
923 JvmtiThreadState *state = thread->jvmti_thread_state();
|
|
924 if (state != NULL && state->is_enabled(JVMTI_EVENT_SINGLE_STEP)) {
|
|
925 state->set_hide_single_stepping();
|
|
926 return true;
|
|
927 } else {
|
|
928 return false;
|
|
929 }
|
|
930 }
|
|
931
|
|
932 void JvmtiExport::post_class_load(JavaThread *thread, klassOop klass) {
|
|
933 HandleMark hm(thread);
|
|
934 KlassHandle kh(thread, klass);
|
|
935
|
|
936 EVT_TRIG_TRACE(JVMTI_EVENT_CLASS_LOAD, ("JVMTI [%s] Trg Class Load triggered",
|
|
937 JvmtiTrace::safe_get_thread_name(thread)));
|
|
938 JvmtiThreadState* state = thread->jvmti_thread_state();
|
|
939 if (state == NULL) {
|
|
940 return;
|
|
941 }
|
|
942 JvmtiEnvThreadStateIterator it(state);
|
|
943 for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
|
|
944 if (ets->is_enabled(JVMTI_EVENT_CLASS_LOAD)) {
|
|
945 EVT_TRACE(JVMTI_EVENT_CLASS_LOAD, ("JVMTI [%s] Evt Class Load sent %s",
|
|
946 JvmtiTrace::safe_get_thread_name(thread),
|
|
947 kh()==NULL? "NULL" : Klass::cast(kh())->external_name() ));
|
|
948
|
|
949 JvmtiEnv *env = ets->get_env();
|
|
950 JvmtiClassEventMark jem(thread, kh());
|
|
951 JvmtiJavaThreadEventTransition jet(thread);
|
|
952 jvmtiEventClassLoad callback = env->callbacks()->ClassLoad;
|
|
953 if (callback != NULL) {
|
|
954 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(), jem.jni_class());
|
|
955 }
|
|
956 }
|
|
957 }
|
|
958 }
|
|
959
|
|
960
|
|
961 void JvmtiExport::post_class_prepare(JavaThread *thread, klassOop klass) {
|
|
962 HandleMark hm(thread);
|
|
963 KlassHandle kh(thread, klass);
|
|
964
|
|
965 EVT_TRIG_TRACE(JVMTI_EVENT_CLASS_PREPARE, ("JVMTI [%s] Trg Class Prepare triggered",
|
|
966 JvmtiTrace::safe_get_thread_name(thread)));
|
|
967 JvmtiThreadState* state = thread->jvmti_thread_state();
|
|
968 if (state == NULL) {
|
|
969 return;
|
|
970 }
|
|
971 JvmtiEnvThreadStateIterator it(state);
|
|
972 for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
|
|
973 if (ets->is_enabled(JVMTI_EVENT_CLASS_PREPARE)) {
|
|
974 EVT_TRACE(JVMTI_EVENT_CLASS_PREPARE, ("JVMTI [%s] Evt Class Prepare sent %s",
|
|
975 JvmtiTrace::safe_get_thread_name(thread),
|
|
976 kh()==NULL? "NULL" : Klass::cast(kh())->external_name() ));
|
|
977
|
|
978 JvmtiEnv *env = ets->get_env();
|
|
979 JvmtiClassEventMark jem(thread, kh());
|
|
980 JvmtiJavaThreadEventTransition jet(thread);
|
|
981 jvmtiEventClassPrepare callback = env->callbacks()->ClassPrepare;
|
|
982 if (callback != NULL) {
|
|
983 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(), jem.jni_class());
|
|
984 }
|
|
985 }
|
|
986 }
|
|
987 }
|
|
988
|
|
989 void JvmtiExport::post_class_unload(klassOop klass) {
|
|
990 Thread *thread = Thread::current();
|
|
991 HandleMark hm(thread);
|
|
992 KlassHandle kh(thread, klass);
|
|
993
|
|
994 EVT_TRIG_TRACE(EXT_EVENT_CLASS_UNLOAD, ("JVMTI [?] Trg Class Unload triggered" ));
|
|
995 if (JvmtiEventController::is_enabled((jvmtiEvent)EXT_EVENT_CLASS_UNLOAD)) {
|
|
996 assert(thread->is_VM_thread(), "wrong thread");
|
|
997
|
|
998 // get JavaThread for whom we are proxy
|
|
999 JavaThread *real_thread =
|
|
1000 (JavaThread *)((VMThread *)thread)->vm_operation()->calling_thread();
|
|
1001
|
|
1002 JvmtiEnvIterator it;
|
|
1003 for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
|
1004 if (env->is_enabled((jvmtiEvent)EXT_EVENT_CLASS_UNLOAD)) {
|
|
1005 EVT_TRACE(EXT_EVENT_CLASS_UNLOAD, ("JVMTI [?] Evt Class Unload sent %s",
|
|
1006 kh()==NULL? "NULL" : Klass::cast(kh())->external_name() ));
|
|
1007
|
|
1008 // do everything manually, since this is a proxy - needs special care
|
|
1009 JNIEnv* jni_env = real_thread->jni_environment();
|
|
1010 jthread jt = (jthread)JNIHandles::make_local(real_thread, real_thread->threadObj());
|
|
1011 jclass jk = (jclass)JNIHandles::make_local(real_thread, Klass::cast(kh())->java_mirror());
|
|
1012
|
|
1013 // Before we call the JVMTI agent, we have to set the state in the
|
|
1014 // thread for which we are proxying.
|
|
1015 JavaThreadState prev_state = real_thread->thread_state();
|
|
1016 assert(prev_state == _thread_blocked, "JavaThread should be at safepoint");
|
|
1017 real_thread->set_thread_state(_thread_in_native);
|
|
1018
|
|
1019 jvmtiExtensionEvent callback = env->ext_callbacks()->ClassUnload;
|
|
1020 if (callback != NULL) {
|
|
1021 (*callback)(env->jvmti_external(), jni_env, jt, jk);
|
|
1022 }
|
|
1023
|
|
1024 assert(real_thread->thread_state() == _thread_in_native,
|
|
1025 "JavaThread should be in native");
|
|
1026 real_thread->set_thread_state(prev_state);
|
|
1027
|
|
1028 JNIHandles::destroy_local(jk);
|
|
1029 JNIHandles::destroy_local(jt);
|
|
1030 }
|
|
1031 }
|
|
1032 }
|
|
1033 }
|
|
1034
|
|
1035
|
|
1036 void JvmtiExport::post_thread_start(JavaThread *thread) {
|
|
1037 assert(thread->thread_state() == _thread_in_vm, "must be in vm state");
|
|
1038
|
|
1039 EVT_TRIG_TRACE(JVMTI_EVENT_THREAD_START, ("JVMTI [%s] Trg Thread Start event triggered",
|
|
1040 JvmtiTrace::safe_get_thread_name(thread)));
|
|
1041
|
|
1042 // do JVMTI thread initialization (if needed)
|
|
1043 JvmtiEventController::thread_started(thread);
|
|
1044
|
|
1045 // Do not post thread start event for hidden java thread.
|
|
1046 if (JvmtiEventController::is_enabled(JVMTI_EVENT_THREAD_START) &&
|
|
1047 !thread->is_hidden_from_external_view()) {
|
|
1048 JvmtiEnvIterator it;
|
|
1049 for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
|
1050 if (env->is_enabled(JVMTI_EVENT_THREAD_START)) {
|
|
1051 EVT_TRACE(JVMTI_EVENT_THREAD_START, ("JVMTI [%s] Evt Thread Start event sent",
|
|
1052 JvmtiTrace::safe_get_thread_name(thread) ));
|
|
1053
|
|
1054 JvmtiThreadEventMark jem(thread);
|
|
1055 JvmtiJavaThreadEventTransition jet(thread);
|
|
1056 jvmtiEventThreadStart callback = env->callbacks()->ThreadStart;
|
|
1057 if (callback != NULL) {
|
|
1058 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread());
|
|
1059 }
|
|
1060 }
|
|
1061 }
|
|
1062 }
|
|
1063 }
|
|
1064
|
|
1065
|
|
1066 void JvmtiExport::post_thread_end(JavaThread *thread) {
|
|
1067 EVT_TRIG_TRACE(JVMTI_EVENT_THREAD_END, ("JVMTI [%s] Trg Thread End event triggered",
|
|
1068 JvmtiTrace::safe_get_thread_name(thread)));
|
|
1069
|
|
1070 JvmtiThreadState *state = thread->jvmti_thread_state();
|
|
1071 if (state == NULL) {
|
|
1072 return;
|
|
1073 }
|
|
1074
|
|
1075 // Do not post thread end event for hidden java thread.
|
|
1076 if (state->is_enabled(JVMTI_EVENT_THREAD_END) &&
|
|
1077 !thread->is_hidden_from_external_view()) {
|
|
1078
|
|
1079 JvmtiEnvThreadStateIterator it(state);
|
|
1080 for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
|
|
1081 if (ets->is_enabled(JVMTI_EVENT_THREAD_END)) {
|
|
1082 EVT_TRACE(JVMTI_EVENT_THREAD_END, ("JVMTI [%s] Evt Thread End event sent",
|
|
1083 JvmtiTrace::safe_get_thread_name(thread) ));
|
|
1084
|
|
1085 JvmtiEnv *env = ets->get_env();
|
|
1086 JvmtiThreadEventMark jem(thread);
|
|
1087 JvmtiJavaThreadEventTransition jet(thread);
|
|
1088 jvmtiEventThreadEnd callback = env->callbacks()->ThreadEnd;
|
|
1089 if (callback != NULL) {
|
|
1090 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread());
|
|
1091 }
|
|
1092 }
|
|
1093 }
|
|
1094 }
|
|
1095 }
|
|
1096
|
|
1097 void JvmtiExport::post_object_free(JvmtiEnv* env, jlong tag) {
|
|
1098 assert(SafepointSynchronize::is_at_safepoint(), "must be executed at safepoint");
|
|
1099 assert(env->is_enabled(JVMTI_EVENT_OBJECT_FREE), "checking");
|
|
1100
|
|
1101 EVT_TRIG_TRACE(JVMTI_EVENT_OBJECT_FREE, ("JVMTI [?] Trg Object Free triggered" ));
|
|
1102 EVT_TRACE(JVMTI_EVENT_OBJECT_FREE, ("JVMTI [?] Evt Object Free sent"));
|
|
1103
|
|
1104 jvmtiEventObjectFree callback = env->callbacks()->ObjectFree;
|
|
1105 if (callback != NULL) {
|
|
1106 (*callback)(env->jvmti_external(), tag);
|
|
1107 }
|
|
1108 }
|
|
1109
|
|
1110 void JvmtiExport::post_resource_exhausted(jint resource_exhausted_flags, const char* description) {
|
|
1111 EVT_TRIG_TRACE(JVMTI_EVENT_RESOURCE_EXHAUSTED, ("JVMTI Trg resource exhausted event triggered" ));
|
|
1112
|
|
1113 JvmtiEnvIterator it;
|
|
1114 for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
|
1115 if (env->is_enabled(JVMTI_EVENT_RESOURCE_EXHAUSTED)) {
|
|
1116 EVT_TRACE(JVMTI_EVENT_RESOURCE_EXHAUSTED, ("JVMTI Evt resource exhausted event sent" ));
|
|
1117
|
|
1118 JavaThread *thread = JavaThread::current();
|
|
1119 JvmtiThreadEventMark jem(thread);
|
|
1120 JvmtiJavaThreadEventTransition jet(thread);
|
|
1121 jvmtiEventResourceExhausted callback = env->callbacks()->ResourceExhausted;
|
|
1122 if (callback != NULL) {
|
|
1123 (*callback)(env->jvmti_external(), jem.jni_env(),
|
|
1124 resource_exhausted_flags, NULL, description);
|
|
1125 }
|
|
1126 }
|
|
1127 }
|
|
1128 }
|
|
1129
|
|
1130 void JvmtiExport::post_method_entry(JavaThread *thread, methodOop method, frame current_frame) {
|
|
1131 HandleMark hm(thread);
|
|
1132 methodHandle mh(thread, method);
|
|
1133
|
|
1134 EVT_TRIG_TRACE(JVMTI_EVENT_METHOD_ENTRY, ("JVMTI [%s] Trg Method Entry triggered %s.%s",
|
|
1135 JvmtiTrace::safe_get_thread_name(thread),
|
|
1136 (mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),
|
|
1137 (mh() == NULL) ? "NULL" : mh()->name()->as_C_string() ));
|
|
1138
|
|
1139 JvmtiThreadState* state = thread->jvmti_thread_state();
|
|
1140 if (state == NULL || !state->is_interp_only_mode()) {
|
|
1141 // for any thread that actually wants method entry, interp_only_mode is set
|
|
1142 return;
|
|
1143 }
|
|
1144
|
|
1145 state->incr_cur_stack_depth();
|
|
1146
|
|
1147 if (state->is_enabled(JVMTI_EVENT_METHOD_ENTRY)) {
|
|
1148 JvmtiEnvThreadStateIterator it(state);
|
|
1149 for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
|
|
1150 if (ets->is_enabled(JVMTI_EVENT_METHOD_ENTRY)) {
|
|
1151 EVT_TRACE(JVMTI_EVENT_METHOD_ENTRY, ("JVMTI [%s] Evt Method Entry sent %s.%s",
|
|
1152 JvmtiTrace::safe_get_thread_name(thread),
|
|
1153 (mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),
|
|
1154 (mh() == NULL) ? "NULL" : mh()->name()->as_C_string() ));
|
|
1155
|
|
1156 JvmtiEnv *env = ets->get_env();
|
|
1157 JvmtiMethodEventMark jem(thread, mh);
|
|
1158 JvmtiJavaThreadEventTransition jet(thread);
|
|
1159 jvmtiEventMethodEntry callback = env->callbacks()->MethodEntry;
|
|
1160 if (callback != NULL) {
|
|
1161 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(), jem.jni_methodID());
|
|
1162 }
|
|
1163 }
|
|
1164 }
|
|
1165 }
|
|
1166 }
|
|
1167
|
|
1168 void JvmtiExport::post_method_exit(JavaThread *thread, methodOop method, frame current_frame) {
|
|
1169 HandleMark hm(thread);
|
|
1170 methodHandle mh(thread, method);
|
|
1171
|
|
1172 EVT_TRIG_TRACE(JVMTI_EVENT_METHOD_EXIT, ("JVMTI [%s] Trg Method Exit triggered %s.%s",
|
|
1173 JvmtiTrace::safe_get_thread_name(thread),
|
|
1174 (mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),
|
|
1175 (mh() == NULL) ? "NULL" : mh()->name()->as_C_string() ));
|
|
1176
|
|
1177 JvmtiThreadState *state = thread->jvmti_thread_state();
|
|
1178 if (state == NULL || !state->is_interp_only_mode()) {
|
|
1179 // for any thread that actually wants method exit, interp_only_mode is set
|
|
1180 return;
|
|
1181 }
|
|
1182
|
|
1183 // return a flag when a method terminates by throwing an exception
|
|
1184 // i.e. if an exception is thrown and it's not caught by the current method
|
|
1185 bool exception_exit = state->is_exception_detected() && !state->is_exception_caught();
|
|
1186
|
|
1187
|
|
1188 if (state->is_enabled(JVMTI_EVENT_METHOD_EXIT)) {
|
|
1189 Handle result;
|
|
1190 jvalue value;
|
|
1191 value.j = 0L;
|
|
1192
|
|
1193 // if the method hasn't been popped because of an exception then we populate
|
|
1194 // the return_value parameter for the callback. At this point we only have
|
|
1195 // the address of a "raw result" and we just call into the interpreter to
|
|
1196 // convert this into a jvalue.
|
|
1197 if (!exception_exit) {
|
|
1198 oop oop_result;
|
|
1199 BasicType type = current_frame.interpreter_frame_result(&oop_result, &value);
|
|
1200 if (type == T_OBJECT || type == T_ARRAY) {
|
|
1201 result = Handle(thread, oop_result);
|
|
1202 }
|
|
1203 }
|
|
1204
|
|
1205 JvmtiEnvThreadStateIterator it(state);
|
|
1206 for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
|
|
1207 if (ets->is_enabled(JVMTI_EVENT_METHOD_EXIT)) {
|
|
1208 EVT_TRACE(JVMTI_EVENT_METHOD_EXIT, ("JVMTI [%s] Evt Method Exit sent %s.%s",
|
|
1209 JvmtiTrace::safe_get_thread_name(thread),
|
|
1210 (mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),
|
|
1211 (mh() == NULL) ? "NULL" : mh()->name()->as_C_string() ));
|
|
1212
|
|
1213 JvmtiEnv *env = ets->get_env();
|
|
1214 JvmtiMethodEventMark jem(thread, mh);
|
|
1215 if (result.not_null()) {
|
|
1216 value.l = JNIHandles::make_local(thread, result());
|
|
1217 }
|
|
1218 JvmtiJavaThreadEventTransition jet(thread);
|
|
1219 jvmtiEventMethodExit callback = env->callbacks()->MethodExit;
|
|
1220 if (callback != NULL) {
|
|
1221 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(),
|
|
1222 jem.jni_methodID(), exception_exit, value);
|
|
1223 }
|
|
1224 }
|
|
1225 }
|
|
1226 }
|
|
1227
|
|
1228 if (state->is_enabled(JVMTI_EVENT_FRAME_POP)) {
|
|
1229 JvmtiEnvThreadStateIterator it(state);
|
|
1230 for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
|
|
1231 int cur_frame_number = state->cur_stack_depth();
|
|
1232
|
|
1233 if (ets->is_frame_pop(cur_frame_number)) {
|
|
1234 // we have a NotifyFramePop entry for this frame.
|
|
1235 // now check that this env/thread wants this event
|
|
1236 if (ets->is_enabled(JVMTI_EVENT_FRAME_POP)) {
|
|
1237 EVT_TRACE(JVMTI_EVENT_FRAME_POP, ("JVMTI [%s] Evt Frame Pop sent %s.%s",
|
|
1238 JvmtiTrace::safe_get_thread_name(thread),
|
|
1239 (mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),
|
|
1240 (mh() == NULL) ? "NULL" : mh()->name()->as_C_string() ));
|
|
1241
|
|
1242 // we also need to issue a frame pop event for this frame
|
|
1243 JvmtiEnv *env = ets->get_env();
|
|
1244 JvmtiMethodEventMark jem(thread, mh);
|
|
1245 JvmtiJavaThreadEventTransition jet(thread);
|
|
1246 jvmtiEventFramePop callback = env->callbacks()->FramePop;
|
|
1247 if (callback != NULL) {
|
|
1248 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(),
|
|
1249 jem.jni_methodID(), exception_exit);
|
|
1250 }
|
|
1251 }
|
|
1252 // remove the frame's entry
|
|
1253 ets->clear_frame_pop(cur_frame_number);
|
|
1254 }
|
|
1255 }
|
|
1256 }
|
|
1257
|
|
1258 state->decr_cur_stack_depth();
|
|
1259 }
|
|
1260
|
|
1261
|
|
1262 // Todo: inline this for optimization
|
|
1263 void JvmtiExport::post_single_step(JavaThread *thread, methodOop method, address location) {
|
|
1264 HandleMark hm(thread);
|
|
1265 methodHandle mh(thread, method);
|
|
1266
|
|
1267 JvmtiThreadState *state = thread->jvmti_thread_state();
|
|
1268 if (state == NULL) {
|
|
1269 return;
|
|
1270 }
|
|
1271 JvmtiEnvThreadStateIterator it(state);
|
|
1272 for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
|
|
1273 ets->compare_and_set_current_location(mh(), location, JVMTI_EVENT_SINGLE_STEP);
|
|
1274 if (!ets->single_stepping_posted() && ets->is_enabled(JVMTI_EVENT_SINGLE_STEP)) {
|
|
1275 EVT_TRACE(JVMTI_EVENT_SINGLE_STEP, ("JVMTI [%s] Evt Single Step sent %s.%s @ %d",
|
|
1276 JvmtiTrace::safe_get_thread_name(thread),
|
|
1277 (mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),
|
|
1278 (mh() == NULL) ? "NULL" : mh()->name()->as_C_string(),
|
|
1279 location - mh()->code_base() ));
|
|
1280
|
|
1281 JvmtiEnv *env = ets->get_env();
|
|
1282 JvmtiLocationEventMark jem(thread, mh, location);
|
|
1283 JvmtiJavaThreadEventTransition jet(thread);
|
|
1284 jvmtiEventSingleStep callback = env->callbacks()->SingleStep;
|
|
1285 if (callback != NULL) {
|
|
1286 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(),
|
|
1287 jem.jni_methodID(), jem.location());
|
|
1288 }
|
|
1289
|
|
1290 ets->set_single_stepping_posted();
|
|
1291 }
|
|
1292 }
|
|
1293 }
|
|
1294
|
|
1295
|
|
1296 void JvmtiExport::post_exception_throw(JavaThread *thread, methodOop method, address location, oop exception) {
|
|
1297 HandleMark hm(thread);
|
|
1298 methodHandle mh(thread, method);
|
|
1299 Handle exception_handle(thread, exception);
|
|
1300
|
|
1301 JvmtiThreadState *state = thread->jvmti_thread_state();
|
|
1302 if (state == NULL) {
|
|
1303 return;
|
|
1304 }
|
|
1305
|
|
1306 EVT_TRIG_TRACE(JVMTI_EVENT_EXCEPTION, ("JVMTI [%s] Trg Exception thrown triggered",
|
|
1307 JvmtiTrace::safe_get_thread_name(thread)));
|
|
1308 if (!state->is_exception_detected()) {
|
|
1309 state->set_exception_detected();
|
|
1310 JvmtiEnvThreadStateIterator it(state);
|
|
1311 for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
|
|
1312 if (ets->is_enabled(JVMTI_EVENT_EXCEPTION) && (exception != NULL)) {
|
|
1313
|
|
1314 EVT_TRACE(JVMTI_EVENT_EXCEPTION,
|
|
1315 ("JVMTI [%s] Evt Exception thrown sent %s.%s @ %d",
|
|
1316 JvmtiTrace::safe_get_thread_name(thread),
|
|
1317 (mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),
|
|
1318 (mh() == NULL) ? "NULL" : mh()->name()->as_C_string(),
|
|
1319 location - mh()->code_base() ));
|
|
1320
|
|
1321 JvmtiEnv *env = ets->get_env();
|
|
1322 JvmtiExceptionEventMark jem(thread, mh, location, exception_handle);
|
|
1323
|
|
1324 // It's okay to clear these exceptions here because we duplicate
|
|
1325 // this lookup in InterpreterRuntime::exception_handler_for_exception.
|
|
1326 EXCEPTION_MARK;
|
|
1327
|
|
1328 bool should_repeat;
|
|
1329 vframeStream st(thread);
|
|
1330 assert(!st.at_end(), "cannot be at end");
|
|
1331 methodOop current_method = NULL;
|
|
1332 int current_bci = -1;
|
|
1333 do {
|
|
1334 current_method = st.method();
|
|
1335 current_bci = st.bci();
|
|
1336 do {
|
|
1337 should_repeat = false;
|
|
1338 KlassHandle eh_klass(thread, exception_handle()->klass());
|
|
1339 current_bci = current_method->fast_exception_handler_bci_for(
|
|
1340 eh_klass, current_bci, THREAD);
|
|
1341 if (HAS_PENDING_EXCEPTION) {
|
|
1342 exception_handle = KlassHandle(thread, PENDING_EXCEPTION);
|
|
1343 CLEAR_PENDING_EXCEPTION;
|
|
1344 should_repeat = true;
|
|
1345 }
|
|
1346 } while (should_repeat && (current_bci != -1));
|
|
1347 st.next();
|
|
1348 } while ((current_bci < 0) && (!st.at_end()));
|
|
1349
|
|
1350 jmethodID catch_jmethodID;
|
|
1351 if (current_bci < 0) {
|
|
1352 catch_jmethodID = 0;
|
|
1353 current_bci = 0;
|
|
1354 } else {
|
|
1355 catch_jmethodID = jem.to_jmethodID(
|
|
1356 methodHandle(thread, current_method));
|
|
1357 }
|
|
1358
|
|
1359 JvmtiJavaThreadEventTransition jet(thread);
|
|
1360 jvmtiEventException callback = env->callbacks()->Exception;
|
|
1361 if (callback != NULL) {
|
|
1362 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(),
|
|
1363 jem.jni_methodID(), jem.location(),
|
|
1364 jem.exception(),
|
|
1365 catch_jmethodID, current_bci);
|
|
1366 }
|
|
1367 }
|
|
1368 }
|
|
1369 }
|
|
1370
|
|
1371 // frames may get popped because of this throw, be safe - invalidate cached depth
|
|
1372 state->invalidate_cur_stack_depth();
|
|
1373 }
|
|
1374
|
|
1375
|
|
1376 void JvmtiExport::notice_unwind_due_to_exception(JavaThread *thread, methodOop method, address location, oop exception, bool in_handler_frame) {
|
|
1377 HandleMark hm(thread);
|
|
1378 methodHandle mh(thread, method);
|
|
1379 Handle exception_handle(thread, exception);
|
|
1380
|
|
1381 JvmtiThreadState *state = thread->jvmti_thread_state();
|
|
1382 if (state == NULL) {
|
|
1383 return;
|
|
1384 }
|
|
1385 EVT_TRIG_TRACE(JVMTI_EVENT_EXCEPTION_CATCH,
|
|
1386 ("JVMTI [%s] Trg unwind_due_to_exception triggered %s.%s @ %s%d - %s",
|
|
1387 JvmtiTrace::safe_get_thread_name(thread),
|
|
1388 (mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),
|
|
1389 (mh() == NULL) ? "NULL" : mh()->name()->as_C_string(),
|
|
1390 location==0? "no location:" : "",
|
|
1391 location==0? 0 : location - mh()->code_base(),
|
|
1392 in_handler_frame? "in handler frame" : "not handler frame" ));
|
|
1393
|
|
1394 if (state->is_exception_detected()) {
|
|
1395
|
|
1396 state->invalidate_cur_stack_depth();
|
|
1397 if (!in_handler_frame) {
|
|
1398 // Not in exception handler.
|
|
1399 if(state->is_interp_only_mode()) {
|
|
1400 // method exit and frame pop events are posted only in interp mode.
|
|
1401 // When these events are enabled code should be in running in interp mode.
|
|
1402 JvmtiExport::post_method_exit(thread, method, thread->last_frame());
|
|
1403 // The cached cur_stack_depth might have changed from the
|
|
1404 // operations of frame pop or method exit. We are not 100% sure
|
|
1405 // the cached cur_stack_depth is still valid depth so invalidate
|
|
1406 // it.
|
|
1407 state->invalidate_cur_stack_depth();
|
|
1408 }
|
|
1409 } else {
|
|
1410 // In exception handler frame. Report exception catch.
|
|
1411 assert(location != NULL, "must be a known location");
|
|
1412 // Update cur_stack_depth - the frames above the current frame
|
|
1413 // have been unwound due to this exception:
|
|
1414 assert(!state->is_exception_caught(), "exception must not be caught yet.");
|
|
1415 state->set_exception_caught();
|
|
1416
|
|
1417 JvmtiEnvThreadStateIterator it(state);
|
|
1418 for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
|
|
1419 if (ets->is_enabled(JVMTI_EVENT_EXCEPTION_CATCH) && (exception_handle() != NULL)) {
|
|
1420 EVT_TRACE(JVMTI_EVENT_EXCEPTION_CATCH,
|
|
1421 ("JVMTI [%s] Evt ExceptionCatch sent %s.%s @ %d",
|
|
1422 JvmtiTrace::safe_get_thread_name(thread),
|
|
1423 (mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),
|
|
1424 (mh() == NULL) ? "NULL" : mh()->name()->as_C_string(),
|
|
1425 location - mh()->code_base() ));
|
|
1426
|
|
1427 JvmtiEnv *env = ets->get_env();
|
|
1428 JvmtiExceptionEventMark jem(thread, mh, location, exception_handle);
|
|
1429 JvmtiJavaThreadEventTransition jet(thread);
|
|
1430 jvmtiEventExceptionCatch callback = env->callbacks()->ExceptionCatch;
|
|
1431 if (callback != NULL) {
|
|
1432 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(),
|
|
1433 jem.jni_methodID(), jem.location(),
|
|
1434 jem.exception());
|
|
1435 }
|
|
1436 }
|
|
1437 }
|
|
1438 }
|
|
1439 }
|
|
1440 }
|
|
1441
|
|
1442 oop JvmtiExport::jni_GetField_probe(JavaThread *thread, jobject jobj, oop obj,
|
|
1443 klassOop klass, jfieldID fieldID, bool is_static) {
|
|
1444 if (*((int *)get_field_access_count_addr()) > 0 && thread->has_last_Java_frame()) {
|
|
1445 // At least one field access watch is set so we have more work
|
|
1446 // to do. This wrapper is used by entry points that allow us
|
|
1447 // to create handles in post_field_access_by_jni().
|
|
1448 post_field_access_by_jni(thread, obj, klass, fieldID, is_static);
|
|
1449 // event posting can block so refetch oop if we were passed a jobj
|
|
1450 if (jobj != NULL) return JNIHandles::resolve_non_null(jobj);
|
|
1451 }
|
|
1452 return obj;
|
|
1453 }
|
|
1454
|
|
1455 oop JvmtiExport::jni_GetField_probe_nh(JavaThread *thread, jobject jobj, oop obj,
|
|
1456 klassOop klass, jfieldID fieldID, bool is_static) {
|
|
1457 if (*((int *)get_field_access_count_addr()) > 0 && thread->has_last_Java_frame()) {
|
|
1458 // At least one field access watch is set so we have more work
|
|
1459 // to do. This wrapper is used by "quick" entry points that don't
|
|
1460 // allow us to create handles in post_field_access_by_jni(). We
|
|
1461 // override that with a ResetNoHandleMark.
|
|
1462 ResetNoHandleMark rnhm;
|
|
1463 post_field_access_by_jni(thread, obj, klass, fieldID, is_static);
|
|
1464 // event posting can block so refetch oop if we were passed a jobj
|
|
1465 if (jobj != NULL) return JNIHandles::resolve_non_null(jobj);
|
|
1466 }
|
|
1467 return obj;
|
|
1468 }
|
|
1469
|
|
1470 void JvmtiExport::post_field_access_by_jni(JavaThread *thread, oop obj,
|
|
1471 klassOop klass, jfieldID fieldID, bool is_static) {
|
|
1472 // We must be called with a Java context in order to provide reasonable
|
|
1473 // values for the klazz, method, and location fields. The callers of this
|
|
1474 // function don't make the call unless there is a Java context.
|
|
1475 assert(thread->has_last_Java_frame(), "must be called with a Java context");
|
|
1476
|
|
1477 ResourceMark rm;
|
|
1478 fieldDescriptor fd;
|
|
1479 // if get_field_descriptor finds fieldID to be invalid, then we just bail
|
|
1480 bool valid_fieldID = JvmtiEnv::get_field_descriptor(klass, fieldID, &fd);
|
|
1481 assert(valid_fieldID == true,"post_field_access_by_jni called with invalid fieldID");
|
|
1482 if (!valid_fieldID) return;
|
|
1483 // field accesses are not watched so bail
|
|
1484 if (!fd.is_field_access_watched()) return;
|
|
1485
|
|
1486 HandleMark hm(thread);
|
|
1487 KlassHandle h_klass(thread, klass);
|
|
1488 Handle h_obj;
|
|
1489 if (!is_static) {
|
|
1490 // non-static field accessors have an object, but we need a handle
|
|
1491 assert(obj != NULL, "non-static needs an object");
|
|
1492 h_obj = Handle(thread, obj);
|
|
1493 }
|
|
1494 post_field_access(thread,
|
|
1495 thread->last_frame().interpreter_frame_method(),
|
|
1496 thread->last_frame().interpreter_frame_bcp(),
|
|
1497 h_klass, h_obj, fieldID);
|
|
1498 }
|
|
1499
|
|
1500 void JvmtiExport::post_field_access(JavaThread *thread, methodOop method,
|
|
1501 address location, KlassHandle field_klass, Handle object, jfieldID field) {
|
|
1502
|
|
1503 HandleMark hm(thread);
|
|
1504 methodHandle mh(thread, method);
|
|
1505
|
|
1506 JvmtiThreadState *state = thread->jvmti_thread_state();
|
|
1507 if (state == NULL) {
|
|
1508 return;
|
|
1509 }
|
|
1510 EVT_TRIG_TRACE(JVMTI_EVENT_FIELD_ACCESS, ("JVMTI [%s] Trg Field Access event triggered",
|
|
1511 JvmtiTrace::safe_get_thread_name(thread)));
|
|
1512 JvmtiEnvThreadStateIterator it(state);
|
|
1513 for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
|
|
1514 if (ets->is_enabled(JVMTI_EVENT_FIELD_ACCESS)) {
|
|
1515 EVT_TRACE(JVMTI_EVENT_FIELD_ACCESS, ("JVMTI [%s] Evt Field Access event sent %s.%s @ %d",
|
|
1516 JvmtiTrace::safe_get_thread_name(thread),
|
|
1517 (mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),
|
|
1518 (mh() == NULL) ? "NULL" : mh()->name()->as_C_string(),
|
|
1519 location - mh()->code_base() ));
|
|
1520
|
|
1521 JvmtiEnv *env = ets->get_env();
|
|
1522 JvmtiLocationEventMark jem(thread, mh, location);
|
|
1523 jclass field_jclass = jem.to_jclass(field_klass());
|
|
1524 jobject field_jobject = jem.to_jobject(object());
|
|
1525 JvmtiJavaThreadEventTransition jet(thread);
|
|
1526 jvmtiEventFieldAccess callback = env->callbacks()->FieldAccess;
|
|
1527 if (callback != NULL) {
|
|
1528 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(),
|
|
1529 jem.jni_methodID(), jem.location(),
|
|
1530 field_jclass, field_jobject, field);
|
|
1531 }
|
|
1532 }
|
|
1533 }
|
|
1534 }
|
|
1535
|
|
1536 oop JvmtiExport::jni_SetField_probe(JavaThread *thread, jobject jobj, oop obj,
|
|
1537 klassOop klass, jfieldID fieldID, bool is_static,
|
|
1538 char sig_type, jvalue *value) {
|
|
1539 if (*((int *)get_field_modification_count_addr()) > 0 && thread->has_last_Java_frame()) {
|
|
1540 // At least one field modification watch is set so we have more work
|
|
1541 // to do. This wrapper is used by entry points that allow us
|
|
1542 // to create handles in post_field_modification_by_jni().
|
|
1543 post_field_modification_by_jni(thread, obj, klass, fieldID, is_static, sig_type, value);
|
|
1544 // event posting can block so refetch oop if we were passed a jobj
|
|
1545 if (jobj != NULL) return JNIHandles::resolve_non_null(jobj);
|
|
1546 }
|
|
1547 return obj;
|
|
1548 }
|
|
1549
|
|
1550 oop JvmtiExport::jni_SetField_probe_nh(JavaThread *thread, jobject jobj, oop obj,
|
|
1551 klassOop klass, jfieldID fieldID, bool is_static,
|
|
1552 char sig_type, jvalue *value) {
|
|
1553 if (*((int *)get_field_modification_count_addr()) > 0 && thread->has_last_Java_frame()) {
|
|
1554 // At least one field modification watch is set so we have more work
|
|
1555 // to do. This wrapper is used by "quick" entry points that don't
|
|
1556 // allow us to create handles in post_field_modification_by_jni(). We
|
|
1557 // override that with a ResetNoHandleMark.
|
|
1558 ResetNoHandleMark rnhm;
|
|
1559 post_field_modification_by_jni(thread, obj, klass, fieldID, is_static, sig_type, value);
|
|
1560 // event posting can block so refetch oop if we were passed a jobj
|
|
1561 if (jobj != NULL) return JNIHandles::resolve_non_null(jobj);
|
|
1562 }
|
|
1563 return obj;
|
|
1564 }
|
|
1565
|
|
1566 void JvmtiExport::post_field_modification_by_jni(JavaThread *thread, oop obj,
|
|
1567 klassOop klass, jfieldID fieldID, bool is_static,
|
|
1568 char sig_type, jvalue *value) {
|
|
1569 // We must be called with a Java context in order to provide reasonable
|
|
1570 // values for the klazz, method, and location fields. The callers of this
|
|
1571 // function don't make the call unless there is a Java context.
|
|
1572 assert(thread->has_last_Java_frame(), "must be called with Java context");
|
|
1573
|
|
1574 ResourceMark rm;
|
|
1575 fieldDescriptor fd;
|
|
1576 // if get_field_descriptor finds fieldID to be invalid, then we just bail
|
|
1577 bool valid_fieldID = JvmtiEnv::get_field_descriptor(klass, fieldID, &fd);
|
|
1578 assert(valid_fieldID == true,"post_field_modification_by_jni called with invalid fieldID");
|
|
1579 if (!valid_fieldID) return;
|
|
1580 // field modifications are not watched so bail
|
|
1581 if (!fd.is_field_modification_watched()) return;
|
|
1582
|
|
1583 HandleMark hm(thread);
|
|
1584
|
|
1585 Handle h_obj;
|
|
1586 if (!is_static) {
|
|
1587 // non-static field accessors have an object, but we need a handle
|
|
1588 assert(obj != NULL, "non-static needs an object");
|
|
1589 h_obj = Handle(thread, obj);
|
|
1590 }
|
|
1591 KlassHandle h_klass(thread, klass);
|
|
1592 post_field_modification(thread,
|
|
1593 thread->last_frame().interpreter_frame_method(),
|
|
1594 thread->last_frame().interpreter_frame_bcp(),
|
|
1595 h_klass, h_obj, fieldID, sig_type, value);
|
|
1596 }
|
|
1597
|
|
1598 void JvmtiExport::post_raw_field_modification(JavaThread *thread, methodOop method,
|
|
1599 address location, KlassHandle field_klass, Handle object, jfieldID field,
|
|
1600 char sig_type, jvalue *value) {
|
|
1601
|
|
1602 if (sig_type == 'I' || sig_type == 'Z' || sig_type == 'C' || sig_type == 'S') {
|
|
1603 // 'I' instructions are used for byte, char, short and int.
|
|
1604 // determine which it really is, and convert
|
|
1605 fieldDescriptor fd;
|
|
1606 bool found = JvmtiEnv::get_field_descriptor(field_klass(), field, &fd);
|
|
1607 // should be found (if not, leave as is)
|
|
1608 if (found) {
|
|
1609 jint ival = value->i;
|
|
1610 // convert value from int to appropriate type
|
|
1611 switch (fd.field_type()) {
|
|
1612 case T_BOOLEAN:
|
|
1613 sig_type = 'Z';
|
|
1614 value->i = 0; // clear it
|
|
1615 value->z = (jboolean)ival;
|
|
1616 break;
|
|
1617 case T_BYTE:
|
|
1618 sig_type = 'B';
|
|
1619 value->i = 0; // clear it
|
|
1620 value->b = (jbyte)ival;
|
|
1621 break;
|
|
1622 case T_CHAR:
|
|
1623 sig_type = 'C';
|
|
1624 value->i = 0; // clear it
|
|
1625 value->c = (jchar)ival;
|
|
1626 break;
|
|
1627 case T_SHORT:
|
|
1628 sig_type = 'S';
|
|
1629 value->i = 0; // clear it
|
|
1630 value->s = (jshort)ival;
|
|
1631 break;
|
|
1632 case T_INT:
|
|
1633 // nothing to do
|
|
1634 break;
|
|
1635 default:
|
|
1636 // this is an integer instruction, should be one of above
|
|
1637 ShouldNotReachHere();
|
|
1638 break;
|
|
1639 }
|
|
1640 }
|
|
1641 }
|
|
1642
|
|
1643 // convert oop to JNI handle.
|
|
1644 if (sig_type == 'L' || sig_type == '[') {
|
|
1645 value->l = (jobject)JNIHandles::make_local(thread, (oop)value->l);
|
|
1646 }
|
|
1647
|
|
1648 post_field_modification(thread, method, location, field_klass, object, field, sig_type, value);
|
|
1649
|
|
1650 // Destroy the JNI handle allocated above.
|
|
1651 if (sig_type == 'L') {
|
|
1652 JNIHandles::destroy_local(value->l);
|
|
1653 }
|
|
1654 }
|
|
1655
|
|
1656 void JvmtiExport::post_field_modification(JavaThread *thread, methodOop method,
|
|
1657 address location, KlassHandle field_klass, Handle object, jfieldID field,
|
|
1658 char sig_type, jvalue *value_ptr) {
|
|
1659
|
|
1660 HandleMark hm(thread);
|
|
1661 methodHandle mh(thread, method);
|
|
1662
|
|
1663 JvmtiThreadState *state = thread->jvmti_thread_state();
|
|
1664 if (state == NULL) {
|
|
1665 return;
|
|
1666 }
|
|
1667 EVT_TRIG_TRACE(JVMTI_EVENT_FIELD_MODIFICATION,
|
|
1668 ("JVMTI [%s] Trg Field Modification event triggered",
|
|
1669 JvmtiTrace::safe_get_thread_name(thread)));
|
|
1670
|
|
1671 JvmtiEnvThreadStateIterator it(state);
|
|
1672 for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
|
|
1673 if (ets->is_enabled(JVMTI_EVENT_FIELD_MODIFICATION)) {
|
|
1674 EVT_TRACE(JVMTI_EVENT_FIELD_MODIFICATION,
|
|
1675 ("JVMTI [%s] Evt Field Modification event sent %s.%s @ %d",
|
|
1676 JvmtiTrace::safe_get_thread_name(thread),
|
|
1677 (mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),
|
|
1678 (mh() == NULL) ? "NULL" : mh()->name()->as_C_string(),
|
|
1679 location - mh()->code_base() ));
|
|
1680
|
|
1681 JvmtiEnv *env = ets->get_env();
|
|
1682 JvmtiLocationEventMark jem(thread, mh, location);
|
|
1683 jclass field_jclass = jem.to_jclass(field_klass());
|
|
1684 jobject field_jobject = jem.to_jobject(object());
|
|
1685 JvmtiJavaThreadEventTransition jet(thread);
|
|
1686 jvmtiEventFieldModification callback = env->callbacks()->FieldModification;
|
|
1687 if (callback != NULL) {
|
|
1688 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(),
|
|
1689 jem.jni_methodID(), jem.location(),
|
|
1690 field_jclass, field_jobject, field, sig_type, *value_ptr);
|
|
1691 }
|
|
1692 }
|
|
1693 }
|
|
1694 }
|
|
1695
|
|
1696 void JvmtiExport::post_native_method_bind(methodOop method, address* function_ptr) {
|
|
1697 JavaThread* thread = JavaThread::current();
|
|
1698 assert(thread->thread_state() == _thread_in_vm, "must be in vm state");
|
|
1699
|
|
1700 HandleMark hm(thread);
|
|
1701 methodHandle mh(thread, method);
|
|
1702
|
|
1703 EVT_TRIG_TRACE(JVMTI_EVENT_NATIVE_METHOD_BIND, ("JVMTI [%s] Trg Native Method Bind event triggered",
|
|
1704 JvmtiTrace::safe_get_thread_name(thread)));
|
|
1705
|
|
1706 if (JvmtiEventController::is_enabled(JVMTI_EVENT_NATIVE_METHOD_BIND)) {
|
|
1707 JvmtiEnvIterator it;
|
|
1708 for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
|
1709 if (env->is_enabled(JVMTI_EVENT_NATIVE_METHOD_BIND)) {
|
|
1710 EVT_TRACE(JVMTI_EVENT_NATIVE_METHOD_BIND, ("JVMTI [%s] Evt Native Method Bind event sent",
|
|
1711 JvmtiTrace::safe_get_thread_name(thread) ));
|
|
1712
|
|
1713 JvmtiMethodEventMark jem(thread, mh);
|
|
1714 JvmtiJavaThreadEventTransition jet(thread);
|
|
1715 JNIEnv* jni_env = JvmtiEnv::get_phase() == JVMTI_PHASE_PRIMORDIAL? NULL : jem.jni_env();
|
|
1716 jvmtiEventNativeMethodBind callback = env->callbacks()->NativeMethodBind;
|
|
1717 if (callback != NULL) {
|
|
1718 (*callback)(env->jvmti_external(), jni_env, jem.jni_thread(),
|
|
1719 jem.jni_methodID(), (void*)(*function_ptr), (void**)function_ptr);
|
|
1720 }
|
|
1721 }
|
|
1722 }
|
|
1723 }
|
|
1724 }
|
|
1725
|
|
1726
|
|
1727 void JvmtiExport::post_compiled_method_load(nmethod *nm) {
|
|
1728 // If there are pending CompiledMethodUnload events then these are
|
|
1729 // posted before this CompiledMethodLoad event. We "lock" the nmethod and
|
|
1730 // maintain a handle to the methodOop to ensure that the nmethod isn't
|
|
1731 // flushed or unloaded while posting the events.
|
|
1732 JavaThread* thread = JavaThread::current();
|
|
1733 if (have_pending_compiled_method_unload_events()) {
|
|
1734 methodHandle mh(thread, nm->method());
|
|
1735 nmethodLocker nml(nm);
|
|
1736 post_pending_compiled_method_unload_events();
|
|
1737 }
|
|
1738
|
|
1739 EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD,
|
|
1740 ("JVMTI [%s] method compile load event triggered",
|
|
1741 JvmtiTrace::safe_get_thread_name(thread)));
|
|
1742
|
|
1743 JvmtiEnvIterator it;
|
|
1744 for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
|
1745 if (env->is_enabled(JVMTI_EVENT_COMPILED_METHOD_LOAD)) {
|
|
1746
|
|
1747 EVT_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD,
|
|
1748 ("JVMTI [%s] class compile method load event sent %s.%s ",
|
|
1749 JvmtiTrace::safe_get_thread_name(thread),
|
|
1750 (nm->method() == NULL) ? "NULL" : nm->method()->klass_name()->as_C_string(),
|
|
1751 (nm->method() == NULL) ? "NULL" : nm->method()->name()->as_C_string()));
|
|
1752
|
|
1753 ResourceMark rm(thread);
|
|
1754 JvmtiCompiledMethodLoadEventMark jem(thread, nm);
|
|
1755 JvmtiJavaThreadEventTransition jet(thread);
|
|
1756 jvmtiEventCompiledMethodLoad callback = env->callbacks()->CompiledMethodLoad;
|
|
1757 if (callback != NULL) {
|
|
1758 (*callback)(env->jvmti_external(), jem.jni_methodID(),
|
|
1759 jem.code_size(), jem.code_data(), jem.map_length(),
|
|
1760 jem.map(), jem.compile_info());
|
|
1761 }
|
|
1762 }
|
|
1763 }
|
|
1764 }
|
|
1765
|
|
1766
|
|
1767 // post a COMPILED_METHOD_LOAD event for a given environment
|
|
1768 void JvmtiExport::post_compiled_method_load(JvmtiEnv* env, const jmethodID method, const jint length,
|
|
1769 const void *code_begin, const jint map_length,
|
|
1770 const jvmtiAddrLocationMap* map)
|
|
1771 {
|
|
1772 JavaThread* thread = JavaThread::current();
|
|
1773 EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD,
|
|
1774 ("JVMTI [%s] method compile load event triggered (by GenerateEvents)",
|
|
1775 JvmtiTrace::safe_get_thread_name(thread)));
|
|
1776 if (env->is_enabled(JVMTI_EVENT_COMPILED_METHOD_LOAD)) {
|
|
1777
|
|
1778 EVT_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD,
|
|
1779 ("JVMTI [%s] class compile method load event sent (by GenerateEvents), jmethodID=" PTR_FORMAT,
|
|
1780 JvmtiTrace::safe_get_thread_name(thread), method));
|
|
1781
|
|
1782 JvmtiEventMark jem(thread);
|
|
1783 JvmtiJavaThreadEventTransition jet(thread);
|
|
1784 jvmtiEventCompiledMethodLoad callback = env->callbacks()->CompiledMethodLoad;
|
|
1785 if (callback != NULL) {
|
|
1786 (*callback)(env->jvmti_external(), method,
|
|
1787 length, code_begin, map_length,
|
|
1788 map, NULL);
|
|
1789 }
|
|
1790 }
|
|
1791 }
|
|
1792
|
|
1793 // used at a safepoint to post a CompiledMethodUnload event
|
|
1794 void JvmtiExport::post_compiled_method_unload_at_safepoint(jmethodID mid, const void *code_begin) {
|
|
1795 assert(SafepointSynchronize::is_at_safepoint(), "must be executed at a safepoint");
|
|
1796
|
|
1797 // create list lazily
|
|
1798 if (_pending_compiled_method_unload_method_ids == NULL) {
|
|
1799 _pending_compiled_method_unload_method_ids = new (ResourceObj::C_HEAP) GrowableArray<jmethodID>(10,true);
|
|
1800 _pending_compiled_method_unload_code_begins = new (ResourceObj::C_HEAP) GrowableArray<const void *>(10,true);
|
|
1801 }
|
|
1802 _pending_compiled_method_unload_method_ids->append(mid);
|
|
1803 _pending_compiled_method_unload_code_begins->append(code_begin);
|
|
1804 _have_pending_compiled_method_unload_events = true;
|
|
1805 }
|
|
1806
|
|
1807 void JvmtiExport::post_dynamic_code_generated_internal(const char *name, const void *code_begin, const void *code_end) {
|
|
1808 JavaThread* thread = JavaThread::current();
|
|
1809 EVT_TRIG_TRACE(JVMTI_EVENT_DYNAMIC_CODE_GENERATED,
|
|
1810 ("JVMTI [%s] method dynamic code generated event triggered",
|
|
1811 JvmtiTrace::safe_get_thread_name(thread)));
|
|
1812 JvmtiEnvIterator it;
|
|
1813 for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
|
1814 if (env->is_enabled(JVMTI_EVENT_DYNAMIC_CODE_GENERATED)) {
|
|
1815 EVT_TRACE(JVMTI_EVENT_DYNAMIC_CODE_GENERATED,
|
|
1816 ("JVMTI [%s] dynamic code generated event sent for %s",
|
|
1817 JvmtiTrace::safe_get_thread_name(thread), name));
|
|
1818 JvmtiEventMark jem(thread);
|
|
1819 JvmtiJavaThreadEventTransition jet(thread);
|
|
1820 jint length = (jint)pointer_delta(code_end, code_begin, sizeof(char));
|
|
1821 jvmtiEventDynamicCodeGenerated callback = env->callbacks()->DynamicCodeGenerated;
|
|
1822 if (callback != NULL) {
|
|
1823 (*callback)(env->jvmti_external(), name, (void*)code_begin, length);
|
|
1824 }
|
|
1825 }
|
|
1826 }
|
|
1827 }
|
|
1828
|
|
1829 void JvmtiExport::post_dynamic_code_generated(const char *name, const void *code_begin, const void *code_end) {
|
|
1830 // In theory everyone coming thru here is in_vm but we need to be certain
|
|
1831 // because a callee will do a vm->native transition
|
|
1832 ThreadInVMfromUnknown __tiv;
|
|
1833 jvmtiPhase phase = JvmtiEnv::get_phase();
|
|
1834 if (phase == JVMTI_PHASE_PRIMORDIAL || phase == JVMTI_PHASE_START) {
|
|
1835 post_dynamic_code_generated_internal(name, code_begin, code_end);
|
|
1836 return;
|
|
1837 }
|
|
1838
|
|
1839 if (have_pending_compiled_method_unload_events()) {
|
|
1840 post_pending_compiled_method_unload_events();
|
|
1841 }
|
|
1842 post_dynamic_code_generated_internal(name, code_begin, code_end);
|
|
1843 }
|
|
1844
|
|
1845
|
|
1846 // post a DYNAMIC_CODE_GENERATED event for a given environment
|
|
1847 // used by GenerateEvents
|
|
1848 void JvmtiExport::post_dynamic_code_generated(JvmtiEnv* env, const char *name,
|
|
1849 const void *code_begin, const void *code_end)
|
|
1850 {
|
|
1851 JavaThread* thread = JavaThread::current();
|
|
1852 EVT_TRIG_TRACE(JVMTI_EVENT_DYNAMIC_CODE_GENERATED,
|
|
1853 ("JVMTI [%s] dynamic code generated event triggered (by GenerateEvents)",
|
|
1854 JvmtiTrace::safe_get_thread_name(thread)));
|
|
1855 if (env->is_enabled(JVMTI_EVENT_DYNAMIC_CODE_GENERATED)) {
|
|
1856 EVT_TRACE(JVMTI_EVENT_DYNAMIC_CODE_GENERATED,
|
|
1857 ("JVMTI [%s] dynamic code generated event sent for %s",
|
|
1858 JvmtiTrace::safe_get_thread_name(thread), name));
|
|
1859 JvmtiEventMark jem(thread);
|
|
1860 JvmtiJavaThreadEventTransition jet(thread);
|
|
1861 jint length = (jint)pointer_delta(code_end, code_begin, sizeof(char));
|
|
1862 jvmtiEventDynamicCodeGenerated callback = env->callbacks()->DynamicCodeGenerated;
|
|
1863 if (callback != NULL) {
|
|
1864 (*callback)(env->jvmti_external(), name, (void*)code_begin, length);
|
|
1865 }
|
|
1866 }
|
|
1867 }
|
|
1868
|
|
1869 // post a DynamicCodeGenerated event while holding locks in the VM.
|
|
1870 void JvmtiExport::post_dynamic_code_generated_while_holding_locks(const char* name,
|
|
1871 address code_begin, address code_end)
|
|
1872 {
|
|
1873 // register the stub with the current dynamic code event collector
|
|
1874 JvmtiThreadState* state = JvmtiThreadState::state_for(JavaThread::current());
|
|
1875 JvmtiDynamicCodeEventCollector* collector = state->get_dynamic_code_event_collector();
|
|
1876 guarantee(collector != NULL, "attempt to register stub without event collector");
|
|
1877 collector->register_stub(name, code_begin, code_end);
|
|
1878 }
|
|
1879
|
|
1880 // Collect all the vm internally allocated objects which are visible to java world
|
|
1881 void JvmtiExport::record_vm_internal_object_allocation(oop obj) {
|
|
1882 Thread* thread = ThreadLocalStorage::thread();
|
|
1883 if (thread != NULL && thread->is_Java_thread()) {
|
|
1884 // Can not take safepoint here.
|
|
1885 No_Safepoint_Verifier no_sfpt;
|
|
1886 // Can not take safepoint here so can not use state_for to get
|
|
1887 // jvmti thread state.
|
|
1888 JvmtiThreadState *state = ((JavaThread*)thread)->jvmti_thread_state();
|
|
1889 if (state != NULL ) {
|
|
1890 // state is non NULL when VMObjectAllocEventCollector is enabled.
|
|
1891 JvmtiVMObjectAllocEventCollector *collector;
|
|
1892 collector = state->get_vm_object_alloc_event_collector();
|
|
1893 if (collector != NULL && collector->is_enabled()) {
|
|
1894 // Don't record classes as these will be notified via the ClassLoad
|
|
1895 // event.
|
|
1896 if (obj->klass() != SystemDictionary::class_klass()) {
|
|
1897 collector->record_allocation(obj);
|
|
1898 }
|
|
1899 }
|
|
1900 }
|
|
1901 }
|
|
1902 }
|
|
1903
|
|
1904 void JvmtiExport::post_garbage_collection_finish() {
|
|
1905 Thread *thread = Thread::current(); // this event is posted from VM-Thread.
|
|
1906 EVT_TRIG_TRACE(JVMTI_EVENT_GARBAGE_COLLECTION_FINISH,
|
|
1907 ("JVMTI [%s] garbage collection finish event triggered",
|
|
1908 JvmtiTrace::safe_get_thread_name(thread)));
|
|
1909 JvmtiEnvIterator it;
|
|
1910 for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
|
1911 if (env->is_enabled(JVMTI_EVENT_GARBAGE_COLLECTION_FINISH)) {
|
|
1912 EVT_TRACE(JVMTI_EVENT_GARBAGE_COLLECTION_FINISH,
|
|
1913 ("JVMTI [%s] garbage collection finish event sent ",
|
|
1914 JvmtiTrace::safe_get_thread_name(thread)));
|
|
1915 JvmtiThreadEventTransition jet(thread);
|
|
1916 // JNIEnv is NULL here because this event is posted from VM Thread
|
|
1917 jvmtiEventGarbageCollectionFinish callback = env->callbacks()->GarbageCollectionFinish;
|
|
1918 if (callback != NULL) {
|
|
1919 (*callback)(env->jvmti_external());
|
|
1920 }
|
|
1921 }
|
|
1922 }
|
|
1923 }
|
|
1924
|
|
1925 void JvmtiExport::post_garbage_collection_start() {
|
|
1926 Thread* thread = Thread::current(); // this event is posted from vm-thread.
|
|
1927 EVT_TRIG_TRACE(JVMTI_EVENT_GARBAGE_COLLECTION_START,
|
|
1928 ("JVMTI [%s] garbage collection start event triggered",
|
|
1929 JvmtiTrace::safe_get_thread_name(thread)));
|
|
1930 JvmtiEnvIterator it;
|
|
1931 for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
|
1932 if (env->is_enabled(JVMTI_EVENT_GARBAGE_COLLECTION_START)) {
|
|
1933 EVT_TRACE(JVMTI_EVENT_GARBAGE_COLLECTION_START,
|
|
1934 ("JVMTI [%s] garbage collection start event sent ",
|
|
1935 JvmtiTrace::safe_get_thread_name(thread)));
|
|
1936 JvmtiThreadEventTransition jet(thread);
|
|
1937 // JNIEnv is NULL here because this event is posted from VM Thread
|
|
1938 jvmtiEventGarbageCollectionStart callback = env->callbacks()->GarbageCollectionStart;
|
|
1939 if (callback != NULL) {
|
|
1940 (*callback)(env->jvmti_external());
|
|
1941 }
|
|
1942 }
|
|
1943 }
|
|
1944 }
|
|
1945
|
|
1946 void JvmtiExport::post_data_dump() {
|
|
1947 Thread *thread = Thread::current();
|
|
1948 EVT_TRIG_TRACE(JVMTI_EVENT_DATA_DUMP_REQUEST,
|
|
1949 ("JVMTI [%s] data dump request event triggered",
|
|
1950 JvmtiTrace::safe_get_thread_name(thread)));
|
|
1951 JvmtiEnvIterator it;
|
|
1952 for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
|
1953 if (env->is_enabled(JVMTI_EVENT_DATA_DUMP_REQUEST)) {
|
|
1954 EVT_TRACE(JVMTI_EVENT_DATA_DUMP_REQUEST,
|
|
1955 ("JVMTI [%s] data dump request event sent ",
|
|
1956 JvmtiTrace::safe_get_thread_name(thread)));
|
|
1957 JvmtiThreadEventTransition jet(thread);
|
|
1958 // JNIEnv is NULL here because this event is posted from VM Thread
|
|
1959 jvmtiEventDataDumpRequest callback = env->callbacks()->DataDumpRequest;
|
|
1960 if (callback != NULL) {
|
|
1961 (*callback)(env->jvmti_external());
|
|
1962 }
|
|
1963 }
|
|
1964 }
|
|
1965 }
|
|
1966
|
|
1967 void JvmtiExport::post_monitor_contended_enter(JavaThread *thread, ObjectMonitor *obj_mntr) {
|
|
1968 oop object = (oop)obj_mntr->object();
|
|
1969 if (!ServiceUtil::visible_oop(object)) {
|
|
1970 // Ignore monitor contended enter for vm internal object.
|
|
1971 return;
|
|
1972 }
|
|
1973 JvmtiThreadState *state = thread->jvmti_thread_state();
|
|
1974 if (state == NULL) {
|
|
1975 return;
|
|
1976 }
|
|
1977
|
|
1978 HandleMark hm(thread);
|
|
1979 Handle h(thread, object);
|
|
1980
|
|
1981 EVT_TRIG_TRACE(JVMTI_EVENT_MONITOR_CONTENDED_ENTER,
|
|
1982 ("JVMTI [%s] montior contended enter event triggered",
|
|
1983 JvmtiTrace::safe_get_thread_name(thread)));
|
|
1984
|
|
1985 JvmtiEnvThreadStateIterator it(state);
|
|
1986 for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
|
|
1987 if (ets->is_enabled(JVMTI_EVENT_MONITOR_CONTENDED_ENTER)) {
|
|
1988 EVT_TRACE(JVMTI_EVENT_MONITOR_CONTENDED_ENTER,
|
|
1989 ("JVMTI [%s] monitor contended enter event sent",
|
|
1990 JvmtiTrace::safe_get_thread_name(thread)));
|
|
1991 JvmtiMonitorEventMark jem(thread, h());
|
|
1992 JvmtiEnv *env = ets->get_env();
|
|
1993 JvmtiThreadEventTransition jet(thread);
|
|
1994 jvmtiEventMonitorContendedEnter callback = env->callbacks()->MonitorContendedEnter;
|
|
1995 if (callback != NULL) {
|
|
1996 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(), jem.jni_object());
|
|
1997 }
|
|
1998 }
|
|
1999 }
|
|
2000 }
|
|
2001
|
|
2002 void JvmtiExport::post_monitor_contended_entered(JavaThread *thread, ObjectMonitor *obj_mntr) {
|
|
2003 oop object = (oop)obj_mntr->object();
|
|
2004 if (!ServiceUtil::visible_oop(object)) {
|
|
2005 // Ignore monitor contended entered for vm internal object.
|
|
2006 return;
|
|
2007 }
|
|
2008 JvmtiThreadState *state = thread->jvmti_thread_state();
|
|
2009 if (state == NULL) {
|
|
2010 return;
|
|
2011 }
|
|
2012
|
|
2013 HandleMark hm(thread);
|
|
2014 Handle h(thread, object);
|
|
2015
|
|
2016 EVT_TRIG_TRACE(JVMTI_EVENT_MONITOR_CONTENDED_ENTERED,
|
|
2017 ("JVMTI [%s] montior contended entered event triggered",
|
|
2018 JvmtiTrace::safe_get_thread_name(thread)));
|
|
2019
|
|
2020 JvmtiEnvThreadStateIterator it(state);
|
|
2021 for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
|
|
2022 if (ets->is_enabled(JVMTI_EVENT_MONITOR_CONTENDED_ENTERED)) {
|
|
2023 EVT_TRACE(JVMTI_EVENT_MONITOR_CONTENDED_ENTERED,
|
|
2024 ("JVMTI [%s] monitor contended enter event sent",
|
|
2025 JvmtiTrace::safe_get_thread_name(thread)));
|
|
2026 JvmtiMonitorEventMark jem(thread, h());
|
|
2027 JvmtiEnv *env = ets->get_env();
|
|
2028 JvmtiThreadEventTransition jet(thread);
|
|
2029 jvmtiEventMonitorContendedEntered callback = env->callbacks()->MonitorContendedEntered;
|
|
2030 if (callback != NULL) {
|
|
2031 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(), jem.jni_object());
|
|
2032 }
|
|
2033 }
|
|
2034 }
|
|
2035 }
|
|
2036
|
|
2037 void JvmtiExport::post_monitor_wait(JavaThread *thread, oop object,
|
|
2038 jlong timeout) {
|
|
2039 JvmtiThreadState *state = thread->jvmti_thread_state();
|
|
2040 if (state == NULL) {
|
|
2041 return;
|
|
2042 }
|
|
2043
|
|
2044 HandleMark hm(thread);
|
|
2045 Handle h(thread, object);
|
|
2046
|
|
2047 EVT_TRIG_TRACE(JVMTI_EVENT_MONITOR_WAIT,
|
|
2048 ("JVMTI [%s] montior wait event triggered",
|
|
2049 JvmtiTrace::safe_get_thread_name(thread)));
|
|
2050
|
|
2051 JvmtiEnvThreadStateIterator it(state);
|
|
2052 for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
|
|
2053 if (ets->is_enabled(JVMTI_EVENT_MONITOR_WAIT)) {
|
|
2054 EVT_TRACE(JVMTI_EVENT_MONITOR_WAIT,
|
|
2055 ("JVMTI [%s] monitor wait event sent ",
|
|
2056 JvmtiTrace::safe_get_thread_name(thread)));
|
|
2057 JvmtiMonitorEventMark jem(thread, h());
|
|
2058 JvmtiEnv *env = ets->get_env();
|
|
2059 JvmtiThreadEventTransition jet(thread);
|
|
2060 jvmtiEventMonitorWait callback = env->callbacks()->MonitorWait;
|
|
2061 if (callback != NULL) {
|
|
2062 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(),
|
|
2063 jem.jni_object(), timeout);
|
|
2064 }
|
|
2065 }
|
|
2066 }
|
|
2067 }
|
|
2068
|
|
2069 void JvmtiExport::post_monitor_waited(JavaThread *thread, ObjectMonitor *obj_mntr, jboolean timed_out) {
|
|
2070 oop object = (oop)obj_mntr->object();
|
|
2071 if (!ServiceUtil::visible_oop(object)) {
|
|
2072 // Ignore monitor waited for vm internal object.
|
|
2073 return;
|
|
2074 }
|
|
2075 JvmtiThreadState *state = thread->jvmti_thread_state();
|
|
2076 if (state == NULL) {
|
|
2077 return;
|
|
2078 }
|
|
2079
|
|
2080 HandleMark hm(thread);
|
|
2081 Handle h(thread, object);
|
|
2082
|
|
2083 EVT_TRIG_TRACE(JVMTI_EVENT_MONITOR_WAITED,
|
|
2084 ("JVMTI [%s] montior waited event triggered",
|
|
2085 JvmtiTrace::safe_get_thread_name(thread)));
|
|
2086
|
|
2087 JvmtiEnvThreadStateIterator it(state);
|
|
2088 for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
|
|
2089 if (ets->is_enabled(JVMTI_EVENT_MONITOR_WAITED)) {
|
|
2090 EVT_TRACE(JVMTI_EVENT_MONITOR_WAITED,
|
|
2091 ("JVMTI [%s] monitor waited event sent ",
|
|
2092 JvmtiTrace::safe_get_thread_name(thread)));
|
|
2093 JvmtiMonitorEventMark jem(thread, h());
|
|
2094 JvmtiEnv *env = ets->get_env();
|
|
2095 JvmtiThreadEventTransition jet(thread);
|
|
2096 jvmtiEventMonitorWaited callback = env->callbacks()->MonitorWaited;
|
|
2097 if (callback != NULL) {
|
|
2098 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(),
|
|
2099 jem.jni_object(), timed_out);
|
|
2100 }
|
|
2101 }
|
|
2102 }
|
|
2103 }
|
|
2104
|
|
2105
|
|
2106 void JvmtiExport::post_vm_object_alloc(JavaThread *thread, oop object) {
|
|
2107 EVT_TRIG_TRACE(JVMTI_EVENT_VM_OBJECT_ALLOC, ("JVMTI [%s] Trg vm object alloc triggered",
|
|
2108 JvmtiTrace::safe_get_thread_name(thread)));
|
|
2109 if (object == NULL) {
|
|
2110 return;
|
|
2111 }
|
|
2112 HandleMark hm(thread);
|
|
2113 Handle h(thread, object);
|
|
2114 JvmtiEnvIterator it;
|
|
2115 for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
|
|
2116 if (env->is_enabled(JVMTI_EVENT_VM_OBJECT_ALLOC)) {
|
|
2117 EVT_TRACE(JVMTI_EVENT_VM_OBJECT_ALLOC, ("JVMTI [%s] Evt vmobject alloc sent %s",
|
|
2118 JvmtiTrace::safe_get_thread_name(thread),
|
|
2119 object==NULL? "NULL" : Klass::cast(java_lang_Class::as_klassOop(object))->external_name()));
|
|
2120
|
|
2121 JvmtiVMObjectAllocEventMark jem(thread, h());
|
|
2122 JvmtiJavaThreadEventTransition jet(thread);
|
|
2123 jvmtiEventVMObjectAlloc callback = env->callbacks()->VMObjectAlloc;
|
|
2124 if (callback != NULL) {
|
|
2125 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(),
|
|
2126 jem.jni_jobject(), jem.jni_class(), jem.size());
|
|
2127 }
|
|
2128 }
|
|
2129 }
|
|
2130 }
|
|
2131
|
|
2132 ////////////////////////////////////////////////////////////////////////////////////////////////
|
|
2133
|
|
2134 void JvmtiExport::cleanup_thread(JavaThread* thread) {
|
|
2135 assert(JavaThread::current() == thread, "thread is not current");
|
|
2136
|
|
2137
|
|
2138 // This has to happen after the thread state is removed, which is
|
|
2139 // why it is not in post_thread_end_event like its complement
|
|
2140 // Maybe both these functions should be rolled into the posts?
|
|
2141 JvmtiEventController::thread_ended(thread);
|
|
2142 }
|
|
2143
|
|
2144 void JvmtiExport::oops_do(OopClosure* f) {
|
|
2145 JvmtiCurrentBreakpoints::oops_do(f);
|
|
2146 JvmtiVMObjectAllocEventCollector::oops_do_for_all_threads(f);
|
|
2147 }
|
|
2148
|
|
2149 // Onload raw monitor transition.
|
|
2150 void JvmtiExport::transition_pending_onload_raw_monitors() {
|
|
2151 JvmtiPendingMonitors::transition_raw_monitors();
|
|
2152 }
|
|
2153
|
|
2154 ////////////////////////////////////////////////////////////////////////////////////////////////
|
|
2155
|
|
2156 // type for the Agent_OnAttach entry point
|
|
2157 extern "C" {
|
|
2158 typedef jint (JNICALL *OnAttachEntry_t)(JavaVM*, char *, void *);
|
|
2159 }
|
|
2160
|
|
2161 #ifndef SERVICES_KERNEL
|
|
2162 jint JvmtiExport::load_agent_library(AttachOperation* op, outputStream* st) {
|
|
2163 char ebuf[1024];
|
|
2164 char buffer[JVM_MAXPATHLEN];
|
|
2165 void* library;
|
|
2166 jint result = JNI_ERR;
|
|
2167
|
|
2168 // get agent name and options
|
|
2169 const char* agent = op->arg(0);
|
|
2170 const char* absParam = op->arg(1);
|
|
2171 const char* options = op->arg(2);
|
|
2172
|
|
2173 // The abs paramter should be "true" or "false"
|
|
2174 bool is_absolute_path = (absParam != NULL) && (strcmp(absParam,"true")==0);
|
|
2175
|
|
2176
|
|
2177 // If the path is absolute we attempt to load the library. Otherwise we try to
|
|
2178 // load it from the standard dll directory.
|
|
2179
|
|
2180 if (is_absolute_path) {
|
|
2181 library = hpi::dll_load(agent, ebuf, sizeof ebuf);
|
|
2182 } else {
|
|
2183 // Try to load the agent from the standard dll directory
|
|
2184 hpi::dll_build_name(buffer, sizeof(buffer), Arguments::get_dll_dir(), agent);
|
|
2185 library = hpi::dll_load(buffer, ebuf, sizeof ebuf);
|
|
2186 if (library == NULL) {
|
|
2187 // not found - try local path
|
|
2188 char ns[1] = {0};
|
|
2189 hpi::dll_build_name(buffer, sizeof(buffer), ns, agent);
|
|
2190 library = hpi::dll_load(buffer, ebuf, sizeof ebuf);
|
|
2191 }
|
|
2192 }
|
|
2193
|
|
2194 // If the library was loaded then we attempt to invoke the Agent_OnAttach
|
|
2195 // function
|
|
2196 if (library != NULL) {
|
|
2197
|
|
2198 // Lookup the Agent_OnAttach function
|
|
2199 OnAttachEntry_t on_attach_entry = NULL;
|
|
2200 const char *on_attach_symbols[] = AGENT_ONATTACH_SYMBOLS;
|
|
2201 for (uint symbol_index = 0; symbol_index < ARRAY_SIZE(on_attach_symbols); symbol_index++) {
|
|
2202 on_attach_entry =
|
|
2203 CAST_TO_FN_PTR(OnAttachEntry_t, hpi::dll_lookup(library, on_attach_symbols[symbol_index]));
|
|
2204 if (on_attach_entry != NULL) break;
|
|
2205 }
|
|
2206
|
|
2207 if (on_attach_entry == NULL) {
|
|
2208 // Agent_OnAttach missing - unload library
|
|
2209 hpi::dll_unload(library);
|
|
2210 } else {
|
|
2211 // Invoke the Agent_OnAttach function
|
|
2212 JavaThread* THREAD = JavaThread::current();
|
|
2213 {
|
|
2214 extern struct JavaVM_ main_vm;
|
|
2215 JvmtiThreadEventMark jem(THREAD);
|
|
2216 JvmtiJavaThreadEventTransition jet(THREAD);
|
|
2217
|
|
2218 result = (*on_attach_entry)(&main_vm, (char*)options, NULL);
|
|
2219 }
|
|
2220
|
|
2221 // Agent_OnAttach may have used JNI
|
|
2222 if (HAS_PENDING_EXCEPTION) {
|
|
2223 CLEAR_PENDING_EXCEPTION;
|
|
2224 }
|
|
2225
|
|
2226 // If OnAttach returns JNI_OK then we add it to the list of
|
|
2227 // agent libraries so that we can call Agent_OnUnload later.
|
|
2228 if (result == JNI_OK) {
|
|
2229 Arguments::add_loaded_agent(agent, (char*)options, is_absolute_path, library);
|
|
2230 }
|
|
2231
|
|
2232 // Agent_OnAttach executed so completion status is JNI_OK
|
|
2233 st->print_cr("%d", result);
|
|
2234 result = JNI_OK;
|
|
2235 }
|
|
2236 }
|
|
2237 return result;
|
|
2238 }
|
|
2239 #endif // SERVICES_KERNEL
|
|
2240
|
|
2241 // CMS has completed referencing processing so may need to update
|
|
2242 // tag maps.
|
|
2243 void JvmtiExport::cms_ref_processing_epilogue() {
|
|
2244 if (JvmtiEnv::environments_might_exist()) {
|
|
2245 JvmtiTagMap::cms_ref_processing_epilogue();
|
|
2246 }
|
|
2247 }
|
|
2248
|
|
2249
|
|
2250 ////////////////////////////////////////////////////////////////////////////////////////////////
|
|
2251
|
|
2252 // Setup current current thread for event collection.
|
|
2253 void JvmtiEventCollector::setup_jvmti_thread_state() {
|
|
2254 // set this event collector to be the current one.
|
|
2255 JvmtiThreadState* state = JvmtiThreadState::state_for(JavaThread::current());
|
|
2256 if (is_vm_object_alloc_event()) {
|
|
2257 _prev = state->get_vm_object_alloc_event_collector();
|
|
2258 state->set_vm_object_alloc_event_collector((JvmtiVMObjectAllocEventCollector *)this);
|
|
2259 } else if (is_dynamic_code_event()) {
|
|
2260 _prev = state->get_dynamic_code_event_collector();
|
|
2261 state->set_dynamic_code_event_collector((JvmtiDynamicCodeEventCollector *)this);
|
|
2262 }
|
|
2263 }
|
|
2264
|
|
2265 // Unset current event collection in this thread and reset it with previous
|
|
2266 // collector.
|
|
2267 void JvmtiEventCollector::unset_jvmti_thread_state() {
|
|
2268 JvmtiThreadState* state = JavaThread::current()->jvmti_thread_state();
|
|
2269 if (state != NULL) {
|
|
2270 // restore the previous event collector (if any)
|
|
2271 if (is_vm_object_alloc_event()) {
|
|
2272 if (state->get_vm_object_alloc_event_collector() == this) {
|
|
2273 state->set_vm_object_alloc_event_collector((JvmtiVMObjectAllocEventCollector *)_prev);
|
|
2274 } else {
|
|
2275 // this thread's jvmti state was created during the scope of
|
|
2276 // the event collector.
|
|
2277 }
|
|
2278 } else {
|
|
2279 if (is_dynamic_code_event()) {
|
|
2280 if (state->get_dynamic_code_event_collector() == this) {
|
|
2281 state->set_dynamic_code_event_collector((JvmtiDynamicCodeEventCollector *)_prev);
|
|
2282 } else {
|
|
2283 // this thread's jvmti state was created during the scope of
|
|
2284 // the event collector.
|
|
2285 }
|
|
2286 }
|
|
2287 }
|
|
2288 }
|
|
2289 }
|
|
2290
|
|
2291 // create the dynamic code event collector
|
|
2292 JvmtiDynamicCodeEventCollector::JvmtiDynamicCodeEventCollector() : _code_blobs(NULL) {
|
|
2293 if (JvmtiExport::should_post_dynamic_code_generated()) {
|
|
2294 setup_jvmti_thread_state();
|
|
2295 }
|
|
2296 }
|
|
2297
|
|
2298 // iterate over any code blob descriptors collected and post a
|
|
2299 // DYNAMIC_CODE_GENERATED event to the profiler.
|
|
2300 JvmtiDynamicCodeEventCollector::~JvmtiDynamicCodeEventCollector() {
|
|
2301 assert(!JavaThread::current()->owns_locks(), "all locks must be released to post deferred events");
|
|
2302 // iterate over any code blob descriptors that we collected
|
|
2303 if (_code_blobs != NULL) {
|
|
2304 for (int i=0; i<_code_blobs->length(); i++) {
|
|
2305 JvmtiCodeBlobDesc* blob = _code_blobs->at(i);
|
|
2306 JvmtiExport::post_dynamic_code_generated(blob->name(), blob->code_begin(), blob->code_end());
|
|
2307 FreeHeap(blob);
|
|
2308 }
|
|
2309 delete _code_blobs;
|
|
2310 }
|
|
2311 unset_jvmti_thread_state();
|
|
2312 }
|
|
2313
|
|
2314 // register a stub
|
|
2315 void JvmtiDynamicCodeEventCollector::register_stub(const char* name, address start, address end) {
|
|
2316 if (_code_blobs == NULL) {
|
|
2317 _code_blobs = new (ResourceObj::C_HEAP) GrowableArray<JvmtiCodeBlobDesc*>(1,true);
|
|
2318 }
|
|
2319 _code_blobs->append(new JvmtiCodeBlobDesc(name, start, end));
|
|
2320 }
|
|
2321
|
|
2322 // Setup current thread to record vm allocated objects.
|
|
2323 JvmtiVMObjectAllocEventCollector::JvmtiVMObjectAllocEventCollector() : _allocated(NULL) {
|
|
2324 if (JvmtiExport::should_post_vm_object_alloc()) {
|
|
2325 _enable = true;
|
|
2326 setup_jvmti_thread_state();
|
|
2327 } else {
|
|
2328 _enable = false;
|
|
2329 }
|
|
2330 }
|
|
2331
|
|
2332 // Post vm_object_alloc event for vm allocated objects visible to java
|
|
2333 // world.
|
|
2334 JvmtiVMObjectAllocEventCollector::~JvmtiVMObjectAllocEventCollector() {
|
|
2335 if (_allocated != NULL) {
|
|
2336 set_enabled(false);
|
|
2337 for (int i = 0; i < _allocated->length(); i++) {
|
|
2338 oop obj = _allocated->at(i);
|
|
2339 if (ServiceUtil::visible_oop(obj)) {
|
|
2340 JvmtiExport::post_vm_object_alloc(JavaThread::current(), obj);
|
|
2341 }
|
|
2342 }
|
|
2343 delete _allocated;
|
|
2344 }
|
|
2345 unset_jvmti_thread_state();
|
|
2346 }
|
|
2347
|
|
2348 void JvmtiVMObjectAllocEventCollector::record_allocation(oop obj) {
|
|
2349 assert(is_enabled(), "VM object alloc event collector is not enabled");
|
|
2350 if (_allocated == NULL) {
|
|
2351 _allocated = new (ResourceObj::C_HEAP) GrowableArray<oop>(1, true);
|
|
2352 }
|
|
2353 _allocated->push(obj);
|
|
2354 }
|
|
2355
|
|
2356 // GC support.
|
|
2357 void JvmtiVMObjectAllocEventCollector::oops_do(OopClosure* f) {
|
|
2358 if (_allocated != NULL) {
|
|
2359 for(int i=_allocated->length() - 1; i >= 0; i--) {
|
|
2360 if (_allocated->at(i) != NULL) {
|
|
2361 f->do_oop(_allocated->adr_at(i));
|
|
2362 }
|
|
2363 }
|
|
2364 }
|
|
2365 }
|
|
2366
|
|
2367 void JvmtiVMObjectAllocEventCollector::oops_do_for_all_threads(OopClosure* f) {
|
|
2368 // no-op if jvmti not enabled
|
|
2369 if (!JvmtiEnv::environments_might_exist()) {
|
|
2370 return;
|
|
2371 }
|
|
2372
|
|
2373 // Runs at safepoint. So no need to acquire Threads_lock.
|
|
2374 for (JavaThread *jthr = Threads::first(); jthr != NULL; jthr = jthr->next()) {
|
|
2375 JvmtiThreadState *state = jthr->jvmti_thread_state();
|
|
2376 if (state != NULL) {
|
|
2377 JvmtiVMObjectAllocEventCollector *collector;
|
|
2378 collector = state->get_vm_object_alloc_event_collector();
|
|
2379 while (collector != NULL) {
|
|
2380 collector->oops_do(f);
|
|
2381 collector = (JvmtiVMObjectAllocEventCollector *)collector->get_prev();
|
|
2382 }
|
|
2383 }
|
|
2384 }
|
|
2385 }
|
|
2386
|
|
2387
|
|
2388 // Disable collection of VMObjectAlloc events
|
|
2389 NoJvmtiVMObjectAllocMark::NoJvmtiVMObjectAllocMark() : _collector(NULL) {
|
|
2390 // a no-op if VMObjectAlloc event is not enabled
|
|
2391 if (!JvmtiExport::should_post_vm_object_alloc()) {
|
|
2392 return;
|
|
2393 }
|
|
2394 Thread* thread = ThreadLocalStorage::thread();
|
|
2395 if (thread != NULL && thread->is_Java_thread()) {
|
|
2396 JavaThread* current_thread = (JavaThread*)thread;
|
|
2397 JvmtiThreadState *state = current_thread->jvmti_thread_state();
|
|
2398 if (state != NULL) {
|
|
2399 JvmtiVMObjectAllocEventCollector *collector;
|
|
2400 collector = state->get_vm_object_alloc_event_collector();
|
|
2401 if (collector != NULL && collector->is_enabled()) {
|
|
2402 _collector = collector;
|
|
2403 _collector->set_enabled(false);
|
|
2404 }
|
|
2405 }
|
|
2406 }
|
|
2407 }
|
|
2408
|
|
2409 // Re-Enable collection of VMObjectAlloc events (if previously enabled)
|
|
2410 NoJvmtiVMObjectAllocMark::~NoJvmtiVMObjectAllocMark() {
|
|
2411 if (was_enabled()) {
|
|
2412 _collector->set_enabled(true);
|
|
2413 }
|
|
2414 };
|
|
2415
|
|
2416 JvmtiGCMarker::JvmtiGCMarker(bool full) : _full(full), _invocation_count(0) {
|
|
2417 assert(Thread::current()->is_VM_thread(), "wrong thread");
|
|
2418
|
|
2419 // if there aren't any JVMTI environments then nothing to do
|
|
2420 if (!JvmtiEnv::environments_might_exist()) {
|
|
2421 return;
|
|
2422 }
|
|
2423
|
|
2424 // GarbageCollectionStart event posted from VM thread - okay because
|
|
2425 // JVMTI is clear that the "world is stopped" and callback shouldn't
|
|
2426 // try to call into the VM.
|
|
2427 if (JvmtiExport::should_post_garbage_collection_start()) {
|
|
2428 JvmtiExport::post_garbage_collection_start();
|
|
2429 }
|
|
2430
|
|
2431 // if "full" is false it probably means this is a scavenge of the young
|
|
2432 // generation. However it could turn out that a "full" GC is required
|
|
2433 // so we record the number of collections so that it can be checked in
|
|
2434 // the destructor.
|
|
2435 if (!_full) {
|
|
2436 if (Universe::heap()->kind() == CollectedHeap::GenCollectedHeap) {
|
|
2437 GenCollectedHeap* gch = GenCollectedHeap::heap();
|
|
2438 assert(gch->n_gens() == 2, "configuration not recognized");
|
|
2439 _invocation_count = (unsigned int)gch->get_gen(1)->stat_record()->invocations;
|
|
2440 } else {
|
|
2441 #ifndef SERIALGC
|
|
2442 assert(Universe::heap()->kind() == CollectedHeap::ParallelScavengeHeap, "checking");
|
|
2443 _invocation_count = PSMarkSweep::total_invocations();
|
|
2444 #else // SERIALGC
|
|
2445 fatal("SerialGC only supported in this configuration.");
|
|
2446 #endif // SERIALGC
|
|
2447 }
|
|
2448 }
|
|
2449
|
|
2450 // Do clean up tasks that need to be done at a safepoint
|
|
2451 JvmtiEnvBase::check_for_periodic_clean_up();
|
|
2452 }
|
|
2453
|
|
2454 JvmtiGCMarker::~JvmtiGCMarker() {
|
|
2455 // if there aren't any JVMTI environments then nothing to do
|
|
2456 if (!JvmtiEnv::environments_might_exist()) {
|
|
2457 return;
|
|
2458 }
|
|
2459
|
|
2460 // JVMTI notify gc finish
|
|
2461 if (JvmtiExport::should_post_garbage_collection_finish()) {
|
|
2462 JvmtiExport::post_garbage_collection_finish();
|
|
2463 }
|
|
2464
|
|
2465 // we might have initially started out doing a scavenge of the young
|
|
2466 // generation but could have ended up doing a "full" GC - check the
|
|
2467 // GC count to see.
|
|
2468 if (!_full) {
|
|
2469 if (Universe::heap()->kind() == CollectedHeap::GenCollectedHeap) {
|
|
2470 GenCollectedHeap* gch = GenCollectedHeap::heap();
|
|
2471 if (_invocation_count != (unsigned int)gch->get_gen(1)->stat_record()->invocations) {
|
|
2472 _full = true;
|
|
2473 }
|
|
2474 } else {
|
|
2475 #ifndef SERIALGC
|
|
2476 if (_invocation_count != PSMarkSweep::total_invocations()) {
|
|
2477 _full = true;
|
|
2478 }
|
|
2479 #else // SERIALGC
|
|
2480 fatal("SerialGC only supported in this configuration.");
|
|
2481 #endif // SERIALGC
|
|
2482 }
|
|
2483 }
|
|
2484
|
|
2485 // Full collection probably means the perm generation has been GC'ed
|
|
2486 // so we clear the breakpoint cache.
|
|
2487 if (_full) {
|
|
2488 JvmtiCurrentBreakpoints::gc_epilogue();
|
|
2489 }
|
|
2490
|
|
2491 // Notify heap/object tagging support
|
|
2492 JvmtiTagMap::gc_epilogue(_full);
|
|
2493 }
|
|
2494 #endif // JVMTI_KERNEL
|