Mercurial > hg > graal-compiler
annotate src/share/vm/prims/jvmtiEnv.cpp @ 3992:d1bdeef3e3e2
7098282: G1: assert(interval >= 0) failed: Sanity check, referencePolicy.cpp: 76
Summary: There is a race between one thread successfully forwarding and copying the klass mirror for the SoftReference class (including the static master clock) and another thread attempting to use the master clock while attempting to discover a soft reference object. Maintain a shadow copy of the soft reference master clock and use the shadow during reference discovery and reference processing.
Reviewed-by: tonyp, brutisso, ysr
author | johnc |
---|---|
date | Wed, 12 Oct 2011 10:25:51 -0700 |
parents | f08d439fab8c |
children | a6eef545f1a2 |
rev | line source |
---|---|
0 | 1 /* |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
2019
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:
1149
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1149
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:
1149
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "classfile/systemDictionary.hpp" | |
27 #include "classfile/vmSymbols.hpp" | |
28 #include "interpreter/bytecodeStream.hpp" | |
29 #include "interpreter/interpreter.hpp" | |
30 #include "jvmtifiles/jvmtiEnv.hpp" | |
31 #include "memory/resourceArea.hpp" | |
32 #include "memory/universe.inline.hpp" | |
33 #include "oops/cpCacheOop.hpp" | |
34 #include "oops/instanceKlass.hpp" | |
35 #include "prims/jniCheck.hpp" | |
36 #include "prims/jvm_misc.hpp" | |
37 #include "prims/jvmtiAgentThread.hpp" | |
38 #include "prims/jvmtiClassFileReconstituter.hpp" | |
39 #include "prims/jvmtiCodeBlobEvents.hpp" | |
40 #include "prims/jvmtiExtensions.hpp" | |
41 #include "prims/jvmtiGetLoadedClasses.hpp" | |
42 #include "prims/jvmtiImpl.hpp" | |
43 #include "prims/jvmtiManageCapabilities.hpp" | |
44 #include "prims/jvmtiRawMonitor.hpp" | |
45 #include "prims/jvmtiRedefineClasses.hpp" | |
46 #include "prims/jvmtiTagMap.hpp" | |
47 #include "prims/jvmtiThreadState.inline.hpp" | |
48 #include "prims/jvmtiUtil.hpp" | |
49 #include "runtime/arguments.hpp" | |
50 #include "runtime/deoptimization.hpp" | |
51 #include "runtime/interfaceSupport.hpp" | |
52 #include "runtime/javaCalls.hpp" | |
53 #include "runtime/jfieldIDWorkaround.hpp" | |
54 #include "runtime/osThread.hpp" | |
55 #include "runtime/reflectionUtils.hpp" | |
56 #include "runtime/signature.hpp" | |
57 #include "runtime/vframe.hpp" | |
58 #include "runtime/vmThread.hpp" | |
59 #include "services/threadService.hpp" | |
60 #include "utilities/exceptions.hpp" | |
61 #include "utilities/preserveException.hpp" | |
62 #ifdef TARGET_OS_FAMILY_linux | |
63 # include "thread_linux.inline.hpp" | |
64 #endif | |
65 #ifdef TARGET_OS_FAMILY_solaris | |
66 # include "thread_solaris.inline.hpp" | |
67 #endif | |
68 #ifdef TARGET_OS_FAMILY_windows | |
69 # include "thread_windows.inline.hpp" | |
70 #endif | |
3960 | 71 #ifdef TARGET_OS_FAMILY_bsd |
72 # include "thread_bsd.inline.hpp" | |
73 #endif | |
1972 | 74 |
0 | 75 |
76 | |
77 #define FIXLATER 0 // REMOVE this when completed. | |
78 | |
79 // FIXLATER: hook into JvmtiTrace | |
80 #define TraceJVMTICalls false | |
81 | |
1121 | 82 JvmtiEnv::JvmtiEnv(jint version) : JvmtiEnvBase(version) { |
0 | 83 } |
84 | |
85 JvmtiEnv::~JvmtiEnv() { | |
86 } | |
87 | |
88 JvmtiEnv* | |
1121 | 89 JvmtiEnv::create_a_jvmti(jint version) { |
90 return new JvmtiEnv(version); | |
0 | 91 } |
92 | |
93 // VM operation class to copy jni function table at safepoint. | |
94 // More than one java threads or jvmti agents may be reading/ | |
95 // modifying jni function tables. To reduce the risk of bad | |
96 // interaction b/w these threads it is copied at safepoint. | |
97 class VM_JNIFunctionTableCopier : public VM_Operation { | |
98 private: | |
99 const struct JNINativeInterface_ *_function_table; | |
100 public: | |
101 VM_JNIFunctionTableCopier(const struct JNINativeInterface_ *func_tbl) { | |
102 _function_table = func_tbl; | |
103 }; | |
104 | |
105 VMOp_Type type() const { return VMOp_JNIFunctionTableCopier; } | |
106 void doit() { | |
107 copy_jni_function_table(_function_table); | |
108 }; | |
109 }; | |
110 | |
111 // | |
112 // Do not change the "prefix" marker below, everything above it is copied | |
113 // unchanged into the filled stub, everything below is controlled by the | |
114 // stub filler (only method bodies are carried forward, and then only for | |
115 // functionality still in the spec). | |
116 // | |
117 // end file prefix | |
118 | |
119 // | |
120 // Memory Management functions | |
121 // | |
122 | |
123 // mem_ptr - pre-checked for NULL | |
124 jvmtiError | |
125 JvmtiEnv::Allocate(jlong size, unsigned char** mem_ptr) { | |
126 return allocate(size, mem_ptr); | |
127 } /* end Allocate */ | |
128 | |
129 | |
130 // mem - NULL is a valid value, must be checked | |
131 jvmtiError | |
132 JvmtiEnv::Deallocate(unsigned char* mem) { | |
133 return deallocate(mem); | |
134 } /* end Deallocate */ | |
135 | |
136 // Threads_lock NOT held, java_thread not protected by lock | |
137 // java_thread - pre-checked | |
138 // data - NULL is a valid value, must be checked | |
139 jvmtiError | |
140 JvmtiEnv::SetThreadLocalStorage(JavaThread* java_thread, const void* data) { | |
141 JvmtiThreadState* state = java_thread->jvmti_thread_state(); | |
142 if (state == NULL) { | |
143 if (data == NULL) { | |
144 // leaving state unset same as data set to NULL | |
145 return JVMTI_ERROR_NONE; | |
146 } | |
147 // otherwise, create the state | |
148 state = JvmtiThreadState::state_for(java_thread); | |
609
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
0
diff
changeset
|
149 if (state == NULL) { |
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
0
diff
changeset
|
150 return JVMTI_ERROR_THREAD_NOT_ALIVE; |
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
0
diff
changeset
|
151 } |
0 | 152 } |
153 state->env_thread_state(this)->set_agent_thread_local_storage_data((void*)data); | |
154 return JVMTI_ERROR_NONE; | |
155 } /* end SetThreadLocalStorage */ | |
156 | |
157 | |
158 // Threads_lock NOT held | |
159 // thread - NOT pre-checked | |
160 // data_ptr - pre-checked for NULL | |
161 jvmtiError | |
162 JvmtiEnv::GetThreadLocalStorage(jthread thread, void** data_ptr) { | |
163 JavaThread* current_thread = JavaThread::current(); | |
164 if (thread == NULL) { | |
165 JvmtiThreadState* state = current_thread->jvmti_thread_state(); | |
166 *data_ptr = (state == NULL) ? NULL : | |
167 state->env_thread_state(this)->get_agent_thread_local_storage_data(); | |
168 } else { | |
169 | |
170 // jvmti_GetThreadLocalStorage is "in native" and doesn't transition | |
171 // the thread to _thread_in_vm. However, when the TLS for a thread | |
172 // other than the current thread is required we need to transition | |
173 // from native so as to resolve the jthread. | |
174 | |
175 ThreadInVMfromNative __tiv(current_thread); | |
176 __ENTRY(jvmtiError, JvmtiEnv::GetThreadLocalStorage , current_thread) | |
177 debug_only(VMNativeEntryWrapper __vew;) | |
178 | |
179 oop thread_oop = JNIHandles::resolve_external_guard(thread); | |
180 if (thread_oop == NULL) { | |
181 return JVMTI_ERROR_INVALID_THREAD; | |
182 } | |
1142 | 183 if (!thread_oop->is_a(SystemDictionary::Thread_klass())) { |
0 | 184 return JVMTI_ERROR_INVALID_THREAD; |
185 } | |
186 JavaThread* java_thread = java_lang_Thread::thread(thread_oop); | |
187 if (java_thread == NULL) { | |
188 return JVMTI_ERROR_THREAD_NOT_ALIVE; | |
189 } | |
190 JvmtiThreadState* state = java_thread->jvmti_thread_state(); | |
191 *data_ptr = (state == NULL) ? NULL : | |
192 state->env_thread_state(this)->get_agent_thread_local_storage_data(); | |
193 } | |
194 return JVMTI_ERROR_NONE; | |
195 } /* end GetThreadLocalStorage */ | |
196 | |
197 // | |
198 // Class functions | |
199 // | |
200 | |
201 // class_count_ptr - pre-checked for NULL | |
202 // classes_ptr - pre-checked for NULL | |
203 jvmtiError | |
204 JvmtiEnv::GetLoadedClasses(jint* class_count_ptr, jclass** classes_ptr) { | |
205 return JvmtiGetLoadedClasses::getLoadedClasses(this, class_count_ptr, classes_ptr); | |
206 } /* end GetLoadedClasses */ | |
207 | |
208 | |
209 // initiating_loader - NULL is a valid value, must be checked | |
210 // class_count_ptr - pre-checked for NULL | |
211 // classes_ptr - pre-checked for NULL | |
212 jvmtiError | |
213 JvmtiEnv::GetClassLoaderClasses(jobject initiating_loader, jint* class_count_ptr, jclass** classes_ptr) { | |
214 return JvmtiGetLoadedClasses::getClassLoaderClasses(this, initiating_loader, | |
215 class_count_ptr, classes_ptr); | |
216 } /* end GetClassLoaderClasses */ | |
217 | |
218 // k_mirror - may be primitive, this must be checked | |
219 // is_modifiable_class_ptr - pre-checked for NULL | |
220 jvmtiError | |
221 JvmtiEnv::IsModifiableClass(oop k_mirror, jboolean* is_modifiable_class_ptr) { | |
222 *is_modifiable_class_ptr = VM_RedefineClasses::is_modifiable_class(k_mirror)? | |
223 JNI_TRUE : JNI_FALSE; | |
224 return JVMTI_ERROR_NONE; | |
225 } /* end IsModifiableClass */ | |
226 | |
227 // class_count - pre-checked to be greater than or equal to 0 | |
228 // classes - pre-checked for NULL | |
229 jvmtiError | |
230 JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) { | |
231 //TODO: add locking | |
232 | |
233 int index; | |
234 JavaThread* current_thread = JavaThread::current(); | |
235 ResourceMark rm(current_thread); | |
236 | |
237 jvmtiClassDefinition* class_definitions = | |
238 NEW_RESOURCE_ARRAY(jvmtiClassDefinition, class_count); | |
239 NULL_CHECK(class_definitions, JVMTI_ERROR_OUT_OF_MEMORY); | |
240 | |
241 for (index = 0; index < class_count; index++) { | |
242 HandleMark hm(current_thread); | |
243 | |
244 jclass jcls = classes[index]; | |
245 oop k_mirror = JNIHandles::resolve_external_guard(jcls); | |
246 if (k_mirror == NULL) { | |
247 return JVMTI_ERROR_INVALID_CLASS; | |
248 } | |
1142 | 249 if (!k_mirror->is_a(SystemDictionary::Class_klass())) { |
0 | 250 return JVMTI_ERROR_INVALID_CLASS; |
251 } | |
252 | |
253 if (java_lang_Class::is_primitive(k_mirror)) { | |
254 return JVMTI_ERROR_UNMODIFIABLE_CLASS; | |
255 } | |
256 | |
257 klassOop k_oop = java_lang_Class::as_klassOop(k_mirror); | |
258 KlassHandle klass(current_thread, k_oop); | |
259 | |
260 jint status = klass->jvmti_class_status(); | |
261 if (status & (JVMTI_CLASS_STATUS_ERROR)) { | |
262 return JVMTI_ERROR_INVALID_CLASS; | |
263 } | |
264 if (status & (JVMTI_CLASS_STATUS_ARRAY)) { | |
265 return JVMTI_ERROR_UNMODIFIABLE_CLASS; | |
266 } | |
267 | |
268 instanceKlassHandle ikh(current_thread, k_oop); | |
269 if (ikh->get_cached_class_file_bytes() == NULL) { | |
270 // not cached, we need to reconstitute the class file from VM representation | |
271 constantPoolHandle constants(current_thread, ikh->constants()); | |
272 ObjectLocker ol(constants, current_thread); // lock constant pool while we query it | |
273 | |
274 JvmtiClassFileReconstituter reconstituter(ikh); | |
275 if (reconstituter.get_error() != JVMTI_ERROR_NONE) { | |
276 return reconstituter.get_error(); | |
277 } | |
278 | |
279 class_definitions[index].class_byte_count = (jint)reconstituter.class_file_size(); | |
280 class_definitions[index].class_bytes = (unsigned char*) | |
281 reconstituter.class_file_bytes(); | |
282 } else { | |
283 // it is cached, get it from the cache | |
284 class_definitions[index].class_byte_count = ikh->get_cached_class_file_len(); | |
285 class_definitions[index].class_bytes = ikh->get_cached_class_file_bytes(); | |
286 } | |
287 class_definitions[index].klass = jcls; | |
288 } | |
289 VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform); | |
290 VMThread::execute(&op); | |
291 return (op.check_error()); | |
292 } /* end RetransformClasses */ | |
293 | |
294 | |
295 // class_count - pre-checked to be greater than or equal to 0 | |
296 // class_definitions - pre-checked for NULL | |
297 jvmtiError | |
298 JvmtiEnv::RedefineClasses(jint class_count, const jvmtiClassDefinition* class_definitions) { | |
299 //TODO: add locking | |
300 VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); | |
301 VMThread::execute(&op); | |
302 return (op.check_error()); | |
303 } /* end RedefineClasses */ | |
304 | |
305 | |
306 // | |
307 // Object functions | |
308 // | |
309 | |
310 // size_ptr - pre-checked for NULL | |
311 jvmtiError | |
312 JvmtiEnv::GetObjectSize(jobject object, jlong* size_ptr) { | |
313 oop mirror = JNIHandles::resolve_external_guard(object); | |
314 NULL_CHECK(mirror, JVMTI_ERROR_INVALID_OBJECT); | |
315 | |
1142 | 316 if (mirror->klass() == SystemDictionary::Class_klass()) { |
0 | 317 if (!java_lang_Class::is_primitive(mirror)) { |
318 mirror = java_lang_Class::as_klassOop(mirror); | |
319 assert(mirror != NULL, "class for non-primitive mirror must exist"); | |
320 } | |
321 } | |
322 | |
323 *size_ptr = mirror->size() * wordSize; | |
324 return JVMTI_ERROR_NONE; | |
325 } /* end GetObjectSize */ | |
326 | |
327 // | |
328 // Method functions | |
329 // | |
330 | |
331 // prefix - NULL is a valid value, must be checked | |
332 jvmtiError | |
333 JvmtiEnv::SetNativeMethodPrefix(const char* prefix) { | |
334 return prefix == NULL? | |
335 SetNativeMethodPrefixes(0, NULL) : | |
336 SetNativeMethodPrefixes(1, (char**)&prefix); | |
337 } /* end SetNativeMethodPrefix */ | |
338 | |
339 | |
340 // prefix_count - pre-checked to be greater than or equal to 0 | |
341 // prefixes - pre-checked for NULL | |
342 jvmtiError | |
343 JvmtiEnv::SetNativeMethodPrefixes(jint prefix_count, char** prefixes) { | |
344 // Have to grab JVMTI thread state lock to be sure that some thread | |
345 // isn't accessing the prefixes at the same time we are setting them. | |
346 // No locks during VM bring-up. | |
347 if (Threads::number_of_threads() == 0) { | |
348 return set_native_method_prefixes(prefix_count, prefixes); | |
349 } else { | |
350 MutexLocker mu(JvmtiThreadState_lock); | |
351 return set_native_method_prefixes(prefix_count, prefixes); | |
352 } | |
353 } /* end SetNativeMethodPrefixes */ | |
354 | |
355 // | |
356 // Event Management functions | |
357 // | |
358 | |
359 // callbacks - NULL is a valid value, must be checked | |
360 // size_of_callbacks - pre-checked to be greater than or equal to 0 | |
361 jvmtiError | |
362 JvmtiEnv::SetEventCallbacks(const jvmtiEventCallbacks* callbacks, jint size_of_callbacks) { | |
363 JvmtiEventController::set_event_callbacks(this, callbacks, size_of_callbacks); | |
364 return JVMTI_ERROR_NONE; | |
365 } /* end SetEventCallbacks */ | |
366 | |
367 | |
368 // event_thread - NULL is a valid value, must be checked | |
369 jvmtiError | |
370 JvmtiEnv::SetEventNotificationMode(jvmtiEventMode mode, jvmtiEvent event_type, jthread event_thread, ...) { | |
371 JavaThread* java_thread = NULL; | |
372 if (event_thread != NULL) { | |
373 oop thread_oop = JNIHandles::resolve_external_guard(event_thread); | |
374 if (thread_oop == NULL) { | |
375 return JVMTI_ERROR_INVALID_THREAD; | |
376 } | |
1142 | 377 if (!thread_oop->is_a(SystemDictionary::Thread_klass())) { |
0 | 378 return JVMTI_ERROR_INVALID_THREAD; |
379 } | |
380 java_thread = java_lang_Thread::thread(thread_oop); | |
381 if (java_thread == NULL) { | |
382 return JVMTI_ERROR_THREAD_NOT_ALIVE; | |
383 } | |
384 } | |
385 | |
386 // event_type must be valid | |
387 if (!JvmtiEventController::is_valid_event_type(event_type)) { | |
388 return JVMTI_ERROR_INVALID_EVENT_TYPE; | |
389 } | |
390 | |
391 // global events cannot be controlled at thread level. | |
392 if (java_thread != NULL && JvmtiEventController::is_global_event(event_type)) { | |
393 return JVMTI_ERROR_ILLEGAL_ARGUMENT; | |
394 } | |
395 | |
396 bool enabled = (mode == JVMTI_ENABLE); | |
397 | |
398 // assure that needed capabilities are present | |
399 if (enabled && !JvmtiUtil::has_event_capability(event_type, get_capabilities())) { | |
400 return JVMTI_ERROR_MUST_POSSESS_CAPABILITY; | |
401 } | |
402 | |
403 if (event_type == JVMTI_EVENT_CLASS_FILE_LOAD_HOOK && enabled) { | |
404 record_class_file_load_hook_enabled(); | |
405 } | |
406 JvmtiEventController::set_user_enabled(this, java_thread, event_type, enabled); | |
407 | |
408 return JVMTI_ERROR_NONE; | |
409 } /* end SetEventNotificationMode */ | |
410 | |
411 // | |
412 // Capability functions | |
413 // | |
414 | |
415 // capabilities_ptr - pre-checked for NULL | |
416 jvmtiError | |
417 JvmtiEnv::GetPotentialCapabilities(jvmtiCapabilities* capabilities_ptr) { | |
418 JvmtiManageCapabilities::get_potential_capabilities(get_capabilities(), | |
419 get_prohibited_capabilities(), | |
420 capabilities_ptr); | |
421 return JVMTI_ERROR_NONE; | |
422 } /* end GetPotentialCapabilities */ | |
423 | |
424 | |
425 // capabilities_ptr - pre-checked for NULL | |
426 jvmtiError | |
427 JvmtiEnv::AddCapabilities(const jvmtiCapabilities* capabilities_ptr) { | |
428 return JvmtiManageCapabilities::add_capabilities(get_capabilities(), | |
429 get_prohibited_capabilities(), | |
430 capabilities_ptr, | |
431 get_capabilities()); | |
432 } /* end AddCapabilities */ | |
433 | |
434 | |
435 // capabilities_ptr - pre-checked for NULL | |
436 jvmtiError | |
437 JvmtiEnv::RelinquishCapabilities(const jvmtiCapabilities* capabilities_ptr) { | |
438 JvmtiManageCapabilities::relinquish_capabilities(get_capabilities(), capabilities_ptr, get_capabilities()); | |
439 return JVMTI_ERROR_NONE; | |
440 } /* end RelinquishCapabilities */ | |
441 | |
442 | |
443 // capabilities_ptr - pre-checked for NULL | |
444 jvmtiError | |
445 JvmtiEnv::GetCapabilities(jvmtiCapabilities* capabilities_ptr) { | |
446 JvmtiManageCapabilities::copy_capabilities(get_capabilities(), capabilities_ptr); | |
447 return JVMTI_ERROR_NONE; | |
448 } /* end GetCapabilities */ | |
449 | |
450 // | |
451 // Class Loader Search functions | |
452 // | |
453 | |
454 // segment - pre-checked for NULL | |
455 jvmtiError | |
456 JvmtiEnv::AddToBootstrapClassLoaderSearch(const char* segment) { | |
457 jvmtiPhase phase = get_phase(); | |
458 if (phase == JVMTI_PHASE_ONLOAD) { | |
459 Arguments::append_sysclasspath(segment); | |
460 return JVMTI_ERROR_NONE; | |
1121 | 461 } else if (use_version_1_0_semantics()) { |
462 // This JvmtiEnv requested version 1.0 semantics and this function | |
463 // is only allowed in the ONLOAD phase in version 1.0 so we need to | |
464 // return an error here. | |
465 return JVMTI_ERROR_WRONG_PHASE; | |
1120
9127aa69352e
6648438: 4/4 src/share/vm/prims/jvmtiEnv.cpp:457 assert(phase == JVMTI_PHASE_LIVE,"sanity check")
dcubed
parents:
0
diff
changeset
|
466 } else if (phase == JVMTI_PHASE_LIVE) { |
9127aa69352e
6648438: 4/4 src/share/vm/prims/jvmtiEnv.cpp:457 assert(phase == JVMTI_PHASE_LIVE,"sanity check")
dcubed
parents:
0
diff
changeset
|
467 // The phase is checked by the wrapper that called this function, |
9127aa69352e
6648438: 4/4 src/share/vm/prims/jvmtiEnv.cpp:457 assert(phase == JVMTI_PHASE_LIVE,"sanity check")
dcubed
parents:
0
diff
changeset
|
468 // but this thread could be racing with the thread that is |
9127aa69352e
6648438: 4/4 src/share/vm/prims/jvmtiEnv.cpp:457 assert(phase == JVMTI_PHASE_LIVE,"sanity check")
dcubed
parents:
0
diff
changeset
|
469 // terminating the VM so we check one more time. |
0 | 470 |
471 // create the zip entry | |
472 ClassPathZipEntry* zip_entry = ClassLoader::create_class_path_zip_entry(segment); | |
473 if (zip_entry == NULL) { | |
474 return JVMTI_ERROR_ILLEGAL_ARGUMENT; | |
475 } | |
476 | |
477 // lock the loader | |
478 Thread* thread = Thread::current(); | |
479 HandleMark hm; | |
480 Handle loader_lock = Handle(thread, SystemDictionary::system_loader_lock()); | |
481 | |
482 ObjectLocker ol(loader_lock, thread); | |
483 | |
484 // add the jar file to the bootclasspath | |
485 if (TraceClassLoading) { | |
486 tty->print_cr("[Opened %s]", zip_entry->name()); | |
487 } | |
488 ClassLoader::add_to_list(zip_entry); | |
489 return JVMTI_ERROR_NONE; | |
1120
9127aa69352e
6648438: 4/4 src/share/vm/prims/jvmtiEnv.cpp:457 assert(phase == JVMTI_PHASE_LIVE,"sanity check")
dcubed
parents:
0
diff
changeset
|
490 } else { |
9127aa69352e
6648438: 4/4 src/share/vm/prims/jvmtiEnv.cpp:457 assert(phase == JVMTI_PHASE_LIVE,"sanity check")
dcubed
parents:
0
diff
changeset
|
491 return JVMTI_ERROR_WRONG_PHASE; |
0 | 492 } |
493 | |
494 } /* end AddToBootstrapClassLoaderSearch */ | |
495 | |
496 | |
497 // segment - pre-checked for NULL | |
498 jvmtiError | |
499 JvmtiEnv::AddToSystemClassLoaderSearch(const char* segment) { | |
500 jvmtiPhase phase = get_phase(); | |
501 | |
502 if (phase == JVMTI_PHASE_ONLOAD) { | |
503 for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) { | |
504 if (strcmp("java.class.path", p->key()) == 0) { | |
505 p->append_value(segment); | |
506 break; | |
507 } | |
508 } | |
509 return JVMTI_ERROR_NONE; | |
1120
9127aa69352e
6648438: 4/4 src/share/vm/prims/jvmtiEnv.cpp:457 assert(phase == JVMTI_PHASE_LIVE,"sanity check")
dcubed
parents:
0
diff
changeset
|
510 } else if (phase == JVMTI_PHASE_LIVE) { |
9127aa69352e
6648438: 4/4 src/share/vm/prims/jvmtiEnv.cpp:457 assert(phase == JVMTI_PHASE_LIVE,"sanity check")
dcubed
parents:
0
diff
changeset
|
511 // The phase is checked by the wrapper that called this function, |
9127aa69352e
6648438: 4/4 src/share/vm/prims/jvmtiEnv.cpp:457 assert(phase == JVMTI_PHASE_LIVE,"sanity check")
dcubed
parents:
0
diff
changeset
|
512 // but this thread could be racing with the thread that is |
9127aa69352e
6648438: 4/4 src/share/vm/prims/jvmtiEnv.cpp:457 assert(phase == JVMTI_PHASE_LIVE,"sanity check")
dcubed
parents:
0
diff
changeset
|
513 // terminating the VM so we check one more time. |
0 | 514 HandleMark hm; |
515 | |
516 // create the zip entry (which will open the zip file and hence | |
517 // check that the segment is indeed a zip file). | |
518 ClassPathZipEntry* zip_entry = ClassLoader::create_class_path_zip_entry(segment); | |
519 if (zip_entry == NULL) { | |
520 return JVMTI_ERROR_ILLEGAL_ARGUMENT; | |
521 } | |
522 delete zip_entry; // no longer needed | |
523 | |
524 // lock the loader | |
525 Thread* THREAD = Thread::current(); | |
526 Handle loader = Handle(THREAD, SystemDictionary::java_system_loader()); | |
527 | |
528 ObjectLocker ol(loader, THREAD); | |
529 | |
530 // need the path as java.lang.String | |
3246
fcc932c8238c
7007254: NullPointerException occurs with jvisualvm placed under a dir. including Japanese chars
thurka
parents:
2177
diff
changeset
|
531 Handle path = java_lang_String::create_from_platform_dependent_str(segment, THREAD); |
0 | 532 if (HAS_PENDING_EXCEPTION) { |
533 CLEAR_PENDING_EXCEPTION; | |
534 return JVMTI_ERROR_INTERNAL; | |
535 } | |
536 | |
537 instanceKlassHandle loader_ik(THREAD, loader->klass()); | |
538 | |
539 // Invoke the appendToClassPathForInstrumentation method - if the method | |
540 // is not found it means the loader doesn't support adding to the class path | |
541 // in the live phase. | |
542 { | |
543 JavaValue res(T_VOID); | |
544 JavaCalls::call_special(&res, | |
545 loader, | |
546 loader_ik, | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2100
diff
changeset
|
547 vmSymbols::appendToClassPathForInstrumentation_name(), |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2100
diff
changeset
|
548 vmSymbols::appendToClassPathForInstrumentation_signature(), |
0 | 549 path, |
550 THREAD); | |
551 if (HAS_PENDING_EXCEPTION) { | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2100
diff
changeset
|
552 Symbol* ex_name = PENDING_EXCEPTION->klass()->klass_part()->name(); |
0 | 553 CLEAR_PENDING_EXCEPTION; |
554 | |
555 if (ex_name == vmSymbols::java_lang_NoSuchMethodError()) { | |
556 return JVMTI_ERROR_CLASS_LOADER_UNSUPPORTED; | |
557 } else { | |
558 return JVMTI_ERROR_INTERNAL; | |
559 } | |
560 } | |
561 } | |
562 | |
563 return JVMTI_ERROR_NONE; | |
1120
9127aa69352e
6648438: 4/4 src/share/vm/prims/jvmtiEnv.cpp:457 assert(phase == JVMTI_PHASE_LIVE,"sanity check")
dcubed
parents:
0
diff
changeset
|
564 } else { |
9127aa69352e
6648438: 4/4 src/share/vm/prims/jvmtiEnv.cpp:457 assert(phase == JVMTI_PHASE_LIVE,"sanity check")
dcubed
parents:
0
diff
changeset
|
565 return JVMTI_ERROR_WRONG_PHASE; |
0 | 566 } |
567 } /* end AddToSystemClassLoaderSearch */ | |
568 | |
569 // | |
570 // General functions | |
571 // | |
572 | |
573 // phase_ptr - pre-checked for NULL | |
574 jvmtiError | |
575 JvmtiEnv::GetPhase(jvmtiPhase* phase_ptr) { | |
576 *phase_ptr = get_phase(); | |
577 return JVMTI_ERROR_NONE; | |
578 } /* end GetPhase */ | |
579 | |
580 | |
581 jvmtiError | |
582 JvmtiEnv::DisposeEnvironment() { | |
583 dispose(); | |
584 return JVMTI_ERROR_NONE; | |
585 } /* end DisposeEnvironment */ | |
586 | |
587 | |
588 // data - NULL is a valid value, must be checked | |
589 jvmtiError | |
590 JvmtiEnv::SetEnvironmentLocalStorage(const void* data) { | |
591 set_env_local_storage(data); | |
592 return JVMTI_ERROR_NONE; | |
593 } /* end SetEnvironmentLocalStorage */ | |
594 | |
595 | |
596 // data_ptr - pre-checked for NULL | |
597 jvmtiError | |
598 JvmtiEnv::GetEnvironmentLocalStorage(void** data_ptr) { | |
599 *data_ptr = (void*)get_env_local_storage(); | |
600 return JVMTI_ERROR_NONE; | |
601 } /* end GetEnvironmentLocalStorage */ | |
602 | |
603 // version_ptr - pre-checked for NULL | |
604 jvmtiError | |
605 JvmtiEnv::GetVersionNumber(jint* version_ptr) { | |
606 *version_ptr = JVMTI_VERSION; | |
607 return JVMTI_ERROR_NONE; | |
608 } /* end GetVersionNumber */ | |
609 | |
610 | |
611 // name_ptr - pre-checked for NULL | |
612 jvmtiError | |
613 JvmtiEnv::GetErrorName(jvmtiError error, char** name_ptr) { | |
614 if (error < JVMTI_ERROR_NONE || error > JVMTI_ERROR_MAX) { | |
615 return JVMTI_ERROR_ILLEGAL_ARGUMENT; | |
616 } | |
617 const char *name = JvmtiUtil::error_name(error); | |
618 if (name == NULL) { | |
619 return JVMTI_ERROR_ILLEGAL_ARGUMENT; | |
620 } | |
621 size_t len = strlen(name) + 1; | |
622 jvmtiError err = allocate(len, (unsigned char**)name_ptr); | |
623 if (err == JVMTI_ERROR_NONE) { | |
624 memcpy(*name_ptr, name, len); | |
625 } | |
626 return err; | |
627 } /* end GetErrorName */ | |
628 | |
629 | |
630 jvmtiError | |
631 JvmtiEnv::SetVerboseFlag(jvmtiVerboseFlag flag, jboolean value) { | |
632 switch (flag) { | |
633 case JVMTI_VERBOSE_OTHER: | |
634 // ignore | |
635 break; | |
636 case JVMTI_VERBOSE_CLASS: | |
637 TraceClassLoading = value != 0; | |
638 TraceClassUnloading = value != 0; | |
639 break; | |
640 case JVMTI_VERBOSE_GC: | |
641 PrintGC = value != 0; | |
642 break; | |
643 case JVMTI_VERBOSE_JNI: | |
644 PrintJNIResolving = value != 0; | |
645 break; | |
646 default: | |
647 return JVMTI_ERROR_ILLEGAL_ARGUMENT; | |
648 }; | |
649 return JVMTI_ERROR_NONE; | |
650 } /* end SetVerboseFlag */ | |
651 | |
652 | |
653 // format_ptr - pre-checked for NULL | |
654 jvmtiError | |
655 JvmtiEnv::GetJLocationFormat(jvmtiJlocationFormat* format_ptr) { | |
656 *format_ptr = JVMTI_JLOCATION_JVMBCI; | |
657 return JVMTI_ERROR_NONE; | |
658 } /* end GetJLocationFormat */ | |
659 | |
660 #ifndef JVMTI_KERNEL | |
661 | |
662 // | |
663 // Thread functions | |
664 // | |
665 | |
666 // Threads_lock NOT held | |
667 // thread - NOT pre-checked | |
668 // thread_state_ptr - pre-checked for NULL | |
669 jvmtiError | |
670 JvmtiEnv::GetThreadState(jthread thread, jint* thread_state_ptr) { | |
671 jint state; | |
672 oop thread_oop; | |
673 JavaThread* thr; | |
674 | |
675 if (thread == NULL) { | |
676 thread_oop = JavaThread::current()->threadObj(); | |
677 } else { | |
678 thread_oop = JNIHandles::resolve_external_guard(thread); | |
679 } | |
680 | |
1142 | 681 if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) { |
0 | 682 return JVMTI_ERROR_INVALID_THREAD; |
683 } | |
684 | |
685 // get most state bits | |
686 state = (jint)java_lang_Thread::get_thread_status(thread_oop); | |
687 | |
688 // add more state bits | |
689 thr = java_lang_Thread::thread(thread_oop); | |
690 if (thr != NULL) { | |
691 JavaThreadState jts = thr->thread_state(); | |
692 | |
693 if (thr->is_being_ext_suspended()) { | |
694 state |= JVMTI_THREAD_STATE_SUSPENDED; | |
695 } | |
696 if (jts == _thread_in_native) { | |
697 state |= JVMTI_THREAD_STATE_IN_NATIVE; | |
698 } | |
699 OSThread* osThread = thr->osthread(); | |
700 if (osThread != NULL && osThread->interrupted()) { | |
701 state |= JVMTI_THREAD_STATE_INTERRUPTED; | |
702 } | |
703 } | |
704 | |
705 *thread_state_ptr = state; | |
706 return JVMTI_ERROR_NONE; | |
707 } /* end GetThreadState */ | |
708 | |
709 | |
710 // thread_ptr - pre-checked for NULL | |
711 jvmtiError | |
712 JvmtiEnv::GetCurrentThread(jthread* thread_ptr) { | |
713 JavaThread* current_thread = JavaThread::current(); | |
714 *thread_ptr = (jthread)JNIHandles::make_local(current_thread, current_thread->threadObj()); | |
715 return JVMTI_ERROR_NONE; | |
716 } /* end GetCurrentThread */ | |
717 | |
718 | |
719 // threads_count_ptr - pre-checked for NULL | |
720 // threads_ptr - pre-checked for NULL | |
721 jvmtiError | |
722 JvmtiEnv::GetAllThreads(jint* threads_count_ptr, jthread** threads_ptr) { | |
723 int nthreads = 0; | |
724 Handle *thread_objs = NULL; | |
725 ResourceMark rm; | |
726 HandleMark hm; | |
727 | |
728 // enumerate threads (including agent threads) | |
729 ThreadsListEnumerator tle(Thread::current(), true); | |
730 nthreads = tle.num_threads(); | |
731 *threads_count_ptr = nthreads; | |
732 | |
733 if (nthreads == 0) { | |
734 *threads_ptr = NULL; | |
735 return JVMTI_ERROR_NONE; | |
736 } | |
737 | |
738 thread_objs = NEW_RESOURCE_ARRAY(Handle, nthreads); | |
739 NULL_CHECK(thread_objs, JVMTI_ERROR_OUT_OF_MEMORY); | |
740 | |
741 for (int i=0; i < nthreads; i++) { | |
742 thread_objs[i] = Handle(tle.get_threadObj(i)); | |
743 } | |
744 | |
745 // have to make global handles outside of Threads_lock | |
746 jthread *jthreads = new_jthreadArray(nthreads, thread_objs); | |
747 NULL_CHECK(jthreads, JVMTI_ERROR_OUT_OF_MEMORY); | |
748 | |
749 *threads_ptr = jthreads; | |
750 return JVMTI_ERROR_NONE; | |
751 } /* end GetAllThreads */ | |
752 | |
753 | |
754 // Threads_lock NOT held, java_thread not protected by lock | |
755 // java_thread - pre-checked | |
756 jvmtiError | |
757 JvmtiEnv::SuspendThread(JavaThread* java_thread) { | |
758 // don't allow hidden thread suspend request. | |
759 if (java_thread->is_hidden_from_external_view()) { | |
760 return (JVMTI_ERROR_NONE); | |
761 } | |
762 | |
763 { | |
764 MutexLockerEx ml(java_thread->SR_lock(), Mutex::_no_safepoint_check_flag); | |
765 if (java_thread->is_external_suspend()) { | |
766 // don't allow nested external suspend requests. | |
767 return (JVMTI_ERROR_THREAD_SUSPENDED); | |
768 } | |
769 if (java_thread->is_exiting()) { // thread is in the process of exiting | |
770 return (JVMTI_ERROR_THREAD_NOT_ALIVE); | |
771 } | |
772 java_thread->set_external_suspend(); | |
773 } | |
774 | |
775 if (!JvmtiSuspendControl::suspend(java_thread)) { | |
776 // the thread was in the process of exiting | |
777 return (JVMTI_ERROR_THREAD_NOT_ALIVE); | |
778 } | |
779 return JVMTI_ERROR_NONE; | |
780 } /* end SuspendThread */ | |
781 | |
782 | |
783 // request_count - pre-checked to be greater than or equal to 0 | |
784 // request_list - pre-checked for NULL | |
785 // results - pre-checked for NULL | |
786 jvmtiError | |
787 JvmtiEnv::SuspendThreadList(jint request_count, const jthread* request_list, jvmtiError* results) { | |
788 int needSafepoint = 0; // > 0 if we need a safepoint | |
789 for (int i = 0; i < request_count; i++) { | |
790 JavaThread *java_thread = get_JavaThread(request_list[i]); | |
791 if (java_thread == NULL) { | |
792 results[i] = JVMTI_ERROR_INVALID_THREAD; | |
793 continue; | |
794 } | |
795 // the thread has not yet run or has exited (not on threads list) | |
796 if (java_thread->threadObj() == NULL) { | |
797 results[i] = JVMTI_ERROR_THREAD_NOT_ALIVE; | |
798 continue; | |
799 } | |
800 if (java_lang_Thread::thread(java_thread->threadObj()) == NULL) { | |
801 results[i] = JVMTI_ERROR_THREAD_NOT_ALIVE; | |
802 continue; | |
803 } | |
804 // don't allow hidden thread suspend request. | |
805 if (java_thread->is_hidden_from_external_view()) { | |
806 results[i] = JVMTI_ERROR_NONE; // indicate successful suspend | |
807 continue; | |
808 } | |
809 | |
810 { | |
811 MutexLockerEx ml(java_thread->SR_lock(), Mutex::_no_safepoint_check_flag); | |
812 if (java_thread->is_external_suspend()) { | |
813 // don't allow nested external suspend requests. | |
814 results[i] = JVMTI_ERROR_THREAD_SUSPENDED; | |
815 continue; | |
816 } | |
817 if (java_thread->is_exiting()) { // thread is in the process of exiting | |
818 results[i] = JVMTI_ERROR_THREAD_NOT_ALIVE; | |
819 continue; | |
820 } | |
821 java_thread->set_external_suspend(); | |
822 } | |
823 if (java_thread->thread_state() == _thread_in_native) { | |
824 // We need to try and suspend native threads here. Threads in | |
825 // other states will self-suspend on their next transition. | |
826 if (!JvmtiSuspendControl::suspend(java_thread)) { | |
827 // The thread was in the process of exiting. Force another | |
828 // safepoint to make sure that this thread transitions. | |
829 needSafepoint++; | |
830 results[i] = JVMTI_ERROR_THREAD_NOT_ALIVE; | |
831 continue; | |
832 } | |
833 } else { | |
834 needSafepoint++; | |
835 } | |
836 results[i] = JVMTI_ERROR_NONE; // indicate successful suspend | |
837 } | |
838 if (needSafepoint > 0) { | |
839 VM_ForceSafepoint vfs; | |
840 VMThread::execute(&vfs); | |
841 } | |
842 // per-thread suspend results returned via results parameter | |
843 return JVMTI_ERROR_NONE; | |
844 } /* end SuspendThreadList */ | |
845 | |
846 | |
847 // Threads_lock NOT held, java_thread not protected by lock | |
848 // java_thread - pre-checked | |
849 jvmtiError | |
850 JvmtiEnv::ResumeThread(JavaThread* java_thread) { | |
851 // don't allow hidden thread resume request. | |
852 if (java_thread->is_hidden_from_external_view()) { | |
853 return JVMTI_ERROR_NONE; | |
854 } | |
855 | |
856 if (!java_thread->is_being_ext_suspended()) { | |
857 return JVMTI_ERROR_THREAD_NOT_SUSPENDED; | |
858 } | |
859 | |
860 if (!JvmtiSuspendControl::resume(java_thread)) { | |
861 return JVMTI_ERROR_INTERNAL; | |
862 } | |
863 return JVMTI_ERROR_NONE; | |
864 } /* end ResumeThread */ | |
865 | |
866 | |
867 // request_count - pre-checked to be greater than or equal to 0 | |
868 // request_list - pre-checked for NULL | |
869 // results - pre-checked for NULL | |
870 jvmtiError | |
871 JvmtiEnv::ResumeThreadList(jint request_count, const jthread* request_list, jvmtiError* results) { | |
872 for (int i = 0; i < request_count; i++) { | |
873 JavaThread *java_thread = get_JavaThread(request_list[i]); | |
874 if (java_thread == NULL) { | |
875 results[i] = JVMTI_ERROR_INVALID_THREAD; | |
876 continue; | |
877 } | |
878 // don't allow hidden thread resume request. | |
879 if (java_thread->is_hidden_from_external_view()) { | |
880 results[i] = JVMTI_ERROR_NONE; // indicate successful resume | |
881 continue; | |
882 } | |
883 if (!java_thread->is_being_ext_suspended()) { | |
884 results[i] = JVMTI_ERROR_THREAD_NOT_SUSPENDED; | |
885 continue; | |
886 } | |
887 | |
888 if (!JvmtiSuspendControl::resume(java_thread)) { | |
889 results[i] = JVMTI_ERROR_INTERNAL; | |
890 continue; | |
891 } | |
892 | |
893 results[i] = JVMTI_ERROR_NONE; // indicate successful suspend | |
894 } | |
895 // per-thread resume results returned via results parameter | |
896 return JVMTI_ERROR_NONE; | |
897 } /* end ResumeThreadList */ | |
898 | |
899 | |
900 // Threads_lock NOT held, java_thread not protected by lock | |
901 // java_thread - pre-checked | |
902 jvmtiError | |
903 JvmtiEnv::StopThread(JavaThread* java_thread, jobject exception) { | |
904 oop e = JNIHandles::resolve_external_guard(exception); | |
905 NULL_CHECK(e, JVMTI_ERROR_NULL_POINTER); | |
906 | |
907 JavaThread::send_async_exception(java_thread->threadObj(), e); | |
908 | |
909 return JVMTI_ERROR_NONE; | |
910 | |
911 } /* end StopThread */ | |
912 | |
913 | |
914 // Threads_lock NOT held | |
915 // thread - NOT pre-checked | |
916 jvmtiError | |
917 JvmtiEnv::InterruptThread(jthread thread) { | |
918 oop thread_oop = JNIHandles::resolve_external_guard(thread); | |
1142 | 919 if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) |
0 | 920 return JVMTI_ERROR_INVALID_THREAD; |
921 | |
922 JavaThread* current_thread = JavaThread::current(); | |
923 | |
924 // Todo: this is a duplicate of JVM_Interrupt; share code in future | |
925 // Ensure that the C++ Thread and OSThread structures aren't freed before we operate | |
926 MutexLockerEx ml(current_thread->threadObj() == thread_oop ? NULL : Threads_lock); | |
927 // We need to re-resolve the java_thread, since a GC might have happened during the | |
928 // acquire of the lock | |
929 | |
930 JavaThread* java_thread = java_lang_Thread::thread(JNIHandles::resolve_external_guard(thread)); | |
931 NULL_CHECK(java_thread, JVMTI_ERROR_THREAD_NOT_ALIVE); | |
932 | |
933 Thread::interrupt(java_thread); | |
934 | |
935 return JVMTI_ERROR_NONE; | |
936 } /* end InterruptThread */ | |
937 | |
938 | |
939 // Threads_lock NOT held | |
940 // thread - NOT pre-checked | |
941 // info_ptr - pre-checked for NULL | |
942 jvmtiError | |
943 JvmtiEnv::GetThreadInfo(jthread thread, jvmtiThreadInfo* info_ptr) { | |
944 ResourceMark rm; | |
945 HandleMark hm; | |
946 | |
947 JavaThread* current_thread = JavaThread::current(); | |
948 | |
949 // if thread is NULL the current thread is used | |
950 oop thread_oop; | |
951 if (thread == NULL) { | |
952 thread_oop = current_thread->threadObj(); | |
953 } else { | |
954 thread_oop = JNIHandles::resolve_external_guard(thread); | |
955 } | |
1142 | 956 if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) |
0 | 957 return JVMTI_ERROR_INVALID_THREAD; |
958 | |
959 Handle thread_obj(current_thread, thread_oop); | |
960 typeArrayHandle name; | |
961 ThreadPriority priority; | |
962 Handle thread_group; | |
963 Handle context_class_loader; | |
964 bool is_daemon; | |
965 | |
966 { MutexLocker mu(Threads_lock); | |
967 | |
968 name = typeArrayHandle(current_thread, java_lang_Thread::name(thread_obj())); | |
969 priority = java_lang_Thread::priority(thread_obj()); | |
970 thread_group = Handle(current_thread, java_lang_Thread::threadGroup(thread_obj())); | |
971 is_daemon = java_lang_Thread::is_daemon(thread_obj()); | |
972 | |
973 oop loader = java_lang_Thread::context_class_loader(thread_obj()); | |
974 context_class_loader = Handle(current_thread, loader); | |
975 } | |
976 { const char *n; | |
977 | |
978 if (name() != NULL) { | |
979 n = UNICODE::as_utf8((jchar*) name->base(T_CHAR), name->length()); | |
980 } else { | |
981 n = UNICODE::as_utf8(NULL, 0); | |
982 } | |
983 | |
984 info_ptr->name = (char *) jvmtiMalloc(strlen(n)+1); | |
985 if (info_ptr->name == NULL) | |
986 return JVMTI_ERROR_OUT_OF_MEMORY; | |
987 | |
988 strcpy(info_ptr->name, n); | |
989 } | |
990 info_ptr->is_daemon = is_daemon; | |
991 info_ptr->priority = priority; | |
992 | |
993 info_ptr->context_class_loader = (context_class_loader.is_null()) ? NULL : | |
994 jni_reference(context_class_loader); | |
995 info_ptr->thread_group = jni_reference(thread_group); | |
996 | |
997 return JVMTI_ERROR_NONE; | |
998 } /* end GetThreadInfo */ | |
999 | |
1000 | |
1001 // Threads_lock NOT held, java_thread not protected by lock | |
1002 // java_thread - pre-checked | |
1003 // owned_monitor_count_ptr - pre-checked for NULL | |
1004 // owned_monitors_ptr - pre-checked for NULL | |
1005 jvmtiError | |
1006 JvmtiEnv::GetOwnedMonitorInfo(JavaThread* java_thread, jint* owned_monitor_count_ptr, jobject** owned_monitors_ptr) { | |
1007 jvmtiError err = JVMTI_ERROR_NONE; | |
1008 JavaThread* calling_thread = JavaThread::current(); | |
1009 | |
1010 // growable array of jvmti monitors info on the C-heap | |
1011 GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list = | |
1012 new (ResourceObj::C_HEAP) GrowableArray<jvmtiMonitorStackDepthInfo*>(1, true); | |
1013 | |
1014 uint32_t debug_bits = 0; | |
1015 if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { | |
1016 err = get_owned_monitors(calling_thread, java_thread, owned_monitors_list); | |
1017 } else { | |
1018 // JVMTI get monitors info at safepoint. Do not require target thread to | |
1019 // be suspended. | |
1020 VM_GetOwnedMonitorInfo op(this, calling_thread, java_thread, owned_monitors_list); | |
1021 VMThread::execute(&op); | |
1022 err = op.result(); | |
1023 } | |
1024 jint owned_monitor_count = owned_monitors_list->length(); | |
1025 if (err == JVMTI_ERROR_NONE) { | |
1026 if ((err = allocate(owned_monitor_count * sizeof(jobject *), | |
1027 (unsigned char**)owned_monitors_ptr)) == JVMTI_ERROR_NONE) { | |
1028 // copy into the returned array | |
1029 for (int i = 0; i < owned_monitor_count; i++) { | |
1030 (*owned_monitors_ptr)[i] = | |
1031 ((jvmtiMonitorStackDepthInfo*)owned_monitors_list->at(i))->monitor; | |
1032 } | |
1033 *owned_monitor_count_ptr = owned_monitor_count; | |
1034 } | |
1035 } | |
1036 // clean up. | |
1037 for (int i = 0; i < owned_monitor_count; i++) { | |
1038 deallocate((unsigned char*)owned_monitors_list->at(i)); | |
1039 } | |
1040 delete owned_monitors_list; | |
1041 | |
1042 return err; | |
1043 } /* end GetOwnedMonitorInfo */ | |
1044 | |
1045 | |
1046 // Threads_lock NOT held, java_thread not protected by lock | |
1047 // java_thread - pre-checked | |
1048 // monitor_info_count_ptr - pre-checked for NULL | |
1049 // monitor_info_ptr - pre-checked for NULL | |
1050 jvmtiError | |
1051 JvmtiEnv::GetOwnedMonitorStackDepthInfo(JavaThread* java_thread, jint* monitor_info_count_ptr, jvmtiMonitorStackDepthInfo** monitor_info_ptr) { | |
1052 jvmtiError err = JVMTI_ERROR_NONE; | |
1053 JavaThread* calling_thread = JavaThread::current(); | |
1054 | |
1055 // growable array of jvmti monitors info on the C-heap | |
1056 GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list = | |
1057 new (ResourceObj::C_HEAP) GrowableArray<jvmtiMonitorStackDepthInfo*>(1, true); | |
1058 | |
1059 uint32_t debug_bits = 0; | |
1060 if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { | |
1061 err = get_owned_monitors(calling_thread, java_thread, owned_monitors_list); | |
1062 } else { | |
1063 // JVMTI get owned monitors info at safepoint. Do not require target thread to | |
1064 // be suspended. | |
1065 VM_GetOwnedMonitorInfo op(this, calling_thread, java_thread, owned_monitors_list); | |
1066 VMThread::execute(&op); | |
1067 err = op.result(); | |
1068 } | |
1069 | |
1070 jint owned_monitor_count = owned_monitors_list->length(); | |
1071 if (err == JVMTI_ERROR_NONE) { | |
1072 if ((err = allocate(owned_monitor_count * sizeof(jvmtiMonitorStackDepthInfo), | |
1073 (unsigned char**)monitor_info_ptr)) == JVMTI_ERROR_NONE) { | |
1074 // copy to output array. | |
1075 for (int i = 0; i < owned_monitor_count; i++) { | |
1076 (*monitor_info_ptr)[i].monitor = | |
1077 ((jvmtiMonitorStackDepthInfo*)owned_monitors_list->at(i))->monitor; | |
1078 (*monitor_info_ptr)[i].stack_depth = | |
1079 ((jvmtiMonitorStackDepthInfo*)owned_monitors_list->at(i))->stack_depth; | |
1080 } | |
1081 } | |
1082 *monitor_info_count_ptr = owned_monitor_count; | |
1083 } | |
1084 | |
1085 // clean up. | |
1086 for (int i = 0; i < owned_monitor_count; i++) { | |
1087 deallocate((unsigned char*)owned_monitors_list->at(i)); | |
1088 } | |
1089 delete owned_monitors_list; | |
1090 | |
1091 return err; | |
1092 } /* end GetOwnedMonitorStackDepthInfo */ | |
1093 | |
1094 | |
1095 // Threads_lock NOT held, java_thread not protected by lock | |
1096 // java_thread - pre-checked | |
1097 // monitor_ptr - pre-checked for NULL | |
1098 jvmtiError | |
1099 JvmtiEnv::GetCurrentContendedMonitor(JavaThread* java_thread, jobject* monitor_ptr) { | |
1100 jvmtiError err = JVMTI_ERROR_NONE; | |
1101 uint32_t debug_bits = 0; | |
1102 JavaThread* calling_thread = JavaThread::current(); | |
1103 if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { | |
1104 err = get_current_contended_monitor(calling_thread, java_thread, monitor_ptr); | |
1105 } else { | |
1106 // get contended monitor information at safepoint. | |
1107 VM_GetCurrentContendedMonitor op(this, calling_thread, java_thread, monitor_ptr); | |
1108 VMThread::execute(&op); | |
1109 err = op.result(); | |
1110 } | |
1111 return err; | |
1112 } /* end GetCurrentContendedMonitor */ | |
1113 | |
1114 | |
1115 // Threads_lock NOT held | |
1116 // thread - NOT pre-checked | |
1117 // proc - pre-checked for NULL | |
1118 // arg - NULL is a valid value, must be checked | |
1119 jvmtiError | |
1120 JvmtiEnv::RunAgentThread(jthread thread, jvmtiStartFunction proc, const void* arg, jint priority) { | |
1121 oop thread_oop = JNIHandles::resolve_external_guard(thread); | |
1142 | 1122 if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) { |
0 | 1123 return JVMTI_ERROR_INVALID_THREAD; |
1124 } | |
1125 if (priority < JVMTI_THREAD_MIN_PRIORITY || priority > JVMTI_THREAD_MAX_PRIORITY) { | |
1126 return JVMTI_ERROR_INVALID_PRIORITY; | |
1127 } | |
1128 | |
1129 //Thread-self | |
1130 JavaThread* current_thread = JavaThread::current(); | |
1131 | |
1132 Handle thread_hndl(current_thread, thread_oop); | |
1133 { | |
1134 MutexLocker mu(Threads_lock); // grab Threads_lock | |
1135 | |
1136 JvmtiAgentThread *new_thread = new JvmtiAgentThread(this, proc, arg); | |
1137 | |
1138 // At this point it may be possible that no osthread was created for the | |
1139 // JavaThread due to lack of memory. | |
1140 if (new_thread == NULL || new_thread->osthread() == NULL) { | |
1141 if (new_thread) delete new_thread; | |
1142 return JVMTI_ERROR_OUT_OF_MEMORY; | |
1143 } | |
1144 | |
1145 java_lang_Thread::set_thread(thread_hndl(), new_thread); | |
1146 java_lang_Thread::set_priority(thread_hndl(), (ThreadPriority)priority); | |
1147 java_lang_Thread::set_daemon(thread_hndl()); | |
1148 | |
1149 new_thread->set_threadObj(thread_hndl()); | |
1150 Threads::add(new_thread); | |
1151 Thread::start(new_thread); | |
1152 } // unlock Threads_lock | |
1153 | |
1154 return JVMTI_ERROR_NONE; | |
1155 } /* end RunAgentThread */ | |
1156 | |
1157 // | |
1158 // Thread Group functions | |
1159 // | |
1160 | |
1161 // group_count_ptr - pre-checked for NULL | |
1162 // groups_ptr - pre-checked for NULL | |
1163 jvmtiError | |
1164 JvmtiEnv::GetTopThreadGroups(jint* group_count_ptr, jthreadGroup** groups_ptr) { | |
1165 JavaThread* current_thread = JavaThread::current(); | |
1166 | |
1167 // Only one top level thread group now. | |
1168 *group_count_ptr = 1; | |
1169 | |
1170 // Allocate memory to store global-refs to the thread groups. | |
1171 // Assume this area is freed by caller. | |
1172 *groups_ptr = (jthreadGroup *) jvmtiMalloc((sizeof(jthreadGroup)) * (*group_count_ptr)); | |
1173 | |
1174 NULL_CHECK(*groups_ptr, JVMTI_ERROR_OUT_OF_MEMORY); | |
1175 | |
1176 // Convert oop to Handle, then convert Handle to global-ref. | |
1177 { | |
1178 HandleMark hm(current_thread); | |
1179 Handle system_thread_group(current_thread, Universe::system_thread_group()); | |
1180 *groups_ptr[0] = jni_reference(system_thread_group); | |
1181 } | |
1182 | |
1183 return JVMTI_ERROR_NONE; | |
1184 } /* end GetTopThreadGroups */ | |
1185 | |
1186 | |
1187 // info_ptr - pre-checked for NULL | |
1188 jvmtiError | |
1189 JvmtiEnv::GetThreadGroupInfo(jthreadGroup group, jvmtiThreadGroupInfo* info_ptr) { | |
1190 ResourceMark rm; | |
1191 HandleMark hm; | |
1192 | |
1193 JavaThread* current_thread = JavaThread::current(); | |
1194 | |
1195 Handle group_obj (current_thread, JNIHandles::resolve_external_guard(group)); | |
1196 NULL_CHECK(group_obj(), JVMTI_ERROR_INVALID_THREAD_GROUP); | |
1197 | |
1198 typeArrayHandle name; | |
1199 Handle parent_group; | |
1200 bool is_daemon; | |
1201 ThreadPriority max_priority; | |
1202 | |
1203 { MutexLocker mu(Threads_lock); | |
1204 | |
1205 name = typeArrayHandle(current_thread, | |
1206 java_lang_ThreadGroup::name(group_obj())); | |
1207 parent_group = Handle(current_thread, java_lang_ThreadGroup::parent(group_obj())); | |
1208 is_daemon = java_lang_ThreadGroup::is_daemon(group_obj()); | |
1209 max_priority = java_lang_ThreadGroup::maxPriority(group_obj()); | |
1210 } | |
1211 | |
1212 info_ptr->is_daemon = is_daemon; | |
1213 info_ptr->max_priority = max_priority; | |
1214 info_ptr->parent = jni_reference(parent_group); | |
1215 | |
1216 if (name() != NULL) { | |
1217 const char* n = UNICODE::as_utf8((jchar*) name->base(T_CHAR), name->length()); | |
1218 info_ptr->name = (char *)jvmtiMalloc(strlen(n)+1); | |
1219 NULL_CHECK(info_ptr->name, JVMTI_ERROR_OUT_OF_MEMORY); | |
1220 strcpy(info_ptr->name, n); | |
1221 } else { | |
1222 info_ptr->name = NULL; | |
1223 } | |
1224 | |
1225 return JVMTI_ERROR_NONE; | |
1226 } /* end GetThreadGroupInfo */ | |
1227 | |
1228 | |
1229 // thread_count_ptr - pre-checked for NULL | |
1230 // threads_ptr - pre-checked for NULL | |
1231 // group_count_ptr - pre-checked for NULL | |
1232 // groups_ptr - pre-checked for NULL | |
1233 jvmtiError | |
1234 JvmtiEnv::GetThreadGroupChildren(jthreadGroup group, jint* thread_count_ptr, jthread** threads_ptr, jint* group_count_ptr, jthreadGroup** groups_ptr) { | |
1235 JavaThread* current_thread = JavaThread::current(); | |
1236 oop group_obj = (oop) JNIHandles::resolve_external_guard(group); | |
1237 NULL_CHECK(group_obj, JVMTI_ERROR_INVALID_THREAD_GROUP); | |
1238 | |
1239 Handle *thread_objs = NULL; | |
1240 Handle *group_objs = NULL; | |
1241 int nthreads = 0; | |
1242 int ngroups = 0; | |
1243 int hidden_threads = 0; | |
1244 | |
1245 ResourceMark rm; | |
1246 HandleMark hm; | |
1247 | |
1248 Handle group_hdl(current_thread, group_obj); | |
1249 | |
1250 { MutexLocker mu(Threads_lock); | |
1251 | |
1252 nthreads = java_lang_ThreadGroup::nthreads(group_hdl()); | |
1253 ngroups = java_lang_ThreadGroup::ngroups(group_hdl()); | |
1254 | |
1255 if (nthreads > 0) { | |
1256 objArrayOop threads = java_lang_ThreadGroup::threads(group_hdl()); | |
1257 assert(nthreads <= threads->length(), "too many threads"); | |
1258 thread_objs = NEW_RESOURCE_ARRAY(Handle,nthreads); | |
1259 for (int i=0, j=0; i<nthreads; i++) { | |
1260 oop thread_obj = threads->obj_at(i); | |
1261 assert(thread_obj != NULL, "thread_obj is NULL"); | |
1262 JavaThread *javathread = java_lang_Thread::thread(thread_obj); | |
1263 // Filter out hidden java threads. | |
1264 if (javathread != NULL && javathread->is_hidden_from_external_view()) { | |
1265 hidden_threads++; | |
1266 continue; | |
1267 } | |
1268 thread_objs[j++] = Handle(current_thread, thread_obj); | |
1269 } | |
1270 nthreads -= hidden_threads; | |
1271 } | |
1272 if (ngroups > 0) { | |
1273 objArrayOop groups = java_lang_ThreadGroup::groups(group_hdl()); | |
1274 assert(ngroups <= groups->length(), "too many threads"); | |
1275 group_objs = NEW_RESOURCE_ARRAY(Handle,ngroups); | |
1276 for (int i=0; i<ngroups; i++) { | |
1277 oop group_obj = groups->obj_at(i); | |
1278 assert(group_obj != NULL, "group_obj != NULL"); | |
1279 group_objs[i] = Handle(current_thread, group_obj); | |
1280 } | |
1281 } | |
1282 } | |
1283 | |
1284 // have to make global handles outside of Threads_lock | |
1285 *group_count_ptr = ngroups; | |
1286 *thread_count_ptr = nthreads; | |
1287 *threads_ptr = new_jthreadArray(nthreads, thread_objs); | |
1288 *groups_ptr = new_jthreadGroupArray(ngroups, group_objs); | |
1289 if ((nthreads > 0) && (*threads_ptr == NULL)) { | |
1290 return JVMTI_ERROR_OUT_OF_MEMORY; | |
1291 } | |
1292 if ((ngroups > 0) && (*groups_ptr == NULL)) { | |
1293 return JVMTI_ERROR_OUT_OF_MEMORY; | |
1294 } | |
1295 | |
1296 return JVMTI_ERROR_NONE; | |
1297 } /* end GetThreadGroupChildren */ | |
1298 | |
1299 | |
1300 // | |
1301 // Stack Frame functions | |
1302 // | |
1303 | |
1304 // Threads_lock NOT held, java_thread not protected by lock | |
1305 // java_thread - pre-checked | |
1306 // max_frame_count - pre-checked to be greater than or equal to 0 | |
1307 // frame_buffer - pre-checked for NULL | |
1308 // count_ptr - pre-checked for NULL | |
1309 jvmtiError | |
1310 JvmtiEnv::GetStackTrace(JavaThread* java_thread, jint start_depth, jint max_frame_count, jvmtiFrameInfo* frame_buffer, jint* count_ptr) { | |
1311 jvmtiError err = JVMTI_ERROR_NONE; | |
1312 uint32_t debug_bits = 0; | |
1313 if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { | |
1314 err = get_stack_trace(java_thread, start_depth, max_frame_count, frame_buffer, count_ptr); | |
1315 } else { | |
1316 // JVMTI get stack trace at safepoint. Do not require target thread to | |
1317 // be suspended. | |
1318 VM_GetStackTrace op(this, java_thread, start_depth, max_frame_count, frame_buffer, count_ptr); | |
1319 VMThread::execute(&op); | |
1320 err = op.result(); | |
1321 } | |
1322 | |
1323 return err; | |
1324 } /* end GetStackTrace */ | |
1325 | |
1326 | |
1327 // max_frame_count - pre-checked to be greater than or equal to 0 | |
1328 // stack_info_ptr - pre-checked for NULL | |
1329 // thread_count_ptr - pre-checked for NULL | |
1330 jvmtiError | |
1331 JvmtiEnv::GetAllStackTraces(jint max_frame_count, jvmtiStackInfo** stack_info_ptr, jint* thread_count_ptr) { | |
1332 jvmtiError err = JVMTI_ERROR_NONE; | |
1333 JavaThread* calling_thread = JavaThread::current(); | |
1334 | |
1335 // JVMTI get stack traces at safepoint. | |
1336 VM_GetAllStackTraces op(this, calling_thread, max_frame_count); | |
1337 VMThread::execute(&op); | |
1338 *thread_count_ptr = op.final_thread_count(); | |
1339 *stack_info_ptr = op.stack_info(); | |
1340 err = op.result(); | |
1341 return err; | |
1342 } /* end GetAllStackTraces */ | |
1343 | |
1344 | |
1345 // thread_count - pre-checked to be greater than or equal to 0 | |
1346 // thread_list - pre-checked for NULL | |
1347 // max_frame_count - pre-checked to be greater than or equal to 0 | |
1348 // stack_info_ptr - pre-checked for NULL | |
1349 jvmtiError | |
1350 JvmtiEnv::GetThreadListStackTraces(jint thread_count, const jthread* thread_list, jint max_frame_count, jvmtiStackInfo** stack_info_ptr) { | |
1351 jvmtiError err = JVMTI_ERROR_NONE; | |
1352 // JVMTI get stack traces at safepoint. | |
1353 VM_GetThreadListStackTraces op(this, thread_count, thread_list, max_frame_count); | |
1354 VMThread::execute(&op); | |
1355 err = op.result(); | |
1356 if (err == JVMTI_ERROR_NONE) { | |
1357 *stack_info_ptr = op.stack_info(); | |
1358 } | |
1359 return err; | |
1360 } /* end GetThreadListStackTraces */ | |
1361 | |
1362 | |
1363 // Threads_lock NOT held, java_thread not protected by lock | |
1364 // java_thread - pre-checked | |
1365 // count_ptr - pre-checked for NULL | |
1366 jvmtiError | |
1367 JvmtiEnv::GetFrameCount(JavaThread* java_thread, jint* count_ptr) { | |
1368 jvmtiError err = JVMTI_ERROR_NONE; | |
1369 | |
1370 // retrieve or create JvmtiThreadState. | |
1371 JvmtiThreadState* state = JvmtiThreadState::state_for(java_thread); | |
609
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
0
diff
changeset
|
1372 if (state == NULL) { |
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
0
diff
changeset
|
1373 return JVMTI_ERROR_THREAD_NOT_ALIVE; |
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
0
diff
changeset
|
1374 } |
0 | 1375 uint32_t debug_bits = 0; |
1376 if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { | |
1377 err = get_frame_count(state, count_ptr); | |
1378 } else { | |
1379 // get java stack frame count at safepoint. | |
1380 VM_GetFrameCount op(this, state, count_ptr); | |
1381 VMThread::execute(&op); | |
1382 err = op.result(); | |
1383 } | |
1384 return err; | |
1385 } /* end GetFrameCount */ | |
1386 | |
1387 | |
1388 // Threads_lock NOT held, java_thread not protected by lock | |
1389 // java_thread - pre-checked | |
1390 jvmtiError | |
1391 JvmtiEnv::PopFrame(JavaThread* java_thread) { | |
1392 JavaThread* current_thread = JavaThread::current(); | |
1393 HandleMark hm(current_thread); | |
1394 uint32_t debug_bits = 0; | |
1395 | |
609
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
0
diff
changeset
|
1396 // retrieve or create the state |
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
0
diff
changeset
|
1397 JvmtiThreadState* state = JvmtiThreadState::state_for(java_thread); |
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
0
diff
changeset
|
1398 if (state == NULL) { |
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
0
diff
changeset
|
1399 return JVMTI_ERROR_THREAD_NOT_ALIVE; |
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
0
diff
changeset
|
1400 } |
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
0
diff
changeset
|
1401 |
0 | 1402 // Check if java_thread is fully suspended |
1403 if (!is_thread_fully_suspended(java_thread, true /* wait for suspend completion */, &debug_bits)) { | |
1404 return JVMTI_ERROR_THREAD_NOT_SUSPENDED; | |
1405 } | |
1406 // Check to see if a PopFrame was already in progress | |
1407 if (java_thread->popframe_condition() != JavaThread::popframe_inactive) { | |
1408 // Probably possible for JVMTI clients to trigger this, but the | |
1409 // JPDA backend shouldn't allow this to happen | |
1410 return JVMTI_ERROR_INTERNAL; | |
1411 } | |
1412 | |
1413 { | |
1414 // Was workaround bug | |
1415 // 4812902: popFrame hangs if the method is waiting at a synchronize | |
1416 // Catch this condition and return an error to avoid hanging. | |
1417 // Now JVMTI spec allows an implementation to bail out with an opaque frame error. | |
1418 OSThread* osThread = java_thread->osthread(); | |
1419 if (osThread->get_state() == MONITOR_WAIT) { | |
1420 return JVMTI_ERROR_OPAQUE_FRAME; | |
1421 } | |
1422 } | |
1423 | |
1424 { | |
1425 ResourceMark rm(current_thread); | |
1426 // Check if there are more than one Java frame in this thread, that the top two frames | |
1427 // are Java (not native) frames, and that there is no intervening VM frame | |
1428 int frame_count = 0; | |
1429 bool is_interpreted[2]; | |
1430 intptr_t *frame_sp[2]; | |
1431 // The 2-nd arg of constructor is needed to stop iterating at java entry frame. | |
1432 for (vframeStream vfs(java_thread, true); !vfs.at_end(); vfs.next()) { | |
1433 methodHandle mh(current_thread, vfs.method()); | |
1434 if (mh->is_native()) return(JVMTI_ERROR_OPAQUE_FRAME); | |
1435 is_interpreted[frame_count] = vfs.is_interpreted_frame(); | |
1436 frame_sp[frame_count] = vfs.frame_id(); | |
1437 if (++frame_count > 1) break; | |
1438 } | |
1439 if (frame_count < 2) { | |
1440 // We haven't found two adjacent non-native Java frames on the top. | |
1441 // There can be two situations here: | |
1442 // 1. There are no more java frames | |
1443 // 2. Two top java frames are separated by non-java native frames | |
1444 if(vframeFor(java_thread, 1) == NULL) { | |
1445 return JVMTI_ERROR_NO_MORE_FRAMES; | |
1446 } else { | |
1447 // Intervening non-java native or VM frames separate java frames. | |
1448 // Current implementation does not support this. See bug #5031735. | |
1449 // In theory it is possible to pop frames in such cases. | |
1450 return JVMTI_ERROR_OPAQUE_FRAME; | |
1451 } | |
1452 } | |
1453 | |
1454 // If any of the top 2 frames is a compiled one, need to deoptimize it | |
1455 for (int i = 0; i < 2; i++) { | |
1456 if (!is_interpreted[i]) { | |
1905
ce6848d0666d
6968367: can_post_on_exceptions is still using VM_DeoptimizeFrame in some places
never
parents:
1552
diff
changeset
|
1457 Deoptimization::deoptimize_frame(java_thread, frame_sp[i]); |
0 | 1458 } |
1459 } | |
1460 | |
1461 // Update the thread state to reflect that the top frame is popped | |
1462 // so that cur_stack_depth is maintained properly and all frameIDs | |
1463 // are invalidated. | |
1464 // The current frame will be popped later when the suspended thread | |
1465 // is resumed and right before returning from VM to Java. | |
1466 // (see call_VM_base() in assembler_<cpu>.cpp). | |
1467 | |
1468 // It's fine to update the thread state here because no JVMTI events | |
1469 // shall be posted for this PopFrame. | |
1470 | |
1471 state->update_for_pop_top_frame(); | |
1472 java_thread->set_popframe_condition(JavaThread::popframe_pending_bit); | |
1473 // Set pending step flag for this popframe and it is cleared when next | |
1474 // step event is posted. | |
1475 state->set_pending_step_for_popframe(); | |
1476 } | |
1477 | |
1478 return JVMTI_ERROR_NONE; | |
1479 } /* end PopFrame */ | |
1480 | |
1481 | |
1482 // Threads_lock NOT held, java_thread not protected by lock | |
1483 // java_thread - pre-checked | |
1484 // java_thread - unchecked | |
1485 // depth - pre-checked as non-negative | |
1486 // method_ptr - pre-checked for NULL | |
1487 // location_ptr - pre-checked for NULL | |
1488 jvmtiError | |
1489 JvmtiEnv::GetFrameLocation(JavaThread* java_thread, jint depth, jmethodID* method_ptr, jlocation* location_ptr) { | |
1490 jvmtiError err = JVMTI_ERROR_NONE; | |
1491 uint32_t debug_bits = 0; | |
1492 | |
1493 if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { | |
1494 err = get_frame_location(java_thread, depth, method_ptr, location_ptr); | |
1495 } else { | |
1496 // JVMTI get java stack frame location at safepoint. | |
1497 VM_GetFrameLocation op(this, java_thread, depth, method_ptr, location_ptr); | |
1498 VMThread::execute(&op); | |
1499 err = op.result(); | |
1500 } | |
1501 return err; | |
1502 } /* end GetFrameLocation */ | |
1503 | |
1504 | |
1505 // Threads_lock NOT held, java_thread not protected by lock | |
1506 // java_thread - pre-checked | |
1507 // java_thread - unchecked | |
1508 // depth - pre-checked as non-negative | |
1509 jvmtiError | |
1510 JvmtiEnv::NotifyFramePop(JavaThread* java_thread, jint depth) { | |
1511 ResourceMark rm; | |
1512 uint32_t debug_bits = 0; | |
1513 | |
609
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
0
diff
changeset
|
1514 JvmtiThreadState *state = JvmtiThreadState::state_for(java_thread); |
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
0
diff
changeset
|
1515 if (state == NULL) { |
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
0
diff
changeset
|
1516 return JVMTI_ERROR_THREAD_NOT_ALIVE; |
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
0
diff
changeset
|
1517 } |
ea20d7ce26b0
6800721: 3/4 JavaThread::jvmti_thread_state() and JvmtiThreadState::state_for() robustness
dcubed
parents:
0
diff
changeset
|
1518 |
0 | 1519 if (!JvmtiEnv::is_thread_fully_suspended(java_thread, true, &debug_bits)) { |
1520 return JVMTI_ERROR_THREAD_NOT_SUSPENDED; | |
1521 } | |
1522 | |
1523 if (TraceJVMTICalls) { | |
1524 JvmtiSuspendControl::print(); | |
1525 } | |
1526 | |
1527 vframe *vf = vframeFor(java_thread, depth); | |
1528 if (vf == NULL) { | |
1529 return JVMTI_ERROR_NO_MORE_FRAMES; | |
1530 } | |
1531 | |
1532 if (!vf->is_java_frame() || ((javaVFrame*) vf)->method()->is_native()) { | |
1533 return JVMTI_ERROR_OPAQUE_FRAME; | |
1534 } | |
1535 | |
1536 assert(vf->frame_pointer() != NULL, "frame pointer mustn't be NULL"); | |
1537 | |
1538 int frame_number = state->count_frames() - depth; | |
1539 state->env_thread_state(this)->set_frame_pop(frame_number); | |
1540 | |
1541 return JVMTI_ERROR_NONE; | |
1542 } /* end NotifyFramePop */ | |
1543 | |
1544 | |
1545 // | |
1546 // Force Early Return functions | |
1547 // | |
1548 | |
1549 // Threads_lock NOT held, java_thread not protected by lock | |
1550 // java_thread - pre-checked | |
1551 jvmtiError | |
1552 JvmtiEnv::ForceEarlyReturnObject(JavaThread* java_thread, jobject value) { | |
1553 jvalue val; | |
1554 val.l = value; | |
1555 return force_early_return(java_thread, val, atos); | |
1556 } /* end ForceEarlyReturnObject */ | |
1557 | |
1558 | |
1559 // Threads_lock NOT held, java_thread not protected by lock | |
1560 // java_thread - pre-checked | |
1561 jvmtiError | |
1562 JvmtiEnv::ForceEarlyReturnInt(JavaThread* java_thread, jint value) { | |
1563 jvalue val; | |
1564 val.i = value; | |
1565 return force_early_return(java_thread, val, itos); | |
1566 } /* end ForceEarlyReturnInt */ | |
1567 | |
1568 | |
1569 // Threads_lock NOT held, java_thread not protected by lock | |
1570 // java_thread - pre-checked | |
1571 jvmtiError | |
1572 JvmtiEnv::ForceEarlyReturnLong(JavaThread* java_thread, jlong value) { | |
1573 jvalue val; | |
1574 val.j = value; | |
1575 return force_early_return(java_thread, val, ltos); | |
1576 } /* end ForceEarlyReturnLong */ | |
1577 | |
1578 | |
1579 // Threads_lock NOT held, java_thread not protected by lock | |
1580 // java_thread - pre-checked | |
1581 jvmtiError | |
1582 JvmtiEnv::ForceEarlyReturnFloat(JavaThread* java_thread, jfloat value) { | |
1583 jvalue val; | |
1584 val.f = value; | |
1585 return force_early_return(java_thread, val, ftos); | |
1586 } /* end ForceEarlyReturnFloat */ | |
1587 | |
1588 | |
1589 // Threads_lock NOT held, java_thread not protected by lock | |
1590 // java_thread - pre-checked | |
1591 jvmtiError | |
1592 JvmtiEnv::ForceEarlyReturnDouble(JavaThread* java_thread, jdouble value) { | |
1593 jvalue val; | |
1594 val.d = value; | |
1595 return force_early_return(java_thread, val, dtos); | |
1596 } /* end ForceEarlyReturnDouble */ | |
1597 | |
1598 | |
1599 // Threads_lock NOT held, java_thread not protected by lock | |
1600 // java_thread - pre-checked | |
1601 jvmtiError | |
1602 JvmtiEnv::ForceEarlyReturnVoid(JavaThread* java_thread) { | |
1603 jvalue val; | |
1604 val.j = 0L; | |
1605 return force_early_return(java_thread, val, vtos); | |
1606 } /* end ForceEarlyReturnVoid */ | |
1607 | |
1608 | |
1609 // | |
1610 // Heap functions | |
1611 // | |
1612 | |
1613 // klass - NULL is a valid value, must be checked | |
1614 // initial_object - NULL is a valid value, must be checked | |
1615 // callbacks - pre-checked for NULL | |
1616 // user_data - NULL is a valid value, must be checked | |
1617 jvmtiError | |
1618 JvmtiEnv::FollowReferences(jint heap_filter, jclass klass, jobject initial_object, const jvmtiHeapCallbacks* callbacks, const void* user_data) { | |
1619 // check klass if provided | |
1620 klassOop k_oop = NULL; | |
1621 if (klass != NULL) { | |
1622 oop k_mirror = JNIHandles::resolve_external_guard(klass); | |
1623 if (k_mirror == NULL) { | |
1624 return JVMTI_ERROR_INVALID_CLASS; | |
1625 } | |
1626 if (java_lang_Class::is_primitive(k_mirror)) { | |
1627 return JVMTI_ERROR_NONE; | |
1628 } | |
1629 k_oop = java_lang_Class::as_klassOop(k_mirror); | |
1630 if (k_oop == NULL) { | |
1631 return JVMTI_ERROR_INVALID_CLASS; | |
1632 } | |
1633 } | |
1634 | |
1635 Thread *thread = Thread::current(); | |
1636 HandleMark hm(thread); | |
1637 KlassHandle kh (thread, k_oop); | |
1638 | |
1639 TraceTime t("FollowReferences", TraceJVMTIObjectTagging); | |
1640 JvmtiTagMap::tag_map_for(this)->follow_references(heap_filter, kh, initial_object, callbacks, user_data); | |
1641 return JVMTI_ERROR_NONE; | |
1642 } /* end FollowReferences */ | |
1643 | |
1644 | |
1645 // klass - NULL is a valid value, must be checked | |
1646 // callbacks - pre-checked for NULL | |
1647 // user_data - NULL is a valid value, must be checked | |
1648 jvmtiError | |
1649 JvmtiEnv::IterateThroughHeap(jint heap_filter, jclass klass, const jvmtiHeapCallbacks* callbacks, const void* user_data) { | |
1650 // check klass if provided | |
1651 klassOop k_oop = NULL; | |
1652 if (klass != NULL) { | |
1653 oop k_mirror = JNIHandles::resolve_external_guard(klass); | |
1654 if (k_mirror == NULL) { | |
1655 return JVMTI_ERROR_INVALID_CLASS; | |
1656 } | |
1657 if (java_lang_Class::is_primitive(k_mirror)) { | |
1658 return JVMTI_ERROR_NONE; | |
1659 } | |
1660 k_oop = java_lang_Class::as_klassOop(k_mirror); | |
1661 if (k_oop == NULL) { | |
1662 return JVMTI_ERROR_INVALID_CLASS; | |
1663 } | |
1664 } | |
1665 | |
1666 Thread *thread = Thread::current(); | |
1667 HandleMark hm(thread); | |
1668 KlassHandle kh (thread, k_oop); | |
1669 | |
1670 TraceTime t("IterateThroughHeap", TraceJVMTIObjectTagging); | |
1671 JvmtiTagMap::tag_map_for(this)->iterate_through_heap(heap_filter, kh, callbacks, user_data); | |
1672 return JVMTI_ERROR_NONE; | |
1673 } /* end IterateThroughHeap */ | |
1674 | |
1675 | |
1676 // tag_ptr - pre-checked for NULL | |
1677 jvmtiError | |
1678 JvmtiEnv::GetTag(jobject object, jlong* tag_ptr) { | |
1679 oop o = JNIHandles::resolve_external_guard(object); | |
1680 NULL_CHECK(o, JVMTI_ERROR_INVALID_OBJECT); | |
1681 *tag_ptr = JvmtiTagMap::tag_map_for(this)->get_tag(object); | |
1682 return JVMTI_ERROR_NONE; | |
1683 } /* end GetTag */ | |
1684 | |
1685 | |
1686 jvmtiError | |
1687 JvmtiEnv::SetTag(jobject object, jlong tag) { | |
1688 oop o = JNIHandles::resolve_external_guard(object); | |
1689 NULL_CHECK(o, JVMTI_ERROR_INVALID_OBJECT); | |
1690 JvmtiTagMap::tag_map_for(this)->set_tag(object, tag); | |
1691 return JVMTI_ERROR_NONE; | |
1692 } /* end SetTag */ | |
1693 | |
1694 | |
1695 // tag_count - pre-checked to be greater than or equal to 0 | |
1696 // tags - pre-checked for NULL | |
1697 // count_ptr - pre-checked for NULL | |
1698 // object_result_ptr - NULL is a valid value, must be checked | |
1699 // tag_result_ptr - NULL is a valid value, must be checked | |
1700 jvmtiError | |
1701 JvmtiEnv::GetObjectsWithTags(jint tag_count, const jlong* tags, jint* count_ptr, jobject** object_result_ptr, jlong** tag_result_ptr) { | |
1702 TraceTime t("GetObjectsWithTags", TraceJVMTIObjectTagging); | |
1703 return JvmtiTagMap::tag_map_for(this)->get_objects_with_tags((jlong*)tags, tag_count, count_ptr, object_result_ptr, tag_result_ptr); | |
1704 } /* end GetObjectsWithTags */ | |
1705 | |
1706 | |
1707 jvmtiError | |
1708 JvmtiEnv::ForceGarbageCollection() { | |
1709 Universe::heap()->collect(GCCause::_jvmti_force_gc); | |
1710 return JVMTI_ERROR_NONE; | |
1711 } /* end ForceGarbageCollection */ | |
1712 | |
1713 | |
1714 // | |
1715 // Heap (1.0) functions | |
1716 // | |
1717 | |
1718 // object_reference_callback - pre-checked for NULL | |
1719 // user_data - NULL is a valid value, must be checked | |
1720 jvmtiError | |
1721 JvmtiEnv::IterateOverObjectsReachableFromObject(jobject object, jvmtiObjectReferenceCallback object_reference_callback, const void* user_data) { | |
1722 oop o = JNIHandles::resolve_external_guard(object); | |
1723 NULL_CHECK(o, JVMTI_ERROR_INVALID_OBJECT); | |
1724 JvmtiTagMap::tag_map_for(this)->iterate_over_objects_reachable_from_object(object, object_reference_callback, user_data); | |
1725 return JVMTI_ERROR_NONE; | |
1726 } /* end IterateOverObjectsReachableFromObject */ | |
1727 | |
1728 | |
1729 // heap_root_callback - NULL is a valid value, must be checked | |
1730 // stack_ref_callback - NULL is a valid value, must be checked | |
1731 // object_ref_callback - NULL is a valid value, must be checked | |
1732 // user_data - NULL is a valid value, must be checked | |
1733 jvmtiError | |
1734 JvmtiEnv::IterateOverReachableObjects(jvmtiHeapRootCallback heap_root_callback, jvmtiStackReferenceCallback stack_ref_callback, jvmtiObjectReferenceCallback object_ref_callback, const void* user_data) { | |
1735 TraceTime t("IterateOverReachableObjects", TraceJVMTIObjectTagging); | |
1736 JvmtiTagMap::tag_map_for(this)->iterate_over_reachable_objects(heap_root_callback, stack_ref_callback, object_ref_callback, user_data); | |
1737 return JVMTI_ERROR_NONE; | |
1738 } /* end IterateOverReachableObjects */ | |
1739 | |
1740 | |
1741 // heap_object_callback - pre-checked for NULL | |
1742 // user_data - NULL is a valid value, must be checked | |
1743 jvmtiError | |
1744 JvmtiEnv::IterateOverHeap(jvmtiHeapObjectFilter object_filter, jvmtiHeapObjectCallback heap_object_callback, const void* user_data) { | |
1745 TraceTime t("IterateOverHeap", TraceJVMTIObjectTagging); | |
1746 Thread *thread = Thread::current(); | |
1747 HandleMark hm(thread); | |
1748 JvmtiTagMap::tag_map_for(this)->iterate_over_heap(object_filter, KlassHandle(), heap_object_callback, user_data); | |
1749 return JVMTI_ERROR_NONE; | |
1750 } /* end IterateOverHeap */ | |
1751 | |
1752 | |
1753 // k_mirror - may be primitive, this must be checked | |
1754 // heap_object_callback - pre-checked for NULL | |
1755 // user_data - NULL is a valid value, must be checked | |
1756 jvmtiError | |
1757 JvmtiEnv::IterateOverInstancesOfClass(oop k_mirror, jvmtiHeapObjectFilter object_filter, jvmtiHeapObjectCallback heap_object_callback, const void* user_data) { | |
1758 if (java_lang_Class::is_primitive(k_mirror)) { | |
1759 // DO PRIMITIVE CLASS PROCESSING | |
1760 return JVMTI_ERROR_NONE; | |
1761 } | |
1762 klassOop k_oop = java_lang_Class::as_klassOop(k_mirror); | |
1763 if (k_oop == NULL) { | |
1764 return JVMTI_ERROR_INVALID_CLASS; | |
1765 } | |
1766 Thread *thread = Thread::current(); | |
1767 HandleMark hm(thread); | |
1768 KlassHandle klass (thread, k_oop); | |
1769 TraceTime t("IterateOverInstancesOfClass", TraceJVMTIObjectTagging); | |
1770 JvmtiTagMap::tag_map_for(this)->iterate_over_heap(object_filter, klass, heap_object_callback, user_data); | |
1771 return JVMTI_ERROR_NONE; | |
1772 } /* end IterateOverInstancesOfClass */ | |
1773 | |
1774 | |
1775 // | |
1776 // Local Variable functions | |
1777 // | |
1778 | |
1779 // Threads_lock NOT held, java_thread not protected by lock | |
1780 // java_thread - pre-checked | |
1781 // java_thread - unchecked | |
1782 // depth - pre-checked as non-negative | |
1783 // value_ptr - pre-checked for NULL | |
1784 jvmtiError | |
1785 JvmtiEnv::GetLocalObject(JavaThread* java_thread, jint depth, jint slot, jobject* value_ptr) { | |
1786 JavaThread* current_thread = JavaThread::current(); | |
1787 // rm object is created to clean up the javaVFrame created in | |
1788 // doit_prologue(), but after doit() is finished with it. | |
1789 ResourceMark rm(current_thread); | |
1790 | |
1791 VM_GetOrSetLocal op(java_thread, current_thread, depth, slot); | |
1792 VMThread::execute(&op); | |
1793 jvmtiError err = op.result(); | |
1794 if (err != JVMTI_ERROR_NONE) { | |
1795 return err; | |
1796 } else { | |
1797 *value_ptr = op.value().l; | |
1798 return JVMTI_ERROR_NONE; | |
1799 } | |
1800 } /* end GetLocalObject */ | |
1801 | |
2019 | 1802 // Threads_lock NOT held, java_thread not protected by lock |
1803 // java_thread - pre-checked | |
1804 // java_thread - unchecked | |
1805 // depth - pre-checked as non-negative | |
1806 // value - pre-checked for NULL | |
1807 jvmtiError | |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
2019
diff
changeset
|
1808 JvmtiEnv::GetLocalInstance(JavaThread* java_thread, jint depth, jobject* value_ptr){ |
2019 | 1809 JavaThread* current_thread = JavaThread::current(); |
1810 // rm object is created to clean up the javaVFrame created in | |
1811 // doit_prologue(), but after doit() is finished with it. | |
1812 ResourceMark rm(current_thread); | |
1813 | |
1814 VM_GetReceiver op(java_thread, current_thread, depth); | |
1815 VMThread::execute(&op); | |
1816 jvmtiError err = op.result(); | |
1817 if (err != JVMTI_ERROR_NONE) { | |
1818 return err; | |
1819 } else { | |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
2019
diff
changeset
|
1820 *value_ptr = op.value().l; |
2019 | 1821 return JVMTI_ERROR_NONE; |
1822 } | |
1823 } /* end GetLocalInstance */ | |
1824 | |
0 | 1825 |
1826 // Threads_lock NOT held, java_thread not protected by lock | |
1827 // java_thread - pre-checked | |
1828 // java_thread - unchecked | |
1829 // depth - pre-checked as non-negative | |
1830 // value_ptr - pre-checked for NULL | |
1831 jvmtiError | |
1832 JvmtiEnv::GetLocalInt(JavaThread* java_thread, jint depth, jint slot, jint* value_ptr) { | |
1833 // rm object is created to clean up the javaVFrame created in | |
1834 // doit_prologue(), but after doit() is finished with it. | |
1835 ResourceMark rm; | |
1836 | |
1837 VM_GetOrSetLocal op(java_thread, depth, slot, T_INT); | |
1838 VMThread::execute(&op); | |
1839 *value_ptr = op.value().i; | |
1840 return op.result(); | |
1841 } /* end GetLocalInt */ | |
1842 | |
1843 | |
1844 // Threads_lock NOT held, java_thread not protected by lock | |
1845 // java_thread - pre-checked | |
1846 // java_thread - unchecked | |
1847 // depth - pre-checked as non-negative | |
1848 // value_ptr - pre-checked for NULL | |
1849 jvmtiError | |
1850 JvmtiEnv::GetLocalLong(JavaThread* java_thread, jint depth, jint slot, jlong* value_ptr) { | |
1851 // rm object is created to clean up the javaVFrame created in | |
1852 // doit_prologue(), but after doit() is finished with it. | |
1853 ResourceMark rm; | |
1854 | |
1855 VM_GetOrSetLocal op(java_thread, depth, slot, T_LONG); | |
1856 VMThread::execute(&op); | |
1857 *value_ptr = op.value().j; | |
1858 return op.result(); | |
1859 } /* end GetLocalLong */ | |
1860 | |
1861 | |
1862 // Threads_lock NOT held, java_thread not protected by lock | |
1863 // java_thread - pre-checked | |
1864 // java_thread - unchecked | |
1865 // depth - pre-checked as non-negative | |
1866 // value_ptr - pre-checked for NULL | |
1867 jvmtiError | |
1868 JvmtiEnv::GetLocalFloat(JavaThread* java_thread, jint depth, jint slot, jfloat* value_ptr) { | |
1869 // rm object is created to clean up the javaVFrame created in | |
1870 // doit_prologue(), but after doit() is finished with it. | |
1871 ResourceMark rm; | |
1872 | |
1873 VM_GetOrSetLocal op(java_thread, depth, slot, T_FLOAT); | |
1874 VMThread::execute(&op); | |
1875 *value_ptr = op.value().f; | |
1876 return op.result(); | |
1877 } /* end GetLocalFloat */ | |
1878 | |
1879 | |
1880 // Threads_lock NOT held, java_thread not protected by lock | |
1881 // java_thread - pre-checked | |
1882 // java_thread - unchecked | |
1883 // depth - pre-checked as non-negative | |
1884 // value_ptr - pre-checked for NULL | |
1885 jvmtiError | |
1886 JvmtiEnv::GetLocalDouble(JavaThread* java_thread, jint depth, jint slot, jdouble* value_ptr) { | |
1887 // rm object is created to clean up the javaVFrame created in | |
1888 // doit_prologue(), but after doit() is finished with it. | |
1889 ResourceMark rm; | |
1890 | |
1891 VM_GetOrSetLocal op(java_thread, depth, slot, T_DOUBLE); | |
1892 VMThread::execute(&op); | |
1893 *value_ptr = op.value().d; | |
1894 return op.result(); | |
1895 } /* end GetLocalDouble */ | |
1896 | |
1897 | |
1898 // Threads_lock NOT held, java_thread not protected by lock | |
1899 // java_thread - pre-checked | |
1900 // java_thread - unchecked | |
1901 // depth - pre-checked as non-negative | |
1902 jvmtiError | |
1903 JvmtiEnv::SetLocalObject(JavaThread* java_thread, jint depth, jint slot, jobject value) { | |
1904 // rm object is created to clean up the javaVFrame created in | |
1905 // doit_prologue(), but after doit() is finished with it. | |
1906 ResourceMark rm; | |
1907 jvalue val; | |
1908 val.l = value; | |
1909 VM_GetOrSetLocal op(java_thread, depth, slot, T_OBJECT, val); | |
1910 VMThread::execute(&op); | |
1911 return op.result(); | |
1912 } /* end SetLocalObject */ | |
1913 | |
1914 | |
1915 // Threads_lock NOT held, java_thread not protected by lock | |
1916 // java_thread - pre-checked | |
1917 // java_thread - unchecked | |
1918 // depth - pre-checked as non-negative | |
1919 jvmtiError | |
1920 JvmtiEnv::SetLocalInt(JavaThread* java_thread, jint depth, jint slot, jint value) { | |
1921 // rm object is created to clean up the javaVFrame created in | |
1922 // doit_prologue(), but after doit() is finished with it. | |
1923 ResourceMark rm; | |
1924 jvalue val; | |
1925 val.i = value; | |
1926 VM_GetOrSetLocal op(java_thread, depth, slot, T_INT, val); | |
1927 VMThread::execute(&op); | |
1928 return op.result(); | |
1929 } /* end SetLocalInt */ | |
1930 | |
1931 | |
1932 // Threads_lock NOT held, java_thread not protected by lock | |
1933 // java_thread - pre-checked | |
1934 // java_thread - unchecked | |
1935 // depth - pre-checked as non-negative | |
1936 jvmtiError | |
1937 JvmtiEnv::SetLocalLong(JavaThread* java_thread, jint depth, jint slot, jlong value) { | |
1938 // rm object is created to clean up the javaVFrame created in | |
1939 // doit_prologue(), but after doit() is finished with it. | |
1940 ResourceMark rm; | |
1941 jvalue val; | |
1942 val.j = value; | |
1943 VM_GetOrSetLocal op(java_thread, depth, slot, T_LONG, val); | |
1944 VMThread::execute(&op); | |
1945 return op.result(); | |
1946 } /* end SetLocalLong */ | |
1947 | |
1948 | |
1949 // Threads_lock NOT held, java_thread not protected by lock | |
1950 // java_thread - pre-checked | |
1951 // java_thread - unchecked | |
1952 // depth - pre-checked as non-negative | |
1953 jvmtiError | |
1954 JvmtiEnv::SetLocalFloat(JavaThread* java_thread, jint depth, jint slot, jfloat value) { | |
1955 // rm object is created to clean up the javaVFrame created in | |
1956 // doit_prologue(), but after doit() is finished with it. | |
1957 ResourceMark rm; | |
1958 jvalue val; | |
1959 val.f = value; | |
1960 VM_GetOrSetLocal op(java_thread, depth, slot, T_FLOAT, val); | |
1961 VMThread::execute(&op); | |
1962 return op.result(); | |
1963 } /* end SetLocalFloat */ | |
1964 | |
1965 | |
1966 // Threads_lock NOT held, java_thread not protected by lock | |
1967 // java_thread - pre-checked | |
1968 // java_thread - unchecked | |
1969 // depth - pre-checked as non-negative | |
1970 jvmtiError | |
1971 JvmtiEnv::SetLocalDouble(JavaThread* java_thread, jint depth, jint slot, jdouble value) { | |
1972 // rm object is created to clean up the javaVFrame created in | |
1973 // doit_prologue(), but after doit() is finished with it. | |
1974 ResourceMark rm; | |
1975 jvalue val; | |
1976 val.d = value; | |
1977 VM_GetOrSetLocal op(java_thread, depth, slot, T_DOUBLE, val); | |
1978 VMThread::execute(&op); | |
1979 return op.result(); | |
1980 } /* end SetLocalDouble */ | |
1981 | |
1982 | |
1983 // | |
1984 // Breakpoint functions | |
1985 // | |
1986 | |
1987 // method_oop - pre-checked for validity, but may be NULL meaning obsolete method | |
1988 jvmtiError | |
1989 JvmtiEnv::SetBreakpoint(methodOop method_oop, jlocation location) { | |
1990 NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); | |
1991 if (location < 0) { // simple invalid location check first | |
1992 return JVMTI_ERROR_INVALID_LOCATION; | |
1993 } | |
1994 // verify that the breakpoint is not past the end of the method | |
1995 if (location >= (jlocation) method_oop->code_size()) { | |
1996 return JVMTI_ERROR_INVALID_LOCATION; | |
1997 } | |
1998 | |
1999 ResourceMark rm; | |
2000 JvmtiBreakpoint bp(method_oop, location); | |
2001 JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints(); | |
2002 if (jvmti_breakpoints.set(bp) == JVMTI_ERROR_DUPLICATE) | |
2003 return JVMTI_ERROR_DUPLICATE; | |
2004 | |
2005 if (TraceJVMTICalls) { | |
2006 jvmti_breakpoints.print(); | |
2007 } | |
2008 | |
2009 return JVMTI_ERROR_NONE; | |
2010 } /* end SetBreakpoint */ | |
2011 | |
2012 | |
2013 // method_oop - pre-checked for validity, but may be NULL meaning obsolete method | |
2014 jvmtiError | |
2015 JvmtiEnv::ClearBreakpoint(methodOop method_oop, jlocation location) { | |
2016 NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); | |
2017 | |
2018 if (location < 0) { // simple invalid location check first | |
2019 return JVMTI_ERROR_INVALID_LOCATION; | |
2020 } | |
2021 | |
2022 // verify that the breakpoint is not past the end of the method | |
2023 if (location >= (jlocation) method_oop->code_size()) { | |
2024 return JVMTI_ERROR_INVALID_LOCATION; | |
2025 } | |
2026 | |
2027 JvmtiBreakpoint bp(method_oop, location); | |
2028 | |
2029 JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints(); | |
2030 if (jvmti_breakpoints.clear(bp) == JVMTI_ERROR_NOT_FOUND) | |
2031 return JVMTI_ERROR_NOT_FOUND; | |
2032 | |
2033 if (TraceJVMTICalls) { | |
2034 jvmti_breakpoints.print(); | |
2035 } | |
2036 | |
2037 return JVMTI_ERROR_NONE; | |
2038 } /* end ClearBreakpoint */ | |
2039 | |
2040 | |
2041 // | |
2042 // Watched Field functions | |
2043 // | |
2044 | |
2045 jvmtiError | |
2046 JvmtiEnv::SetFieldAccessWatch(fieldDescriptor* fdesc_ptr) { | |
2047 // make sure we haven't set this watch before | |
2048 if (fdesc_ptr->is_field_access_watched()) return JVMTI_ERROR_DUPLICATE; | |
2049 fdesc_ptr->set_is_field_access_watched(true); | |
2050 | |
2051 JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_ACCESS, true); | |
2052 | |
2053 return JVMTI_ERROR_NONE; | |
2054 } /* end SetFieldAccessWatch */ | |
2055 | |
2056 | |
2057 jvmtiError | |
2058 JvmtiEnv::ClearFieldAccessWatch(fieldDescriptor* fdesc_ptr) { | |
2059 // make sure we have a watch to clear | |
2060 if (!fdesc_ptr->is_field_access_watched()) return JVMTI_ERROR_NOT_FOUND; | |
2061 fdesc_ptr->set_is_field_access_watched(false); | |
2062 | |
2063 JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_ACCESS, false); | |
2064 | |
2065 return JVMTI_ERROR_NONE; | |
2066 } /* end ClearFieldAccessWatch */ | |
2067 | |
2068 | |
2069 jvmtiError | |
2070 JvmtiEnv::SetFieldModificationWatch(fieldDescriptor* fdesc_ptr) { | |
2071 // make sure we haven't set this watch before | |
2072 if (fdesc_ptr->is_field_modification_watched()) return JVMTI_ERROR_DUPLICATE; | |
2073 fdesc_ptr->set_is_field_modification_watched(true); | |
2074 | |
2075 JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_MODIFICATION, true); | |
2076 | |
2077 return JVMTI_ERROR_NONE; | |
2078 } /* end SetFieldModificationWatch */ | |
2079 | |
2080 | |
2081 jvmtiError | |
2082 JvmtiEnv::ClearFieldModificationWatch(fieldDescriptor* fdesc_ptr) { | |
2083 // make sure we have a watch to clear | |
2084 if (!fdesc_ptr->is_field_modification_watched()) return JVMTI_ERROR_NOT_FOUND; | |
2085 fdesc_ptr->set_is_field_modification_watched(false); | |
2086 | |
2087 JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_MODIFICATION, false); | |
2088 | |
2089 return JVMTI_ERROR_NONE; | |
2090 } /* end ClearFieldModificationWatch */ | |
2091 | |
2092 // | |
2093 // Class functions | |
2094 // | |
2095 | |
2096 | |
2097 // k_mirror - may be primitive, this must be checked | |
2098 // signature_ptr - NULL is a valid value, must be checked | |
2099 // generic_ptr - NULL is a valid value, must be checked | |
2100 jvmtiError | |
2101 JvmtiEnv::GetClassSignature(oop k_mirror, char** signature_ptr, char** generic_ptr) { | |
2102 ResourceMark rm; | |
2103 bool isPrimitive = java_lang_Class::is_primitive(k_mirror); | |
2104 klassOop k = NULL; | |
2105 if (!isPrimitive) { | |
2106 k = java_lang_Class::as_klassOop(k_mirror); | |
2107 NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); | |
2108 } | |
2109 if (signature_ptr != NULL) { | |
2110 char* result = NULL; | |
2111 if (isPrimitive) { | |
2112 char tchar = type2char(java_lang_Class::primitive_type(k_mirror)); | |
2113 result = (char*) jvmtiMalloc(2); | |
2114 result[0] = tchar; | |
2115 result[1] = '\0'; | |
2116 } else { | |
2117 const char* class_sig = Klass::cast(k)->signature_name(); | |
2118 result = (char *) jvmtiMalloc(strlen(class_sig)+1); | |
2119 strcpy(result, class_sig); | |
2120 } | |
2121 *signature_ptr = result; | |
2122 } | |
2123 if (generic_ptr != NULL) { | |
2124 *generic_ptr = NULL; | |
2125 if (!isPrimitive && Klass::cast(k)->oop_is_instance()) { | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2100
diff
changeset
|
2126 Symbol* soo = instanceKlass::cast(k)->generic_signature(); |
0 | 2127 if (soo != NULL) { |
2128 const char *gen_sig = soo->as_C_string(); | |
2129 if (gen_sig != NULL) { | |
2130 char* gen_result; | |
2131 jvmtiError err = allocate(strlen(gen_sig) + 1, | |
2132 (unsigned char **)&gen_result); | |
2133 if (err != JVMTI_ERROR_NONE) { | |
2134 return err; | |
2135 } | |
2136 strcpy(gen_result, gen_sig); | |
2137 *generic_ptr = gen_result; | |
2138 } | |
2139 } | |
2140 } | |
2141 } | |
2142 return JVMTI_ERROR_NONE; | |
2143 } /* end GetClassSignature */ | |
2144 | |
2145 | |
2146 // k_mirror - may be primitive, this must be checked | |
2147 // status_ptr - pre-checked for NULL | |
2148 jvmtiError | |
2149 JvmtiEnv::GetClassStatus(oop k_mirror, jint* status_ptr) { | |
2150 jint result = 0; | |
2151 if (java_lang_Class::is_primitive(k_mirror)) { | |
2152 result |= JVMTI_CLASS_STATUS_PRIMITIVE; | |
2153 } else { | |
2154 klassOop k = java_lang_Class::as_klassOop(k_mirror); | |
2155 NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); | |
2156 result = Klass::cast(k)->jvmti_class_status(); | |
2157 } | |
2158 *status_ptr = result; | |
2159 | |
2160 return JVMTI_ERROR_NONE; | |
2161 } /* end GetClassStatus */ | |
2162 | |
2163 | |
2164 // k_mirror - may be primitive, this must be checked | |
2165 // source_name_ptr - pre-checked for NULL | |
2166 jvmtiError | |
2167 JvmtiEnv::GetSourceFileName(oop k_mirror, char** source_name_ptr) { | |
2168 if (java_lang_Class::is_primitive(k_mirror)) { | |
2169 return JVMTI_ERROR_ABSENT_INFORMATION; | |
2170 } | |
2171 klassOop k_klass = java_lang_Class::as_klassOop(k_mirror); | |
2172 NULL_CHECK(k_klass, JVMTI_ERROR_INVALID_CLASS); | |
2173 | |
2174 if (!Klass::cast(k_klass)->oop_is_instance()) { | |
2175 return JVMTI_ERROR_ABSENT_INFORMATION; | |
2176 } | |
2177 | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2100
diff
changeset
|
2178 Symbol* sfnOop = instanceKlass::cast(k_klass)->source_file_name(); |
0 | 2179 NULL_CHECK(sfnOop, JVMTI_ERROR_ABSENT_INFORMATION); |
2180 { | |
2181 JavaThread* current_thread = JavaThread::current(); | |
2182 ResourceMark rm(current_thread); | |
2183 const char* sfncp = (const char*) sfnOop->as_C_string(); | |
2184 *source_name_ptr = (char *) jvmtiMalloc(strlen(sfncp)+1); | |
2185 strcpy(*source_name_ptr, sfncp); | |
2186 } | |
2187 | |
2188 return JVMTI_ERROR_NONE; | |
2189 } /* end GetSourceFileName */ | |
2190 | |
2191 | |
2192 // k_mirror - may be primitive, this must be checked | |
2193 // modifiers_ptr - pre-checked for NULL | |
2194 jvmtiError | |
2195 JvmtiEnv::GetClassModifiers(oop k_mirror, jint* modifiers_ptr) { | |
2196 JavaThread* current_thread = JavaThread::current(); | |
2197 jint result = 0; | |
2198 if (!java_lang_Class::is_primitive(k_mirror)) { | |
2199 klassOop k = java_lang_Class::as_klassOop(k_mirror); | |
2200 NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); | |
2201 assert((Klass::cast(k)->oop_is_instance() || Klass::cast(k)->oop_is_array()), "should be an instance or an array klass"); | |
2202 result = Klass::cast(k)->compute_modifier_flags(current_thread); | |
2203 JavaThread* THREAD = current_thread; // pass to macros | |
2204 if (HAS_PENDING_EXCEPTION) { | |
2205 CLEAR_PENDING_EXCEPTION; | |
2206 return JVMTI_ERROR_INTERNAL; | |
2207 }; | |
2208 | |
2209 // Reset the deleted ACC_SUPER bit ( deleted in compute_modifier_flags()). | |
2210 if(Klass::cast(k)->is_super()) { | |
2211 result |= JVM_ACC_SUPER; | |
2212 } | |
2213 } else { | |
2214 result = (JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC); | |
2215 } | |
2216 *modifiers_ptr = result; | |
2217 | |
2218 return JVMTI_ERROR_NONE; | |
2219 } /* end GetClassModifiers */ | |
2220 | |
2221 | |
2222 // k_mirror - may be primitive, this must be checked | |
2223 // method_count_ptr - pre-checked for NULL | |
2224 // methods_ptr - pre-checked for NULL | |
2225 jvmtiError | |
2226 JvmtiEnv::GetClassMethods(oop k_mirror, jint* method_count_ptr, jmethodID** methods_ptr) { | |
2227 JavaThread* current_thread = JavaThread::current(); | |
2228 HandleMark hm(current_thread); | |
2229 | |
2230 if (java_lang_Class::is_primitive(k_mirror)) { | |
2231 *method_count_ptr = 0; | |
2232 *methods_ptr = (jmethodID*) jvmtiMalloc(0 * sizeof(jmethodID)); | |
2233 return JVMTI_ERROR_NONE; | |
2234 } | |
2235 klassOop k = java_lang_Class::as_klassOop(k_mirror); | |
2236 NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); | |
2237 | |
2238 // Return CLASS_NOT_PREPARED error as per JVMTI spec. | |
2239 if (!(Klass::cast(k)->jvmti_class_status() & (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY) )) { | |
2240 return JVMTI_ERROR_CLASS_NOT_PREPARED; | |
2241 } | |
2242 | |
2243 if (!Klass::cast(k)->oop_is_instance()) { | |
2244 *method_count_ptr = 0; | |
2245 *methods_ptr = (jmethodID*) jvmtiMalloc(0 * sizeof(jmethodID)); | |
2246 return JVMTI_ERROR_NONE; | |
2247 } | |
2248 instanceKlassHandle instanceK_h(current_thread, k); | |
2249 // Allocate the result and fill it in | |
2250 int result_length = instanceK_h->methods()->length(); | |
2251 jmethodID* result_list = (jmethodID*)jvmtiMalloc(result_length * sizeof(jmethodID)); | |
2252 int index; | |
2253 if (JvmtiExport::can_maintain_original_method_order()) { | |
2254 // Use the original method ordering indices stored in the class, so we can emit | |
2255 // jmethodIDs in the order they appeared in the class file | |
2256 for (index = 0; index < result_length; index++) { | |
2257 methodOop m = methodOop(instanceK_h->methods()->obj_at(index)); | |
2258 int original_index = instanceK_h->method_ordering()->int_at(index); | |
2259 assert(original_index >= 0 && original_index < result_length, "invalid original method index"); | |
2260 jmethodID id = m->jmethod_id(); | |
2261 result_list[original_index] = id; | |
2262 } | |
2263 } else { | |
2264 // otherwise just copy in any order | |
2265 for (index = 0; index < result_length; index++) { | |
2266 methodOop m = methodOop(instanceK_h->methods()->obj_at(index)); | |
2267 jmethodID id = m->jmethod_id(); | |
2268 result_list[index] = id; | |
2269 } | |
2270 } | |
2271 // Fill in return value. | |
2272 *method_count_ptr = result_length; | |
2273 *methods_ptr = result_list; | |
2274 | |
2275 return JVMTI_ERROR_NONE; | |
2276 } /* end GetClassMethods */ | |
2277 | |
2278 | |
2279 // k_mirror - may be primitive, this must be checked | |
2280 // field_count_ptr - pre-checked for NULL | |
2281 // fields_ptr - pre-checked for NULL | |
2282 jvmtiError | |
2283 JvmtiEnv::GetClassFields(oop k_mirror, jint* field_count_ptr, jfieldID** fields_ptr) { | |
2284 if (java_lang_Class::is_primitive(k_mirror)) { | |
2285 *field_count_ptr = 0; | |
2286 *fields_ptr = (jfieldID*) jvmtiMalloc(0 * sizeof(jfieldID)); | |
2287 return JVMTI_ERROR_NONE; | |
2288 } | |
2289 JavaThread* current_thread = JavaThread::current(); | |
2290 HandleMark hm(current_thread); | |
2291 klassOop k = java_lang_Class::as_klassOop(k_mirror); | |
2292 NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); | |
2293 | |
2294 // Return CLASS_NOT_PREPARED error as per JVMTI spec. | |
2295 if (!(Klass::cast(k)->jvmti_class_status() & (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY) )) { | |
2296 return JVMTI_ERROR_CLASS_NOT_PREPARED; | |
2297 } | |
2298 | |
2299 if (!Klass::cast(k)->oop_is_instance()) { | |
2300 *field_count_ptr = 0; | |
2301 *fields_ptr = (jfieldID*) jvmtiMalloc(0 * sizeof(jfieldID)); | |
2302 return JVMTI_ERROR_NONE; | |
2303 } | |
2304 | |
2305 | |
2306 instanceKlassHandle instanceK_h(current_thread, k); | |
2307 | |
2308 int result_count = 0; | |
2309 // First, count the fields. | |
2310 FilteredFieldStream flds(instanceK_h, true, true); | |
2311 result_count = flds.field_count(); | |
2312 | |
2313 // Allocate the result and fill it in | |
2314 jfieldID* result_list = (jfieldID*) jvmtiMalloc(result_count * sizeof(jfieldID)); | |
2315 // The JVMTI spec requires fields in the order they occur in the class file, | |
2316 // this is the reverse order of what FieldStream hands out. | |
2317 int id_index = (result_count - 1); | |
2318 | |
2319 for (FilteredFieldStream src_st(instanceK_h, true, true); !src_st.eos(); src_st.next()) { | |
2320 result_list[id_index--] = jfieldIDWorkaround::to_jfieldID( | |
2321 instanceK_h, src_st.offset(), | |
2322 src_st.access_flags().is_static()); | |
2323 } | |
2324 assert(id_index == -1, "just checking"); | |
2325 // Fill in the results | |
2326 *field_count_ptr = result_count; | |
2327 *fields_ptr = result_list; | |
2328 | |
2329 return JVMTI_ERROR_NONE; | |
2330 } /* end GetClassFields */ | |
2331 | |
2332 | |
2333 // k_mirror - may be primitive, this must be checked | |
2334 // interface_count_ptr - pre-checked for NULL | |
2335 // interfaces_ptr - pre-checked for NULL | |
2336 jvmtiError | |
2337 JvmtiEnv::GetImplementedInterfaces(oop k_mirror, jint* interface_count_ptr, jclass** interfaces_ptr) { | |
2338 { | |
2339 if (java_lang_Class::is_primitive(k_mirror)) { | |
2340 *interface_count_ptr = 0; | |
2341 *interfaces_ptr = (jclass*) jvmtiMalloc(0 * sizeof(jclass)); | |
2342 return JVMTI_ERROR_NONE; | |
2343 } | |
2344 JavaThread* current_thread = JavaThread::current(); | |
2345 HandleMark hm(current_thread); | |
2346 klassOop k = java_lang_Class::as_klassOop(k_mirror); | |
2347 NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); | |
2348 | |
2349 // Return CLASS_NOT_PREPARED error as per JVMTI spec. | |
2350 if (!(Klass::cast(k)->jvmti_class_status() & (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY) )) | |
2351 return JVMTI_ERROR_CLASS_NOT_PREPARED; | |
2352 | |
2353 if (!Klass::cast(k)->oop_is_instance()) { | |
2354 *interface_count_ptr = 0; | |
2355 *interfaces_ptr = (jclass*) jvmtiMalloc(0 * sizeof(jclass)); | |
2356 return JVMTI_ERROR_NONE; | |
2357 } | |
2358 | |
2359 objArrayHandle interface_list(current_thread, instanceKlass::cast(k)->local_interfaces()); | |
2360 const int result_length = (interface_list.is_null() ? 0 : interface_list->length()); | |
2361 jclass* result_list = (jclass*) jvmtiMalloc(result_length * sizeof(jclass)); | |
2362 for (int i_index = 0; i_index < result_length; i_index += 1) { | |
2363 oop oop_at = interface_list->obj_at(i_index); | |
2364 assert(oop_at->is_klass(), "interfaces must be klassOops"); | |
2365 klassOop klassOop_at = klassOop(oop_at); // ???: is there a better way? | |
2366 assert(Klass::cast(klassOop_at)->is_interface(), "interfaces must be interfaces"); | |
2367 oop mirror_at = Klass::cast(klassOop_at)->java_mirror(); | |
2368 Handle handle_at = Handle(current_thread, mirror_at); | |
2369 result_list[i_index] = (jclass) jni_reference(handle_at); | |
2370 } | |
2371 *interface_count_ptr = result_length; | |
2372 *interfaces_ptr = result_list; | |
2373 } | |
2374 | |
2375 return JVMTI_ERROR_NONE; | |
2376 } /* end GetImplementedInterfaces */ | |
2377 | |
2378 | |
2379 // k_mirror - may be primitive, this must be checked | |
2380 // minor_version_ptr - pre-checked for NULL | |
2381 // major_version_ptr - pre-checked for NULL | |
2382 jvmtiError | |
2383 JvmtiEnv::GetClassVersionNumbers(oop k_mirror, jint* minor_version_ptr, jint* major_version_ptr) { | |
2384 if (java_lang_Class::is_primitive(k_mirror)) { | |
2385 return JVMTI_ERROR_ABSENT_INFORMATION; | |
2386 } | |
2387 klassOop k_oop = java_lang_Class::as_klassOop(k_mirror); | |
2388 Thread *thread = Thread::current(); | |
2389 HandleMark hm(thread); | |
2390 KlassHandle klass(thread, k_oop); | |
2391 | |
2392 jint status = klass->jvmti_class_status(); | |
2393 if (status & (JVMTI_CLASS_STATUS_ERROR)) { | |
2394 return JVMTI_ERROR_INVALID_CLASS; | |
2395 } | |
2396 if (status & (JVMTI_CLASS_STATUS_ARRAY)) { | |
2397 return JVMTI_ERROR_ABSENT_INFORMATION; | |
2398 } | |
2399 | |
2400 instanceKlassHandle ik(thread, k_oop); | |
2401 *minor_version_ptr = ik->minor_version(); | |
2402 *major_version_ptr = ik->major_version(); | |
2403 | |
2404 return JVMTI_ERROR_NONE; | |
2405 } /* end GetClassVersionNumbers */ | |
2406 | |
2407 | |
2408 // k_mirror - may be primitive, this must be checked | |
2409 // constant_pool_count_ptr - pre-checked for NULL | |
2410 // constant_pool_byte_count_ptr - pre-checked for NULL | |
2411 // constant_pool_bytes_ptr - pre-checked for NULL | |
2412 jvmtiError | |
2413 JvmtiEnv::GetConstantPool(oop k_mirror, jint* constant_pool_count_ptr, jint* constant_pool_byte_count_ptr, unsigned char** constant_pool_bytes_ptr) { | |
2414 if (java_lang_Class::is_primitive(k_mirror)) { | |
2415 return JVMTI_ERROR_ABSENT_INFORMATION; | |
2416 } | |
2417 | |
2418 klassOop k_oop = java_lang_Class::as_klassOop(k_mirror); | |
2419 Thread *thread = Thread::current(); | |
2420 HandleMark hm(thread); | |
2421 ResourceMark rm(thread); | |
2422 KlassHandle klass(thread, k_oop); | |
2423 | |
2424 jint status = klass->jvmti_class_status(); | |
2425 if (status & (JVMTI_CLASS_STATUS_ERROR)) { | |
2426 return JVMTI_ERROR_INVALID_CLASS; | |
2427 } | |
2428 if (status & (JVMTI_CLASS_STATUS_ARRAY)) { | |
2429 return JVMTI_ERROR_ABSENT_INFORMATION; | |
2430 } | |
2431 | |
2432 instanceKlassHandle ikh(thread, k_oop); | |
2433 constantPoolHandle constants(thread, ikh->constants()); | |
2434 ObjectLocker ol(constants, thread); // lock constant pool while we query it | |
2435 | |
2436 JvmtiConstantPoolReconstituter reconstituter(ikh); | |
2437 if (reconstituter.get_error() != JVMTI_ERROR_NONE) { | |
2438 return reconstituter.get_error(); | |
2439 } | |
2440 | |
2441 unsigned char *cpool_bytes; | |
2442 int cpool_size = reconstituter.cpool_size(); | |
2443 if (reconstituter.get_error() != JVMTI_ERROR_NONE) { | |
2444 return reconstituter.get_error(); | |
2445 } | |
2446 jvmtiError res = allocate(cpool_size, &cpool_bytes); | |
2447 if (res != JVMTI_ERROR_NONE) { | |
2448 return res; | |
2449 } | |
2450 reconstituter.copy_cpool_bytes(cpool_bytes); | |
2451 if (reconstituter.get_error() != JVMTI_ERROR_NONE) { | |
2452 return reconstituter.get_error(); | |
2453 } | |
2454 | |
2455 *constant_pool_count_ptr = constants->length(); | |
2456 *constant_pool_byte_count_ptr = cpool_size; | |
2457 *constant_pool_bytes_ptr = cpool_bytes; | |
2458 | |
2459 return JVMTI_ERROR_NONE; | |
2460 } /* end GetConstantPool */ | |
2461 | |
2462 | |
2463 // k_mirror - may be primitive, this must be checked | |
2464 // is_interface_ptr - pre-checked for NULL | |
2465 jvmtiError | |
2466 JvmtiEnv::IsInterface(oop k_mirror, jboolean* is_interface_ptr) { | |
2467 { | |
2468 bool result = false; | |
2469 if (!java_lang_Class::is_primitive(k_mirror)) { | |
2470 klassOop k = java_lang_Class::as_klassOop(k_mirror); | |
2471 if (k != NULL && Klass::cast(k)->is_interface()) { | |
2472 result = true; | |
2473 } | |
2474 } | |
2475 *is_interface_ptr = result; | |
2476 } | |
2477 | |
2478 return JVMTI_ERROR_NONE; | |
2479 } /* end IsInterface */ | |
2480 | |
2481 | |
2482 // k_mirror - may be primitive, this must be checked | |
2483 // is_array_class_ptr - pre-checked for NULL | |
2484 jvmtiError | |
2485 JvmtiEnv::IsArrayClass(oop k_mirror, jboolean* is_array_class_ptr) { | |
2486 { | |
2487 bool result = false; | |
2488 if (!java_lang_Class::is_primitive(k_mirror)) { | |
2489 klassOop k = java_lang_Class::as_klassOop(k_mirror); | |
2490 if (k != NULL && Klass::cast(k)->oop_is_array()) { | |
2491 result = true; | |
2492 } | |
2493 } | |
2494 *is_array_class_ptr = result; | |
2495 } | |
2496 | |
2497 return JVMTI_ERROR_NONE; | |
2498 } /* end IsArrayClass */ | |
2499 | |
2500 | |
2501 // k_mirror - may be primitive, this must be checked | |
2502 // classloader_ptr - pre-checked for NULL | |
2503 jvmtiError | |
2504 JvmtiEnv::GetClassLoader(oop k_mirror, jobject* classloader_ptr) { | |
2505 { | |
2506 if (java_lang_Class::is_primitive(k_mirror)) { | |
2507 *classloader_ptr = (jclass) jni_reference(Handle()); | |
2508 return JVMTI_ERROR_NONE; | |
2509 } | |
2510 JavaThread* current_thread = JavaThread::current(); | |
2511 HandleMark hm(current_thread); | |
2512 klassOop k = java_lang_Class::as_klassOop(k_mirror); | |
2513 NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); | |
2514 | |
2515 oop result_oop = Klass::cast(k)->class_loader(); | |
2516 if (result_oop == NULL) { | |
2517 *classloader_ptr = (jclass) jni_reference(Handle()); | |
2518 return JVMTI_ERROR_NONE; | |
2519 } | |
2520 Handle result_handle = Handle(current_thread, result_oop); | |
2521 jclass result_jnihandle = (jclass) jni_reference(result_handle); | |
2522 *classloader_ptr = result_jnihandle; | |
2523 } | |
2524 return JVMTI_ERROR_NONE; | |
2525 } /* end GetClassLoader */ | |
2526 | |
2527 | |
2528 // k_mirror - may be primitive, this must be checked | |
2529 // source_debug_extension_ptr - pre-checked for NULL | |
2530 jvmtiError | |
2531 JvmtiEnv::GetSourceDebugExtension(oop k_mirror, char** source_debug_extension_ptr) { | |
2532 { | |
2533 if (java_lang_Class::is_primitive(k_mirror)) { | |
2534 return JVMTI_ERROR_ABSENT_INFORMATION; | |
2535 } | |
2536 klassOop k = java_lang_Class::as_klassOop(k_mirror); | |
2537 NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); | |
2538 if (!Klass::cast(k)->oop_is_instance()) { | |
2539 return JVMTI_ERROR_ABSENT_INFORMATION; | |
2540 } | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2100
diff
changeset
|
2541 Symbol* sdeOop = instanceKlass::cast(k)->source_debug_extension(); |
0 | 2542 NULL_CHECK(sdeOop, JVMTI_ERROR_ABSENT_INFORMATION); |
2543 | |
2544 { | |
2545 JavaThread* current_thread = JavaThread::current(); | |
2546 ResourceMark rm(current_thread); | |
2547 const char* sdecp = (const char*) sdeOop->as_C_string(); | |
2548 *source_debug_extension_ptr = (char *) jvmtiMalloc(strlen(sdecp)+1); | |
2549 strcpy(*source_debug_extension_ptr, sdecp); | |
2550 } | |
2551 } | |
2552 | |
2553 return JVMTI_ERROR_NONE; | |
2554 } /* end GetSourceDebugExtension */ | |
2555 | |
2556 // | |
2557 // Object functions | |
2558 // | |
2559 | |
2560 // hash_code_ptr - pre-checked for NULL | |
2561 jvmtiError | |
2562 JvmtiEnv::GetObjectHashCode(jobject object, jint* hash_code_ptr) { | |
2563 oop mirror = JNIHandles::resolve_external_guard(object); | |
2564 NULL_CHECK(mirror, JVMTI_ERROR_INVALID_OBJECT); | |
2565 NULL_CHECK(hash_code_ptr, JVMTI_ERROR_NULL_POINTER); | |
2566 | |
2567 { | |
2568 jint result = (jint) mirror->identity_hash(); | |
2569 *hash_code_ptr = result; | |
2570 } | |
2571 return JVMTI_ERROR_NONE; | |
2572 } /* end GetObjectHashCode */ | |
2573 | |
2574 | |
2575 // info_ptr - pre-checked for NULL | |
2576 jvmtiError | |
2577 JvmtiEnv::GetObjectMonitorUsage(jobject object, jvmtiMonitorUsage* info_ptr) { | |
2578 JavaThread* calling_thread = JavaThread::current(); | |
2579 jvmtiError err = get_object_monitor_usage(calling_thread, object, info_ptr); | |
2580 if (err == JVMTI_ERROR_THREAD_NOT_SUSPENDED) { | |
2581 // Some of the critical threads were not suspended. go to a safepoint and try again | |
2582 VM_GetObjectMonitorUsage op(this, calling_thread, object, info_ptr); | |
2583 VMThread::execute(&op); | |
2584 err = op.result(); | |
2585 } | |
2586 return err; | |
2587 } /* end GetObjectMonitorUsage */ | |
2588 | |
2589 | |
2590 // | |
2591 // Field functions | |
2592 // | |
2593 | |
2594 // name_ptr - NULL is a valid value, must be checked | |
2595 // signature_ptr - NULL is a valid value, must be checked | |
2596 // generic_ptr - NULL is a valid value, must be checked | |
2597 jvmtiError | |
2598 JvmtiEnv::GetFieldName(fieldDescriptor* fdesc_ptr, char** name_ptr, char** signature_ptr, char** generic_ptr) { | |
2599 JavaThread* current_thread = JavaThread::current(); | |
2600 ResourceMark rm(current_thread); | |
2601 if (name_ptr == NULL) { | |
2602 // just don't return the name | |
2603 } else { | |
2604 const char* fieldName = fdesc_ptr->name()->as_C_string(); | |
2605 *name_ptr = (char*) jvmtiMalloc(strlen(fieldName) + 1); | |
2606 if (*name_ptr == NULL) | |
2607 return JVMTI_ERROR_OUT_OF_MEMORY; | |
2608 strcpy(*name_ptr, fieldName); | |
2609 } | |
2610 if (signature_ptr== NULL) { | |
2611 // just don't return the signature | |
2612 } else { | |
2613 const char* fieldSignature = fdesc_ptr->signature()->as_C_string(); | |
2614 *signature_ptr = (char*) jvmtiMalloc(strlen(fieldSignature) + 1); | |
2615 if (*signature_ptr == NULL) | |
2616 return JVMTI_ERROR_OUT_OF_MEMORY; | |
2617 strcpy(*signature_ptr, fieldSignature); | |
2618 } | |
2619 if (generic_ptr != NULL) { | |
2620 *generic_ptr = NULL; | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2100
diff
changeset
|
2621 Symbol* soop = fdesc_ptr->generic_signature(); |
0 | 2622 if (soop != NULL) { |
2623 const char* gen_sig = soop->as_C_string(); | |
2624 if (gen_sig != NULL) { | |
2625 jvmtiError err = allocate(strlen(gen_sig) + 1, (unsigned char **)generic_ptr); | |
2626 if (err != JVMTI_ERROR_NONE) { | |
2627 return err; | |
2628 } | |
2629 strcpy(*generic_ptr, gen_sig); | |
2630 } | |
2631 } | |
2632 } | |
2633 return JVMTI_ERROR_NONE; | |
2634 } /* end GetFieldName */ | |
2635 | |
2636 | |
2637 // declaring_class_ptr - pre-checked for NULL | |
2638 jvmtiError | |
2639 JvmtiEnv::GetFieldDeclaringClass(fieldDescriptor* fdesc_ptr, jclass* declaring_class_ptr) { | |
2640 | |
2641 *declaring_class_ptr = get_jni_class_non_null(fdesc_ptr->field_holder()); | |
2642 return JVMTI_ERROR_NONE; | |
2643 } /* end GetFieldDeclaringClass */ | |
2644 | |
2645 | |
2646 // modifiers_ptr - pre-checked for NULL | |
2647 jvmtiError | |
2648 JvmtiEnv::GetFieldModifiers(fieldDescriptor* fdesc_ptr, jint* modifiers_ptr) { | |
2649 | |
2650 AccessFlags resultFlags = fdesc_ptr->access_flags(); | |
2651 jint result = resultFlags.as_int(); | |
2652 *modifiers_ptr = result; | |
2653 | |
2654 return JVMTI_ERROR_NONE; | |
2655 } /* end GetFieldModifiers */ | |
2656 | |
2657 | |
2658 // is_synthetic_ptr - pre-checked for NULL | |
2659 jvmtiError | |
2660 JvmtiEnv::IsFieldSynthetic(fieldDescriptor* fdesc_ptr, jboolean* is_synthetic_ptr) { | |
2661 *is_synthetic_ptr = fdesc_ptr->is_synthetic(); | |
2662 return JVMTI_ERROR_NONE; | |
2663 } /* end IsFieldSynthetic */ | |
2664 | |
2665 | |
2666 // | |
2667 // Method functions | |
2668 // | |
2669 | |
2670 // method_oop - pre-checked for validity, but may be NULL meaning obsolete method | |
2671 // name_ptr - NULL is a valid value, must be checked | |
2672 // signature_ptr - NULL is a valid value, must be checked | |
2673 // generic_ptr - NULL is a valid value, must be checked | |
2674 jvmtiError | |
2675 JvmtiEnv::GetMethodName(methodOop method_oop, char** name_ptr, char** signature_ptr, char** generic_ptr) { | |
2676 NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); | |
2677 JavaThread* current_thread = JavaThread::current(); | |
2678 | |
2679 ResourceMark rm(current_thread); // get the utf8 name and signature | |
2680 if (name_ptr == NULL) { | |
2681 // just don't return the name | |
2682 } else { | |
2683 const char* utf8_name = (const char *) method_oop->name()->as_utf8(); | |
2684 *name_ptr = (char *) jvmtiMalloc(strlen(utf8_name)+1); | |
2685 strcpy(*name_ptr, utf8_name); | |
2686 } | |
2687 if (signature_ptr == NULL) { | |
2688 // just don't return the signature | |
2689 } else { | |
2690 const char* utf8_signature = (const char *) method_oop->signature()->as_utf8(); | |
2691 *signature_ptr = (char *) jvmtiMalloc(strlen(utf8_signature) + 1); | |
2692 strcpy(*signature_ptr, utf8_signature); | |
2693 } | |
2694 | |
2695 if (generic_ptr != NULL) { | |
2696 *generic_ptr = NULL; | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
2100
diff
changeset
|
2697 Symbol* soop = method_oop->generic_signature(); |
0 | 2698 if (soop != NULL) { |
2699 const char* gen_sig = soop->as_C_string(); | |
2700 if (gen_sig != NULL) { | |
2701 jvmtiError err = allocate(strlen(gen_sig) + 1, (unsigned char **)generic_ptr); | |
2702 if (err != JVMTI_ERROR_NONE) { | |
2703 return err; | |
2704 } | |
2705 strcpy(*generic_ptr, gen_sig); | |
2706 } | |
2707 } | |
2708 } | |
2709 return JVMTI_ERROR_NONE; | |
2710 } /* end GetMethodName */ | |
2711 | |
2712 | |
2713 // method_oop - pre-checked for validity, but may be NULL meaning obsolete method | |
2714 // declaring_class_ptr - pre-checked for NULL | |
2715 jvmtiError | |
2716 JvmtiEnv::GetMethodDeclaringClass(methodOop method_oop, jclass* declaring_class_ptr) { | |
2717 NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); | |
2718 (*declaring_class_ptr) = get_jni_class_non_null(method_oop->method_holder()); | |
2719 return JVMTI_ERROR_NONE; | |
2720 } /* end GetMethodDeclaringClass */ | |
2721 | |
2722 | |
2723 // method_oop - pre-checked for validity, but may be NULL meaning obsolete method | |
2724 // modifiers_ptr - pre-checked for NULL | |
2725 jvmtiError | |
2726 JvmtiEnv::GetMethodModifiers(methodOop method_oop, jint* modifiers_ptr) { | |
2727 NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); | |
2728 (*modifiers_ptr) = method_oop->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS; | |
2729 return JVMTI_ERROR_NONE; | |
2730 } /* end GetMethodModifiers */ | |
2731 | |
2732 | |
2733 // method_oop - pre-checked for validity, but may be NULL meaning obsolete method | |
2734 // max_ptr - pre-checked for NULL | |
2735 jvmtiError | |
2736 JvmtiEnv::GetMaxLocals(methodOop method_oop, jint* max_ptr) { | |
2737 NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); | |
2738 // get max stack | |
2739 (*max_ptr) = method_oop->max_locals(); | |
2740 return JVMTI_ERROR_NONE; | |
2741 } /* end GetMaxLocals */ | |
2742 | |
2743 | |
2744 // method_oop - pre-checked for validity, but may be NULL meaning obsolete method | |
2745 // size_ptr - pre-checked for NULL | |
2746 jvmtiError | |
2747 JvmtiEnv::GetArgumentsSize(methodOop method_oop, jint* size_ptr) { | |
2748 NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); | |
2749 // get size of arguments | |
2750 | |
2751 (*size_ptr) = method_oop->size_of_parameters(); | |
2752 return JVMTI_ERROR_NONE; | |
2753 } /* end GetArgumentsSize */ | |
2754 | |
2755 | |
2756 // method_oop - pre-checked for validity, but may be NULL meaning obsolete method | |
2757 // entry_count_ptr - pre-checked for NULL | |
2758 // table_ptr - pre-checked for NULL | |
2759 jvmtiError | |
2760 JvmtiEnv::GetLineNumberTable(methodOop method_oop, jint* entry_count_ptr, jvmtiLineNumberEntry** table_ptr) { | |
2761 NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); | |
2762 if (!method_oop->has_linenumber_table()) { | |
2763 return (JVMTI_ERROR_ABSENT_INFORMATION); | |
2764 } | |
2765 | |
2766 // The line number table is compressed so we don't know how big it is until decompressed. | |
2767 // Decompression is really fast so we just do it twice. | |
2768 | |
2769 // Compute size of table | |
2770 jint num_entries = 0; | |
2771 CompressedLineNumberReadStream stream(method_oop->compressed_linenumber_table()); | |
2772 while (stream.read_pair()) { | |
2773 num_entries++; | |
2774 } | |
2775 jvmtiLineNumberEntry *jvmti_table = | |
2776 (jvmtiLineNumberEntry *)jvmtiMalloc(num_entries * (sizeof(jvmtiLineNumberEntry))); | |
2777 | |
2778 // Fill jvmti table | |
2779 if (num_entries > 0) { | |
2780 int index = 0; | |
2781 CompressedLineNumberReadStream stream(method_oop->compressed_linenumber_table()); | |
2782 while (stream.read_pair()) { | |
2783 jvmti_table[index].start_location = (jlocation) stream.bci(); | |
2784 jvmti_table[index].line_number = (jint) stream.line(); | |
2785 index++; | |
2786 } | |
2787 assert(index == num_entries, "sanity check"); | |
2788 } | |
2789 | |
2790 // Set up results | |
2791 (*entry_count_ptr) = num_entries; | |
2792 (*table_ptr) = jvmti_table; | |
2793 | |
2794 return JVMTI_ERROR_NONE; | |
2795 } /* end GetLineNumberTable */ | |
2796 | |
2797 | |
2798 // method_oop - pre-checked for validity, but may be NULL meaning obsolete method | |
2799 // start_location_ptr - pre-checked for NULL | |
2800 // end_location_ptr - pre-checked for NULL | |
2801 jvmtiError | |
2802 JvmtiEnv::GetMethodLocation(methodOop method_oop, jlocation* start_location_ptr, jlocation* end_location_ptr) { | |
2803 | |
2804 NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); | |
2805 // get start and end location | |
2806 (*end_location_ptr) = (jlocation) (method_oop->code_size() - 1); | |
2807 if (method_oop->code_size() == 0) { | |
2808 // there is no code so there is no start location | |
2809 (*start_location_ptr) = (jlocation)(-1); | |
2810 } else { | |
2811 (*start_location_ptr) = (jlocation)(0); | |
2812 } | |
2813 | |
2814 return JVMTI_ERROR_NONE; | |
2815 } /* end GetMethodLocation */ | |
2816 | |
2817 | |
2818 // method_oop - pre-checked for validity, but may be NULL meaning obsolete method | |
2819 // entry_count_ptr - pre-checked for NULL | |
2820 // table_ptr - pre-checked for NULL | |
2821 jvmtiError | |
2822 JvmtiEnv::GetLocalVariableTable(methodOop method_oop, jint* entry_count_ptr, jvmtiLocalVariableEntry** table_ptr) { | |
2823 | |
2824 NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); | |
2825 JavaThread* current_thread = JavaThread::current(); | |
2826 | |
2827 // does the klass have any local variable information? | |
2828 instanceKlass* ik = instanceKlass::cast(method_oop->method_holder()); | |
2829 if (!ik->access_flags().has_localvariable_table()) { | |
2830 return (JVMTI_ERROR_ABSENT_INFORMATION); | |
2831 } | |
2832 | |
2833 constantPoolOop constants = method_oop->constants(); | |
2834 NULL_CHECK(constants, JVMTI_ERROR_ABSENT_INFORMATION); | |
2835 | |
2836 // in the vm localvariable table representation, 6 consecutive elements in the table | |
2837 // represent a 6-tuple of shorts | |
2838 // [start_pc, length, name_index, descriptor_index, signature_index, index] | |
2839 jint num_entries = method_oop->localvariable_table_length(); | |
2840 jvmtiLocalVariableEntry *jvmti_table = (jvmtiLocalVariableEntry *) | |
2841 jvmtiMalloc(num_entries * (sizeof(jvmtiLocalVariableEntry))); | |
2842 | |
2843 if (num_entries > 0) { | |
2844 LocalVariableTableElement* table = method_oop->localvariable_table_start(); | |
2845 for (int i = 0; i < num_entries; i++) { | |
2846 // get the 5 tuple information from the vm table | |
2847 jlocation start_location = (jlocation) table[i].start_bci; | |
2848 jint length = (jint) table[i].length; | |
2849 int name_index = (int) table[i].name_cp_index; | |
2850 int signature_index = (int) table[i].descriptor_cp_index; | |
2851 int generic_signature_index = (int) table[i].signature_cp_index; | |
2852 jint slot = (jint) table[i].slot; | |
2853 | |
2854 // get utf8 name and signature | |
2855 char *name_buf = NULL; | |
2856 char *sig_buf = NULL; | |
2857 char *gen_sig_buf = NULL; | |
2858 { | |
2859 ResourceMark rm(current_thread); | |
2860 | |
2861 const char *utf8_name = (const char *) constants->symbol_at(name_index)->as_utf8(); | |
2862 name_buf = (char *) jvmtiMalloc(strlen(utf8_name)+1); | |
2863 strcpy(name_buf, utf8_name); | |
2864 | |
2865 const char *utf8_signature = (const char *) constants->symbol_at(signature_index)->as_utf8(); | |
2866 sig_buf = (char *) jvmtiMalloc(strlen(utf8_signature)+1); | |
2867 strcpy(sig_buf, utf8_signature); | |
2868 | |
2869 if (generic_signature_index > 0) { | |
2870 const char *utf8_gen_sign = (const char *) | |
2871 constants->symbol_at(generic_signature_index)->as_utf8(); | |
2872 gen_sig_buf = (char *) jvmtiMalloc(strlen(utf8_gen_sign)+1); | |
2873 strcpy(gen_sig_buf, utf8_gen_sign); | |
2874 } | |
2875 } | |
2876 | |
2877 // fill in the jvmti local variable table | |
2878 jvmti_table[i].start_location = start_location; | |
2879 jvmti_table[i].length = length; | |
2880 jvmti_table[i].name = name_buf; | |
2881 jvmti_table[i].signature = sig_buf; | |
2882 jvmti_table[i].generic_signature = gen_sig_buf; | |
2883 jvmti_table[i].slot = slot; | |
2884 } | |
2885 } | |
2886 | |
2887 // set results | |
2888 (*entry_count_ptr) = num_entries; | |
2889 (*table_ptr) = jvmti_table; | |
2890 | |
2891 return JVMTI_ERROR_NONE; | |
2892 } /* end GetLocalVariableTable */ | |
2893 | |
2894 | |
2895 // method_oop - pre-checked for validity, but may be NULL meaning obsolete method | |
2896 // bytecode_count_ptr - pre-checked for NULL | |
2897 // bytecodes_ptr - pre-checked for NULL | |
2898 jvmtiError | |
2899 JvmtiEnv::GetBytecodes(methodOop method_oop, jint* bytecode_count_ptr, unsigned char** bytecodes_ptr) { | |
2900 NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); | |
2901 | |
2902 HandleMark hm; | |
2903 methodHandle method(method_oop); | |
2904 jint size = (jint)method->code_size(); | |
2905 jvmtiError err = allocate(size, bytecodes_ptr); | |
2906 if (err != JVMTI_ERROR_NONE) { | |
2907 return err; | |
2908 } | |
2909 | |
2910 (*bytecode_count_ptr) = size; | |
2911 // get byte codes | |
2912 JvmtiClassFileReconstituter::copy_bytecodes(method, *bytecodes_ptr); | |
2913 | |
2914 return JVMTI_ERROR_NONE; | |
2915 } /* end GetBytecodes */ | |
2916 | |
2917 | |
2918 // method_oop - pre-checked for validity, but may be NULL meaning obsolete method | |
2919 // is_native_ptr - pre-checked for NULL | |
2920 jvmtiError | |
2921 JvmtiEnv::IsMethodNative(methodOop method_oop, jboolean* is_native_ptr) { | |
2922 NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); | |
2923 (*is_native_ptr) = method_oop->is_native(); | |
2924 return JVMTI_ERROR_NONE; | |
2925 } /* end IsMethodNative */ | |
2926 | |
2927 | |
2928 // method_oop - pre-checked for validity, but may be NULL meaning obsolete method | |
2929 // is_synthetic_ptr - pre-checked for NULL | |
2930 jvmtiError | |
2931 JvmtiEnv::IsMethodSynthetic(methodOop method_oop, jboolean* is_synthetic_ptr) { | |
2932 NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); | |
2933 (*is_synthetic_ptr) = method_oop->is_synthetic(); | |
2934 return JVMTI_ERROR_NONE; | |
2935 } /* end IsMethodSynthetic */ | |
2936 | |
2937 | |
2938 // method_oop - pre-checked for validity, but may be NULL meaning obsolete method | |
2939 // is_obsolete_ptr - pre-checked for NULL | |
2940 jvmtiError | |
2941 JvmtiEnv::IsMethodObsolete(methodOop method_oop, jboolean* is_obsolete_ptr) { | |
1121 | 2942 if (use_version_1_0_semantics() && |
2943 get_capabilities()->can_redefine_classes == 0) { | |
2944 // This JvmtiEnv requested version 1.0 semantics and this function | |
2945 // requires the can_redefine_classes capability in version 1.0 so | |
2946 // we need to return an error here. | |
2947 return JVMTI_ERROR_MUST_POSSESS_CAPABILITY; | |
2948 } | |
2949 | |
0 | 2950 if (method_oop == NULL || method_oop->is_obsolete()) { |
2951 *is_obsolete_ptr = true; | |
2952 } else { | |
2953 *is_obsolete_ptr = false; | |
2954 } | |
2955 return JVMTI_ERROR_NONE; | |
2956 } /* end IsMethodObsolete */ | |
2957 | |
2958 // | |
2959 // Raw Monitor functions | |
2960 // | |
2961 | |
2962 // name - pre-checked for NULL | |
2963 // monitor_ptr - pre-checked for NULL | |
2964 jvmtiError | |
2965 JvmtiEnv::CreateRawMonitor(const char* name, jrawMonitorID* monitor_ptr) { | |
2966 JvmtiRawMonitor* rmonitor = new JvmtiRawMonitor(name); | |
2967 NULL_CHECK(rmonitor, JVMTI_ERROR_OUT_OF_MEMORY); | |
2968 | |
2969 *monitor_ptr = (jrawMonitorID)rmonitor; | |
2970 | |
2971 return JVMTI_ERROR_NONE; | |
2972 } /* end CreateRawMonitor */ | |
2973 | |
2974 | |
2975 // rmonitor - pre-checked for validity | |
2976 jvmtiError | |
2977 JvmtiEnv::DestroyRawMonitor(JvmtiRawMonitor * rmonitor) { | |
2978 if (Threads::number_of_threads() == 0) { | |
2979 // Remove this monitor from pending raw monitors list | |
2980 // if it has entered in onload or start phase. | |
2981 JvmtiPendingMonitors::destroy(rmonitor); | |
2982 } else { | |
2983 Thread* thread = Thread::current(); | |
2984 if (rmonitor->is_entered(thread)) { | |
2985 // The caller owns this monitor which we are about to destroy. | |
2986 // We exit the underlying synchronization object so that the | |
2987 // "delete monitor" call below can work without an assertion | |
2988 // failure on systems that don't like destroying synchronization | |
2989 // objects that are locked. | |
2990 int r; | |
2991 intptr_t recursion = rmonitor->recursions(); | |
2992 for (intptr_t i=0; i <= recursion; i++) { | |
2993 r = rmonitor->raw_exit(thread); | |
2994 assert(r == ObjectMonitor::OM_OK, "raw_exit should have worked"); | |
2995 if (r != ObjectMonitor::OM_OK) { // robustness | |
2996 return JVMTI_ERROR_INTERNAL; | |
2997 } | |
2998 } | |
2999 } | |
3000 if (rmonitor->owner() != NULL) { | |
3001 // The caller is trying to destroy a monitor that is locked by | |
3002 // someone else. While this is not forbidden by the JVMTI | |
3003 // spec, it will cause an assertion failure on systems that don't | |
3004 // like destroying synchronization objects that are locked. | |
3005 // We indicate a problem with the error return (and leak the | |
3006 // monitor's memory). | |
3007 return JVMTI_ERROR_NOT_MONITOR_OWNER; | |
3008 } | |
3009 } | |
3010 | |
3011 delete rmonitor; | |
3012 | |
3013 return JVMTI_ERROR_NONE; | |
3014 } /* end DestroyRawMonitor */ | |
3015 | |
3016 | |
3017 // rmonitor - pre-checked for validity | |
3018 jvmtiError | |
3019 JvmtiEnv::RawMonitorEnter(JvmtiRawMonitor * rmonitor) { | |
3020 if (Threads::number_of_threads() == 0) { | |
3021 // No JavaThreads exist so ObjectMonitor enter cannot be | |
3022 // used, add this raw monitor to the pending list. | |
3023 // The pending monitors will be actually entered when | |
3024 // the VM is setup. | |
3025 // See transition_pending_raw_monitors in create_vm() | |
3026 // in thread.cpp. | |
3027 JvmtiPendingMonitors::enter(rmonitor); | |
3028 } else { | |
3029 int r; | |
3030 Thread* thread = Thread::current(); | |
3031 | |
3032 if (thread->is_Java_thread()) { | |
3033 JavaThread* current_thread = (JavaThread*)thread; | |
3034 | |
3035 #ifdef PROPER_TRANSITIONS | |
3036 // Not really unknown but ThreadInVMfromNative does more than we want | |
3037 ThreadInVMfromUnknown __tiv; | |
3038 { | |
3039 ThreadBlockInVM __tbivm(current_thread); | |
3040 r = rmonitor->raw_enter(current_thread); | |
3041 } | |
3042 #else | |
3043 /* Transition to thread_blocked without entering vm state */ | |
3044 /* This is really evil. Normally you can't undo _thread_blocked */ | |
3045 /* transitions like this because it would cause us to miss a */ | |
3046 /* safepoint but since the thread was already in _thread_in_native */ | |
3047 /* the thread is not leaving a safepoint safe state and it will */ | |
3048 /* block when it tries to return from native. We can't safepoint */ | |
3049 /* block in here because we could deadlock the vmthread. Blech. */ | |
3050 | |
3051 JavaThreadState state = current_thread->thread_state(); | |
3052 assert(state == _thread_in_native, "Must be _thread_in_native"); | |
3053 // frame should already be walkable since we are in native | |
3054 assert(!current_thread->has_last_Java_frame() || | |
3055 current_thread->frame_anchor()->walkable(), "Must be walkable"); | |
3056 current_thread->set_thread_state(_thread_blocked); | |
3057 | |
3058 r = rmonitor->raw_enter(current_thread); | |
3059 // restore state, still at a safepoint safe state | |
3060 current_thread->set_thread_state(state); | |
3061 | |
3062 #endif /* PROPER_TRANSITIONS */ | |
3063 assert(r == ObjectMonitor::OM_OK, "raw_enter should have worked"); | |
3064 } else { | |
3065 if (thread->is_VM_thread() || thread->is_ConcurrentGC_thread()) { | |
3066 r = rmonitor->raw_enter(thread); | |
3067 } else { | |
3068 ShouldNotReachHere(); | |
3069 } | |
3070 } | |
3071 | |
3072 if (r != ObjectMonitor::OM_OK) { // robustness | |
3073 return JVMTI_ERROR_INTERNAL; | |
3074 } | |
3075 } | |
3076 return JVMTI_ERROR_NONE; | |
3077 } /* end RawMonitorEnter */ | |
3078 | |
3079 | |
3080 // rmonitor - pre-checked for validity | |
3081 jvmtiError | |
3082 JvmtiEnv::RawMonitorExit(JvmtiRawMonitor * rmonitor) { | |
3083 jvmtiError err = JVMTI_ERROR_NONE; | |
3084 | |
3085 if (Threads::number_of_threads() == 0) { | |
3086 // No JavaThreads exist so just remove this monitor from the pending list. | |
3087 // Bool value from exit is false if rmonitor is not in the list. | |
3088 if (!JvmtiPendingMonitors::exit(rmonitor)) { | |
3089 err = JVMTI_ERROR_NOT_MONITOR_OWNER; | |
3090 } | |
3091 } else { | |
3092 int r; | |
3093 Thread* thread = Thread::current(); | |
3094 | |
3095 if (thread->is_Java_thread()) { | |
3096 JavaThread* current_thread = (JavaThread*)thread; | |
3097 #ifdef PROPER_TRANSITIONS | |
3098 // Not really unknown but ThreadInVMfromNative does more than we want | |
3099 ThreadInVMfromUnknown __tiv; | |
3100 #endif /* PROPER_TRANSITIONS */ | |
3101 r = rmonitor->raw_exit(current_thread); | |
3102 } else { | |
3103 if (thread->is_VM_thread() || thread->is_ConcurrentGC_thread()) { | |
3104 r = rmonitor->raw_exit(thread); | |
3105 } else { | |
3106 ShouldNotReachHere(); | |
3107 } | |
3108 } | |
3109 | |
3110 if (r == ObjectMonitor::OM_ILLEGAL_MONITOR_STATE) { | |
3111 err = JVMTI_ERROR_NOT_MONITOR_OWNER; | |
3112 } else { | |
3113 assert(r == ObjectMonitor::OM_OK, "raw_exit should have worked"); | |
3114 if (r != ObjectMonitor::OM_OK) { // robustness | |
3115 err = JVMTI_ERROR_INTERNAL; | |
3116 } | |
3117 } | |
3118 } | |
3119 return err; | |
3120 } /* end RawMonitorExit */ | |
3121 | |
3122 | |
3123 // rmonitor - pre-checked for validity | |
3124 jvmtiError | |
3125 JvmtiEnv::RawMonitorWait(JvmtiRawMonitor * rmonitor, jlong millis) { | |
3126 int r; | |
3127 Thread* thread = Thread::current(); | |
3128 | |
3129 if (thread->is_Java_thread()) { | |
3130 JavaThread* current_thread = (JavaThread*)thread; | |
3131 #ifdef PROPER_TRANSITIONS | |
3132 // Not really unknown but ThreadInVMfromNative does more than we want | |
3133 ThreadInVMfromUnknown __tiv; | |
3134 { | |
3135 ThreadBlockInVM __tbivm(current_thread); | |
3136 r = rmonitor->raw_wait(millis, true, current_thread); | |
3137 } | |
3138 #else | |
3139 /* Transition to thread_blocked without entering vm state */ | |
3140 /* This is really evil. Normally you can't undo _thread_blocked */ | |
3141 /* transitions like this because it would cause us to miss a */ | |
3142 /* safepoint but since the thread was already in _thread_in_native */ | |
3143 /* the thread is not leaving a safepoint safe state and it will */ | |
3144 /* block when it tries to return from native. We can't safepoint */ | |
3145 /* block in here because we could deadlock the vmthread. Blech. */ | |
3146 | |
3147 JavaThreadState state = current_thread->thread_state(); | |
3148 assert(state == _thread_in_native, "Must be _thread_in_native"); | |
3149 // frame should already be walkable since we are in native | |
3150 assert(!current_thread->has_last_Java_frame() || | |
3151 current_thread->frame_anchor()->walkable(), "Must be walkable"); | |
3152 current_thread->set_thread_state(_thread_blocked); | |
3153 | |
3154 r = rmonitor->raw_wait(millis, true, current_thread); | |
3155 // restore state, still at a safepoint safe state | |
3156 current_thread->set_thread_state(state); | |
3157 | |
3158 #endif /* PROPER_TRANSITIONS */ | |
3159 } else { | |
3160 if (thread->is_VM_thread() || thread->is_ConcurrentGC_thread()) { | |
3161 r = rmonitor->raw_wait(millis, true, thread); | |
3162 } else { | |
3163 ShouldNotReachHere(); | |
3164 } | |
3165 } | |
3166 | |
3167 switch (r) { | |
3168 case ObjectMonitor::OM_INTERRUPTED: | |
3169 return JVMTI_ERROR_INTERRUPT; | |
3170 case ObjectMonitor::OM_ILLEGAL_MONITOR_STATE: | |
3171 return JVMTI_ERROR_NOT_MONITOR_OWNER; | |
3172 } | |
3173 assert(r == ObjectMonitor::OM_OK, "raw_wait should have worked"); | |
3174 if (r != ObjectMonitor::OM_OK) { // robustness | |
3175 return JVMTI_ERROR_INTERNAL; | |
3176 } | |
3177 | |
3178 return JVMTI_ERROR_NONE; | |
3179 } /* end RawMonitorWait */ | |
3180 | |
3181 | |
3182 // rmonitor - pre-checked for validity | |
3183 jvmtiError | |
3184 JvmtiEnv::RawMonitorNotify(JvmtiRawMonitor * rmonitor) { | |
3185 int r; | |
3186 Thread* thread = Thread::current(); | |
3187 | |
3188 if (thread->is_Java_thread()) { | |
3189 JavaThread* current_thread = (JavaThread*)thread; | |
3190 // Not really unknown but ThreadInVMfromNative does more than we want | |
3191 ThreadInVMfromUnknown __tiv; | |
3192 r = rmonitor->raw_notify(current_thread); | |
3193 } else { | |
3194 if (thread->is_VM_thread() || thread->is_ConcurrentGC_thread()) { | |
3195 r = rmonitor->raw_notify(thread); | |
3196 } else { | |
3197 ShouldNotReachHere(); | |
3198 } | |
3199 } | |
3200 | |
3201 if (r == ObjectMonitor::OM_ILLEGAL_MONITOR_STATE) { | |
3202 return JVMTI_ERROR_NOT_MONITOR_OWNER; | |
3203 } | |
3204 assert(r == ObjectMonitor::OM_OK, "raw_notify should have worked"); | |
3205 if (r != ObjectMonitor::OM_OK) { // robustness | |
3206 return JVMTI_ERROR_INTERNAL; | |
3207 } | |
3208 | |
3209 return JVMTI_ERROR_NONE; | |
3210 } /* end RawMonitorNotify */ | |
3211 | |
3212 | |
3213 // rmonitor - pre-checked for validity | |
3214 jvmtiError | |
3215 JvmtiEnv::RawMonitorNotifyAll(JvmtiRawMonitor * rmonitor) { | |
3216 int r; | |
3217 Thread* thread = Thread::current(); | |
3218 | |
3219 if (thread->is_Java_thread()) { | |
3220 JavaThread* current_thread = (JavaThread*)thread; | |
3221 ThreadInVMfromUnknown __tiv; | |
3222 r = rmonitor->raw_notifyAll(current_thread); | |
3223 } else { | |
3224 if (thread->is_VM_thread() || thread->is_ConcurrentGC_thread()) { | |
3225 r = rmonitor->raw_notifyAll(thread); | |
3226 } else { | |
3227 ShouldNotReachHere(); | |
3228 } | |
3229 } | |
3230 | |
3231 if (r == ObjectMonitor::OM_ILLEGAL_MONITOR_STATE) { | |
3232 return JVMTI_ERROR_NOT_MONITOR_OWNER; | |
3233 } | |
3234 assert(r == ObjectMonitor::OM_OK, "raw_notifyAll should have worked"); | |
3235 if (r != ObjectMonitor::OM_OK) { // robustness | |
3236 return JVMTI_ERROR_INTERNAL; | |
3237 } | |
3238 | |
3239 return JVMTI_ERROR_NONE; | |
3240 } /* end RawMonitorNotifyAll */ | |
3241 | |
3242 | |
3243 // | |
3244 // JNI Function Interception functions | |
3245 // | |
3246 | |
3247 | |
3248 // function_table - pre-checked for NULL | |
3249 jvmtiError | |
3250 JvmtiEnv::SetJNIFunctionTable(const jniNativeInterface* function_table) { | |
3251 // Copy jni function table at safepoint. | |
3252 VM_JNIFunctionTableCopier copier(function_table); | |
3253 VMThread::execute(&copier); | |
3254 | |
3255 return JVMTI_ERROR_NONE; | |
3256 } /* end SetJNIFunctionTable */ | |
3257 | |
3258 | |
3259 // function_table - pre-checked for NULL | |
3260 jvmtiError | |
3261 JvmtiEnv::GetJNIFunctionTable(jniNativeInterface** function_table) { | |
3262 *function_table=(jniNativeInterface*)jvmtiMalloc(sizeof(jniNativeInterface)); | |
3263 if (*function_table == NULL) | |
3264 return JVMTI_ERROR_OUT_OF_MEMORY; | |
3265 memcpy(*function_table,(JavaThread::current())->get_jni_functions(),sizeof(jniNativeInterface)); | |
3266 return JVMTI_ERROR_NONE; | |
3267 } /* end GetJNIFunctionTable */ | |
3268 | |
3269 | |
3270 // | |
3271 // Event Management functions | |
3272 // | |
3273 | |
3274 jvmtiError | |
3275 JvmtiEnv::GenerateEvents(jvmtiEvent event_type) { | |
3276 // can only generate two event types | |
3277 if (event_type != JVMTI_EVENT_COMPILED_METHOD_LOAD && | |
3278 event_type != JVMTI_EVENT_DYNAMIC_CODE_GENERATED) { | |
3279 return JVMTI_ERROR_ILLEGAL_ARGUMENT; | |
3280 } | |
3281 | |
3282 // for compiled_method_load events we must check that the environment | |
3283 // has the can_generate_compiled_method_load_events capability. | |
3284 if (event_type == JVMTI_EVENT_COMPILED_METHOD_LOAD) { | |
3285 if (get_capabilities()->can_generate_compiled_method_load_events == 0) { | |
3286 return JVMTI_ERROR_MUST_POSSESS_CAPABILITY; | |
3287 } | |
3288 return JvmtiCodeBlobEvents::generate_compiled_method_load_events(this); | |
3289 } else { | |
3290 return JvmtiCodeBlobEvents::generate_dynamic_code_events(this); | |
3291 } | |
3292 | |
3293 } /* end GenerateEvents */ | |
3294 | |
3295 | |
3296 // | |
3297 // Extension Mechanism functions | |
3298 // | |
3299 | |
3300 // extension_count_ptr - pre-checked for NULL | |
3301 // extensions - pre-checked for NULL | |
3302 jvmtiError | |
3303 JvmtiEnv::GetExtensionFunctions(jint* extension_count_ptr, jvmtiExtensionFunctionInfo** extensions) { | |
3304 return JvmtiExtensions::get_functions(this, extension_count_ptr, extensions); | |
3305 } /* end GetExtensionFunctions */ | |
3306 | |
3307 | |
3308 // extension_count_ptr - pre-checked for NULL | |
3309 // extensions - pre-checked for NULL | |
3310 jvmtiError | |
3311 JvmtiEnv::GetExtensionEvents(jint* extension_count_ptr, jvmtiExtensionEventInfo** extensions) { | |
3312 return JvmtiExtensions::get_events(this, extension_count_ptr, extensions); | |
3313 } /* end GetExtensionEvents */ | |
3314 | |
3315 | |
3316 // callback - NULL is a valid value, must be checked | |
3317 jvmtiError | |
3318 JvmtiEnv::SetExtensionEventCallback(jint extension_event_index, jvmtiExtensionEvent callback) { | |
3319 return JvmtiExtensions::set_event_callback(this, extension_event_index, callback); | |
3320 } /* end SetExtensionEventCallback */ | |
3321 | |
3322 // | |
3323 // Timers functions | |
3324 // | |
3325 | |
3326 // info_ptr - pre-checked for NULL | |
3327 jvmtiError | |
3328 JvmtiEnv::GetCurrentThreadCpuTimerInfo(jvmtiTimerInfo* info_ptr) { | |
3329 os::current_thread_cpu_time_info(info_ptr); | |
3330 return JVMTI_ERROR_NONE; | |
3331 } /* end GetCurrentThreadCpuTimerInfo */ | |
3332 | |
3333 | |
3334 // nanos_ptr - pre-checked for NULL | |
3335 jvmtiError | |
3336 JvmtiEnv::GetCurrentThreadCpuTime(jlong* nanos_ptr) { | |
3337 *nanos_ptr = os::current_thread_cpu_time(); | |
3338 return JVMTI_ERROR_NONE; | |
3339 } /* end GetCurrentThreadCpuTime */ | |
3340 | |
3341 | |
3342 // info_ptr - pre-checked for NULL | |
3343 jvmtiError | |
3344 JvmtiEnv::GetThreadCpuTimerInfo(jvmtiTimerInfo* info_ptr) { | |
3345 os::thread_cpu_time_info(info_ptr); | |
3346 return JVMTI_ERROR_NONE; | |
3347 } /* end GetThreadCpuTimerInfo */ | |
3348 | |
3349 | |
3350 // Threads_lock NOT held, java_thread not protected by lock | |
3351 // java_thread - pre-checked | |
3352 // nanos_ptr - pre-checked for NULL | |
3353 jvmtiError | |
3354 JvmtiEnv::GetThreadCpuTime(JavaThread* java_thread, jlong* nanos_ptr) { | |
3355 *nanos_ptr = os::thread_cpu_time(java_thread); | |
3356 return JVMTI_ERROR_NONE; | |
3357 } /* end GetThreadCpuTime */ | |
3358 | |
3359 | |
3360 // info_ptr - pre-checked for NULL | |
3361 jvmtiError | |
3362 JvmtiEnv::GetTimerInfo(jvmtiTimerInfo* info_ptr) { | |
3363 os::javaTimeNanos_info(info_ptr); | |
3364 return JVMTI_ERROR_NONE; | |
3365 } /* end GetTimerInfo */ | |
3366 | |
3367 | |
3368 // nanos_ptr - pre-checked for NULL | |
3369 jvmtiError | |
3370 JvmtiEnv::GetTime(jlong* nanos_ptr) { | |
3371 *nanos_ptr = os::javaTimeNanos(); | |
3372 return JVMTI_ERROR_NONE; | |
3373 } /* end GetTime */ | |
3374 | |
3375 | |
3376 // processor_count_ptr - pre-checked for NULL | |
3377 jvmtiError | |
3378 JvmtiEnv::GetAvailableProcessors(jint* processor_count_ptr) { | |
3379 *processor_count_ptr = os::active_processor_count(); | |
3380 return JVMTI_ERROR_NONE; | |
3381 } /* end GetAvailableProcessors */ | |
3382 | |
3383 // | |
3384 // System Properties functions | |
3385 // | |
3386 | |
3387 // count_ptr - pre-checked for NULL | |
3388 // property_ptr - pre-checked for NULL | |
3389 jvmtiError | |
3390 JvmtiEnv::GetSystemProperties(jint* count_ptr, char*** property_ptr) { | |
3391 jvmtiError err = JVMTI_ERROR_NONE; | |
3392 | |
3393 *count_ptr = Arguments::PropertyList_count(Arguments::system_properties()); | |
3394 | |
3395 err = allocate(*count_ptr * sizeof(char *), (unsigned char **)property_ptr); | |
3396 if (err != JVMTI_ERROR_NONE) { | |
3397 return err; | |
3398 } | |
3399 int i = 0 ; | |
3400 for (SystemProperty* p = Arguments::system_properties(); p != NULL && i < *count_ptr; p = p->next(), i++) { | |
3401 const char *key = p->key(); | |
3402 char **tmp_value = *property_ptr+i; | |
3403 err = allocate((strlen(key)+1) * sizeof(char), (unsigned char**)tmp_value); | |
3404 if (err == JVMTI_ERROR_NONE) { | |
3405 strcpy(*tmp_value, key); | |
3406 } else { | |
3407 // clean up previously allocated memory. | |
3408 for (int j=0; j<i; j++) { | |
3409 Deallocate((unsigned char*)*property_ptr+j); | |
3410 } | |
3411 Deallocate((unsigned char*)property_ptr); | |
3412 break; | |
3413 } | |
3414 } | |
3415 return err; | |
3416 } /* end GetSystemProperties */ | |
3417 | |
3418 | |
3419 // property - pre-checked for NULL | |
3420 // value_ptr - pre-checked for NULL | |
3421 jvmtiError | |
3422 JvmtiEnv::GetSystemProperty(const char* property, char** value_ptr) { | |
3423 jvmtiError err = JVMTI_ERROR_NONE; | |
3424 const char *value; | |
3425 | |
3426 value = Arguments::PropertyList_get_value(Arguments::system_properties(), property); | |
3427 if (value == NULL) { | |
3428 err = JVMTI_ERROR_NOT_AVAILABLE; | |
3429 } else { | |
3430 err = allocate((strlen(value)+1) * sizeof(char), (unsigned char **)value_ptr); | |
3431 if (err == JVMTI_ERROR_NONE) { | |
3432 strcpy(*value_ptr, value); | |
3433 } | |
3434 } | |
3435 return err; | |
3436 } /* end GetSystemProperty */ | |
3437 | |
3438 | |
3439 // property - pre-checked for NULL | |
3440 // value - NULL is a valid value, must be checked | |
3441 jvmtiError | |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
2019
diff
changeset
|
3442 JvmtiEnv::SetSystemProperty(const char* property, const char* value_ptr) { |
0 | 3443 jvmtiError err =JVMTI_ERROR_NOT_AVAILABLE; |
3444 | |
3445 for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) { | |
3446 if (strcmp(property, p->key()) == 0) { | |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
2019
diff
changeset
|
3447 if (p->set_value((char *)value_ptr)) { |
0 | 3448 err = JVMTI_ERROR_NONE; |
3449 } | |
3450 } | |
3451 } | |
3452 return err; | |
3453 } /* end SetSystemProperty */ | |
3454 | |
3455 #endif // !JVMTI_KERNEL |