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