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