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