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