Mercurial > hg > truffle
annotate src/share/vm/prims/jvmtiEnvBase.cpp @ 20543:e7d0505c8a30
8059758: Footprint regressions with JDK-8038423
Summary: Changes in JDK-8038423 always initialize (zero out) virtual memory used for auxiliary data structures. This causes a footprint regression for G1 in startup benchmarks. This is because they do not touch that memory at all, so the operating system does not actually commit these pages. The fix is to, if the initialization value of the data structures matches the default value of just committed memory (=0), do not do anything.
Reviewed-by: jwilhelm, brutisso
author | tschatzl |
---|---|
date | Fri, 10 Oct 2014 15:51:58 +0200 |
parents | ce8f6bb717c9 |
children | 7848fc12602b |
rev | line source |
---|---|
0 | 1 /* |
7951 | 2 * Copyright (c) 2003, 2013, 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:
1144
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1144
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:
1144
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "classfile/systemDictionary.hpp" | |
27 #include "jvmtifiles/jvmtiEnv.hpp" | |
28 #include "oops/objArrayKlass.hpp" | |
29 #include "oops/objArrayOop.hpp" | |
30 #include "prims/jvmtiEnvBase.hpp" | |
31 #include "prims/jvmtiEventController.inline.hpp" | |
32 #include "prims/jvmtiExtensions.hpp" | |
33 #include "prims/jvmtiImpl.hpp" | |
34 #include "prims/jvmtiManageCapabilities.hpp" | |
35 #include "prims/jvmtiTagMap.hpp" | |
36 #include "prims/jvmtiThreadState.inline.hpp" | |
37 #include "runtime/biasedLocking.hpp" | |
38 #include "runtime/deoptimization.hpp" | |
39 #include "runtime/interfaceSupport.hpp" | |
40 #include "runtime/jfieldIDWorkaround.hpp" | |
41 #include "runtime/objectMonitor.hpp" | |
42 #include "runtime/objectMonitor.inline.hpp" | |
43 #include "runtime/signature.hpp" | |
20197
ce8f6bb717c9
8042195: Introduce umbrella header orderAccess.inline.hpp.
goetz
parents:
8673
diff
changeset
|
44 #include "runtime/thread.inline.hpp" |
1972 | 45 #include "runtime/vframe.hpp" |
46 #include "runtime/vframe_hp.hpp" | |
47 #include "runtime/vmThread.hpp" | |
48 #include "runtime/vm_operations.hpp" | |
0 | 49 |
50 /////////////////////////////////////////////////////////////// | |
51 // | |
52 // JvmtiEnvBase | |
53 // | |
54 | |
55 JvmtiEnvBase* JvmtiEnvBase::_head_environment = NULL; | |
56 | |
57 bool JvmtiEnvBase::_globally_initialized = false; | |
58 volatile bool JvmtiEnvBase::_needs_clean_up = false; | |
59 | |
60 jvmtiPhase JvmtiEnvBase::_phase = JVMTI_PHASE_PRIMORDIAL; | |
61 | |
62 volatile int JvmtiEnvBase::_dying_thread_env_iteration_count = 0; | |
63 | |
64 extern jvmtiInterface_1_ jvmti_Interface; | |
65 extern jvmtiInterface_1_ jvmtiTrace_Interface; | |
66 | |
67 | |
68 // perform initializations that must occur before any JVMTI environments | |
69 // are released but which should only be initialized once (no matter | |
70 // how many environments are created). | |
71 void | |
72 JvmtiEnvBase::globally_initialize() { | |
73 assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check"); | |
74 assert(_globally_initialized == false, "bad call"); | |
75 | |
76 JvmtiManageCapabilities::initialize(); | |
77 | |
78 // register extension functions and events | |
79 JvmtiExtensions::register_extensions(); | |
80 | |
81 #ifdef JVMTI_TRACE | |
82 JvmtiTrace::initialize(); | |
83 #endif | |
84 | |
85 _globally_initialized = true; | |
86 } | |
87 | |
88 | |
89 void | |
90 JvmtiEnvBase::initialize() { | |
91 assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check"); | |
92 | |
93 // Add this environment to the end of the environment list (order is important) | |
94 { | |
95 // This block of code must not contain any safepoints, as list deallocation | |
96 // (which occurs at a safepoint) cannot occur simultaneously with this list | |
97 // addition. Note: No_Safepoint_Verifier cannot, currently, be used before | |
98 // threads exist. | |
99 JvmtiEnvIterator it; | |
100 JvmtiEnvBase *previous_env = NULL; | |
101 for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) { | |
102 previous_env = env; | |
103 } | |
104 if (previous_env == NULL) { | |
105 _head_environment = this; | |
106 } else { | |
107 previous_env->set_next_environment(this); | |
108 } | |
109 } | |
110 | |
111 if (_globally_initialized == false) { | |
112 globally_initialize(); | |
113 } | |
114 } | |
115 | |
116 | |
611
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
117 bool |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
118 JvmtiEnvBase::is_valid() { |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
119 jint value = 0; |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
120 |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
121 // This object might not be a JvmtiEnvBase so we can't assume |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
122 // the _magic field is properly aligned. Get the value in a safe |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
123 // way and then check against JVMTI_MAGIC. |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
124 |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
125 switch (sizeof(_magic)) { |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
126 case 2: |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
127 value = Bytes::get_native_u2((address)&_magic); |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
128 break; |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
129 |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
130 case 4: |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
131 value = Bytes::get_native_u4((address)&_magic); |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
132 break; |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
133 |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
134 case 8: |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
135 value = Bytes::get_native_u8((address)&_magic); |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
136 break; |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
137 |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
138 default: |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
139 guarantee(false, "_magic field is an unexpected size"); |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
140 } |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
141 |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
142 return value == JVMTI_MAGIC; |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
143 } |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
144 |
2f716c0acb64
6567360: 3/4 SIGBUS in jvmti RawMonitor magic check for unaligned bad monitor pointer
dcubed
parents:
609
diff
changeset
|
145 |
1122 | 146 bool |
1121 | 147 JvmtiEnvBase::use_version_1_0_semantics() { |
148 int major, minor, micro; | |
149 | |
150 JvmtiExport::decode_version_values(_version, &major, &minor, µ); | |
151 return major == 1 && minor == 0; // micro version doesn't matter here | |
152 } | |
153 | |
154 | |
155 bool | |
156 JvmtiEnvBase::use_version_1_1_semantics() { | |
157 int major, minor, micro; | |
158 | |
159 JvmtiExport::decode_version_values(_version, &major, &minor, µ); | |
160 return major == 1 && minor == 1; // micro version doesn't matter here | |
161 } | |
162 | |
1988 | 163 bool |
164 JvmtiEnvBase::use_version_1_2_semantics() { | |
165 int major, minor, micro; | |
166 | |
167 JvmtiExport::decode_version_values(_version, &major, &minor, µ); | |
168 return major == 1 && minor == 2; // micro version doesn't matter here | |
169 } | |
170 | |
1121 | 171 |
172 JvmtiEnvBase::JvmtiEnvBase(jint version) : _env_event_enable() { | |
173 _version = version; | |
0 | 174 _env_local_storage = NULL; |
175 _tag_map = NULL; | |
176 _native_method_prefix_count = 0; | |
177 _native_method_prefixes = NULL; | |
178 _next = NULL; | |
179 _class_file_load_hook_ever_enabled = false; | |
180 | |
181 // Moot since ClassFileLoadHook not yet enabled. | |
182 // But "true" will give a more predictable ClassFileLoadHook behavior | |
183 // for environment creation during ClassFileLoadHook. | |
184 _is_retransformable = true; | |
185 | |
186 // all callbacks initially NULL | |
187 memset(&_event_callbacks,0,sizeof(jvmtiEventCallbacks)); | |
188 | |
189 // all capabilities initially off | |
190 memset(&_current_capabilities, 0, sizeof(_current_capabilities)); | |
191 | |
192 // all prohibited capabilities initially off | |
193 memset(&_prohibited_capabilities, 0, sizeof(_prohibited_capabilities)); | |
194 | |
195 _magic = JVMTI_MAGIC; | |
196 | |
197 JvmtiEventController::env_initialize((JvmtiEnv*)this); | |
198 | |
199 #ifdef JVMTI_TRACE | |
371 | 200 _jvmti_external.functions = TraceJVMTI != NULL ? &jvmtiTrace_Interface : &jvmti_Interface; |
0 | 201 #else |
202 _jvmti_external.functions = &jvmti_Interface; | |
203 #endif | |
204 } | |
205 | |
206 | |
207 void | |
208 JvmtiEnvBase::dispose() { | |
209 | |
210 #ifdef JVMTI_TRACE | |
211 JvmtiTrace::shutdown(); | |
212 #endif | |
213 | |
214 // Dispose of event info and let the event controller call us back | |
215 // in a locked state (env_dispose, below) | |
216 JvmtiEventController::env_dispose(this); | |
217 } | |
218 | |
219 void | |
220 JvmtiEnvBase::env_dispose() { | |
221 assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check"); | |
222 | |
223 // We have been entered with all events disabled on this environment. | |
224 // A race to re-enable events (by setting callbacks) is prevented by | |
225 // checking for a valid environment when setting callbacks (while | |
226 // holding the JvmtiThreadState_lock). | |
227 | |
228 // Mark as invalid. | |
229 _magic = DISPOSED_MAGIC; | |
230 | |
231 // Relinquish all capabilities. | |
232 jvmtiCapabilities *caps = get_capabilities(); | |
233 JvmtiManageCapabilities::relinquish_capabilities(caps, caps, caps); | |
234 | |
235 // Same situation as with events (see above) | |
236 set_native_method_prefixes(0, NULL); | |
237 | |
238 JvmtiTagMap* tag_map_to_deallocate = _tag_map; | |
239 set_tag_map(NULL); | |
240 // A tag map can be big, deallocate it now | |
241 if (tag_map_to_deallocate != NULL) { | |
242 delete tag_map_to_deallocate; | |
243 } | |
244 | |
245 _needs_clean_up = true; | |
246 } | |
247 | |
248 | |
249 JvmtiEnvBase::~JvmtiEnvBase() { | |
250 assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); | |
251 | |
252 // There is a small window of time during which the tag map of a | |
253 // disposed environment could have been reallocated. | |
254 // Make sure it is gone. | |
255 JvmtiTagMap* tag_map_to_deallocate = _tag_map; | |
256 set_tag_map(NULL); | |
257 // A tag map can be big, deallocate it now | |
258 if (tag_map_to_deallocate != NULL) { | |
259 delete tag_map_to_deallocate; | |
260 } | |
261 | |
262 _magic = BAD_MAGIC; | |
263 } | |
264 | |
265 | |
266 void | |
267 JvmtiEnvBase::periodic_clean_up() { | |
268 assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); | |
269 | |
270 // JvmtiEnvBase reference is saved in JvmtiEnvThreadState. So | |
271 // clean up JvmtiThreadState before deleting JvmtiEnv pointer. | |
272 JvmtiThreadState::periodic_clean_up(); | |
273 | |
274 // Unlink all invalid environments from the list of environments | |
275 // and deallocate them | |
276 JvmtiEnvIterator it; | |
277 JvmtiEnvBase* previous_env = NULL; | |
278 JvmtiEnvBase* env = it.first(); | |
279 while (env != NULL) { | |
280 if (env->is_valid()) { | |
281 previous_env = env; | |
282 env = it.next(env); | |
283 } else { | |
284 // This one isn't valid, remove it from the list and deallocate it | |
285 JvmtiEnvBase* defunct_env = env; | |
286 env = it.next(env); | |
287 if (previous_env == NULL) { | |
288 _head_environment = env; | |
289 } else { | |
290 previous_env->set_next_environment(env); | |
291 } | |
292 delete defunct_env; | |
293 } | |
294 } | |
295 | |
296 } | |
297 | |
298 | |
299 void | |
300 JvmtiEnvBase::check_for_periodic_clean_up() { | |
301 assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); | |
302 | |
303 class ThreadInsideIterationClosure: public ThreadClosure { | |
304 private: | |
305 bool _inside; | |
306 public: | |
307 ThreadInsideIterationClosure() : _inside(false) {}; | |
308 | |
309 void do_thread(Thread* thread) { | |
310 _inside |= thread->is_inside_jvmti_env_iteration(); | |
311 } | |
312 | |
313 bool is_inside_jvmti_env_iteration() { | |
314 return _inside; | |
315 } | |
316 }; | |
317 | |
318 if (_needs_clean_up) { | |
319 // Check if we are currently iterating environment, | |
320 // deallocation should not occur if we are | |
321 ThreadInsideIterationClosure tiic; | |
322 Threads::threads_do(&tiic); | |
323 if (!tiic.is_inside_jvmti_env_iteration() && | |
324 !is_inside_dying_thread_env_iteration()) { | |
325 _needs_clean_up = false; | |
326 JvmtiEnvBase::periodic_clean_up(); | |
327 } | |
328 } | |
329 } | |
330 | |
331 | |
332 void | |
333 JvmtiEnvBase::record_first_time_class_file_load_hook_enabled() { | |
334 assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), | |
335 "sanity check"); | |
336 | |
337 if (!_class_file_load_hook_ever_enabled) { | |
338 _class_file_load_hook_ever_enabled = true; | |
339 | |
340 if (get_capabilities()->can_retransform_classes) { | |
341 _is_retransformable = true; | |
342 } else { | |
343 _is_retransformable = false; | |
344 | |
345 // cannot add retransform capability after ClassFileLoadHook has been enabled | |
346 get_prohibited_capabilities()->can_retransform_classes = 1; | |
347 } | |
348 } | |
349 } | |
350 | |
351 | |
352 void | |
353 JvmtiEnvBase::record_class_file_load_hook_enabled() { | |
354 if (!_class_file_load_hook_ever_enabled) { | |
355 if (Threads::number_of_threads() == 0) { | |
356 record_first_time_class_file_load_hook_enabled(); | |
357 } else { | |
358 MutexLocker mu(JvmtiThreadState_lock); | |
359 record_first_time_class_file_load_hook_enabled(); | |
360 } | |
361 } | |
362 } | |
363 | |
364 | |
365 jvmtiError | |
366 JvmtiEnvBase::set_native_method_prefixes(jint prefix_count, char** prefixes) { | |
367 assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), | |
368 "sanity check"); | |
369 | |
370 int old_prefix_count = get_native_method_prefix_count(); | |
371 char **old_prefixes = get_native_method_prefixes(); | |
372 | |
373 // allocate and install the new prefixex | |
374 if (prefix_count == 0 || !is_valid()) { | |
375 _native_method_prefix_count = 0; | |
376 _native_method_prefixes = NULL; | |
377 } else { | |
378 // there are prefixes, allocate an array to hold them, and fill it | |
6197 | 379 char** new_prefixes = (char**)os::malloc((prefix_count) * sizeof(char*), mtInternal); |
0 | 380 if (new_prefixes == NULL) { |
381 return JVMTI_ERROR_OUT_OF_MEMORY; | |
382 } | |
383 for (int i = 0; i < prefix_count; i++) { | |
384 char* prefix = prefixes[i]; | |
385 if (prefix == NULL) { | |
386 for (int j = 0; j < (i-1); j++) { | |
387 os::free(new_prefixes[j]); | |
388 } | |
389 os::free(new_prefixes); | |
390 return JVMTI_ERROR_NULL_POINTER; | |
391 } | |
392 prefix = os::strdup(prefixes[i]); | |
393 if (prefix == NULL) { | |
394 for (int j = 0; j < (i-1); j++) { | |
395 os::free(new_prefixes[j]); | |
396 } | |
397 os::free(new_prefixes); | |
398 return JVMTI_ERROR_OUT_OF_MEMORY; | |
399 } | |
400 new_prefixes[i] = prefix; | |
401 } | |
402 _native_method_prefix_count = prefix_count; | |
403 _native_method_prefixes = new_prefixes; | |
404 } | |
405 | |
406 // now that we know the new prefixes have been successfully installed we can | |
407 // safely remove the old ones | |
408 if (old_prefix_count != 0) { | |
409 for (int i = 0; i < old_prefix_count; i++) { | |
410 os::free(old_prefixes[i]); | |
411 } | |
412 os::free(old_prefixes); | |
413 } | |
414 | |
415 return JVMTI_ERROR_NONE; | |
416 } | |
417 | |
418 | |
419 // Collect all the prefixes which have been set in any JVM TI environments | |
420 // by the SetNativeMethodPrefix(es) functions. Be sure to maintain the | |
421 // order of environments and the order of prefixes within each environment. | |
422 // Return in a resource allocated array. | |
423 char** | |
424 JvmtiEnvBase::get_all_native_method_prefixes(int* count_ptr) { | |
425 assert(Threads::number_of_threads() == 0 || | |
426 SafepointSynchronize::is_at_safepoint() || | |
427 JvmtiThreadState_lock->is_locked(), | |
428 "sanity check"); | |
429 | |
430 int total_count = 0; | |
431 GrowableArray<char*>* prefix_array =new GrowableArray<char*>(5); | |
432 | |
433 JvmtiEnvIterator it; | |
434 for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) { | |
435 int prefix_count = env->get_native_method_prefix_count(); | |
436 char** prefixes = env->get_native_method_prefixes(); | |
437 for (int j = 0; j < prefix_count; j++) { | |
438 // retrieve a prefix and so that it is safe against asynchronous changes | |
439 // copy it into the resource area | |
440 char* prefix = prefixes[j]; | |
441 char* prefix_copy = NEW_RESOURCE_ARRAY(char, strlen(prefix)+1); | |
442 strcpy(prefix_copy, prefix); | |
443 prefix_array->at_put_grow(total_count++, prefix_copy); | |
444 } | |
445 } | |
446 | |
447 char** all_prefixes = NEW_RESOURCE_ARRAY(char*, total_count); | |
448 char** p = all_prefixes; | |
449 for (int i = 0; i < total_count; ++i) { | |
450 *p++ = prefix_array->at(i); | |
451 } | |
452 *count_ptr = total_count; | |
453 return all_prefixes; | |
454 } | |
455 | |
456 void | |
457 JvmtiEnvBase::set_event_callbacks(const jvmtiEventCallbacks* callbacks, | |
458 jint size_of_callbacks) { | |
459 assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check"); | |
460 | |
461 size_t byte_cnt = sizeof(jvmtiEventCallbacks); | |
462 | |
463 // clear in either case to be sure we got any gap between sizes | |
464 memset(&_event_callbacks, 0, byte_cnt); | |
465 | |
466 // Now that JvmtiThreadState_lock is held, prevent a possible race condition where events | |
467 // are re-enabled by a call to set event callbacks where the DisposeEnvironment | |
468 // occurs after the boiler-plate environment check and before the lock is acquired. | |
469 if (callbacks != NULL && is_valid()) { | |
470 if (size_of_callbacks < (jint)byte_cnt) { | |
471 byte_cnt = size_of_callbacks; | |
472 } | |
473 memcpy(&_event_callbacks, callbacks, byte_cnt); | |
474 } | |
475 } | |
476 | |
477 // Called from JVMTI entry points which perform stack walking. If the | |
478 // associated JavaThread is the current thread, then wait_for_suspend | |
479 // is not used. Otherwise, it determines if we should wait for the | |
480 // "other" thread to complete external suspension. (NOTE: in future | |
481 // releases the suspension mechanism should be reimplemented so this | |
482 // is not necessary.) | |
483 // | |
484 bool | |
485 JvmtiEnvBase::is_thread_fully_suspended(JavaThread* thr, bool wait_for_suspend, uint32_t *bits) { | |
486 // "other" threads require special handling | |
487 if (thr != JavaThread::current()) { | |
488 if (wait_for_suspend) { | |
489 // We are allowed to wait for the external suspend to complete | |
490 // so give the other thread a chance to get suspended. | |
491 if (!thr->wait_for_ext_suspend_completion(SuspendRetryCount, | |
492 SuspendRetryDelay, bits)) { | |
493 // didn't make it so let the caller know | |
494 return false; | |
495 } | |
496 } | |
497 // We aren't allowed to wait for the external suspend to complete | |
498 // so if the other thread isn't externally suspended we need to | |
499 // let the caller know. | |
500 else if (!thr->is_ext_suspend_completed_with_lock(bits)) { | |
501 return false; | |
502 } | |
503 } | |
504 | |
505 return true; | |
506 } | |
507 | |
508 | |
509 // In the fullness of time, all users of the method should instead | |
510 // directly use allocate, besides being cleaner and faster, this will | |
511 // mean much better out of memory handling | |
512 unsigned char * | |
513 JvmtiEnvBase::jvmtiMalloc(jlong size) { | |
514 unsigned char* mem; | |
515 jvmtiError result = allocate(size, &mem); | |
516 assert(result == JVMTI_ERROR_NONE, "Allocate failed"); | |
517 return mem; | |
518 } | |
519 | |
520 | |
521 // | |
522 // Threads | |
523 // | |
524 | |
525 jobject * | |
526 JvmtiEnvBase::new_jobjectArray(int length, Handle *handles) { | |
527 if (length == 0) { | |
528 return NULL; | |
529 } | |
530 | |
531 jobject *objArray = (jobject *) jvmtiMalloc(sizeof(jobject) * length); | |
532 NULL_CHECK(objArray, NULL); | |
533 | |
534 for (int i=0; i<length; i++) { | |
535 objArray[i] = jni_reference(handles[i]); | |
536 } | |
537 return objArray; | |
538 } | |
539 | |
540 jthread * | |
541 JvmtiEnvBase::new_jthreadArray(int length, Handle *handles) { | |
542 return (jthread *) new_jobjectArray(length,handles); | |
543 } | |
544 | |
545 jthreadGroup * | |
546 JvmtiEnvBase::new_jthreadGroupArray(int length, Handle *handles) { | |
547 return (jthreadGroup *) new_jobjectArray(length,handles); | |
548 } | |
549 | |
550 | |
551 JavaThread * | |
552 JvmtiEnvBase::get_JavaThread(jthread jni_thread) { | |
553 oop t = JNIHandles::resolve_external_guard(jni_thread); | |
1142 | 554 if (t == NULL || !t->is_a(SystemDictionary::Thread_klass())) { |
0 | 555 return NULL; |
556 } | |
557 // The following returns NULL if the thread has not yet run or is in | |
558 // process of exiting | |
559 return java_lang_Thread::thread(t); | |
560 } | |
561 | |
562 | |
563 // return the vframe on the specified thread and depth, NULL if no such frame | |
564 vframe* | |
565 JvmtiEnvBase::vframeFor(JavaThread* java_thread, jint depth) { | |
566 if (!java_thread->has_last_Java_frame()) { | |
567 return NULL; | |
568 } | |
569 RegisterMap reg_map(java_thread); | |
570 vframe *vf = java_thread->last_java_vframe(®_map); | |
571 int d = 0; | |
572 while ((vf != NULL) && (d < depth)) { | |
573 vf = vf->java_sender(); | |
574 d++; | |
575 } | |
576 return vf; | |
577 } | |
578 | |
579 | |
580 // | |
581 // utilities: JNI objects | |
582 // | |
583 | |
584 | |
585 jclass | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
586 JvmtiEnvBase::get_jni_class_non_null(Klass* k) { |
0 | 587 assert(k != NULL, "k != NULL"); |
6983 | 588 return (jclass)jni_reference(k->java_mirror()); |
0 | 589 } |
590 | |
591 // | |
592 // Field Information | |
593 // | |
594 | |
595 bool | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
596 JvmtiEnvBase::get_field_descriptor(Klass* k, jfieldID field, fieldDescriptor* fd) { |
0 | 597 if (!jfieldIDWorkaround::is_valid_jfieldID(k, field)) { |
598 return false; | |
599 } | |
600 bool found = false; | |
601 if (jfieldIDWorkaround::is_static_jfieldID(field)) { | |
602 JNIid* id = jfieldIDWorkaround::from_static_jfieldID(field); | |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
2177
diff
changeset
|
603 found = id->find_local_field(fd); |
0 | 604 } else { |
605 // Non-static field. The fieldID is really the offset of the field within the object. | |
606 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, field); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
607 found = InstanceKlass::cast(k)->find_field_from_offset(offset, false, fd); |
0 | 608 } |
609 return found; | |
610 } | |
611 | |
612 // | |
613 // Object Monitor Information | |
614 // | |
615 | |
616 // | |
617 // Count the number of objects for a lightweight monitor. The hobj | |
618 // parameter is object that owns the monitor so this routine will | |
619 // count the number of times the same object was locked by frames | |
620 // in java_thread. | |
621 // | |
622 jint | |
623 JvmtiEnvBase::count_locked_objects(JavaThread *java_thread, Handle hobj) { | |
624 jint ret = 0; | |
625 if (!java_thread->has_last_Java_frame()) { | |
626 return ret; // no Java frames so no monitors | |
627 } | |
628 | |
629 ResourceMark rm; | |
630 HandleMark hm; | |
631 RegisterMap reg_map(java_thread); | |
632 | |
633 for(javaVFrame *jvf=java_thread->last_java_vframe(®_map); jvf != NULL; | |
634 jvf = jvf->java_sender()) { | |
635 GrowableArray<MonitorInfo*>* mons = jvf->monitors(); | |
636 if (!mons->is_empty()) { | |
637 for (int i = 0; i < mons->length(); i++) { | |
638 MonitorInfo *mi = mons->at(i); | |
818
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
611
diff
changeset
|
639 if (mi->owner_is_scalar_replaced()) continue; |
0 | 640 |
641 // see if owner of the monitor is our object | |
642 if (mi->owner() != NULL && mi->owner() == hobj()) { | |
643 ret++; | |
644 } | |
645 } | |
646 } | |
647 } | |
648 return ret; | |
649 } | |
650 | |
651 | |
652 | |
653 jvmtiError | |
654 JvmtiEnvBase::get_current_contended_monitor(JavaThread *calling_thread, JavaThread *java_thread, jobject *monitor_ptr) { | |
655 #ifdef ASSERT | |
656 uint32_t debug_bits = 0; | |
657 #endif | |
658 assert((SafepointSynchronize::is_at_safepoint() || | |
659 is_thread_fully_suspended(java_thread, false, &debug_bits)), | |
660 "at safepoint or target thread is suspended"); | |
661 oop obj = NULL; | |
662 ObjectMonitor *mon = java_thread->current_waiting_monitor(); | |
663 if (mon == NULL) { | |
664 // thread is not doing an Object.wait() call | |
665 mon = java_thread->current_pending_monitor(); | |
666 if (mon != NULL) { | |
667 // The thread is trying to enter() or raw_enter() an ObjectMonitor. | |
668 obj = (oop)mon->object(); | |
669 // If obj == NULL, then ObjectMonitor is raw which doesn't count | |
670 // as contended for this API | |
671 } | |
672 // implied else: no contended ObjectMonitor | |
673 } else { | |
674 // thread is doing an Object.wait() call | |
675 obj = (oop)mon->object(); | |
676 assert(obj != NULL, "Object.wait() should have an object"); | |
677 } | |
678 | |
679 if (obj == NULL) { | |
680 *monitor_ptr = NULL; | |
681 } else { | |
682 HandleMark hm; | |
683 Handle hobj(obj); | |
684 *monitor_ptr = jni_reference(calling_thread, hobj); | |
685 } | |
686 return JVMTI_ERROR_NONE; | |
687 } | |
688 | |
689 | |
690 jvmtiError | |
691 JvmtiEnvBase::get_owned_monitors(JavaThread *calling_thread, JavaThread* java_thread, | |
692 GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list) { | |
693 jvmtiError err = JVMTI_ERROR_NONE; | |
694 #ifdef ASSERT | |
695 uint32_t debug_bits = 0; | |
696 #endif | |
697 assert((SafepointSynchronize::is_at_safepoint() || | |
698 is_thread_fully_suspended(java_thread, false, &debug_bits)), | |
699 "at safepoint or target thread is suspended"); | |
700 | |
701 if (java_thread->has_last_Java_frame()) { | |
702 ResourceMark rm; | |
703 HandleMark hm; | |
704 RegisterMap reg_map(java_thread); | |
705 | |
706 int depth = 0; | |
707 for (javaVFrame *jvf = java_thread->last_java_vframe(®_map); jvf != NULL; | |
708 jvf = jvf->java_sender()) { | |
709 if (depth++ < MaxJavaStackTraceDepth) { // check for stack too deep | |
710 // add locked objects for this frame into list | |
711 err = get_locked_objects_in_frame(calling_thread, java_thread, jvf, owned_monitors_list, depth-1); | |
712 if (err != JVMTI_ERROR_NONE) { | |
713 return err; | |
714 } | |
715 } | |
716 } | |
717 } | |
718 | |
719 // Get off stack monitors. (e.g. acquired via jni MonitorEnter). | |
720 JvmtiMonitorClosure jmc(java_thread, calling_thread, owned_monitors_list, this); | |
721 ObjectSynchronizer::monitors_iterate(&jmc); | |
722 err = jmc.error(); | |
723 | |
724 return err; | |
725 } | |
726 | |
727 // Save JNI local handles for any objects that this frame owns. | |
728 jvmtiError | |
729 JvmtiEnvBase::get_locked_objects_in_frame(JavaThread* calling_thread, JavaThread* java_thread, | |
730 javaVFrame *jvf, GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitors_list, int stack_depth) { | |
731 jvmtiError err = JVMTI_ERROR_NONE; | |
732 ResourceMark rm; | |
733 | |
734 GrowableArray<MonitorInfo*>* mons = jvf->monitors(); | |
735 if (mons->is_empty()) { | |
736 return err; // this javaVFrame holds no monitors | |
737 } | |
738 | |
739 HandleMark hm; | |
740 oop wait_obj = NULL; | |
741 { | |
742 // save object of current wait() call (if any) for later comparison | |
743 ObjectMonitor *mon = java_thread->current_waiting_monitor(); | |
744 if (mon != NULL) { | |
745 wait_obj = (oop)mon->object(); | |
746 } | |
747 } | |
748 oop pending_obj = NULL; | |
749 { | |
750 // save object of current enter() call (if any) for later comparison | |
751 ObjectMonitor *mon = java_thread->current_pending_monitor(); | |
752 if (mon != NULL) { | |
753 pending_obj = (oop)mon->object(); | |
754 } | |
755 } | |
756 | |
757 for (int i = 0; i < mons->length(); i++) { | |
758 MonitorInfo *mi = mons->at(i); | |
759 | |
818
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
611
diff
changeset
|
760 if (mi->owner_is_scalar_replaced()) continue; |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
611
diff
changeset
|
761 |
0 | 762 oop obj = mi->owner(); |
763 if (obj == NULL) { | |
764 // this monitor doesn't have an owning object so skip it | |
765 continue; | |
766 } | |
767 | |
768 if (wait_obj == obj) { | |
769 // the thread is waiting on this monitor so it isn't really owned | |
770 continue; | |
771 } | |
772 | |
773 if (pending_obj == obj) { | |
774 // the thread is pending on this monitor so it isn't really owned | |
775 continue; | |
776 } | |
777 | |
778 if (owned_monitors_list->length() > 0) { | |
779 // Our list has at least one object on it so we have to check | |
780 // for recursive object locking | |
781 bool found = false; | |
782 for (int j = 0; j < owned_monitors_list->length(); j++) { | |
783 jobject jobj = ((jvmtiMonitorStackDepthInfo*)owned_monitors_list->at(j))->monitor; | |
784 oop check = JNIHandles::resolve(jobj); | |
785 if (check == obj) { | |
786 found = true; // we found the object | |
787 break; | |
788 } | |
789 } | |
790 | |
791 if (found) { | |
792 // already have this object so don't include it | |
793 continue; | |
794 } | |
795 } | |
796 | |
797 // add the owning object to our list | |
798 jvmtiMonitorStackDepthInfo *jmsdi; | |
799 err = allocate(sizeof(jvmtiMonitorStackDepthInfo), (unsigned char **)&jmsdi); | |
800 if (err != JVMTI_ERROR_NONE) { | |
801 return err; | |
802 } | |
803 Handle hobj(obj); | |
804 jmsdi->monitor = jni_reference(calling_thread, hobj); | |
805 jmsdi->stack_depth = stack_depth; | |
806 owned_monitors_list->append(jmsdi); | |
807 } | |
808 | |
809 return err; | |
810 } | |
811 | |
812 jvmtiError | |
813 JvmtiEnvBase::get_stack_trace(JavaThread *java_thread, | |
814 jint start_depth, jint max_count, | |
815 jvmtiFrameInfo* frame_buffer, jint* count_ptr) { | |
816 #ifdef ASSERT | |
817 uint32_t debug_bits = 0; | |
818 #endif | |
819 assert((SafepointSynchronize::is_at_safepoint() || | |
820 is_thread_fully_suspended(java_thread, false, &debug_bits)), | |
821 "at safepoint or target thread is suspended"); | |
822 int count = 0; | |
823 if (java_thread->has_last_Java_frame()) { | |
824 RegisterMap reg_map(java_thread); | |
825 Thread* current_thread = Thread::current(); | |
826 ResourceMark rm(current_thread); | |
827 javaVFrame *jvf = java_thread->last_java_vframe(®_map); | |
828 HandleMark hm(current_thread); | |
829 if (start_depth != 0) { | |
830 if (start_depth > 0) { | |
831 for (int j = 0; j < start_depth && jvf != NULL; j++) { | |
832 jvf = jvf->java_sender(); | |
833 } | |
834 if (jvf == NULL) { | |
835 // start_depth is deeper than the stack depth | |
836 return JVMTI_ERROR_ILLEGAL_ARGUMENT; | |
837 } | |
838 } else { // start_depth < 0 | |
839 // we are referencing the starting depth based on the oldest | |
840 // part of the stack. | |
841 // optimize to limit the number of times that java_sender() is called | |
842 javaVFrame *jvf_cursor = jvf; | |
843 javaVFrame *jvf_prev = NULL; | |
844 javaVFrame *jvf_prev_prev; | |
845 int j = 0; | |
846 while (jvf_cursor != NULL) { | |
847 jvf_prev_prev = jvf_prev; | |
848 jvf_prev = jvf_cursor; | |
849 for (j = 0; j > start_depth && jvf_cursor != NULL; j--) { | |
850 jvf_cursor = jvf_cursor->java_sender(); | |
851 } | |
852 } | |
853 if (j == start_depth) { | |
854 // previous pointer is exactly where we want to start | |
855 jvf = jvf_prev; | |
856 } else { | |
857 // we need to back up further to get to the right place | |
858 if (jvf_prev_prev == NULL) { | |
859 // the -start_depth is greater than the stack depth | |
860 return JVMTI_ERROR_ILLEGAL_ARGUMENT; | |
861 } | |
862 // j now is the number of frames on the stack starting with | |
863 // jvf_prev, we start from jvf_prev_prev and move older on | |
864 // the stack that many, the result is -start_depth frames | |
865 // remaining. | |
866 jvf = jvf_prev_prev; | |
867 for (; j < 0; j++) { | |
868 jvf = jvf->java_sender(); | |
869 } | |
870 } | |
871 } | |
872 } | |
873 for (; count < max_count && jvf != NULL; count++) { | |
874 frame_buffer[count].method = jvf->method()->jmethod_id(); | |
875 frame_buffer[count].location = (jvf->method()->is_native() ? -1 : jvf->bci()); | |
876 jvf = jvf->java_sender(); | |
877 } | |
878 } else { | |
879 if (start_depth != 0) { | |
880 // no frames and there is a starting depth | |
881 return JVMTI_ERROR_ILLEGAL_ARGUMENT; | |
882 } | |
883 } | |
884 *count_ptr = count; | |
885 return JVMTI_ERROR_NONE; | |
886 } | |
887 | |
888 jvmtiError | |
889 JvmtiEnvBase::get_frame_count(JvmtiThreadState *state, jint *count_ptr) { | |
890 assert((state != NULL), | |
891 "JavaThread should create JvmtiThreadState before calling this method"); | |
892 *count_ptr = state->count_frames(); | |
893 return JVMTI_ERROR_NONE; | |
894 } | |
895 | |
896 jvmtiError | |
897 JvmtiEnvBase::get_frame_location(JavaThread *java_thread, jint depth, | |
898 jmethodID* method_ptr, jlocation* location_ptr) { | |
899 #ifdef ASSERT | |
900 uint32_t debug_bits = 0; | |
901 #endif | |
902 assert((SafepointSynchronize::is_at_safepoint() || | |
903 is_thread_fully_suspended(java_thread, false, &debug_bits)), | |
904 "at safepoint or target thread is suspended"); | |
905 Thread* current_thread = Thread::current(); | |
906 ResourceMark rm(current_thread); | |
907 | |
908 vframe *vf = vframeFor(java_thread, depth); | |
909 if (vf == NULL) { | |
910 return JVMTI_ERROR_NO_MORE_FRAMES; | |
911 } | |
912 | |
913 // vframeFor should return a java frame. If it doesn't | |
914 // it means we've got an internal error and we return the | |
915 // error in product mode. In debug mode we will instead | |
916 // attempt to cast the vframe to a javaVFrame and will | |
917 // cause an assertion/crash to allow further diagnosis. | |
918 #ifdef PRODUCT | |
919 if (!vf->is_java_frame()) { | |
920 return JVMTI_ERROR_INTERNAL; | |
921 } | |
922 #endif | |
923 | |
924 HandleMark hm(current_thread); | |
925 javaVFrame *jvf = javaVFrame::cast(vf); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6197
diff
changeset
|
926 Method* method = jvf->method(); |
0 | 927 if (method->is_native()) { |
928 *location_ptr = -1; | |
929 } else { | |
930 *location_ptr = jvf->bci(); | |
931 } | |
932 *method_ptr = method->jmethod_id(); | |
933 | |
934 return JVMTI_ERROR_NONE; | |
935 } | |
936 | |
937 | |
938 jvmtiError | |
939 JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject object, jvmtiMonitorUsage* info_ptr) { | |
940 HandleMark hm; | |
941 Handle hobj; | |
942 | |
943 bool at_safepoint = SafepointSynchronize::is_at_safepoint(); | |
944 | |
945 // Check arguments | |
946 { | |
947 oop mirror = JNIHandles::resolve_external_guard(object); | |
948 NULL_CHECK(mirror, JVMTI_ERROR_INVALID_OBJECT); | |
949 NULL_CHECK(info_ptr, JVMTI_ERROR_NULL_POINTER); | |
950 | |
951 hobj = Handle(mirror); | |
952 } | |
953 | |
954 JavaThread *owning_thread = NULL; | |
955 ObjectMonitor *mon = NULL; | |
956 jvmtiMonitorUsage ret = { | |
957 NULL, 0, 0, NULL, 0, NULL | |
958 }; | |
959 | |
960 uint32_t debug_bits = 0; | |
961 // first derive the object's owner and entry_count (if any) | |
962 { | |
963 // Revoke any biases before querying the mark word | |
964 if (SafepointSynchronize::is_at_safepoint()) { | |
965 BiasedLocking::revoke_at_safepoint(hobj); | |
966 } else { | |
967 BiasedLocking::revoke_and_rebias(hobj, false, calling_thread); | |
968 } | |
969 | |
970 address owner = NULL; | |
971 { | |
972 markOop mark = hobj()->mark(); | |
973 | |
974 if (!mark->has_monitor()) { | |
975 // this object has a lightweight monitor | |
976 | |
977 if (mark->has_locker()) { | |
978 owner = (address)mark->locker(); // save the address of the Lock word | |
979 } | |
980 // implied else: no owner | |
981 } else { | |
982 // this object has a heavyweight monitor | |
983 mon = mark->monitor(); | |
984 | |
985 // The owner field of a heavyweight monitor may be NULL for no | |
986 // owner, a JavaThread * or it may still be the address of the | |
987 // Lock word in a JavaThread's stack. A monitor can be inflated | |
988 // by a non-owning JavaThread, but only the owning JavaThread | |
989 // can change the owner field from the Lock word to the | |
990 // JavaThread * and it may not have done that yet. | |
991 owner = (address)mon->owner(); | |
992 } | |
993 } | |
994 | |
995 if (owner != NULL) { | |
996 // This monitor is owned so we have to find the owning JavaThread. | |
997 // Since owning_thread_from_monitor_owner() grabs a lock, GC can | |
998 // move our object at this point. However, our owner value is safe | |
999 // since it is either the Lock word on a stack or a JavaThread *. | |
1000 owning_thread = Threads::owning_thread_from_monitor_owner(owner, !at_safepoint); | |
8673
5ee250974db9
8007476: assert(the_owner != NULL) failed: Did not find owning Java thread for lock word address
dcubed
parents:
7951
diff
changeset
|
1001 // Cannot assume (owning_thread != NULL) here because this function |
5ee250974db9
8007476: assert(the_owner != NULL) failed: Did not find owning Java thread for lock word address
dcubed
parents:
7951
diff
changeset
|
1002 // may not have been called at a safepoint and the owning_thread |
5ee250974db9
8007476: assert(the_owner != NULL) failed: Did not find owning Java thread for lock word address
dcubed
parents:
7951
diff
changeset
|
1003 // might not be suspended. |
5ee250974db9
8007476: assert(the_owner != NULL) failed: Did not find owning Java thread for lock word address
dcubed
parents:
7951
diff
changeset
|
1004 if (owning_thread != NULL) { |
0 | 1005 // The monitor's owner either has to be the current thread, at safepoint |
1006 // or it has to be suspended. Any of these conditions will prevent both | |
1007 // contending and waiting threads from modifying the state of | |
1008 // the monitor. | |
1009 if (!at_safepoint && !JvmtiEnv::is_thread_fully_suspended(owning_thread, true, &debug_bits)) { | |
8673
5ee250974db9
8007476: assert(the_owner != NULL) failed: Did not find owning Java thread for lock word address
dcubed
parents:
7951
diff
changeset
|
1010 // Don't worry! This return of JVMTI_ERROR_THREAD_NOT_SUSPENDED |
5ee250974db9
8007476: assert(the_owner != NULL) failed: Did not find owning Java thread for lock word address
dcubed
parents:
7951
diff
changeset
|
1011 // will not make it back to the JVM/TI agent. The error code will |
5ee250974db9
8007476: assert(the_owner != NULL) failed: Did not find owning Java thread for lock word address
dcubed
parents:
7951
diff
changeset
|
1012 // get intercepted in JvmtiEnv::GetObjectMonitorUsage() which |
5ee250974db9
8007476: assert(the_owner != NULL) failed: Did not find owning Java thread for lock word address
dcubed
parents:
7951
diff
changeset
|
1013 // will retry the call via a VM_GetObjectMonitorUsage VM op. |
0 | 1014 return JVMTI_ERROR_THREAD_NOT_SUSPENDED; |
1015 } | |
1016 HandleMark hm; | |
1017 Handle th(owning_thread->threadObj()); | |
1018 ret.owner = (jthread)jni_reference(calling_thread, th); | |
1019 } | |
1020 // implied else: no owner | |
1021 } | |
1022 | |
1023 if (owning_thread != NULL) { // monitor is owned | |
1024 if ((address)owning_thread == owner) { | |
1025 // the owner field is the JavaThread * | |
1026 assert(mon != NULL, | |
1027 "must have heavyweight monitor with JavaThread * owner"); | |
1028 ret.entry_count = mon->recursions() + 1; | |
1029 } else { | |
1030 // The owner field is the Lock word on the JavaThread's stack | |
1031 // so the recursions field is not valid. We have to count the | |
1032 // number of recursive monitor entries the hard way. We pass | |
1033 // a handle to survive any GCs along the way. | |
1034 ResourceMark rm; | |
1035 ret.entry_count = count_locked_objects(owning_thread, hobj); | |
1036 } | |
1037 } | |
1038 // implied else: entry_count == 0 | |
1039 } | |
1040 | |
1041 int nWant,nWait; | |
1042 if (mon != NULL) { | |
1043 // this object has a heavyweight monitor | |
1044 nWant = mon->contentions(); // # of threads contending for monitor | |
1045 nWait = mon->waiters(); // # of threads in Object.wait() | |
1046 ret.waiter_count = nWant + nWait; | |
1047 ret.notify_waiter_count = nWait; | |
1048 } else { | |
1049 // this object has a lightweight monitor | |
1050 ret.waiter_count = 0; | |
1051 ret.notify_waiter_count = 0; | |
1052 } | |
1053 | |
1054 // Allocate memory for heavyweight and lightweight monitor. | |
1055 jvmtiError err; | |
1056 err = allocate(ret.waiter_count * sizeof(jthread *), (unsigned char**)&ret.waiters); | |
1057 if (err != JVMTI_ERROR_NONE) { | |
1058 return err; | |
1059 } | |
1060 err = allocate(ret.notify_waiter_count * sizeof(jthread *), | |
1061 (unsigned char**)&ret.notify_waiters); | |
1062 if (err != JVMTI_ERROR_NONE) { | |
1063 deallocate((unsigned char*)ret.waiters); | |
1064 return err; | |
1065 } | |
1066 | |
1067 // now derive the rest of the fields | |
1068 if (mon != NULL) { | |
1069 // this object has a heavyweight monitor | |
1070 | |
1071 // Number of waiters may actually be less than the waiter count. | |
1072 // So NULL out memory so that unused memory will be NULL. | |
1073 memset(ret.waiters, 0, ret.waiter_count * sizeof(jthread *)); | |
1074 memset(ret.notify_waiters, 0, ret.notify_waiter_count * sizeof(jthread *)); | |
1075 | |
1076 if (ret.waiter_count > 0) { | |
1077 // we have contending and/or waiting threads | |
1078 HandleMark hm; | |
1079 if (nWant > 0) { | |
1080 // we have contending threads | |
1081 ResourceMark rm; | |
1082 // get_pending_threads returns only java thread so we do not need to | |
1083 // check for non java threads. | |
1084 GrowableArray<JavaThread*>* wantList = Threads::get_pending_threads( | |
1085 nWant, (address)mon, !at_safepoint); | |
1086 if (wantList->length() < nWant) { | |
1087 // robustness: the pending list has gotten smaller | |
1088 nWant = wantList->length(); | |
1089 } | |
1090 for (int i = 0; i < nWant; i++) { | |
1091 JavaThread *pending_thread = wantList->at(i); | |
1092 // If the monitor has no owner, then a non-suspended contending | |
1093 // thread could potentially change the state of the monitor by | |
1094 // entering it. The JVM/TI spec doesn't allow this. | |
1095 if (owning_thread == NULL && !at_safepoint & | |
1096 !JvmtiEnv::is_thread_fully_suspended(pending_thread, true, &debug_bits)) { | |
1097 if (ret.owner != NULL) { | |
1098 destroy_jni_reference(calling_thread, ret.owner); | |
1099 } | |
1100 for (int j = 0; j < i; j++) { | |
1101 destroy_jni_reference(calling_thread, ret.waiters[j]); | |
1102 } | |
1103 deallocate((unsigned char*)ret.waiters); | |
1104 deallocate((unsigned char*)ret.notify_waiters); | |
1105 return JVMTI_ERROR_THREAD_NOT_SUSPENDED; | |
1106 } | |
1107 Handle th(pending_thread->threadObj()); | |
1108 ret.waiters[i] = (jthread)jni_reference(calling_thread, th); | |
1109 } | |
1110 } | |
1111 if (nWait > 0) { | |
1112 // we have threads in Object.wait() | |
1113 int offset = nWant; // add after any contending threads | |
1114 ObjectWaiter *waiter = mon->first_waiter(); | |
1115 for (int i = 0, j = 0; i < nWait; i++) { | |
1116 if (waiter == NULL) { | |
1117 // robustness: the waiting list has gotten smaller | |
1118 nWait = j; | |
1119 break; | |
1120 } | |
1121 Thread *t = mon->thread_of_waiter(waiter); | |
1122 if (t != NULL && t->is_Java_thread()) { | |
1123 JavaThread *wjava_thread = (JavaThread *)t; | |
1124 // If the thread was found on the ObjectWaiter list, then | |
1125 // it has not been notified. This thread can't change the | |
1126 // state of the monitor so it doesn't need to be suspended. | |
1127 Handle th(wjava_thread->threadObj()); | |
1128 ret.waiters[offset + j] = (jthread)jni_reference(calling_thread, th); | |
1129 ret.notify_waiters[j++] = (jthread)jni_reference(calling_thread, th); | |
1130 } | |
1131 waiter = mon->next_waiter(waiter); | |
1132 } | |
1133 } | |
1134 } | |
1135 | |
1136 // Adjust count. nWant and nWait count values may be less than original. | |
1137 ret.waiter_count = nWant + nWait; | |
1138 ret.notify_waiter_count = nWait; | |
1139 } else { | |
1140 // this object has a lightweight monitor and we have nothing more | |
1141 // to do here because the defaults are just fine. | |
1142 } | |
1143 | |
1144 // we don't update return parameter unless everything worked | |
1145 *info_ptr = ret; | |
1146 | |
1147 return JVMTI_ERROR_NONE; | |
1148 } | |
1149 | |
1150 ResourceTracker::ResourceTracker(JvmtiEnv* env) { | |
1151 _env = env; | |
6197 | 1152 _allocations = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<unsigned char*>(20, true); |
0 | 1153 _failed = false; |
1154 } | |
1155 ResourceTracker::~ResourceTracker() { | |
1156 if (_failed) { | |
1157 for (int i=0; i<_allocations->length(); i++) { | |
1158 _env->deallocate(_allocations->at(i)); | |
1159 } | |
1160 } | |
1161 delete _allocations; | |
1162 } | |
1163 | |
1164 jvmtiError ResourceTracker::allocate(jlong size, unsigned char** mem_ptr) { | |
1165 unsigned char *ptr; | |
1166 jvmtiError err = _env->allocate(size, &ptr); | |
1167 if (err == JVMTI_ERROR_NONE) { | |
1168 _allocations->append(ptr); | |
1169 *mem_ptr = ptr; | |
1170 } else { | |
1171 *mem_ptr = NULL; | |
1172 _failed = true; | |
1173 } | |
1174 return err; | |
1175 } | |
1176 | |
1177 unsigned char* ResourceTracker::allocate(jlong size) { | |
1178 unsigned char* ptr; | |
1179 allocate(size, &ptr); | |
1180 return ptr; | |
1181 } | |
1182 | |
1183 char* ResourceTracker::strdup(const char* str) { | |
1184 char *dup_str = (char*)allocate(strlen(str)+1); | |
1185 if (dup_str != NULL) { | |
1186 strcpy(dup_str, str); | |
1187 } | |
1188 return dup_str; | |
1189 } | |
1190 | |
1191 struct StackInfoNode { | |
1192 struct StackInfoNode *next; | |
1193 jvmtiStackInfo info; | |
1194 }; | |
1195 | |
1196 // Create a jvmtiStackInfo inside a linked list node and create a | |
1197 // buffer for the frame information, both allocated as resource objects. | |
1198 // Fill in both the jvmtiStackInfo and the jvmtiFrameInfo. | |
1199 // Note that either or both of thr and thread_oop | |
1200 // may be null if the thread is new or has exited. | |
1201 void | |
1202 VM_GetMultipleStackTraces::fill_frames(jthread jt, JavaThread *thr, oop thread_oop) { | |
1203 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); | |
1204 | |
1205 jint state = 0; | |
1206 struct StackInfoNode *node = NEW_RESOURCE_OBJ(struct StackInfoNode); | |
1207 jvmtiStackInfo *infop = &(node->info); | |
1208 node->next = head(); | |
1209 set_head(node); | |
1210 infop->frame_count = 0; | |
1211 infop->thread = jt; | |
1212 | |
1213 if (thread_oop != NULL) { | |
1214 // get most state bits | |
1215 state = (jint)java_lang_Thread::get_thread_status(thread_oop); | |
1216 } | |
1217 | |
1218 if (thr != NULL) { // add more state bits if there is a JavaThead to query | |
1219 // same as is_being_ext_suspended() but without locking | |
1220 if (thr->is_ext_suspended() || thr->is_external_suspend()) { | |
1221 state |= JVMTI_THREAD_STATE_SUSPENDED; | |
1222 } | |
1223 JavaThreadState jts = thr->thread_state(); | |
1224 if (jts == _thread_in_native) { | |
1225 state |= JVMTI_THREAD_STATE_IN_NATIVE; | |
1226 } | |
1227 OSThread* osThread = thr->osthread(); | |
1228 if (osThread != NULL && osThread->interrupted()) { | |
1229 state |= JVMTI_THREAD_STATE_INTERRUPTED; | |
1230 } | |
1231 } | |
1232 infop->state = state; | |
1233 | |
1234 if (thr != NULL || (state & JVMTI_THREAD_STATE_ALIVE) != 0) { | |
1235 infop->frame_buffer = NEW_RESOURCE_ARRAY(jvmtiFrameInfo, max_frame_count()); | |
1236 env()->get_stack_trace(thr, 0, max_frame_count(), | |
1237 infop->frame_buffer, &(infop->frame_count)); | |
1238 } else { | |
1239 infop->frame_buffer = NULL; | |
1240 infop->frame_count = 0; | |
1241 } | |
1242 _frame_count_total += infop->frame_count; | |
1243 } | |
1244 | |
1245 // Based on the stack information in the linked list, allocate memory | |
1246 // block to return and fill it from the info in the linked list. | |
1247 void | |
1248 VM_GetMultipleStackTraces::allocate_and_fill_stacks(jint thread_count) { | |
1249 // do I need to worry about alignment issues? | |
1250 jlong alloc_size = thread_count * sizeof(jvmtiStackInfo) | |
1251 + _frame_count_total * sizeof(jvmtiFrameInfo); | |
1252 env()->allocate(alloc_size, (unsigned char **)&_stack_info); | |
1253 | |
1254 // pointers to move through the newly allocated space as it is filled in | |
1255 jvmtiStackInfo *si = _stack_info + thread_count; // bottom of stack info | |
1256 jvmtiFrameInfo *fi = (jvmtiFrameInfo *)si; // is the top of frame info | |
1257 | |
1258 // copy information in resource area into allocated buffer | |
1259 // insert stack info backwards since linked list is backwards | |
1260 // insert frame info forwards | |
1261 // walk the StackInfoNodes | |
1262 for (struct StackInfoNode *sin = head(); sin != NULL; sin = sin->next) { | |
1263 jint frame_count = sin->info.frame_count; | |
1264 size_t frames_size = frame_count * sizeof(jvmtiFrameInfo); | |
1265 --si; | |
1266 memcpy(si, &(sin->info), sizeof(jvmtiStackInfo)); | |
1267 if (frames_size == 0) { | |
1268 si->frame_buffer = NULL; | |
1269 } else { | |
1270 memcpy(fi, sin->info.frame_buffer, frames_size); | |
1271 si->frame_buffer = fi; // point to the new allocated copy of the frames | |
1272 fi += frame_count; | |
1273 } | |
1274 } | |
1275 assert(si == _stack_info, "the last copied stack info must be the first record"); | |
1276 assert((unsigned char *)fi == ((unsigned char *)_stack_info) + alloc_size, | |
1277 "the last copied frame info must be the last record"); | |
1278 } | |
1279 | |
1280 | |
1281 void | |
1282 VM_GetThreadListStackTraces::doit() { | |
1283 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); | |
1284 | |
1285 ResourceMark rm; | |
1286 for (int i = 0; i < _thread_count; ++i) { | |
1287 jthread jt = _thread_list[i]; | |
1288 oop thread_oop = JNIHandles::resolve_external_guard(jt); | |
1142 | 1289 if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) { |
0 | 1290 set_result(JVMTI_ERROR_INVALID_THREAD); |
1291 return; | |
1292 } | |
1293 fill_frames(jt, java_lang_Thread::thread(thread_oop), thread_oop); | |
1294 } | |
1295 allocate_and_fill_stacks(_thread_count); | |
1296 } | |
1297 | |
1298 void | |
1299 VM_GetAllStackTraces::doit() { | |
1300 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); | |
1301 | |
1302 ResourceMark rm; | |
1303 _final_thread_count = 0; | |
1304 for (JavaThread *jt = Threads::first(); jt != NULL; jt = jt->next()) { | |
1305 oop thread_oop = jt->threadObj(); | |
1306 if (thread_oop != NULL && | |
1307 !jt->is_exiting() && | |
1308 java_lang_Thread::is_alive(thread_oop) && | |
1309 !jt->is_hidden_from_external_view()) { | |
1310 ++_final_thread_count; | |
1311 // Handle block of the calling thread is used to create local refs. | |
1312 fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), | |
1313 jt, thread_oop); | |
1314 } | |
1315 } | |
1316 allocate_and_fill_stacks(_final_thread_count); | |
1317 } | |
1318 | |
1319 // Verifies that the top frame is a java frame in an expected state. | |
1320 // Deoptimizes frame if needed. | |
1321 // Checks that the frame method signature matches the return type (tos). | |
1322 // HandleMark must be defined in the caller only. | |
1323 // It is to keep a ret_ob_h handle alive after return to the caller. | |
1324 jvmtiError | |
1325 JvmtiEnvBase::check_top_frame(JavaThread* current_thread, JavaThread* java_thread, | |
1326 jvalue value, TosState tos, Handle* ret_ob_h) { | |
1327 ResourceMark rm(current_thread); | |
1328 | |
1329 vframe *vf = vframeFor(java_thread, 0); | |
1330 NULL_CHECK(vf, JVMTI_ERROR_NO_MORE_FRAMES); | |
1331 | |
1332 javaVFrame *jvf = (javaVFrame*) vf; | |
1333 if (!vf->is_java_frame() || jvf->method()->is_native()) { | |
1334 return JVMTI_ERROR_OPAQUE_FRAME; | |
1335 } | |
1336 | |
1337 // If the frame is a compiled one, need to deoptimize it. | |
1338 if (vf->is_compiled_frame()) { | |
1339 if (!vf->fr().can_be_deoptimized()) { | |
1340 return JVMTI_ERROR_OPAQUE_FRAME; | |
1341 } | |
1905
ce6848d0666d
6968367: can_post_on_exceptions is still using VM_DeoptimizeFrame in some places
never
parents:
1552
diff
changeset
|
1342 Deoptimization::deoptimize_frame(java_thread, jvf->fr().id()); |
0 | 1343 } |
1344 | |
1345 // Get information about method return type | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1988
diff
changeset
|
1346 Symbol* signature = jvf->method()->signature(); |
0 | 1347 |
1348 ResultTypeFinder rtf(signature); | |
1349 TosState fr_tos = as_TosState(rtf.type()); | |
1350 if (fr_tos != tos) { | |
1351 if (tos != itos || (fr_tos != btos && fr_tos != ctos && fr_tos != stos)) { | |
1352 return JVMTI_ERROR_TYPE_MISMATCH; | |
1353 } | |
1354 } | |
1355 | |
1356 // Check that the jobject class matches the return type signature. | |
1357 jobject jobj = value.l; | |
1358 if (tos == atos && jobj != NULL) { // NULL reference is allowed | |
1359 Handle ob_h = Handle(current_thread, JNIHandles::resolve_external_guard(jobj)); | |
1360 NULL_CHECK(ob_h, JVMTI_ERROR_INVALID_OBJECT); | |
1361 KlassHandle ob_kh = KlassHandle(current_thread, ob_h()->klass()); | |
1362 NULL_CHECK(ob_kh, JVMTI_ERROR_INVALID_OBJECT); | |
1363 | |
1364 // Method return type signature. | |
1365 char* ty_sign = 1 + strchr(signature->as_C_string(), ')'); | |
1366 | |
6983 | 1367 if (!VM_GetOrSetLocal::is_assignable(ty_sign, ob_kh(), current_thread)) { |
0 | 1368 return JVMTI_ERROR_TYPE_MISMATCH; |
1369 } | |
1370 *ret_ob_h = ob_h; | |
1371 } | |
1372 return JVMTI_ERROR_NONE; | |
1373 } /* end check_top_frame */ | |
1374 | |
1375 | |
1376 // ForceEarlyReturn<type> follows the PopFrame approach in many aspects. | |
1377 // Main difference is on the last stage in the interpreter. | |
1378 // The PopFrame stops method execution to continue execution | |
1379 // from the same method call instruction. | |
1380 // The ForceEarlyReturn forces return from method so the execution | |
1381 // continues at the bytecode following the method call. | |
1382 | |
1383 // Threads_lock NOT held, java_thread not protected by lock | |
1384 // java_thread - pre-checked | |
1385 | |
1386 jvmtiError | |
1387 JvmtiEnvBase::force_early_return(JavaThread* java_thread, jvalue value, TosState tos) { | |
1388 JavaThread* current_thread = JavaThread::current(); | |
1389 HandleMark hm(current_thread); | |
1390 uint32_t debug_bits = 0; | |
1391 | |
609
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
470
diff
changeset
|
1392 // retrieve or create the state |
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
470
diff
changeset
|
1393 JvmtiThreadState* state = JvmtiThreadState::state_for(java_thread); |
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
470
diff
changeset
|
1394 if (state == NULL) { |
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
470
diff
changeset
|
1395 return JVMTI_ERROR_THREAD_NOT_ALIVE; |
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
470
diff
changeset
|
1396 } |
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
470
diff
changeset
|
1397 |
0 | 1398 // Check if java_thread is fully suspended |
1399 if (!is_thread_fully_suspended(java_thread, | |
1400 true /* wait for suspend completion */, | |
1401 &debug_bits)) { | |
1402 return JVMTI_ERROR_THREAD_NOT_SUSPENDED; | |
1403 } | |
1404 | |
1405 // Check to see if a ForceEarlyReturn was already in progress | |
1406 if (state->is_earlyret_pending()) { | |
1407 // Probably possible for JVMTI clients to trigger this, but the | |
1408 // JPDA backend shouldn't allow this to happen | |
1409 return JVMTI_ERROR_INTERNAL; | |
1410 } | |
1411 { | |
1412 // The same as for PopFrame. Workaround bug: | |
1413 // 4812902: popFrame hangs if the method is waiting at a synchronize | |
1414 // Catch this condition and return an error to avoid hanging. | |
1415 // Now JVMTI spec allows an implementation to bail out with an opaque | |
1416 // frame error. | |
1417 OSThread* osThread = java_thread->osthread(); | |
1418 if (osThread->get_state() == MONITOR_WAIT) { | |
1419 return JVMTI_ERROR_OPAQUE_FRAME; | |
1420 } | |
1421 } | |
1422 Handle ret_ob_h = Handle(); | |
1423 jvmtiError err = check_top_frame(current_thread, java_thread, value, tos, &ret_ob_h); | |
1424 if (err != JVMTI_ERROR_NONE) { | |
1425 return err; | |
1426 } | |
1427 assert(tos != atos || value.l == NULL || ret_ob_h() != NULL, | |
1428 "return object oop must not be NULL if jobject is not NULL"); | |
1429 | |
1430 // Update the thread state to reflect that the top frame must be | |
1431 // forced to return. | |
1432 // The current frame will be returned later when the suspended | |
1433 // thread is resumed and right before returning from VM to Java. | |
1434 // (see call_VM_base() in assembler_<cpu>.cpp). | |
1435 | |
1436 state->set_earlyret_pending(); | |
1437 state->set_earlyret_oop(ret_ob_h()); | |
1438 state->set_earlyret_value(value, tos); | |
1439 | |
1440 // Set pending step flag for this early return. | |
1441 // It is cleared when next step event is posted. | |
1442 state->set_pending_step_for_earlyret(); | |
1443 | |
1444 return JVMTI_ERROR_NONE; | |
1445 } /* end force_early_return */ | |
1446 | |
1447 void | |
1448 JvmtiMonitorClosure::do_monitor(ObjectMonitor* mon) { | |
1449 if ( _error != JVMTI_ERROR_NONE) { | |
1450 // Error occurred in previous iteration so no need to add | |
1451 // to the list. | |
1452 return; | |
1453 } | |
1454 if (mon->owner() == _java_thread ) { | |
1455 // Filter out on stack monitors collected during stack walk. | |
1456 oop obj = (oop)mon->object(); | |
1457 bool found = false; | |
1458 for (int j = 0; j < _owned_monitors_list->length(); j++) { | |
1459 jobject jobj = ((jvmtiMonitorStackDepthInfo*)_owned_monitors_list->at(j))->monitor; | |
1460 oop check = JNIHandles::resolve(jobj); | |
1461 if (check == obj) { | |
1462 // On stack monitor already collected during the stack walk. | |
1463 found = true; | |
1464 break; | |
1465 } | |
1466 } | |
1467 if (found == false) { | |
1468 // This is off stack monitor (e.g. acquired via jni MonitorEnter). | |
1469 jvmtiError err; | |
1470 jvmtiMonitorStackDepthInfo *jmsdi; | |
1471 err = _env->allocate(sizeof(jvmtiMonitorStackDepthInfo), (unsigned char **)&jmsdi); | |
1472 if (err != JVMTI_ERROR_NONE) { | |
1473 _error = err; | |
1474 return; | |
1475 } | |
1476 Handle hobj(obj); | |
1477 jmsdi->monitor = _env->jni_reference(_calling_thread, hobj); | |
1478 // stack depth is unknown for this monitor. | |
1479 jmsdi->stack_depth = -1; | |
1480 _owned_monitors_list->append(jmsdi); | |
1481 } | |
1482 } | |
1483 } |