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