Mercurial > hg > truffle
annotate src/share/vm/prims/jvmtiEnvBase.hpp @ 1716:be3f9c242c9d
6948538: CMS: BOT walkers can fall into object allocation and initialization cracks
Summary: GC workers now recognize an intermediate transient state of blocks which are allocated but have not yet completed initialization. blk_start() calls do not attempt to determine the size of a block in the transient state, rather waiting for the block to become initialized so that it is safe to query its size. Audited and ensured the order of initialization of object fields (klass, free bit and size) to respect block state transition protocol. Also included some new assertion checking code enabled in debug mode.
Reviewed-by: chrisphi, johnc, poonam
author | ysr |
---|---|
date | Mon, 16 Aug 2010 15:58:42 -0700 |
parents | c18cbe5936b8 |
children | f95d63e2154a |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1122
diff
changeset
|
2 * Copyright (c) 2003, 2009, 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:
1122
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1122
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:
1122
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 #ifndef _JAVA_JVMTIENVBASE_H_ | |
26 #define _JAVA_JVMTIENVBASE_H_ | |
27 | |
28 // | |
29 // Forward Declarations | |
30 // | |
31 | |
32 class JvmtiEnv; | |
33 class JvmtiThreadState; | |
34 class JvmtiRawMonitor; // for jvmtiEnv.hpp | |
35 class JvmtiEventControllerPrivate; | |
36 class JvmtiTagMap; | |
37 | |
38 | |
39 | |
40 // One JvmtiEnv object is created per jvmti attachment; | |
41 // done via JNI GetEnv() call. Multiple attachments are | |
42 // allowed in jvmti. | |
43 | |
44 class JvmtiEnvBase : public CHeapObj { | |
45 | |
46 private: | |
47 | |
48 static JvmtiEnvBase* _head_environment; // head of environment list | |
49 | |
50 static bool _globally_initialized; | |
51 static jvmtiPhase _phase; | |
52 static volatile int _dying_thread_env_iteration_count; | |
53 | |
54 public: | |
55 | |
56 enum { | |
57 JDK15_JVMTI_VERSION = JVMTI_VERSION_1_0 + 33, /* version: 1.0.33 */ | |
58 JDK16_JVMTI_VERSION = JVMTI_VERSION_1_1 + 102 /* version: 1.1.102 */ | |
59 }; | |
60 | |
61 static jvmtiPhase get_phase() { return _phase; } | |
62 static void set_phase(jvmtiPhase phase) { _phase = phase; } | |
63 static bool is_vm_live() { return _phase == JVMTI_PHASE_LIVE; } | |
64 | |
65 static void entering_dying_thread_env_iteration() { ++_dying_thread_env_iteration_count; } | |
66 static void leaving_dying_thread_env_iteration() { --_dying_thread_env_iteration_count; } | |
67 static bool is_inside_dying_thread_env_iteration(){ return _dying_thread_env_iteration_count > 0; } | |
68 | |
69 private: | |
70 | |
71 enum { | |
72 JVMTI_MAGIC = 0x71EE, | |
73 DISPOSED_MAGIC = 0xDEFC, | |
74 BAD_MAGIC = 0xDEAD | |
75 }; | |
76 | |
77 jvmtiEnv _jvmti_external; | |
78 jint _magic; | |
1121 | 79 jint _version; // version value passed to JNI GetEnv() |
0 | 80 JvmtiEnvBase* _next; |
81 bool _is_retransformable; | |
82 const void *_env_local_storage; // per env agent allocated data. | |
83 jvmtiEventCallbacks _event_callbacks; | |
84 jvmtiExtEventCallbacks _ext_event_callbacks; | |
85 JvmtiTagMap* _tag_map; | |
86 JvmtiEnvEventEnable _env_event_enable; | |
87 jvmtiCapabilities _current_capabilities; | |
88 jvmtiCapabilities _prohibited_capabilities; | |
89 volatile bool _class_file_load_hook_ever_enabled; | |
90 static volatile bool _needs_clean_up; | |
91 char** _native_method_prefixes; | |
92 int _native_method_prefix_count; | |
93 | |
94 protected: | |
1121 | 95 JvmtiEnvBase(jint version); |
0 | 96 ~JvmtiEnvBase(); |
97 void dispose(); | |
98 void env_dispose(); | |
99 | |
100 void set_env_local_storage(const void* data) { _env_local_storage = data; } | |
101 const void* get_env_local_storage() { return _env_local_storage; } | |
102 | |
103 void record_class_file_load_hook_enabled(); | |
104 void record_first_time_class_file_load_hook_enabled(); | |
105 | |
106 char** get_native_method_prefixes() { return _native_method_prefixes; } | |
107 int get_native_method_prefix_count() { return _native_method_prefix_count; } | |
108 jvmtiError set_native_method_prefixes(jint prefix_count, char** prefixes); | |
109 | |
110 private: | |
111 friend class JvmtiEventControllerPrivate; | |
112 void initialize(); | |
113 void set_event_callbacks(const jvmtiEventCallbacks* callbacks, jint size_of_callbacks); | |
114 static void globally_initialize(); | |
115 static void periodic_clean_up(); | |
116 | |
117 friend class JvmtiEnvIterator; | |
118 JvmtiEnv* next_environment() { return (JvmtiEnv*)_next; } | |
119 void set_next_environment(JvmtiEnvBase* env) { _next = env; } | |
120 static JvmtiEnv* head_environment() { return (JvmtiEnv*)_head_environment; } | |
121 | |
122 public: | |
123 | |
611
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
0
diff
changeset
|
124 bool is_valid(); |
0 | 125 |
1121 | 126 bool use_version_1_0_semantics(); // agent asked for version 1.0 |
127 bool use_version_1_1_semantics(); // agent asked for version 1.1 | |
128 | |
0 | 129 bool is_retransformable() { return _is_retransformable; } |
130 | |
131 static ByteSize jvmti_external_offset() { | |
132 return byte_offset_of(JvmtiEnvBase, _jvmti_external); | |
133 }; | |
134 | |
135 static JvmtiEnv* JvmtiEnv_from_jvmti_env(jvmtiEnv *env) { | |
136 return (JvmtiEnv*)((intptr_t)env - in_bytes(jvmti_external_offset())); | |
137 }; | |
138 | |
139 jvmtiCapabilities *get_capabilities() { return &_current_capabilities; } | |
140 | |
141 jvmtiCapabilities *get_prohibited_capabilities() { return &_prohibited_capabilities; } | |
142 | |
143 static char** get_all_native_method_prefixes(int* count_ptr); | |
144 | |
145 // This test will answer true when all environments have been disposed and some have | |
146 // not yet been deallocated. As a result, this test should only be used as an | |
147 // optimization for the no environment case. | |
148 static bool environments_might_exist() { | |
149 return head_environment() != NULL; | |
150 } | |
151 | |
152 static void check_for_periodic_clean_up(); | |
153 | |
154 JvmtiEnvEventEnable *env_event_enable() { | |
155 return &_env_event_enable; | |
156 } | |
157 | |
158 jvmtiError allocate(jlong size, unsigned char** mem_ptr) { | |
159 if (size < 0) { | |
160 return JVMTI_ERROR_ILLEGAL_ARGUMENT; | |
161 } | |
162 if (size == 0) { | |
163 *mem_ptr = NULL; | |
164 } else { | |
165 *mem_ptr = (unsigned char *)os::malloc((size_t)size); | |
166 if (*mem_ptr == NULL) { | |
167 return JVMTI_ERROR_OUT_OF_MEMORY; | |
168 } | |
169 } | |
170 return JVMTI_ERROR_NONE; | |
171 } | |
172 | |
173 jvmtiError deallocate(unsigned char* mem) { | |
174 if (mem != NULL) { | |
175 os::free(mem); | |
176 } | |
177 return JVMTI_ERROR_NONE; | |
178 } | |
179 | |
180 | |
181 // Memory functions | |
182 unsigned char* jvmtiMalloc(jlong size); // don't use this - call allocate | |
183 | |
184 // method to create a local handle | |
185 jobject jni_reference(Handle hndl) { | |
186 return JNIHandles::make_local(hndl()); | |
187 } | |
188 | |
189 // method to create a local handle. | |
190 // This function allows caller to specify which | |
191 // threads local handle table to use. | |
192 jobject jni_reference(JavaThread *thread, Handle hndl) { | |
193 return JNIHandles::make_local(thread, hndl()); | |
194 } | |
195 | |
196 // method to destroy a local handle | |
197 void destroy_jni_reference(jobject jobj) { | |
198 JNIHandles::destroy_local(jobj); | |
199 } | |
200 | |
201 // method to destroy a local handle. | |
202 // This function allows caller to specify which | |
203 // threads local handle table to use although currently it is | |
204 // not used. | |
205 void destroy_jni_reference(JavaThread *thread, jobject jobj) { | |
206 destroy_jni_reference(jobj); | |
207 } | |
208 | |
209 jvmtiEnv* jvmti_external() { return &_jvmti_external; }; | |
210 | |
211 // Event Dispatch | |
212 | |
213 bool has_callback(jvmtiEvent event_type) { | |
214 assert(event_type >= JVMTI_MIN_EVENT_TYPE_VAL && | |
215 event_type <= JVMTI_MAX_EVENT_TYPE_VAL, "checking"); | |
216 return ((void**)&_event_callbacks)[event_type-JVMTI_MIN_EVENT_TYPE_VAL] != NULL; | |
217 } | |
218 | |
219 jvmtiEventCallbacks* callbacks() { | |
220 return &_event_callbacks; | |
221 } | |
222 | |
223 jvmtiExtEventCallbacks* ext_callbacks() { | |
224 return &_ext_event_callbacks; | |
225 } | |
226 | |
227 void set_tag_map(JvmtiTagMap* tag_map) { | |
228 _tag_map = tag_map; | |
229 } | |
230 | |
231 JvmtiTagMap* tag_map() { | |
232 return _tag_map; | |
233 } | |
234 | |
235 | |
236 // return true if event is enabled globally or for any thread | |
237 // True only if there is a callback for it. | |
238 bool is_enabled(jvmtiEvent event_type) { | |
239 return _env_event_enable.is_enabled(event_type); | |
240 } | |
241 | |
242 // Random Utilities | |
243 | |
244 protected: | |
245 // helper methods for creating arrays of global JNI Handles from local Handles | |
246 // allocated into environment specific storage | |
247 jobject * new_jobjectArray(int length, Handle *handles); | |
248 jthread * new_jthreadArray(int length, Handle *handles); | |
249 jthreadGroup * new_jthreadGroupArray(int length, Handle *handles); | |
250 | |
251 // convert from JNIHandle to JavaThread * | |
252 JavaThread * get_JavaThread(jthread jni_thread); | |
253 | |
254 // convert to a jni jclass from a non-null klassOop | |
255 jclass get_jni_class_non_null(klassOop k); | |
256 | |
257 void update_klass_field_access_flag(fieldDescriptor *fd); | |
258 | |
259 jint count_locked_objects(JavaThread *java_thread, Handle hobj); | |
260 jvmtiError get_locked_objects_in_frame(JavaThread *calling_thread, | |
261 JavaThread* java_thread, | |
262 javaVFrame *jvf, | |
263 GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitors_list, | |
264 jint depth); | |
265 vframe* vframeFor(JavaThread* java_thread, jint depth); | |
266 | |
267 public: | |
268 // get a field descriptor for the specified class and field | |
269 static bool get_field_descriptor(klassOop k, jfieldID field, fieldDescriptor* fd); | |
270 // test for suspend - most (all?) of these should go away | |
271 static bool is_thread_fully_suspended(JavaThread *thread, | |
272 bool wait_for_suspend, | |
273 uint32_t *bits); | |
274 | |
275 | |
276 // JVMTI API helper functions which are called at safepoint or thread is suspended. | |
277 jvmtiError get_frame_count(JvmtiThreadState *state, jint *count_ptr); | |
278 jvmtiError get_frame_location(JavaThread* java_thread, jint depth, | |
279 jmethodID* method_ptr, jlocation* location_ptr); | |
280 jvmtiError get_object_monitor_usage(JavaThread *calling_thread, | |
281 jobject object, jvmtiMonitorUsage* info_ptr); | |
282 jvmtiError get_stack_trace(JavaThread *java_thread, | |
283 jint stack_depth, jint max_count, | |
284 jvmtiFrameInfo* frame_buffer, jint* count_ptr); | |
285 jvmtiError get_current_contended_monitor(JavaThread *calling_thread, | |
286 JavaThread *java_thread, | |
287 jobject *monitor_ptr); | |
288 jvmtiError get_owned_monitors(JavaThread *calling_thread, JavaThread* java_thread, | |
289 GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list); | |
290 jvmtiError check_top_frame(JavaThread* current_thread, JavaThread* java_thread, | |
291 jvalue value, TosState tos, Handle* ret_ob_h); | |
292 jvmtiError force_early_return(JavaThread* java_thread, jvalue value, TosState tos); | |
293 }; | |
294 | |
295 // This class is the only safe means of iterating through environments. | |
296 // Note that this iteratation includes invalid environments pending | |
297 // deallocation -- in fact, some uses depend on this behavior. | |
298 | |
299 class JvmtiEnvIterator : public StackObj { | |
300 private: | |
301 bool _entry_was_marked; | |
302 public: | |
303 JvmtiEnvIterator() { | |
304 if (Threads::number_of_threads() == 0) { | |
305 _entry_was_marked = false; // we are single-threaded, no need | |
306 } else { | |
307 Thread::current()->entering_jvmti_env_iteration(); | |
308 _entry_was_marked = true; | |
309 } | |
310 } | |
311 ~JvmtiEnvIterator() { | |
312 if (_entry_was_marked) { | |
313 Thread::current()->leaving_jvmti_env_iteration(); | |
314 } | |
315 } | |
316 JvmtiEnv* first() { return JvmtiEnvBase::head_environment(); } | |
317 JvmtiEnv* next(JvmtiEnvBase* env) { return env->next_environment(); } | |
318 }; | |
319 | |
320 | |
321 // VM operation to get monitor information with stack depth. | |
322 class VM_GetOwnedMonitorInfo : public VM_Operation { | |
323 private: | |
324 JvmtiEnv *_env; | |
325 JavaThread* _calling_thread; | |
326 JavaThread *_java_thread; | |
327 jvmtiError _result; | |
328 GrowableArray<jvmtiMonitorStackDepthInfo*> *_owned_monitors_list; | |
329 | |
330 public: | |
331 VM_GetOwnedMonitorInfo(JvmtiEnv* env, JavaThread* calling_thread, | |
332 JavaThread* java_thread, | |
333 GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitor_list) { | |
334 _env = env; | |
335 _calling_thread = calling_thread; | |
336 _java_thread = java_thread; | |
337 _owned_monitors_list = owned_monitor_list; | |
338 _result = JVMTI_ERROR_NONE; | |
339 } | |
340 VMOp_Type type() const { return VMOp_GetOwnedMonitorInfo; } | |
341 void doit() { | |
342 ((JvmtiEnvBase *)_env)->get_owned_monitors(_calling_thread, _java_thread, | |
343 _owned_monitors_list); | |
344 } | |
345 jvmtiError result() { return _result; } | |
346 }; | |
347 | |
348 | |
349 // VM operation to get object monitor usage. | |
350 class VM_GetObjectMonitorUsage : public VM_Operation { | |
351 private: | |
352 JvmtiEnv *_env; | |
353 jobject _object; | |
354 JavaThread* _calling_thread; | |
355 jvmtiMonitorUsage* _info_ptr; | |
356 jvmtiError _result; | |
357 | |
358 public: | |
359 VM_GetObjectMonitorUsage(JvmtiEnv *env, JavaThread* calling_thread, jobject object, jvmtiMonitorUsage* info_ptr) { | |
360 _env = env; | |
361 _object = object; | |
362 _calling_thread = calling_thread; | |
363 _info_ptr = info_ptr; | |
364 } | |
365 VMOp_Type type() const { return VMOp_GetObjectMonitorUsage; } | |
366 jvmtiError result() { return _result; } | |
367 void doit() { | |
368 _result = ((JvmtiEnvBase*) _env)->get_object_monitor_usage(_calling_thread, _object, _info_ptr); | |
369 } | |
370 | |
371 }; | |
372 | |
373 // VM operation to get current contended monitor. | |
374 class VM_GetCurrentContendedMonitor : public VM_Operation { | |
375 private: | |
376 JvmtiEnv *_env; | |
377 JavaThread *_calling_thread; | |
378 JavaThread *_java_thread; | |
379 jobject *_owned_monitor_ptr; | |
380 jvmtiError _result; | |
381 | |
382 public: | |
383 VM_GetCurrentContendedMonitor(JvmtiEnv *env, JavaThread *calling_thread, JavaThread *java_thread, jobject *mon_ptr) { | |
384 _env = env; | |
385 _calling_thread = calling_thread; | |
386 _java_thread = java_thread; | |
387 _owned_monitor_ptr = mon_ptr; | |
388 } | |
389 VMOp_Type type() const { return VMOp_GetCurrentContendedMonitor; } | |
390 jvmtiError result() { return _result; } | |
391 void doit() { | |
392 _result = ((JvmtiEnvBase *)_env)->get_current_contended_monitor(_calling_thread,_java_thread,_owned_monitor_ptr); | |
393 } | |
394 }; | |
395 | |
396 // VM operation to get stack trace at safepoint. | |
397 class VM_GetStackTrace : public VM_Operation { | |
398 private: | |
399 JvmtiEnv *_env; | |
400 JavaThread *_java_thread; | |
401 jint _start_depth; | |
402 jint _max_count; | |
403 jvmtiFrameInfo *_frame_buffer; | |
404 jint *_count_ptr; | |
405 jvmtiError _result; | |
406 | |
407 public: | |
408 VM_GetStackTrace(JvmtiEnv *env, JavaThread *java_thread, | |
409 jint start_depth, jint max_count, | |
410 jvmtiFrameInfo* frame_buffer, jint* count_ptr) { | |
411 _env = env; | |
412 _java_thread = java_thread; | |
413 _start_depth = start_depth; | |
414 _max_count = max_count; | |
415 _frame_buffer = frame_buffer; | |
416 _count_ptr = count_ptr; | |
417 } | |
418 jvmtiError result() { return _result; } | |
419 VMOp_Type type() const { return VMOp_GetStackTrace; } | |
420 void doit() { | |
421 _result = ((JvmtiEnvBase *)_env)->get_stack_trace(_java_thread, | |
422 _start_depth, _max_count, | |
423 _frame_buffer, _count_ptr); | |
424 } | |
425 }; | |
426 | |
427 // forward declaration | |
428 struct StackInfoNode; | |
429 | |
430 // VM operation to get stack trace at safepoint. | |
431 class VM_GetMultipleStackTraces : public VM_Operation { | |
432 private: | |
433 JvmtiEnv *_env; | |
434 jint _max_frame_count; | |
435 jvmtiStackInfo *_stack_info; | |
436 jvmtiError _result; | |
437 int _frame_count_total; | |
438 struct StackInfoNode *_head; | |
439 | |
440 JvmtiEnvBase *env() { return (JvmtiEnvBase *)_env; } | |
441 jint max_frame_count() { return _max_frame_count; } | |
442 struct StackInfoNode *head() { return _head; } | |
443 void set_head(StackInfoNode *head) { _head = head; } | |
444 | |
445 protected: | |
446 void set_result(jvmtiError result) { _result = result; } | |
447 void fill_frames(jthread jt, JavaThread *thr, oop thread_oop); | |
448 void allocate_and_fill_stacks(jint thread_count); | |
449 | |
450 public: | |
451 VM_GetMultipleStackTraces(JvmtiEnv *env, jint max_frame_count) { | |
452 _env = env; | |
453 _max_frame_count = max_frame_count; | |
454 _frame_count_total = 0; | |
455 _head = NULL; | |
456 _result = JVMTI_ERROR_NONE; | |
457 } | |
458 VMOp_Type type() const { return VMOp_GetMultipleStackTraces; } | |
459 jvmtiStackInfo *stack_info() { return _stack_info; } | |
460 jvmtiError result() { return _result; } | |
461 }; | |
462 | |
463 | |
464 // VM operation to get stack trace at safepoint. | |
465 class VM_GetAllStackTraces : public VM_GetMultipleStackTraces { | |
466 private: | |
467 JavaThread *_calling_thread; | |
468 jint _final_thread_count; | |
469 | |
470 public: | |
471 VM_GetAllStackTraces(JvmtiEnv *env, JavaThread *calling_thread, | |
472 jint max_frame_count) | |
473 : VM_GetMultipleStackTraces(env, max_frame_count) { | |
474 _calling_thread = calling_thread; | |
475 } | |
476 VMOp_Type type() const { return VMOp_GetAllStackTraces; } | |
477 void doit(); | |
478 jint final_thread_count() { return _final_thread_count; } | |
479 }; | |
480 | |
481 // VM operation to get stack trace at safepoint. | |
482 class VM_GetThreadListStackTraces : public VM_GetMultipleStackTraces { | |
483 private: | |
484 jint _thread_count; | |
485 const jthread* _thread_list; | |
486 | |
487 public: | |
488 VM_GetThreadListStackTraces(JvmtiEnv *env, jint thread_count, const jthread* thread_list, jint max_frame_count) | |
489 : VM_GetMultipleStackTraces(env, max_frame_count) { | |
490 _thread_count = thread_count; | |
491 _thread_list = thread_list; | |
492 } | |
493 VMOp_Type type() const { return VMOp_GetThreadListStackTraces; } | |
494 void doit(); | |
495 }; | |
496 | |
497 | |
498 // VM operation to count stack frames at safepoint. | |
499 class VM_GetFrameCount : public VM_Operation { | |
500 private: | |
501 JvmtiEnv *_env; | |
502 JvmtiThreadState *_state; | |
503 jint *_count_ptr; | |
504 jvmtiError _result; | |
505 | |
506 public: | |
507 VM_GetFrameCount(JvmtiEnv *env, JvmtiThreadState *state, jint *count_ptr) { | |
508 _env = env; | |
509 _state = state; | |
510 _count_ptr = count_ptr; | |
511 } | |
512 VMOp_Type type() const { return VMOp_GetFrameCount; } | |
513 jvmtiError result() { return _result; } | |
514 void doit() { | |
515 _result = ((JvmtiEnvBase*)_env)->get_frame_count(_state, _count_ptr); | |
516 } | |
517 }; | |
518 | |
519 // VM operation to frame location at safepoint. | |
520 class VM_GetFrameLocation : public VM_Operation { | |
521 private: | |
522 JvmtiEnv *_env; | |
523 JavaThread* _java_thread; | |
524 jint _depth; | |
525 jmethodID* _method_ptr; | |
526 jlocation* _location_ptr; | |
527 jvmtiError _result; | |
528 | |
529 public: | |
530 VM_GetFrameLocation(JvmtiEnv *env, JavaThread* java_thread, jint depth, | |
531 jmethodID* method_ptr, jlocation* location_ptr) { | |
532 _env = env; | |
533 _java_thread = java_thread; | |
534 _depth = depth; | |
535 _method_ptr = method_ptr; | |
536 _location_ptr = location_ptr; | |
537 } | |
538 VMOp_Type type() const { return VMOp_GetFrameLocation; } | |
539 jvmtiError result() { return _result; } | |
540 void doit() { | |
541 _result = ((JvmtiEnvBase*)_env)->get_frame_location(_java_thread, _depth, | |
542 _method_ptr, _location_ptr); | |
543 } | |
544 }; | |
545 | |
546 | |
547 // ResourceTracker | |
548 // | |
549 // ResourceTracker works a little like a ResourceMark. All allocates | |
550 // using the resource tracker are recorded. If an allocate using the | |
551 // resource tracker fails the destructor will free any resources | |
552 // that were allocated using the tracker. | |
553 // The motive for this class is to avoid messy error recovery code | |
554 // in situations where multiple allocations are done in sequence. If | |
555 // the second or subsequent allocation fails it avoids any code to | |
556 // release memory allocated in the previous calls. | |
557 // | |
558 // Usage :- | |
559 // ResourceTracker rt(env); | |
560 // : | |
561 // err = rt.allocate(1024, &ptr); | |
562 | |
563 class ResourceTracker : public StackObj { | |
564 private: | |
565 JvmtiEnv* _env; | |
566 GrowableArray<unsigned char*> *_allocations; | |
567 bool _failed; | |
568 public: | |
569 ResourceTracker(JvmtiEnv* env); | |
570 ~ResourceTracker(); | |
571 jvmtiError allocate(jlong size, unsigned char** mem_ptr); | |
572 unsigned char* allocate(jlong size); | |
573 char* strdup(const char* str); | |
574 }; | |
575 | |
576 | |
577 // Jvmti monitor closure to collect off stack monitors. | |
578 class JvmtiMonitorClosure: public MonitorClosure { | |
579 private: | |
580 JavaThread *_java_thread; | |
581 JavaThread *_calling_thread; | |
582 GrowableArray<jvmtiMonitorStackDepthInfo*> *_owned_monitors_list; | |
583 jvmtiError _error; | |
584 JvmtiEnvBase *_env; | |
585 | |
586 public: | |
587 JvmtiMonitorClosure(JavaThread* thread, JavaThread *calling_thread, | |
588 GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors, | |
589 JvmtiEnvBase *env) { | |
590 _java_thread = thread; | |
591 _calling_thread = calling_thread; | |
592 _owned_monitors_list = owned_monitors; | |
593 _error = JVMTI_ERROR_NONE; | |
594 _env = env; | |
595 } | |
596 void do_monitor(ObjectMonitor* mon); | |
597 jvmtiError error() { return _error;} | |
598 }; | |
599 | |
600 #endif /* _JAVA_JVMTIENVBASE_H_ */ |