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