Mercurial > hg > graal-jvmci-8
annotate src/share/vm/prims/jvmtiExport.cpp @ 3249:e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
Summary: A referent object that is only weakly reachable at the start of concurrent marking but is re-attached to the strongly reachable object graph during marking may not be marked as live. This can cause the reference object to be processed prematurely and leave dangling pointers to the referent object. Implement a read barrier for the java.lang.ref.Reference::referent field by intrinsifying the Reference.get() method, and intercepting accesses though JNI, reflection, and Unsafe, so that when a non-null referent object is read it is also logged in an SATB buffer.
Reviewed-by: kvn, iveresov, never, tonyp, dholmes
author | johnc |
---|---|
date | Thu, 07 Apr 2011 09:53:20 -0700 |
parents | f91db74a6810 |
children | 0cddebc420d8 |
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) { | |
1807 JavaThread* thread = JavaThread::current(); | |
2301
f91db74a6810
7017640: Fix for 6766644 deadlocks on some NSK tests when running with -Xcomp
kamg
parents:
2195
diff
changeset
|
1808 // 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
|
1809 // 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
|
1810 ThreadInVMfromUnknown __tiv; |
f91db74a6810
7017640: Fix for 6766644 deadlocks on some NSK tests when running with -Xcomp
kamg
parents:
2195
diff
changeset
|
1811 |
0 | 1812 EVT_TRIG_TRACE(JVMTI_EVENT_DYNAMIC_CODE_GENERATED, |
1813 ("JVMTI [%s] method dynamic code generated event triggered", | |
1814 JvmtiTrace::safe_get_thread_name(thread))); | |
1815 JvmtiEnvIterator it; | |
1816 for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) { | |
1817 if (env->is_enabled(JVMTI_EVENT_DYNAMIC_CODE_GENERATED)) { | |
1818 EVT_TRACE(JVMTI_EVENT_DYNAMIC_CODE_GENERATED, | |
1819 ("JVMTI [%s] dynamic code generated event sent for %s", | |
1820 JvmtiTrace::safe_get_thread_name(thread), name)); | |
1821 JvmtiEventMark jem(thread); | |
1822 JvmtiJavaThreadEventTransition jet(thread); | |
1823 jint length = (jint)pointer_delta(code_end, code_begin, sizeof(char)); | |
1824 jvmtiEventDynamicCodeGenerated callback = env->callbacks()->DynamicCodeGenerated; | |
1825 if (callback != NULL) { | |
1826 (*callback)(env->jvmti_external(), name, (void*)code_begin, length); | |
1827 } | |
1828 } | |
1829 } | |
1830 } | |
1831 | |
1832 void JvmtiExport::post_dynamic_code_generated(const char *name, const void *code_begin, const void *code_end) { | |
1833 jvmtiPhase phase = JvmtiEnv::get_phase(); | |
1834 if (phase == JVMTI_PHASE_PRIMORDIAL || phase == JVMTI_PHASE_START) { | |
1835 post_dynamic_code_generated_internal(name, code_begin, code_end); | |
2301
f91db74a6810
7017640: Fix for 6766644 deadlocks on some NSK tests when running with -Xcomp
kamg
parents:
2195
diff
changeset
|
1836 } else { |
f91db74a6810
7017640: Fix for 6766644 deadlocks on some NSK tests when running with -Xcomp
kamg
parents:
2195
diff
changeset
|
1837 // 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
|
1838 // 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
|
1839 // context and in-order. |
f91db74a6810
7017640: Fix for 6766644 deadlocks on some NSK tests when running with -Xcomp
kamg
parents:
2195
diff
changeset
|
1840 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
|
1841 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
|
1842 name, code_begin, code_end); |
f91db74a6810
7017640: Fix for 6766644 deadlocks on some NSK tests when running with -Xcomp
kamg
parents:
2195
diff
changeset
|
1843 JvmtiDeferredEventQueue::enqueue(event); |
0 | 1844 } |
1845 } | |
1846 | |
1847 | |
1848 // post a DYNAMIC_CODE_GENERATED event for a given environment | |
1849 // used by GenerateEvents | |
1850 void JvmtiExport::post_dynamic_code_generated(JvmtiEnv* env, const char *name, | |
1851 const void *code_begin, const void *code_end) | |
1852 { | |
1853 JavaThread* thread = JavaThread::current(); | |
1854 EVT_TRIG_TRACE(JVMTI_EVENT_DYNAMIC_CODE_GENERATED, | |
1855 ("JVMTI [%s] dynamic code generated event triggered (by GenerateEvents)", | |
1856 JvmtiTrace::safe_get_thread_name(thread))); | |
1857 if (env->is_enabled(JVMTI_EVENT_DYNAMIC_CODE_GENERATED)) { | |
1858 EVT_TRACE(JVMTI_EVENT_DYNAMIC_CODE_GENERATED, | |
1859 ("JVMTI [%s] dynamic code generated event sent for %s", | |
1860 JvmtiTrace::safe_get_thread_name(thread), name)); | |
1861 JvmtiEventMark jem(thread); | |
1862 JvmtiJavaThreadEventTransition jet(thread); | |
1863 jint length = (jint)pointer_delta(code_end, code_begin, sizeof(char)); | |
1864 jvmtiEventDynamicCodeGenerated callback = env->callbacks()->DynamicCodeGenerated; | |
1865 if (callback != NULL) { | |
1866 (*callback)(env->jvmti_external(), name, (void*)code_begin, length); | |
1867 } | |
1868 } | |
1869 } | |
1870 | |
1871 // post a DynamicCodeGenerated event while holding locks in the VM. | |
1872 void JvmtiExport::post_dynamic_code_generated_while_holding_locks(const char* name, | |
1873 address code_begin, address code_end) | |
1874 { | |
1875 // register the stub with the current dynamic code event collector | |
1876 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
|
1877 // 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
|
1878 // 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
|
1879 guarantee(state != NULL, "attempt to register stub via an exiting thread"); |
0 | 1880 JvmtiDynamicCodeEventCollector* collector = state->get_dynamic_code_event_collector(); |
1881 guarantee(collector != NULL, "attempt to register stub without event collector"); | |
1882 collector->register_stub(name, code_begin, code_end); | |
1883 } | |
1884 | |
1885 // Collect all the vm internally allocated objects which are visible to java world | |
1886 void JvmtiExport::record_vm_internal_object_allocation(oop obj) { | |
1887 Thread* thread = ThreadLocalStorage::thread(); | |
1888 if (thread != NULL && thread->is_Java_thread()) { | |
1889 // Can not take safepoint here. | |
1890 No_Safepoint_Verifier no_sfpt; | |
1891 // Can not take safepoint here so can not use state_for to get | |
1892 // jvmti thread state. | |
1893 JvmtiThreadState *state = ((JavaThread*)thread)->jvmti_thread_state(); | |
1894 if (state != NULL ) { | |
1895 // state is non NULL when VMObjectAllocEventCollector is enabled. | |
1896 JvmtiVMObjectAllocEventCollector *collector; | |
1897 collector = state->get_vm_object_alloc_event_collector(); | |
1898 if (collector != NULL && collector->is_enabled()) { | |
1899 // Don't record classes as these will be notified via the ClassLoad | |
1900 // event. | |
1142 | 1901 if (obj->klass() != SystemDictionary::Class_klass()) { |
0 | 1902 collector->record_allocation(obj); |
1903 } | |
1904 } | |
1905 } | |
1906 } | |
1907 } | |
1908 | |
1909 void JvmtiExport::post_garbage_collection_finish() { | |
1910 Thread *thread = Thread::current(); // this event is posted from VM-Thread. | |
1911 EVT_TRIG_TRACE(JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, | |
1912 ("JVMTI [%s] garbage collection finish event triggered", | |
1913 JvmtiTrace::safe_get_thread_name(thread))); | |
1914 JvmtiEnvIterator it; | |
1915 for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) { | |
1916 if (env->is_enabled(JVMTI_EVENT_GARBAGE_COLLECTION_FINISH)) { | |
1917 EVT_TRACE(JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, | |
1918 ("JVMTI [%s] garbage collection finish event sent ", | |
1919 JvmtiTrace::safe_get_thread_name(thread))); | |
1920 JvmtiThreadEventTransition jet(thread); | |
1921 // JNIEnv is NULL here because this event is posted from VM Thread | |
1922 jvmtiEventGarbageCollectionFinish callback = env->callbacks()->GarbageCollectionFinish; | |
1923 if (callback != NULL) { | |
1924 (*callback)(env->jvmti_external()); | |
1925 } | |
1926 } | |
1927 } | |
1928 } | |
1929 | |
1930 void JvmtiExport::post_garbage_collection_start() { | |
1931 Thread* thread = Thread::current(); // this event is posted from vm-thread. | |
1932 EVT_TRIG_TRACE(JVMTI_EVENT_GARBAGE_COLLECTION_START, | |
1933 ("JVMTI [%s] garbage collection start event triggered", | |
1934 JvmtiTrace::safe_get_thread_name(thread))); | |
1935 JvmtiEnvIterator it; | |
1936 for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) { | |
1937 if (env->is_enabled(JVMTI_EVENT_GARBAGE_COLLECTION_START)) { | |
1938 EVT_TRACE(JVMTI_EVENT_GARBAGE_COLLECTION_START, | |
1939 ("JVMTI [%s] garbage collection start event sent ", | |
1940 JvmtiTrace::safe_get_thread_name(thread))); | |
1941 JvmtiThreadEventTransition jet(thread); | |
1942 // JNIEnv is NULL here because this event is posted from VM Thread | |
1943 jvmtiEventGarbageCollectionStart callback = env->callbacks()->GarbageCollectionStart; | |
1944 if (callback != NULL) { | |
1945 (*callback)(env->jvmti_external()); | |
1946 } | |
1947 } | |
1948 } | |
1949 } | |
1950 | |
1951 void JvmtiExport::post_data_dump() { | |
1952 Thread *thread = Thread::current(); | |
1953 EVT_TRIG_TRACE(JVMTI_EVENT_DATA_DUMP_REQUEST, | |
1954 ("JVMTI [%s] data dump request event triggered", | |
1955 JvmtiTrace::safe_get_thread_name(thread))); | |
1956 JvmtiEnvIterator it; | |
1957 for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) { | |
1958 if (env->is_enabled(JVMTI_EVENT_DATA_DUMP_REQUEST)) { | |
1959 EVT_TRACE(JVMTI_EVENT_DATA_DUMP_REQUEST, | |
1960 ("JVMTI [%s] data dump request event sent ", | |
1961 JvmtiTrace::safe_get_thread_name(thread))); | |
1962 JvmtiThreadEventTransition jet(thread); | |
1963 // JNIEnv is NULL here because this event is posted from VM Thread | |
1964 jvmtiEventDataDumpRequest callback = env->callbacks()->DataDumpRequest; | |
1965 if (callback != NULL) { | |
1966 (*callback)(env->jvmti_external()); | |
1967 } | |
1968 } | |
1969 } | |
1970 } | |
1971 | |
1972 void JvmtiExport::post_monitor_contended_enter(JavaThread *thread, ObjectMonitor *obj_mntr) { | |
1973 oop object = (oop)obj_mntr->object(); | |
1974 if (!ServiceUtil::visible_oop(object)) { | |
1975 // Ignore monitor contended enter for vm internal object. | |
1976 return; | |
1977 } | |
1978 JvmtiThreadState *state = thread->jvmti_thread_state(); | |
1979 if (state == NULL) { | |
1980 return; | |
1981 } | |
1982 | |
1983 HandleMark hm(thread); | |
1984 Handle h(thread, object); | |
1985 | |
1986 EVT_TRIG_TRACE(JVMTI_EVENT_MONITOR_CONTENDED_ENTER, | |
1987 ("JVMTI [%s] montior contended enter event triggered", | |
1988 JvmtiTrace::safe_get_thread_name(thread))); | |
1989 | |
1990 JvmtiEnvThreadStateIterator it(state); | |
1991 for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) { | |
1992 if (ets->is_enabled(JVMTI_EVENT_MONITOR_CONTENDED_ENTER)) { | |
1993 EVT_TRACE(JVMTI_EVENT_MONITOR_CONTENDED_ENTER, | |
1994 ("JVMTI [%s] monitor contended enter event sent", | |
1995 JvmtiTrace::safe_get_thread_name(thread))); | |
1996 JvmtiMonitorEventMark jem(thread, h()); | |
1997 JvmtiEnv *env = ets->get_env(); | |
1998 JvmtiThreadEventTransition jet(thread); | |
1999 jvmtiEventMonitorContendedEnter callback = env->callbacks()->MonitorContendedEnter; | |
2000 if (callback != NULL) { | |
2001 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(), jem.jni_object()); | |
2002 } | |
2003 } | |
2004 } | |
2005 } | |
2006 | |
2007 void JvmtiExport::post_monitor_contended_entered(JavaThread *thread, ObjectMonitor *obj_mntr) { | |
2008 oop object = (oop)obj_mntr->object(); | |
2009 if (!ServiceUtil::visible_oop(object)) { | |
2010 // Ignore monitor contended entered for vm internal object. | |
2011 return; | |
2012 } | |
2013 JvmtiThreadState *state = thread->jvmti_thread_state(); | |
2014 if (state == NULL) { | |
2015 return; | |
2016 } | |
2017 | |
2018 HandleMark hm(thread); | |
2019 Handle h(thread, object); | |
2020 | |
2021 EVT_TRIG_TRACE(JVMTI_EVENT_MONITOR_CONTENDED_ENTERED, | |
2022 ("JVMTI [%s] montior contended entered event triggered", | |
2023 JvmtiTrace::safe_get_thread_name(thread))); | |
2024 | |
2025 JvmtiEnvThreadStateIterator it(state); | |
2026 for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) { | |
2027 if (ets->is_enabled(JVMTI_EVENT_MONITOR_CONTENDED_ENTERED)) { | |
2028 EVT_TRACE(JVMTI_EVENT_MONITOR_CONTENDED_ENTERED, | |
2029 ("JVMTI [%s] monitor contended enter event sent", | |
2030 JvmtiTrace::safe_get_thread_name(thread))); | |
2031 JvmtiMonitorEventMark jem(thread, h()); | |
2032 JvmtiEnv *env = ets->get_env(); | |
2033 JvmtiThreadEventTransition jet(thread); | |
2034 jvmtiEventMonitorContendedEntered callback = env->callbacks()->MonitorContendedEntered; | |
2035 if (callback != NULL) { | |
2036 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(), jem.jni_object()); | |
2037 } | |
2038 } | |
2039 } | |
2040 } | |
2041 | |
2042 void JvmtiExport::post_monitor_wait(JavaThread *thread, oop object, | |
2043 jlong timeout) { | |
2044 JvmtiThreadState *state = thread->jvmti_thread_state(); | |
2045 if (state == NULL) { | |
2046 return; | |
2047 } | |
2048 | |
2049 HandleMark hm(thread); | |
2050 Handle h(thread, object); | |
2051 | |
2052 EVT_TRIG_TRACE(JVMTI_EVENT_MONITOR_WAIT, | |
2053 ("JVMTI [%s] montior wait event triggered", | |
2054 JvmtiTrace::safe_get_thread_name(thread))); | |
2055 | |
2056 JvmtiEnvThreadStateIterator it(state); | |
2057 for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) { | |
2058 if (ets->is_enabled(JVMTI_EVENT_MONITOR_WAIT)) { | |
2059 EVT_TRACE(JVMTI_EVENT_MONITOR_WAIT, | |
2060 ("JVMTI [%s] monitor wait event sent ", | |
2061 JvmtiTrace::safe_get_thread_name(thread))); | |
2062 JvmtiMonitorEventMark jem(thread, h()); | |
2063 JvmtiEnv *env = ets->get_env(); | |
2064 JvmtiThreadEventTransition jet(thread); | |
2065 jvmtiEventMonitorWait callback = env->callbacks()->MonitorWait; | |
2066 if (callback != NULL) { | |
2067 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(), | |
2068 jem.jni_object(), timeout); | |
2069 } | |
2070 } | |
2071 } | |
2072 } | |
2073 | |
2074 void JvmtiExport::post_monitor_waited(JavaThread *thread, ObjectMonitor *obj_mntr, jboolean timed_out) { | |
2075 oop object = (oop)obj_mntr->object(); | |
2076 if (!ServiceUtil::visible_oop(object)) { | |
2077 // Ignore monitor waited for vm internal object. | |
2078 return; | |
2079 } | |
2080 JvmtiThreadState *state = thread->jvmti_thread_state(); | |
2081 if (state == NULL) { | |
2082 return; | |
2083 } | |
2084 | |
2085 HandleMark hm(thread); | |
2086 Handle h(thread, object); | |
2087 | |
2088 EVT_TRIG_TRACE(JVMTI_EVENT_MONITOR_WAITED, | |
2089 ("JVMTI [%s] montior waited event triggered", | |
2090 JvmtiTrace::safe_get_thread_name(thread))); | |
2091 | |
2092 JvmtiEnvThreadStateIterator it(state); | |
2093 for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) { | |
2094 if (ets->is_enabled(JVMTI_EVENT_MONITOR_WAITED)) { | |
2095 EVT_TRACE(JVMTI_EVENT_MONITOR_WAITED, | |
2096 ("JVMTI [%s] monitor waited event sent ", | |
2097 JvmtiTrace::safe_get_thread_name(thread))); | |
2098 JvmtiMonitorEventMark jem(thread, h()); | |
2099 JvmtiEnv *env = ets->get_env(); | |
2100 JvmtiThreadEventTransition jet(thread); | |
2101 jvmtiEventMonitorWaited callback = env->callbacks()->MonitorWaited; | |
2102 if (callback != NULL) { | |
2103 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(), | |
2104 jem.jni_object(), timed_out); | |
2105 } | |
2106 } | |
2107 } | |
2108 } | |
2109 | |
2110 | |
2111 void JvmtiExport::post_vm_object_alloc(JavaThread *thread, oop object) { | |
2112 EVT_TRIG_TRACE(JVMTI_EVENT_VM_OBJECT_ALLOC, ("JVMTI [%s] Trg vm object alloc triggered", | |
2113 JvmtiTrace::safe_get_thread_name(thread))); | |
2114 if (object == NULL) { | |
2115 return; | |
2116 } | |
2117 HandleMark hm(thread); | |
2118 Handle h(thread, object); | |
2119 JvmtiEnvIterator it; | |
2120 for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) { | |
2121 if (env->is_enabled(JVMTI_EVENT_VM_OBJECT_ALLOC)) { | |
2122 EVT_TRACE(JVMTI_EVENT_VM_OBJECT_ALLOC, ("JVMTI [%s] Evt vmobject alloc sent %s", | |
2123 JvmtiTrace::safe_get_thread_name(thread), | |
2124 object==NULL? "NULL" : Klass::cast(java_lang_Class::as_klassOop(object))->external_name())); | |
2125 | |
2126 JvmtiVMObjectAllocEventMark jem(thread, h()); | |
2127 JvmtiJavaThreadEventTransition jet(thread); | |
2128 jvmtiEventVMObjectAlloc callback = env->callbacks()->VMObjectAlloc; | |
2129 if (callback != NULL) { | |
2130 (*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(), | |
2131 jem.jni_jobject(), jem.jni_class(), jem.size()); | |
2132 } | |
2133 } | |
2134 } | |
2135 } | |
2136 | |
2137 //////////////////////////////////////////////////////////////////////////////////////////////// | |
2138 | |
2139 void JvmtiExport::cleanup_thread(JavaThread* thread) { | |
2140 assert(JavaThread::current() == thread, "thread is not current"); | |
2126
db2b0f8c1cef
6814943: getcpool001 catches more than one JvmtiThreadState problem
kamg
parents:
2125
diff
changeset
|
2141 MutexLocker mu(JvmtiThreadState_lock); |
0 | 2142 |
2126
db2b0f8c1cef
6814943: getcpool001 catches more than one JvmtiThreadState problem
kamg
parents:
2125
diff
changeset
|
2143 if (thread->jvmti_thread_state() != NULL) { |
db2b0f8c1cef
6814943: getcpool001 catches more than one JvmtiThreadState problem
kamg
parents:
2125
diff
changeset
|
2144 // 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
|
2145 // 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
|
2146 // Maybe both these functions should be rolled into the posts? |
db2b0f8c1cef
6814943: getcpool001 catches more than one JvmtiThreadState problem
kamg
parents:
2125
diff
changeset
|
2147 JvmtiEventController::thread_ended(thread); |
db2b0f8c1cef
6814943: getcpool001 catches more than one JvmtiThreadState problem
kamg
parents:
2125
diff
changeset
|
2148 } |
0 | 2149 } |
2150 | |
2151 void JvmtiExport::oops_do(OopClosure* f) { | |
2152 JvmtiCurrentBreakpoints::oops_do(f); | |
2153 JvmtiVMObjectAllocEventCollector::oops_do_for_all_threads(f); | |
2154 } | |
2155 | |
2147
9afee0b9fc1d
7012505: BreakpointWithFullGC.sh fails with Internal Error (src/share/vm/oops/methodOop.cpp:220)
kamg
parents:
2126
diff
changeset
|
2156 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
|
2157 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
|
2158 } |
9afee0b9fc1d
7012505: BreakpointWithFullGC.sh fails with Internal Error (src/share/vm/oops/methodOop.cpp:220)
kamg
parents:
2126
diff
changeset
|
2159 |
9afee0b9fc1d
7012505: BreakpointWithFullGC.sh fails with Internal Error (src/share/vm/oops/methodOop.cpp:220)
kamg
parents:
2126
diff
changeset
|
2160 void JvmtiExport::gc_epilogue() { |
9afee0b9fc1d
7012505: BreakpointWithFullGC.sh fails with Internal Error (src/share/vm/oops/methodOop.cpp:220)
kamg
parents:
2126
diff
changeset
|
2161 JvmtiCurrentBreakpoints::gc_epilogue(); |
9afee0b9fc1d
7012505: BreakpointWithFullGC.sh fails with Internal Error (src/share/vm/oops/methodOop.cpp:220)
kamg
parents:
2126
diff
changeset
|
2162 } |
9afee0b9fc1d
7012505: BreakpointWithFullGC.sh fails with Internal Error (src/share/vm/oops/methodOop.cpp:220)
kamg
parents:
2126
diff
changeset
|
2163 |
0 | 2164 // Onload raw monitor transition. |
2165 void JvmtiExport::transition_pending_onload_raw_monitors() { | |
2166 JvmtiPendingMonitors::transition_raw_monitors(); | |
2167 } | |
2168 | |
2169 //////////////////////////////////////////////////////////////////////////////////////////////// | |
2170 | |
2171 // type for the Agent_OnAttach entry point | |
2172 extern "C" { | |
2173 typedef jint (JNICALL *OnAttachEntry_t)(JavaVM*, char *, void *); | |
2174 } | |
2175 | |
2176 #ifndef SERVICES_KERNEL | |
2177 jint JvmtiExport::load_agent_library(AttachOperation* op, outputStream* st) { | |
2178 char ebuf[1024]; | |
2179 char buffer[JVM_MAXPATHLEN]; | |
2180 void* library; | |
2181 jint result = JNI_ERR; | |
2182 | |
2183 // get agent name and options | |
2184 const char* agent = op->arg(0); | |
2185 const char* absParam = op->arg(1); | |
2186 const char* options = op->arg(2); | |
2187 | |
2188 // The abs paramter should be "true" or "false" | |
2189 bool is_absolute_path = (absParam != NULL) && (strcmp(absParam,"true")==0); | |
2190 | |
2191 | |
2192 // If the path is absolute we attempt to load the library. Otherwise we try to | |
2193 // load it from the standard dll directory. | |
2194 | |
2195 if (is_absolute_path) { | |
1980
828eafbd85cc
6348631: remove the use of the HPI library from Hotspot
ikrylov
parents:
1972
diff
changeset
|
2196 library = os::dll_load(agent, ebuf, sizeof ebuf); |
0 | 2197 } else { |
2198 // 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
|
2199 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
|
2200 library = os::dll_load(buffer, ebuf, sizeof ebuf); |
0 | 2201 if (library == NULL) { |
2202 // not found - try local path | |
2203 char ns[1] = {0}; | |
1980
828eafbd85cc
6348631: remove the use of the HPI library from Hotspot
ikrylov
parents:
1972
diff
changeset
|
2204 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
|
2205 library = os::dll_load(buffer, ebuf, sizeof ebuf); |
0 | 2206 } |
2207 } | |
2208 | |
2209 // If the library was loaded then we attempt to invoke the Agent_OnAttach | |
2210 // function | |
2211 if (library != NULL) { | |
2212 | |
2213 // Lookup the Agent_OnAttach function | |
2214 OnAttachEntry_t on_attach_entry = NULL; | |
2215 const char *on_attach_symbols[] = AGENT_ONATTACH_SYMBOLS; | |
2216 for (uint symbol_index = 0; symbol_index < ARRAY_SIZE(on_attach_symbols); symbol_index++) { | |
2217 on_attach_entry = | |
1980
828eafbd85cc
6348631: remove the use of the HPI library from Hotspot
ikrylov
parents:
1972
diff
changeset
|
2218 CAST_TO_FN_PTR(OnAttachEntry_t, os::dll_lookup(library, on_attach_symbols[symbol_index])); |
0 | 2219 if (on_attach_entry != NULL) break; |
2220 } | |
2221 | |
2222 if (on_attach_entry == NULL) { | |
2223 // Agent_OnAttach missing - unload library | |
1980
828eafbd85cc
6348631: remove the use of the HPI library from Hotspot
ikrylov
parents:
1972
diff
changeset
|
2224 os::dll_unload(library); |
0 | 2225 } else { |
2226 // Invoke the Agent_OnAttach function | |
2227 JavaThread* THREAD = JavaThread::current(); | |
2228 { | |
2229 extern struct JavaVM_ main_vm; | |
2230 JvmtiThreadEventMark jem(THREAD); | |
2231 JvmtiJavaThreadEventTransition jet(THREAD); | |
2232 | |
2233 result = (*on_attach_entry)(&main_vm, (char*)options, NULL); | |
2234 } | |
2235 | |
2236 // Agent_OnAttach may have used JNI | |
2237 if (HAS_PENDING_EXCEPTION) { | |
2238 CLEAR_PENDING_EXCEPTION; | |
2239 } | |
2240 | |
2241 // If OnAttach returns JNI_OK then we add it to the list of | |
2242 // agent libraries so that we can call Agent_OnUnload later. | |
2243 if (result == JNI_OK) { | |
2244 Arguments::add_loaded_agent(agent, (char*)options, is_absolute_path, library); | |
2245 } | |
2246 | |
2247 // Agent_OnAttach executed so completion status is JNI_OK | |
2248 st->print_cr("%d", result); | |
2249 result = JNI_OK; | |
2250 } | |
2251 } | |
2252 return result; | |
2253 } | |
2254 #endif // SERVICES_KERNEL | |
2255 | |
2256 //////////////////////////////////////////////////////////////////////////////////////////////// | |
2257 | |
2258 // Setup current current thread for event collection. | |
2259 void JvmtiEventCollector::setup_jvmti_thread_state() { | |
2260 // set this event collector to be the current one. | |
2261 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
|
2262 // 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
|
2263 // 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
|
2264 guarantee(state != NULL, "exiting thread called setup_jvmti_thread_state"); |
0 | 2265 if (is_vm_object_alloc_event()) { |
2266 _prev = state->get_vm_object_alloc_event_collector(); | |
2267 state->set_vm_object_alloc_event_collector((JvmtiVMObjectAllocEventCollector *)this); | |
2268 } else if (is_dynamic_code_event()) { | |
2269 _prev = state->get_dynamic_code_event_collector(); | |
2270 state->set_dynamic_code_event_collector((JvmtiDynamicCodeEventCollector *)this); | |
2271 } | |
2272 } | |
2273 | |
2274 // Unset current event collection in this thread and reset it with previous | |
2275 // collector. | |
2276 void JvmtiEventCollector::unset_jvmti_thread_state() { | |
2277 JvmtiThreadState* state = JavaThread::current()->jvmti_thread_state(); | |
2278 if (state != NULL) { | |
2279 // restore the previous event collector (if any) | |
2280 if (is_vm_object_alloc_event()) { | |
2281 if (state->get_vm_object_alloc_event_collector() == this) { | |
2282 state->set_vm_object_alloc_event_collector((JvmtiVMObjectAllocEventCollector *)_prev); | |
2283 } else { | |
2284 // this thread's jvmti state was created during the scope of | |
2285 // the event collector. | |
2286 } | |
2287 } else { | |
2288 if (is_dynamic_code_event()) { | |
2289 if (state->get_dynamic_code_event_collector() == this) { | |
2290 state->set_dynamic_code_event_collector((JvmtiDynamicCodeEventCollector *)_prev); | |
2291 } else { | |
2292 // this thread's jvmti state was created during the scope of | |
2293 // the event collector. | |
2294 } | |
2295 } | |
2296 } | |
2297 } | |
2298 } | |
2299 | |
2300 // create the dynamic code event collector | |
2301 JvmtiDynamicCodeEventCollector::JvmtiDynamicCodeEventCollector() : _code_blobs(NULL) { | |
2302 if (JvmtiExport::should_post_dynamic_code_generated()) { | |
2303 setup_jvmti_thread_state(); | |
2304 } | |
2305 } | |
2306 | |
2307 // iterate over any code blob descriptors collected and post a | |
2308 // DYNAMIC_CODE_GENERATED event to the profiler. | |
2309 JvmtiDynamicCodeEventCollector::~JvmtiDynamicCodeEventCollector() { | |
2310 assert(!JavaThread::current()->owns_locks(), "all locks must be released to post deferred events"); | |
2311 // iterate over any code blob descriptors that we collected | |
2312 if (_code_blobs != NULL) { | |
2313 for (int i=0; i<_code_blobs->length(); i++) { | |
2314 JvmtiCodeBlobDesc* blob = _code_blobs->at(i); | |
2315 JvmtiExport::post_dynamic_code_generated(blob->name(), blob->code_begin(), blob->code_end()); | |
2316 FreeHeap(blob); | |
2317 } | |
2318 delete _code_blobs; | |
2319 } | |
2320 unset_jvmti_thread_state(); | |
2321 } | |
2322 | |
2323 // register a stub | |
2324 void JvmtiDynamicCodeEventCollector::register_stub(const char* name, address start, address end) { | |
2325 if (_code_blobs == NULL) { | |
2326 _code_blobs = new (ResourceObj::C_HEAP) GrowableArray<JvmtiCodeBlobDesc*>(1,true); | |
2327 } | |
2328 _code_blobs->append(new JvmtiCodeBlobDesc(name, start, end)); | |
2329 } | |
2330 | |
2331 // Setup current thread to record vm allocated objects. | |
2332 JvmtiVMObjectAllocEventCollector::JvmtiVMObjectAllocEventCollector() : _allocated(NULL) { | |
2333 if (JvmtiExport::should_post_vm_object_alloc()) { | |
2334 _enable = true; | |
2335 setup_jvmti_thread_state(); | |
2336 } else { | |
2337 _enable = false; | |
2338 } | |
2339 } | |
2340 | |
2341 // Post vm_object_alloc event for vm allocated objects visible to java | |
2342 // world. | |
2343 JvmtiVMObjectAllocEventCollector::~JvmtiVMObjectAllocEventCollector() { | |
2344 if (_allocated != NULL) { | |
2345 set_enabled(false); | |
2346 for (int i = 0; i < _allocated->length(); i++) { | |
2347 oop obj = _allocated->at(i); | |
2348 if (ServiceUtil::visible_oop(obj)) { | |
2349 JvmtiExport::post_vm_object_alloc(JavaThread::current(), obj); | |
2350 } | |
2351 } | |
2352 delete _allocated; | |
2353 } | |
2354 unset_jvmti_thread_state(); | |
2355 } | |
2356 | |
2357 void JvmtiVMObjectAllocEventCollector::record_allocation(oop obj) { | |
2358 assert(is_enabled(), "VM object alloc event collector is not enabled"); | |
2359 if (_allocated == NULL) { | |
2360 _allocated = new (ResourceObj::C_HEAP) GrowableArray<oop>(1, true); | |
2361 } | |
2362 _allocated->push(obj); | |
2363 } | |
2364 | |
2365 // GC support. | |
2366 void JvmtiVMObjectAllocEventCollector::oops_do(OopClosure* f) { | |
2367 if (_allocated != NULL) { | |
2368 for(int i=_allocated->length() - 1; i >= 0; i--) { | |
2369 if (_allocated->at(i) != NULL) { | |
2370 f->do_oop(_allocated->adr_at(i)); | |
2371 } | |
2372 } | |
2373 } | |
2374 } | |
2375 | |
2376 void JvmtiVMObjectAllocEventCollector::oops_do_for_all_threads(OopClosure* f) { | |
2377 // no-op if jvmti not enabled | |
2378 if (!JvmtiEnv::environments_might_exist()) { | |
2379 return; | |
2380 } | |
2381 | |
2382 // Runs at safepoint. So no need to acquire Threads_lock. | |
2383 for (JavaThread *jthr = Threads::first(); jthr != NULL; jthr = jthr->next()) { | |
2384 JvmtiThreadState *state = jthr->jvmti_thread_state(); | |
2385 if (state != NULL) { | |
2386 JvmtiVMObjectAllocEventCollector *collector; | |
2387 collector = state->get_vm_object_alloc_event_collector(); | |
2388 while (collector != NULL) { | |
2389 collector->oops_do(f); | |
2390 collector = (JvmtiVMObjectAllocEventCollector *)collector->get_prev(); | |
2391 } | |
2392 } | |
2393 } | |
2394 } | |
2395 | |
2396 | |
2397 // Disable collection of VMObjectAlloc events | |
2398 NoJvmtiVMObjectAllocMark::NoJvmtiVMObjectAllocMark() : _collector(NULL) { | |
2399 // a no-op if VMObjectAlloc event is not enabled | |
2400 if (!JvmtiExport::should_post_vm_object_alloc()) { | |
2401 return; | |
2402 } | |
2403 Thread* thread = ThreadLocalStorage::thread(); | |
2404 if (thread != NULL && thread->is_Java_thread()) { | |
2405 JavaThread* current_thread = (JavaThread*)thread; | |
2406 JvmtiThreadState *state = current_thread->jvmti_thread_state(); | |
2407 if (state != NULL) { | |
2408 JvmtiVMObjectAllocEventCollector *collector; | |
2409 collector = state->get_vm_object_alloc_event_collector(); | |
2410 if (collector != NULL && collector->is_enabled()) { | |
2411 _collector = collector; | |
2412 _collector->set_enabled(false); | |
2413 } | |
2414 } | |
2415 } | |
2416 } | |
2417 | |
2418 // Re-Enable collection of VMObjectAlloc events (if previously enabled) | |
2419 NoJvmtiVMObjectAllocMark::~NoJvmtiVMObjectAllocMark() { | |
2420 if (was_enabled()) { | |
2421 _collector->set_enabled(true); | |
2422 } | |
2423 }; | |
2424 | |
2125
7246a374a9f2
6458402: 3 jvmti tests fail with CMS and +ExplicitGCInvokesConcurrent
kamg
parents:
1988
diff
changeset
|
2425 JvmtiGCMarker::JvmtiGCMarker() { |
0 | 2426 // if there aren't any JVMTI environments then nothing to do |
2427 if (!JvmtiEnv::environments_might_exist()) { | |
2428 return; | |
2429 } | |
2430 | |
2431 if (JvmtiExport::should_post_garbage_collection_start()) { | |
2432 JvmtiExport::post_garbage_collection_start(); | |
2433 } | |
2434 | |
2125
7246a374a9f2
6458402: 3 jvmti tests fail with CMS and +ExplicitGCInvokesConcurrent
kamg
parents:
1988
diff
changeset
|
2435 if (SafepointSynchronize::is_at_safepoint()) { |
7246a374a9f2
6458402: 3 jvmti tests fail with CMS and +ExplicitGCInvokesConcurrent
kamg
parents:
1988
diff
changeset
|
2436 // 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
|
2437 JvmtiEnvBase::check_for_periodic_clean_up(); |
0 | 2438 } |
2439 } | |
2440 | |
2441 JvmtiGCMarker::~JvmtiGCMarker() { | |
2442 // if there aren't any JVMTI environments then nothing to do | |
2443 if (!JvmtiEnv::environments_might_exist()) { | |
2444 return; | |
2445 } | |
2446 | |
2447 // JVMTI notify gc finish | |
2448 if (JvmtiExport::should_post_garbage_collection_finish()) { | |
2449 JvmtiExport::post_garbage_collection_finish(); | |
2450 } | |
2451 } | |
2452 #endif // JVMTI_KERNEL |