duke@435: /* zgu@4492: * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: stefank@2314: #include "precompiled.hpp" stefank@2314: #include "classfile/systemDictionary.hpp" stefank@2314: #include "classfile/vmSymbols.hpp" stefank@2314: #include "interpreter/bytecodeStream.hpp" stefank@2314: #include "interpreter/interpreter.hpp" stefank@2314: #include "jvmtifiles/jvmtiEnv.hpp" stefank@2314: #include "memory/resourceArea.hpp" stefank@2314: #include "memory/universe.inline.hpp" stefank@2314: #include "oops/instanceKlass.hpp" stefank@2314: #include "prims/jniCheck.hpp" stefank@2314: #include "prims/jvm_misc.hpp" stefank@2314: #include "prims/jvmtiAgentThread.hpp" stefank@2314: #include "prims/jvmtiClassFileReconstituter.hpp" stefank@2314: #include "prims/jvmtiCodeBlobEvents.hpp" stefank@2314: #include "prims/jvmtiExtensions.hpp" stefank@2314: #include "prims/jvmtiGetLoadedClasses.hpp" stefank@2314: #include "prims/jvmtiImpl.hpp" stefank@2314: #include "prims/jvmtiManageCapabilities.hpp" stefank@2314: #include "prims/jvmtiRawMonitor.hpp" stefank@2314: #include "prims/jvmtiRedefineClasses.hpp" stefank@2314: #include "prims/jvmtiTagMap.hpp" stefank@2314: #include "prims/jvmtiThreadState.inline.hpp" stefank@2314: #include "prims/jvmtiUtil.hpp" stefank@2314: #include "runtime/arguments.hpp" stefank@2314: #include "runtime/deoptimization.hpp" stefank@2314: #include "runtime/interfaceSupport.hpp" stefank@2314: #include "runtime/javaCalls.hpp" stefank@2314: #include "runtime/jfieldIDWorkaround.hpp" stefank@2314: #include "runtime/osThread.hpp" stefank@2314: #include "runtime/reflectionUtils.hpp" stefank@2314: #include "runtime/signature.hpp" stefank@4299: #include "runtime/thread.inline.hpp" stefank@2314: #include "runtime/vframe.hpp" stefank@2314: #include "runtime/vmThread.hpp" stefank@2314: #include "services/threadService.hpp" stefank@2314: #include "utilities/exceptions.hpp" stefank@2314: #include "utilities/preserveException.hpp" duke@435: duke@435: duke@435: #define FIXLATER 0 // REMOVE this when completed. duke@435: duke@435: // FIXLATER: hook into JvmtiTrace duke@435: #define TraceJVMTICalls false duke@435: dcubed@1556: JvmtiEnv::JvmtiEnv(jint version) : JvmtiEnvBase(version) { duke@435: } duke@435: duke@435: JvmtiEnv::~JvmtiEnv() { duke@435: } duke@435: duke@435: JvmtiEnv* dcubed@1556: JvmtiEnv::create_a_jvmti(jint version) { dcubed@1556: return new JvmtiEnv(version); duke@435: } duke@435: duke@435: // VM operation class to copy jni function table at safepoint. duke@435: // More than one java threads or jvmti agents may be reading/ duke@435: // modifying jni function tables. To reduce the risk of bad duke@435: // interaction b/w these threads it is copied at safepoint. duke@435: class VM_JNIFunctionTableCopier : public VM_Operation { duke@435: private: duke@435: const struct JNINativeInterface_ *_function_table; duke@435: public: duke@435: VM_JNIFunctionTableCopier(const struct JNINativeInterface_ *func_tbl) { duke@435: _function_table = func_tbl; duke@435: }; duke@435: duke@435: VMOp_Type type() const { return VMOp_JNIFunctionTableCopier; } duke@435: void doit() { duke@435: copy_jni_function_table(_function_table); duke@435: }; duke@435: }; duke@435: duke@435: // duke@435: // Do not change the "prefix" marker below, everything above it is copied duke@435: // unchanged into the filled stub, everything below is controlled by the duke@435: // stub filler (only method bodies are carried forward, and then only for duke@435: // functionality still in the spec). duke@435: // duke@435: // end file prefix duke@435: duke@435: // duke@435: // Memory Management functions duke@435: // duke@435: duke@435: // mem_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::Allocate(jlong size, unsigned char** mem_ptr) { duke@435: return allocate(size, mem_ptr); duke@435: } /* end Allocate */ duke@435: duke@435: duke@435: // mem - NULL is a valid value, must be checked duke@435: jvmtiError duke@435: JvmtiEnv::Deallocate(unsigned char* mem) { duke@435: return deallocate(mem); duke@435: } /* end Deallocate */ duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: // data - NULL is a valid value, must be checked duke@435: jvmtiError duke@435: JvmtiEnv::SetThreadLocalStorage(JavaThread* java_thread, const void* data) { duke@435: JvmtiThreadState* state = java_thread->jvmti_thread_state(); duke@435: if (state == NULL) { duke@435: if (data == NULL) { duke@435: // leaving state unset same as data set to NULL duke@435: return JVMTI_ERROR_NONE; duke@435: } duke@435: // otherwise, create the state duke@435: state = JvmtiThreadState::state_for(java_thread); dcubed@1044: if (state == NULL) { dcubed@1044: return JVMTI_ERROR_THREAD_NOT_ALIVE; dcubed@1044: } duke@435: } duke@435: state->env_thread_state(this)->set_agent_thread_local_storage_data((void*)data); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end SetThreadLocalStorage */ duke@435: duke@435: duke@435: // Threads_lock NOT held duke@435: // thread - NOT pre-checked duke@435: // data_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetThreadLocalStorage(jthread thread, void** data_ptr) { duke@435: JavaThread* current_thread = JavaThread::current(); duke@435: if (thread == NULL) { duke@435: JvmtiThreadState* state = current_thread->jvmti_thread_state(); duke@435: *data_ptr = (state == NULL) ? NULL : duke@435: state->env_thread_state(this)->get_agent_thread_local_storage_data(); duke@435: } else { duke@435: duke@435: // jvmti_GetThreadLocalStorage is "in native" and doesn't transition duke@435: // the thread to _thread_in_vm. However, when the TLS for a thread duke@435: // other than the current thread is required we need to transition duke@435: // from native so as to resolve the jthread. duke@435: duke@435: ThreadInVMfromNative __tiv(current_thread); never@3241: VM_ENTRY_BASE(jvmtiError, JvmtiEnv::GetThreadLocalStorage , current_thread) duke@435: debug_only(VMNativeEntryWrapper __vew;) duke@435: duke@435: oop thread_oop = JNIHandles::resolve_external_guard(thread); duke@435: if (thread_oop == NULL) { duke@435: return JVMTI_ERROR_INVALID_THREAD; duke@435: } never@1577: if (!thread_oop->is_a(SystemDictionary::Thread_klass())) { duke@435: return JVMTI_ERROR_INVALID_THREAD; duke@435: } duke@435: JavaThread* java_thread = java_lang_Thread::thread(thread_oop); duke@435: if (java_thread == NULL) { duke@435: return JVMTI_ERROR_THREAD_NOT_ALIVE; duke@435: } duke@435: JvmtiThreadState* state = java_thread->jvmti_thread_state(); duke@435: *data_ptr = (state == NULL) ? NULL : duke@435: state->env_thread_state(this)->get_agent_thread_local_storage_data(); duke@435: } duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetThreadLocalStorage */ duke@435: duke@435: // duke@435: // Class functions duke@435: // duke@435: duke@435: // class_count_ptr - pre-checked for NULL duke@435: // classes_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetLoadedClasses(jint* class_count_ptr, jclass** classes_ptr) { duke@435: return JvmtiGetLoadedClasses::getLoadedClasses(this, class_count_ptr, classes_ptr); duke@435: } /* end GetLoadedClasses */ duke@435: duke@435: duke@435: // initiating_loader - NULL is a valid value, must be checked duke@435: // class_count_ptr - pre-checked for NULL duke@435: // classes_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetClassLoaderClasses(jobject initiating_loader, jint* class_count_ptr, jclass** classes_ptr) { duke@435: return JvmtiGetLoadedClasses::getClassLoaderClasses(this, initiating_loader, duke@435: class_count_ptr, classes_ptr); duke@435: } /* end GetClassLoaderClasses */ duke@435: duke@435: // k_mirror - may be primitive, this must be checked duke@435: // is_modifiable_class_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::IsModifiableClass(oop k_mirror, jboolean* is_modifiable_class_ptr) { duke@435: *is_modifiable_class_ptr = VM_RedefineClasses::is_modifiable_class(k_mirror)? duke@435: JNI_TRUE : JNI_FALSE; duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end IsModifiableClass */ duke@435: duke@435: // class_count - pre-checked to be greater than or equal to 0 duke@435: // classes - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) { duke@435: //TODO: add locking duke@435: duke@435: int index; duke@435: JavaThread* current_thread = JavaThread::current(); duke@435: ResourceMark rm(current_thread); duke@435: duke@435: jvmtiClassDefinition* class_definitions = duke@435: NEW_RESOURCE_ARRAY(jvmtiClassDefinition, class_count); duke@435: NULL_CHECK(class_definitions, JVMTI_ERROR_OUT_OF_MEMORY); duke@435: duke@435: for (index = 0; index < class_count; index++) { duke@435: HandleMark hm(current_thread); duke@435: duke@435: jclass jcls = classes[index]; duke@435: oop k_mirror = JNIHandles::resolve_external_guard(jcls); duke@435: if (k_mirror == NULL) { duke@435: return JVMTI_ERROR_INVALID_CLASS; duke@435: } never@1577: if (!k_mirror->is_a(SystemDictionary::Class_klass())) { duke@435: return JVMTI_ERROR_INVALID_CLASS; duke@435: } duke@435: duke@435: if (java_lang_Class::is_primitive(k_mirror)) { duke@435: return JVMTI_ERROR_UNMODIFIABLE_CLASS; duke@435: } duke@435: coleenp@4037: Klass* k_oop = java_lang_Class::as_Klass(k_mirror); duke@435: KlassHandle klass(current_thread, k_oop); duke@435: duke@435: jint status = klass->jvmti_class_status(); duke@435: if (status & (JVMTI_CLASS_STATUS_ERROR)) { duke@435: return JVMTI_ERROR_INVALID_CLASS; duke@435: } duke@435: if (status & (JVMTI_CLASS_STATUS_ARRAY)) { duke@435: return JVMTI_ERROR_UNMODIFIABLE_CLASS; duke@435: } duke@435: duke@435: instanceKlassHandle ikh(current_thread, k_oop); duke@435: if (ikh->get_cached_class_file_bytes() == NULL) { dcubed@3360: // Not cached, we need to reconstitute the class file from the dcubed@3360: // VM representation. We don't attach the reconstituted class coleenp@4037: // bytes to the InstanceKlass here because they have not been dcubed@3360: // validated and we're not at a safepoint. duke@435: constantPoolHandle constants(current_thread, ikh->constants()); iklam@5971: MonitorLockerEx ml(constants->lock()); // lock constant pool while we query it duke@435: duke@435: JvmtiClassFileReconstituter reconstituter(ikh); duke@435: if (reconstituter.get_error() != JVMTI_ERROR_NONE) { duke@435: return reconstituter.get_error(); duke@435: } duke@435: duke@435: class_definitions[index].class_byte_count = (jint)reconstituter.class_file_size(); duke@435: class_definitions[index].class_bytes = (unsigned char*) duke@435: reconstituter.class_file_bytes(); duke@435: } else { duke@435: // it is cached, get it from the cache duke@435: class_definitions[index].class_byte_count = ikh->get_cached_class_file_len(); duke@435: class_definitions[index].class_bytes = ikh->get_cached_class_file_bytes(); duke@435: } duke@435: class_definitions[index].klass = jcls; duke@435: } duke@435: VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform); duke@435: VMThread::execute(&op); duke@435: return (op.check_error()); duke@435: } /* end RetransformClasses */ duke@435: duke@435: duke@435: // class_count - pre-checked to be greater than or equal to 0 duke@435: // class_definitions - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::RedefineClasses(jint class_count, const jvmtiClassDefinition* class_definitions) { duke@435: //TODO: add locking duke@435: VM_RedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_redefine); duke@435: VMThread::execute(&op); duke@435: return (op.check_error()); duke@435: } /* end RedefineClasses */ duke@435: duke@435: duke@435: // duke@435: // Object functions duke@435: // duke@435: duke@435: // size_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetObjectSize(jobject object, jlong* size_ptr) { duke@435: oop mirror = JNIHandles::resolve_external_guard(object); duke@435: NULL_CHECK(mirror, JVMTI_ERROR_INVALID_OBJECT); duke@435: coleenp@4037: if (mirror->klass() == SystemDictionary::Class_klass() && coleenp@4037: !java_lang_Class::is_primitive(mirror)) { coleenp@4037: Klass* k = java_lang_Class::as_Klass(mirror); coleenp@4037: assert(k != NULL, "class for non-primitive mirror must exist"); coleenp@4037: *size_ptr = k->size() * wordSize; coleenp@4037: } else { coleenp@4037: *size_ptr = mirror->size() * wordSize; duke@435: } duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetObjectSize */ duke@435: duke@435: // duke@435: // Method functions duke@435: // duke@435: duke@435: // prefix - NULL is a valid value, must be checked duke@435: jvmtiError duke@435: JvmtiEnv::SetNativeMethodPrefix(const char* prefix) { duke@435: return prefix == NULL? duke@435: SetNativeMethodPrefixes(0, NULL) : duke@435: SetNativeMethodPrefixes(1, (char**)&prefix); duke@435: } /* end SetNativeMethodPrefix */ duke@435: duke@435: duke@435: // prefix_count - pre-checked to be greater than or equal to 0 duke@435: // prefixes - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::SetNativeMethodPrefixes(jint prefix_count, char** prefixes) { duke@435: // Have to grab JVMTI thread state lock to be sure that some thread duke@435: // isn't accessing the prefixes at the same time we are setting them. duke@435: // No locks during VM bring-up. duke@435: if (Threads::number_of_threads() == 0) { duke@435: return set_native_method_prefixes(prefix_count, prefixes); duke@435: } else { duke@435: MutexLocker mu(JvmtiThreadState_lock); duke@435: return set_native_method_prefixes(prefix_count, prefixes); duke@435: } duke@435: } /* end SetNativeMethodPrefixes */ duke@435: duke@435: // duke@435: // Event Management functions duke@435: // duke@435: duke@435: // callbacks - NULL is a valid value, must be checked duke@435: // size_of_callbacks - pre-checked to be greater than or equal to 0 duke@435: jvmtiError duke@435: JvmtiEnv::SetEventCallbacks(const jvmtiEventCallbacks* callbacks, jint size_of_callbacks) { duke@435: JvmtiEventController::set_event_callbacks(this, callbacks, size_of_callbacks); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end SetEventCallbacks */ duke@435: duke@435: duke@435: // event_thread - NULL is a valid value, must be checked duke@435: jvmtiError duke@435: JvmtiEnv::SetEventNotificationMode(jvmtiEventMode mode, jvmtiEvent event_type, jthread event_thread, ...) { duke@435: JavaThread* java_thread = NULL; duke@435: if (event_thread != NULL) { duke@435: oop thread_oop = JNIHandles::resolve_external_guard(event_thread); duke@435: if (thread_oop == NULL) { duke@435: return JVMTI_ERROR_INVALID_THREAD; duke@435: } never@1577: if (!thread_oop->is_a(SystemDictionary::Thread_klass())) { duke@435: return JVMTI_ERROR_INVALID_THREAD; duke@435: } duke@435: java_thread = java_lang_Thread::thread(thread_oop); duke@435: if (java_thread == NULL) { duke@435: return JVMTI_ERROR_THREAD_NOT_ALIVE; duke@435: } duke@435: } duke@435: duke@435: // event_type must be valid duke@435: if (!JvmtiEventController::is_valid_event_type(event_type)) { duke@435: return JVMTI_ERROR_INVALID_EVENT_TYPE; duke@435: } duke@435: duke@435: // global events cannot be controlled at thread level. duke@435: if (java_thread != NULL && JvmtiEventController::is_global_event(event_type)) { duke@435: return JVMTI_ERROR_ILLEGAL_ARGUMENT; duke@435: } duke@435: duke@435: bool enabled = (mode == JVMTI_ENABLE); duke@435: duke@435: // assure that needed capabilities are present duke@435: if (enabled && !JvmtiUtil::has_event_capability(event_type, get_capabilities())) { duke@435: return JVMTI_ERROR_MUST_POSSESS_CAPABILITY; duke@435: } duke@435: duke@435: if (event_type == JVMTI_EVENT_CLASS_FILE_LOAD_HOOK && enabled) { duke@435: record_class_file_load_hook_enabled(); duke@435: } duke@435: JvmtiEventController::set_user_enabled(this, java_thread, event_type, enabled); duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end SetEventNotificationMode */ duke@435: duke@435: // duke@435: // Capability functions duke@435: // duke@435: duke@435: // capabilities_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetPotentialCapabilities(jvmtiCapabilities* capabilities_ptr) { duke@435: JvmtiManageCapabilities::get_potential_capabilities(get_capabilities(), duke@435: get_prohibited_capabilities(), duke@435: capabilities_ptr); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetPotentialCapabilities */ duke@435: duke@435: duke@435: // capabilities_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::AddCapabilities(const jvmtiCapabilities* capabilities_ptr) { duke@435: return JvmtiManageCapabilities::add_capabilities(get_capabilities(), duke@435: get_prohibited_capabilities(), duke@435: capabilities_ptr, duke@435: get_capabilities()); duke@435: } /* end AddCapabilities */ duke@435: duke@435: duke@435: // capabilities_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::RelinquishCapabilities(const jvmtiCapabilities* capabilities_ptr) { duke@435: JvmtiManageCapabilities::relinquish_capabilities(get_capabilities(), capabilities_ptr, get_capabilities()); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end RelinquishCapabilities */ duke@435: duke@435: duke@435: // capabilities_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetCapabilities(jvmtiCapabilities* capabilities_ptr) { duke@435: JvmtiManageCapabilities::copy_capabilities(get_capabilities(), capabilities_ptr); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetCapabilities */ duke@435: duke@435: // duke@435: // Class Loader Search functions duke@435: // duke@435: duke@435: // segment - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::AddToBootstrapClassLoaderSearch(const char* segment) { duke@435: jvmtiPhase phase = get_phase(); duke@435: if (phase == JVMTI_PHASE_ONLOAD) { duke@435: Arguments::append_sysclasspath(segment); duke@435: return JVMTI_ERROR_NONE; dcubed@1556: } else if (use_version_1_0_semantics()) { dcubed@1556: // This JvmtiEnv requested version 1.0 semantics and this function dcubed@1556: // is only allowed in the ONLOAD phase in version 1.0 so we need to dcubed@1556: // return an error here. dcubed@1556: return JVMTI_ERROR_WRONG_PHASE; dcubed@1555: } else if (phase == JVMTI_PHASE_LIVE) { dcubed@1555: // The phase is checked by the wrapper that called this function, dcubed@1555: // but this thread could be racing with the thread that is dcubed@1555: // terminating the VM so we check one more time. duke@435: duke@435: // create the zip entry duke@435: ClassPathZipEntry* zip_entry = ClassLoader::create_class_path_zip_entry(segment); duke@435: if (zip_entry == NULL) { duke@435: return JVMTI_ERROR_ILLEGAL_ARGUMENT; duke@435: } duke@435: duke@435: // lock the loader duke@435: Thread* thread = Thread::current(); duke@435: HandleMark hm; duke@435: Handle loader_lock = Handle(thread, SystemDictionary::system_loader_lock()); duke@435: duke@435: ObjectLocker ol(loader_lock, thread); duke@435: duke@435: // add the jar file to the bootclasspath duke@435: if (TraceClassLoading) { duke@435: tty->print_cr("[Opened %s]", zip_entry->name()); duke@435: } duke@435: ClassLoader::add_to_list(zip_entry); duke@435: return JVMTI_ERROR_NONE; dcubed@1555: } else { dcubed@1555: return JVMTI_ERROR_WRONG_PHASE; duke@435: } duke@435: duke@435: } /* end AddToBootstrapClassLoaderSearch */ duke@435: duke@435: duke@435: // segment - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::AddToSystemClassLoaderSearch(const char* segment) { duke@435: jvmtiPhase phase = get_phase(); duke@435: duke@435: if (phase == JVMTI_PHASE_ONLOAD) { duke@435: for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) { duke@435: if (strcmp("java.class.path", p->key()) == 0) { duke@435: p->append_value(segment); duke@435: break; duke@435: } duke@435: } duke@435: return JVMTI_ERROR_NONE; dcubed@1555: } else if (phase == JVMTI_PHASE_LIVE) { dcubed@1555: // The phase is checked by the wrapper that called this function, dcubed@1555: // but this thread could be racing with the thread that is dcubed@1555: // terminating the VM so we check one more time. duke@435: HandleMark hm; duke@435: duke@435: // create the zip entry (which will open the zip file and hence duke@435: // check that the segment is indeed a zip file). duke@435: ClassPathZipEntry* zip_entry = ClassLoader::create_class_path_zip_entry(segment); duke@435: if (zip_entry == NULL) { duke@435: return JVMTI_ERROR_ILLEGAL_ARGUMENT; duke@435: } duke@435: delete zip_entry; // no longer needed duke@435: duke@435: // lock the loader duke@435: Thread* THREAD = Thread::current(); duke@435: Handle loader = Handle(THREAD, SystemDictionary::java_system_loader()); duke@435: duke@435: ObjectLocker ol(loader, THREAD); duke@435: duke@435: // need the path as java.lang.String thurka@2778: Handle path = java_lang_String::create_from_platform_dependent_str(segment, THREAD); duke@435: if (HAS_PENDING_EXCEPTION) { duke@435: CLEAR_PENDING_EXCEPTION; duke@435: return JVMTI_ERROR_INTERNAL; duke@435: } duke@435: duke@435: instanceKlassHandle loader_ik(THREAD, loader->klass()); duke@435: duke@435: // Invoke the appendToClassPathForInstrumentation method - if the method duke@435: // is not found it means the loader doesn't support adding to the class path duke@435: // in the live phase. duke@435: { duke@435: JavaValue res(T_VOID); duke@435: JavaCalls::call_special(&res, duke@435: loader, duke@435: loader_ik, coleenp@2497: vmSymbols::appendToClassPathForInstrumentation_name(), coleenp@2497: vmSymbols::appendToClassPathForInstrumentation_signature(), duke@435: path, duke@435: THREAD); duke@435: if (HAS_PENDING_EXCEPTION) { coleenp@4037: Symbol* ex_name = PENDING_EXCEPTION->klass()->name(); duke@435: CLEAR_PENDING_EXCEPTION; duke@435: duke@435: if (ex_name == vmSymbols::java_lang_NoSuchMethodError()) { duke@435: return JVMTI_ERROR_CLASS_LOADER_UNSUPPORTED; duke@435: } else { duke@435: return JVMTI_ERROR_INTERNAL; duke@435: } duke@435: } duke@435: } duke@435: duke@435: return JVMTI_ERROR_NONE; dcubed@1555: } else { dcubed@1555: return JVMTI_ERROR_WRONG_PHASE; duke@435: } duke@435: } /* end AddToSystemClassLoaderSearch */ duke@435: duke@435: // duke@435: // General functions duke@435: // duke@435: duke@435: // phase_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetPhase(jvmtiPhase* phase_ptr) { duke@435: *phase_ptr = get_phase(); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetPhase */ duke@435: duke@435: duke@435: jvmtiError duke@435: JvmtiEnv::DisposeEnvironment() { duke@435: dispose(); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end DisposeEnvironment */ duke@435: duke@435: duke@435: // data - NULL is a valid value, must be checked duke@435: jvmtiError duke@435: JvmtiEnv::SetEnvironmentLocalStorage(const void* data) { duke@435: set_env_local_storage(data); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end SetEnvironmentLocalStorage */ duke@435: duke@435: duke@435: // data_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetEnvironmentLocalStorage(void** data_ptr) { duke@435: *data_ptr = (void*)get_env_local_storage(); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetEnvironmentLocalStorage */ duke@435: duke@435: // version_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetVersionNumber(jint* version_ptr) { duke@435: *version_ptr = JVMTI_VERSION; duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetVersionNumber */ duke@435: duke@435: duke@435: // name_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetErrorName(jvmtiError error, char** name_ptr) { duke@435: if (error < JVMTI_ERROR_NONE || error > JVMTI_ERROR_MAX) { duke@435: return JVMTI_ERROR_ILLEGAL_ARGUMENT; duke@435: } duke@435: const char *name = JvmtiUtil::error_name(error); duke@435: if (name == NULL) { duke@435: return JVMTI_ERROR_ILLEGAL_ARGUMENT; duke@435: } duke@435: size_t len = strlen(name) + 1; duke@435: jvmtiError err = allocate(len, (unsigned char**)name_ptr); duke@435: if (err == JVMTI_ERROR_NONE) { duke@435: memcpy(*name_ptr, name, len); duke@435: } duke@435: return err; duke@435: } /* end GetErrorName */ duke@435: duke@435: duke@435: jvmtiError duke@435: JvmtiEnv::SetVerboseFlag(jvmtiVerboseFlag flag, jboolean value) { duke@435: switch (flag) { duke@435: case JVMTI_VERBOSE_OTHER: duke@435: // ignore duke@435: break; duke@435: case JVMTI_VERBOSE_CLASS: duke@435: TraceClassLoading = value != 0; duke@435: TraceClassUnloading = value != 0; duke@435: break; duke@435: case JVMTI_VERBOSE_GC: duke@435: PrintGC = value != 0; duke@435: break; duke@435: case JVMTI_VERBOSE_JNI: duke@435: PrintJNIResolving = value != 0; duke@435: break; duke@435: default: duke@435: return JVMTI_ERROR_ILLEGAL_ARGUMENT; duke@435: }; duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end SetVerboseFlag */ duke@435: duke@435: duke@435: // format_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetJLocationFormat(jvmtiJlocationFormat* format_ptr) { duke@435: *format_ptr = JVMTI_JLOCATION_JVMBCI; duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetJLocationFormat */ duke@435: duke@435: // duke@435: // Thread functions duke@435: // duke@435: duke@435: // Threads_lock NOT held duke@435: // thread - NOT pre-checked duke@435: // thread_state_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetThreadState(jthread thread, jint* thread_state_ptr) { duke@435: jint state; duke@435: oop thread_oop; duke@435: JavaThread* thr; duke@435: duke@435: if (thread == NULL) { duke@435: thread_oop = JavaThread::current()->threadObj(); duke@435: } else { duke@435: thread_oop = JNIHandles::resolve_external_guard(thread); duke@435: } duke@435: never@1577: if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) { duke@435: return JVMTI_ERROR_INVALID_THREAD; duke@435: } duke@435: duke@435: // get most state bits duke@435: state = (jint)java_lang_Thread::get_thread_status(thread_oop); duke@435: duke@435: // add more state bits duke@435: thr = java_lang_Thread::thread(thread_oop); duke@435: if (thr != NULL) { duke@435: JavaThreadState jts = thr->thread_state(); duke@435: duke@435: if (thr->is_being_ext_suspended()) { duke@435: state |= JVMTI_THREAD_STATE_SUSPENDED; duke@435: } duke@435: if (jts == _thread_in_native) { duke@435: state |= JVMTI_THREAD_STATE_IN_NATIVE; duke@435: } duke@435: OSThread* osThread = thr->osthread(); duke@435: if (osThread != NULL && osThread->interrupted()) { duke@435: state |= JVMTI_THREAD_STATE_INTERRUPTED; duke@435: } duke@435: } duke@435: duke@435: *thread_state_ptr = state; duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetThreadState */ duke@435: duke@435: duke@435: // thread_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetCurrentThread(jthread* thread_ptr) { duke@435: JavaThread* current_thread = JavaThread::current(); duke@435: *thread_ptr = (jthread)JNIHandles::make_local(current_thread, current_thread->threadObj()); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetCurrentThread */ duke@435: duke@435: duke@435: // threads_count_ptr - pre-checked for NULL duke@435: // threads_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetAllThreads(jint* threads_count_ptr, jthread** threads_ptr) { duke@435: int nthreads = 0; duke@435: Handle *thread_objs = NULL; duke@435: ResourceMark rm; duke@435: HandleMark hm; duke@435: duke@435: // enumerate threads (including agent threads) duke@435: ThreadsListEnumerator tle(Thread::current(), true); duke@435: nthreads = tle.num_threads(); duke@435: *threads_count_ptr = nthreads; duke@435: duke@435: if (nthreads == 0) { duke@435: *threads_ptr = NULL; duke@435: return JVMTI_ERROR_NONE; duke@435: } duke@435: duke@435: thread_objs = NEW_RESOURCE_ARRAY(Handle, nthreads); duke@435: NULL_CHECK(thread_objs, JVMTI_ERROR_OUT_OF_MEMORY); duke@435: duke@435: for (int i=0; i < nthreads; i++) { duke@435: thread_objs[i] = Handle(tle.get_threadObj(i)); duke@435: } duke@435: duke@435: // have to make global handles outside of Threads_lock duke@435: jthread *jthreads = new_jthreadArray(nthreads, thread_objs); duke@435: NULL_CHECK(jthreads, JVMTI_ERROR_OUT_OF_MEMORY); duke@435: duke@435: *threads_ptr = jthreads; duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetAllThreads */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: jvmtiError duke@435: JvmtiEnv::SuspendThread(JavaThread* java_thread) { duke@435: // don't allow hidden thread suspend request. duke@435: if (java_thread->is_hidden_from_external_view()) { duke@435: return (JVMTI_ERROR_NONE); duke@435: } duke@435: duke@435: { duke@435: MutexLockerEx ml(java_thread->SR_lock(), Mutex::_no_safepoint_check_flag); duke@435: if (java_thread->is_external_suspend()) { duke@435: // don't allow nested external suspend requests. duke@435: return (JVMTI_ERROR_THREAD_SUSPENDED); duke@435: } duke@435: if (java_thread->is_exiting()) { // thread is in the process of exiting duke@435: return (JVMTI_ERROR_THREAD_NOT_ALIVE); duke@435: } duke@435: java_thread->set_external_suspend(); duke@435: } duke@435: duke@435: if (!JvmtiSuspendControl::suspend(java_thread)) { duke@435: // the thread was in the process of exiting duke@435: return (JVMTI_ERROR_THREAD_NOT_ALIVE); duke@435: } duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end SuspendThread */ duke@435: duke@435: duke@435: // request_count - pre-checked to be greater than or equal to 0 duke@435: // request_list - pre-checked for NULL duke@435: // results - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::SuspendThreadList(jint request_count, const jthread* request_list, jvmtiError* results) { duke@435: int needSafepoint = 0; // > 0 if we need a safepoint duke@435: for (int i = 0; i < request_count; i++) { duke@435: JavaThread *java_thread = get_JavaThread(request_list[i]); duke@435: if (java_thread == NULL) { duke@435: results[i] = JVMTI_ERROR_INVALID_THREAD; duke@435: continue; duke@435: } duke@435: // the thread has not yet run or has exited (not on threads list) duke@435: if (java_thread->threadObj() == NULL) { duke@435: results[i] = JVMTI_ERROR_THREAD_NOT_ALIVE; duke@435: continue; duke@435: } duke@435: if (java_lang_Thread::thread(java_thread->threadObj()) == NULL) { duke@435: results[i] = JVMTI_ERROR_THREAD_NOT_ALIVE; duke@435: continue; duke@435: } duke@435: // don't allow hidden thread suspend request. duke@435: if (java_thread->is_hidden_from_external_view()) { duke@435: results[i] = JVMTI_ERROR_NONE; // indicate successful suspend duke@435: continue; duke@435: } duke@435: duke@435: { duke@435: MutexLockerEx ml(java_thread->SR_lock(), Mutex::_no_safepoint_check_flag); duke@435: if (java_thread->is_external_suspend()) { duke@435: // don't allow nested external suspend requests. duke@435: results[i] = JVMTI_ERROR_THREAD_SUSPENDED; duke@435: continue; duke@435: } duke@435: if (java_thread->is_exiting()) { // thread is in the process of exiting duke@435: results[i] = JVMTI_ERROR_THREAD_NOT_ALIVE; duke@435: continue; duke@435: } duke@435: java_thread->set_external_suspend(); duke@435: } duke@435: if (java_thread->thread_state() == _thread_in_native) { duke@435: // We need to try and suspend native threads here. Threads in duke@435: // other states will self-suspend on their next transition. duke@435: if (!JvmtiSuspendControl::suspend(java_thread)) { duke@435: // The thread was in the process of exiting. Force another duke@435: // safepoint to make sure that this thread transitions. duke@435: needSafepoint++; duke@435: results[i] = JVMTI_ERROR_THREAD_NOT_ALIVE; duke@435: continue; duke@435: } duke@435: } else { duke@435: needSafepoint++; duke@435: } duke@435: results[i] = JVMTI_ERROR_NONE; // indicate successful suspend duke@435: } duke@435: if (needSafepoint > 0) { duke@435: VM_ForceSafepoint vfs; duke@435: VMThread::execute(&vfs); duke@435: } duke@435: // per-thread suspend results returned via results parameter duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end SuspendThreadList */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: jvmtiError duke@435: JvmtiEnv::ResumeThread(JavaThread* java_thread) { duke@435: // don't allow hidden thread resume request. duke@435: if (java_thread->is_hidden_from_external_view()) { duke@435: return JVMTI_ERROR_NONE; duke@435: } duke@435: duke@435: if (!java_thread->is_being_ext_suspended()) { duke@435: return JVMTI_ERROR_THREAD_NOT_SUSPENDED; duke@435: } duke@435: duke@435: if (!JvmtiSuspendControl::resume(java_thread)) { duke@435: return JVMTI_ERROR_INTERNAL; duke@435: } duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end ResumeThread */ duke@435: duke@435: duke@435: // request_count - pre-checked to be greater than or equal to 0 duke@435: // request_list - pre-checked for NULL duke@435: // results - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::ResumeThreadList(jint request_count, const jthread* request_list, jvmtiError* results) { duke@435: for (int i = 0; i < request_count; i++) { duke@435: JavaThread *java_thread = get_JavaThread(request_list[i]); duke@435: if (java_thread == NULL) { duke@435: results[i] = JVMTI_ERROR_INVALID_THREAD; duke@435: continue; duke@435: } duke@435: // don't allow hidden thread resume request. duke@435: if (java_thread->is_hidden_from_external_view()) { duke@435: results[i] = JVMTI_ERROR_NONE; // indicate successful resume duke@435: continue; duke@435: } duke@435: if (!java_thread->is_being_ext_suspended()) { duke@435: results[i] = JVMTI_ERROR_THREAD_NOT_SUSPENDED; duke@435: continue; duke@435: } duke@435: duke@435: if (!JvmtiSuspendControl::resume(java_thread)) { duke@435: results[i] = JVMTI_ERROR_INTERNAL; duke@435: continue; duke@435: } duke@435: duke@435: results[i] = JVMTI_ERROR_NONE; // indicate successful suspend duke@435: } duke@435: // per-thread resume results returned via results parameter duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end ResumeThreadList */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: jvmtiError duke@435: JvmtiEnv::StopThread(JavaThread* java_thread, jobject exception) { duke@435: oop e = JNIHandles::resolve_external_guard(exception); duke@435: NULL_CHECK(e, JVMTI_ERROR_NULL_POINTER); duke@435: duke@435: JavaThread::send_async_exception(java_thread->threadObj(), e); duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: duke@435: } /* end StopThread */ duke@435: duke@435: duke@435: // Threads_lock NOT held duke@435: // thread - NOT pre-checked duke@435: jvmtiError duke@435: JvmtiEnv::InterruptThread(jthread thread) { duke@435: oop thread_oop = JNIHandles::resolve_external_guard(thread); never@1577: if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) duke@435: return JVMTI_ERROR_INVALID_THREAD; duke@435: duke@435: JavaThread* current_thread = JavaThread::current(); duke@435: duke@435: // Todo: this is a duplicate of JVM_Interrupt; share code in future duke@435: // Ensure that the C++ Thread and OSThread structures aren't freed before we operate duke@435: MutexLockerEx ml(current_thread->threadObj() == thread_oop ? NULL : Threads_lock); duke@435: // We need to re-resolve the java_thread, since a GC might have happened during the duke@435: // acquire of the lock duke@435: duke@435: JavaThread* java_thread = java_lang_Thread::thread(JNIHandles::resolve_external_guard(thread)); duke@435: NULL_CHECK(java_thread, JVMTI_ERROR_THREAD_NOT_ALIVE); duke@435: duke@435: Thread::interrupt(java_thread); duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end InterruptThread */ duke@435: duke@435: duke@435: // Threads_lock NOT held duke@435: // thread - NOT pre-checked duke@435: // info_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetThreadInfo(jthread thread, jvmtiThreadInfo* info_ptr) { duke@435: ResourceMark rm; duke@435: HandleMark hm; duke@435: duke@435: JavaThread* current_thread = JavaThread::current(); duke@435: duke@435: // if thread is NULL the current thread is used duke@435: oop thread_oop; duke@435: if (thread == NULL) { duke@435: thread_oop = current_thread->threadObj(); duke@435: } else { duke@435: thread_oop = JNIHandles::resolve_external_guard(thread); duke@435: } never@1577: if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) duke@435: return JVMTI_ERROR_INVALID_THREAD; duke@435: duke@435: Handle thread_obj(current_thread, thread_oop); duke@435: typeArrayHandle name; duke@435: ThreadPriority priority; duke@435: Handle thread_group; duke@435: Handle context_class_loader; duke@435: bool is_daemon; duke@435: duke@435: { MutexLocker mu(Threads_lock); duke@435: duke@435: name = typeArrayHandle(current_thread, java_lang_Thread::name(thread_obj())); duke@435: priority = java_lang_Thread::priority(thread_obj()); duke@435: thread_group = Handle(current_thread, java_lang_Thread::threadGroup(thread_obj())); duke@435: is_daemon = java_lang_Thread::is_daemon(thread_obj()); duke@435: duke@435: oop loader = java_lang_Thread::context_class_loader(thread_obj()); duke@435: context_class_loader = Handle(current_thread, loader); duke@435: } duke@435: { const char *n; duke@435: duke@435: if (name() != NULL) { duke@435: n = UNICODE::as_utf8((jchar*) name->base(T_CHAR), name->length()); duke@435: } else { duke@435: n = UNICODE::as_utf8(NULL, 0); duke@435: } duke@435: duke@435: info_ptr->name = (char *) jvmtiMalloc(strlen(n)+1); duke@435: if (info_ptr->name == NULL) duke@435: return JVMTI_ERROR_OUT_OF_MEMORY; duke@435: duke@435: strcpy(info_ptr->name, n); duke@435: } duke@435: info_ptr->is_daemon = is_daemon; duke@435: info_ptr->priority = priority; duke@435: duke@435: info_ptr->context_class_loader = (context_class_loader.is_null()) ? NULL : duke@435: jni_reference(context_class_loader); duke@435: info_ptr->thread_group = jni_reference(thread_group); duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetThreadInfo */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: // owned_monitor_count_ptr - pre-checked for NULL duke@435: // owned_monitors_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetOwnedMonitorInfo(JavaThread* java_thread, jint* owned_monitor_count_ptr, jobject** owned_monitors_ptr) { duke@435: jvmtiError err = JVMTI_ERROR_NONE; duke@435: JavaThread* calling_thread = JavaThread::current(); duke@435: duke@435: // growable array of jvmti monitors info on the C-heap duke@435: GrowableArray *owned_monitors_list = zgu@3900: new (ResourceObj::C_HEAP, mtInternal) GrowableArray(1, true); duke@435: duke@435: uint32_t debug_bits = 0; duke@435: if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { duke@435: err = get_owned_monitors(calling_thread, java_thread, owned_monitors_list); duke@435: } else { duke@435: // JVMTI get monitors info at safepoint. Do not require target thread to duke@435: // be suspended. duke@435: VM_GetOwnedMonitorInfo op(this, calling_thread, java_thread, owned_monitors_list); duke@435: VMThread::execute(&op); duke@435: err = op.result(); duke@435: } duke@435: jint owned_monitor_count = owned_monitors_list->length(); duke@435: if (err == JVMTI_ERROR_NONE) { duke@435: if ((err = allocate(owned_monitor_count * sizeof(jobject *), duke@435: (unsigned char**)owned_monitors_ptr)) == JVMTI_ERROR_NONE) { duke@435: // copy into the returned array duke@435: for (int i = 0; i < owned_monitor_count; i++) { duke@435: (*owned_monitors_ptr)[i] = duke@435: ((jvmtiMonitorStackDepthInfo*)owned_monitors_list->at(i))->monitor; duke@435: } duke@435: *owned_monitor_count_ptr = owned_monitor_count; duke@435: } duke@435: } duke@435: // clean up. duke@435: for (int i = 0; i < owned_monitor_count; i++) { duke@435: deallocate((unsigned char*)owned_monitors_list->at(i)); duke@435: } duke@435: delete owned_monitors_list; duke@435: duke@435: return err; duke@435: } /* end GetOwnedMonitorInfo */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: // monitor_info_count_ptr - pre-checked for NULL duke@435: // monitor_info_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetOwnedMonitorStackDepthInfo(JavaThread* java_thread, jint* monitor_info_count_ptr, jvmtiMonitorStackDepthInfo** monitor_info_ptr) { duke@435: jvmtiError err = JVMTI_ERROR_NONE; duke@435: JavaThread* calling_thread = JavaThread::current(); duke@435: duke@435: // growable array of jvmti monitors info on the C-heap duke@435: GrowableArray *owned_monitors_list = zgu@3900: new (ResourceObj::C_HEAP, mtInternal) GrowableArray(1, true); duke@435: duke@435: uint32_t debug_bits = 0; duke@435: if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { duke@435: err = get_owned_monitors(calling_thread, java_thread, owned_monitors_list); duke@435: } else { duke@435: // JVMTI get owned monitors info at safepoint. Do not require target thread to duke@435: // be suspended. duke@435: VM_GetOwnedMonitorInfo op(this, calling_thread, java_thread, owned_monitors_list); duke@435: VMThread::execute(&op); duke@435: err = op.result(); duke@435: } duke@435: duke@435: jint owned_monitor_count = owned_monitors_list->length(); duke@435: if (err == JVMTI_ERROR_NONE) { duke@435: if ((err = allocate(owned_monitor_count * sizeof(jvmtiMonitorStackDepthInfo), duke@435: (unsigned char**)monitor_info_ptr)) == JVMTI_ERROR_NONE) { duke@435: // copy to output array. duke@435: for (int i = 0; i < owned_monitor_count; i++) { duke@435: (*monitor_info_ptr)[i].monitor = duke@435: ((jvmtiMonitorStackDepthInfo*)owned_monitors_list->at(i))->monitor; duke@435: (*monitor_info_ptr)[i].stack_depth = duke@435: ((jvmtiMonitorStackDepthInfo*)owned_monitors_list->at(i))->stack_depth; duke@435: } duke@435: } duke@435: *monitor_info_count_ptr = owned_monitor_count; duke@435: } duke@435: duke@435: // clean up. duke@435: for (int i = 0; i < owned_monitor_count; i++) { duke@435: deallocate((unsigned char*)owned_monitors_list->at(i)); duke@435: } duke@435: delete owned_monitors_list; duke@435: duke@435: return err; duke@435: } /* end GetOwnedMonitorStackDepthInfo */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: // monitor_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetCurrentContendedMonitor(JavaThread* java_thread, jobject* monitor_ptr) { duke@435: jvmtiError err = JVMTI_ERROR_NONE; duke@435: uint32_t debug_bits = 0; duke@435: JavaThread* calling_thread = JavaThread::current(); duke@435: if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { duke@435: err = get_current_contended_monitor(calling_thread, java_thread, monitor_ptr); duke@435: } else { duke@435: // get contended monitor information at safepoint. duke@435: VM_GetCurrentContendedMonitor op(this, calling_thread, java_thread, monitor_ptr); duke@435: VMThread::execute(&op); duke@435: err = op.result(); duke@435: } duke@435: return err; duke@435: } /* end GetCurrentContendedMonitor */ duke@435: duke@435: duke@435: // Threads_lock NOT held duke@435: // thread - NOT pre-checked duke@435: // proc - pre-checked for NULL duke@435: // arg - NULL is a valid value, must be checked duke@435: jvmtiError duke@435: JvmtiEnv::RunAgentThread(jthread thread, jvmtiStartFunction proc, const void* arg, jint priority) { duke@435: oop thread_oop = JNIHandles::resolve_external_guard(thread); never@1577: if (thread_oop == NULL || !thread_oop->is_a(SystemDictionary::Thread_klass())) { duke@435: return JVMTI_ERROR_INVALID_THREAD; duke@435: } duke@435: if (priority < JVMTI_THREAD_MIN_PRIORITY || priority > JVMTI_THREAD_MAX_PRIORITY) { duke@435: return JVMTI_ERROR_INVALID_PRIORITY; duke@435: } duke@435: duke@435: //Thread-self duke@435: JavaThread* current_thread = JavaThread::current(); duke@435: duke@435: Handle thread_hndl(current_thread, thread_oop); duke@435: { duke@435: MutexLocker mu(Threads_lock); // grab Threads_lock duke@435: duke@435: JvmtiAgentThread *new_thread = new JvmtiAgentThread(this, proc, arg); duke@435: duke@435: // At this point it may be possible that no osthread was created for the duke@435: // JavaThread due to lack of memory. duke@435: if (new_thread == NULL || new_thread->osthread() == NULL) { duke@435: if (new_thread) delete new_thread; duke@435: return JVMTI_ERROR_OUT_OF_MEMORY; duke@435: } duke@435: duke@435: java_lang_Thread::set_thread(thread_hndl(), new_thread); duke@435: java_lang_Thread::set_priority(thread_hndl(), (ThreadPriority)priority); duke@435: java_lang_Thread::set_daemon(thread_hndl()); duke@435: duke@435: new_thread->set_threadObj(thread_hndl()); duke@435: Threads::add(new_thread); duke@435: Thread::start(new_thread); duke@435: } // unlock Threads_lock duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end RunAgentThread */ duke@435: duke@435: // duke@435: // Thread Group functions duke@435: // duke@435: duke@435: // group_count_ptr - pre-checked for NULL duke@435: // groups_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetTopThreadGroups(jint* group_count_ptr, jthreadGroup** groups_ptr) { duke@435: JavaThread* current_thread = JavaThread::current(); duke@435: duke@435: // Only one top level thread group now. duke@435: *group_count_ptr = 1; duke@435: duke@435: // Allocate memory to store global-refs to the thread groups. duke@435: // Assume this area is freed by caller. duke@435: *groups_ptr = (jthreadGroup *) jvmtiMalloc((sizeof(jthreadGroup)) * (*group_count_ptr)); duke@435: duke@435: NULL_CHECK(*groups_ptr, JVMTI_ERROR_OUT_OF_MEMORY); duke@435: duke@435: // Convert oop to Handle, then convert Handle to global-ref. duke@435: { duke@435: HandleMark hm(current_thread); duke@435: Handle system_thread_group(current_thread, Universe::system_thread_group()); duke@435: *groups_ptr[0] = jni_reference(system_thread_group); duke@435: } duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetTopThreadGroups */ duke@435: duke@435: duke@435: // info_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetThreadGroupInfo(jthreadGroup group, jvmtiThreadGroupInfo* info_ptr) { duke@435: ResourceMark rm; duke@435: HandleMark hm; duke@435: duke@435: JavaThread* current_thread = JavaThread::current(); duke@435: duke@435: Handle group_obj (current_thread, JNIHandles::resolve_external_guard(group)); duke@435: NULL_CHECK(group_obj(), JVMTI_ERROR_INVALID_THREAD_GROUP); duke@435: duke@435: typeArrayHandle name; duke@435: Handle parent_group; duke@435: bool is_daemon; duke@435: ThreadPriority max_priority; duke@435: duke@435: { MutexLocker mu(Threads_lock); duke@435: duke@435: name = typeArrayHandle(current_thread, duke@435: java_lang_ThreadGroup::name(group_obj())); duke@435: parent_group = Handle(current_thread, java_lang_ThreadGroup::parent(group_obj())); duke@435: is_daemon = java_lang_ThreadGroup::is_daemon(group_obj()); duke@435: max_priority = java_lang_ThreadGroup::maxPriority(group_obj()); duke@435: } duke@435: duke@435: info_ptr->is_daemon = is_daemon; duke@435: info_ptr->max_priority = max_priority; duke@435: info_ptr->parent = jni_reference(parent_group); duke@435: duke@435: if (name() != NULL) { duke@435: const char* n = UNICODE::as_utf8((jchar*) name->base(T_CHAR), name->length()); duke@435: info_ptr->name = (char *)jvmtiMalloc(strlen(n)+1); duke@435: NULL_CHECK(info_ptr->name, JVMTI_ERROR_OUT_OF_MEMORY); duke@435: strcpy(info_ptr->name, n); duke@435: } else { duke@435: info_ptr->name = NULL; duke@435: } duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetThreadGroupInfo */ duke@435: duke@435: duke@435: // thread_count_ptr - pre-checked for NULL duke@435: // threads_ptr - pre-checked for NULL duke@435: // group_count_ptr - pre-checked for NULL duke@435: // groups_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetThreadGroupChildren(jthreadGroup group, jint* thread_count_ptr, jthread** threads_ptr, jint* group_count_ptr, jthreadGroup** groups_ptr) { duke@435: JavaThread* current_thread = JavaThread::current(); duke@435: oop group_obj = (oop) JNIHandles::resolve_external_guard(group); duke@435: NULL_CHECK(group_obj, JVMTI_ERROR_INVALID_THREAD_GROUP); duke@435: duke@435: Handle *thread_objs = NULL; duke@435: Handle *group_objs = NULL; duke@435: int nthreads = 0; duke@435: int ngroups = 0; duke@435: int hidden_threads = 0; duke@435: duke@435: ResourceMark rm; duke@435: HandleMark hm; duke@435: duke@435: Handle group_hdl(current_thread, group_obj); duke@435: duke@435: { MutexLocker mu(Threads_lock); duke@435: duke@435: nthreads = java_lang_ThreadGroup::nthreads(group_hdl()); duke@435: ngroups = java_lang_ThreadGroup::ngroups(group_hdl()); duke@435: duke@435: if (nthreads > 0) { duke@435: objArrayOop threads = java_lang_ThreadGroup::threads(group_hdl()); duke@435: assert(nthreads <= threads->length(), "too many threads"); duke@435: thread_objs = NEW_RESOURCE_ARRAY(Handle,nthreads); duke@435: for (int i=0, j=0; iobj_at(i); duke@435: assert(thread_obj != NULL, "thread_obj is NULL"); duke@435: JavaThread *javathread = java_lang_Thread::thread(thread_obj); duke@435: // Filter out hidden java threads. duke@435: if (javathread != NULL && javathread->is_hidden_from_external_view()) { duke@435: hidden_threads++; duke@435: continue; duke@435: } duke@435: thread_objs[j++] = Handle(current_thread, thread_obj); duke@435: } duke@435: nthreads -= hidden_threads; duke@435: } duke@435: if (ngroups > 0) { duke@435: objArrayOop groups = java_lang_ThreadGroup::groups(group_hdl()); duke@435: assert(ngroups <= groups->length(), "too many threads"); duke@435: group_objs = NEW_RESOURCE_ARRAY(Handle,ngroups); duke@435: for (int i=0; iobj_at(i); duke@435: assert(group_obj != NULL, "group_obj != NULL"); duke@435: group_objs[i] = Handle(current_thread, group_obj); duke@435: } duke@435: } duke@435: } duke@435: duke@435: // have to make global handles outside of Threads_lock duke@435: *group_count_ptr = ngroups; duke@435: *thread_count_ptr = nthreads; duke@435: *threads_ptr = new_jthreadArray(nthreads, thread_objs); duke@435: *groups_ptr = new_jthreadGroupArray(ngroups, group_objs); duke@435: if ((nthreads > 0) && (*threads_ptr == NULL)) { duke@435: return JVMTI_ERROR_OUT_OF_MEMORY; duke@435: } duke@435: if ((ngroups > 0) && (*groups_ptr == NULL)) { duke@435: return JVMTI_ERROR_OUT_OF_MEMORY; duke@435: } duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetThreadGroupChildren */ duke@435: duke@435: duke@435: // duke@435: // Stack Frame functions duke@435: // duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: // max_frame_count - pre-checked to be greater than or equal to 0 duke@435: // frame_buffer - pre-checked for NULL duke@435: // count_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetStackTrace(JavaThread* java_thread, jint start_depth, jint max_frame_count, jvmtiFrameInfo* frame_buffer, jint* count_ptr) { duke@435: jvmtiError err = JVMTI_ERROR_NONE; duke@435: uint32_t debug_bits = 0; duke@435: if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { duke@435: err = get_stack_trace(java_thread, start_depth, max_frame_count, frame_buffer, count_ptr); duke@435: } else { duke@435: // JVMTI get stack trace at safepoint. Do not require target thread to duke@435: // be suspended. duke@435: VM_GetStackTrace op(this, java_thread, start_depth, max_frame_count, frame_buffer, count_ptr); duke@435: VMThread::execute(&op); duke@435: err = op.result(); duke@435: } duke@435: duke@435: return err; duke@435: } /* end GetStackTrace */ duke@435: duke@435: duke@435: // max_frame_count - pre-checked to be greater than or equal to 0 duke@435: // stack_info_ptr - pre-checked for NULL duke@435: // thread_count_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetAllStackTraces(jint max_frame_count, jvmtiStackInfo** stack_info_ptr, jint* thread_count_ptr) { duke@435: jvmtiError err = JVMTI_ERROR_NONE; duke@435: JavaThread* calling_thread = JavaThread::current(); duke@435: duke@435: // JVMTI get stack traces at safepoint. duke@435: VM_GetAllStackTraces op(this, calling_thread, max_frame_count); duke@435: VMThread::execute(&op); duke@435: *thread_count_ptr = op.final_thread_count(); duke@435: *stack_info_ptr = op.stack_info(); duke@435: err = op.result(); duke@435: return err; duke@435: } /* end GetAllStackTraces */ duke@435: duke@435: duke@435: // thread_count - pre-checked to be greater than or equal to 0 duke@435: // thread_list - pre-checked for NULL duke@435: // max_frame_count - pre-checked to be greater than or equal to 0 duke@435: // stack_info_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetThreadListStackTraces(jint thread_count, const jthread* thread_list, jint max_frame_count, jvmtiStackInfo** stack_info_ptr) { duke@435: jvmtiError err = JVMTI_ERROR_NONE; duke@435: // JVMTI get stack traces at safepoint. duke@435: VM_GetThreadListStackTraces op(this, thread_count, thread_list, max_frame_count); duke@435: VMThread::execute(&op); duke@435: err = op.result(); duke@435: if (err == JVMTI_ERROR_NONE) { duke@435: *stack_info_ptr = op.stack_info(); duke@435: } duke@435: return err; duke@435: } /* end GetThreadListStackTraces */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: // count_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetFrameCount(JavaThread* java_thread, jint* count_ptr) { duke@435: jvmtiError err = JVMTI_ERROR_NONE; duke@435: duke@435: // retrieve or create JvmtiThreadState. duke@435: JvmtiThreadState* state = JvmtiThreadState::state_for(java_thread); dcubed@1044: if (state == NULL) { dcubed@1044: return JVMTI_ERROR_THREAD_NOT_ALIVE; dcubed@1044: } duke@435: uint32_t debug_bits = 0; duke@435: if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { duke@435: err = get_frame_count(state, count_ptr); duke@435: } else { duke@435: // get java stack frame count at safepoint. duke@435: VM_GetFrameCount op(this, state, count_ptr); duke@435: VMThread::execute(&op); duke@435: err = op.result(); duke@435: } duke@435: return err; duke@435: } /* end GetFrameCount */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: jvmtiError duke@435: JvmtiEnv::PopFrame(JavaThread* java_thread) { duke@435: JavaThread* current_thread = JavaThread::current(); duke@435: HandleMark hm(current_thread); duke@435: uint32_t debug_bits = 0; duke@435: dcubed@1044: // retrieve or create the state dcubed@1044: JvmtiThreadState* state = JvmtiThreadState::state_for(java_thread); dcubed@1044: if (state == NULL) { dcubed@1044: return JVMTI_ERROR_THREAD_NOT_ALIVE; dcubed@1044: } dcubed@1044: duke@435: // Check if java_thread is fully suspended duke@435: if (!is_thread_fully_suspended(java_thread, true /* wait for suspend completion */, &debug_bits)) { duke@435: return JVMTI_ERROR_THREAD_NOT_SUSPENDED; duke@435: } duke@435: // Check to see if a PopFrame was already in progress duke@435: if (java_thread->popframe_condition() != JavaThread::popframe_inactive) { duke@435: // Probably possible for JVMTI clients to trigger this, but the duke@435: // JPDA backend shouldn't allow this to happen duke@435: return JVMTI_ERROR_INTERNAL; duke@435: } duke@435: duke@435: { duke@435: // Was workaround bug duke@435: // 4812902: popFrame hangs if the method is waiting at a synchronize duke@435: // Catch this condition and return an error to avoid hanging. duke@435: // Now JVMTI spec allows an implementation to bail out with an opaque frame error. duke@435: OSThread* osThread = java_thread->osthread(); duke@435: if (osThread->get_state() == MONITOR_WAIT) { duke@435: return JVMTI_ERROR_OPAQUE_FRAME; duke@435: } duke@435: } duke@435: duke@435: { duke@435: ResourceMark rm(current_thread); duke@435: // Check if there are more than one Java frame in this thread, that the top two frames duke@435: // are Java (not native) frames, and that there is no intervening VM frame duke@435: int frame_count = 0; duke@435: bool is_interpreted[2]; duke@435: intptr_t *frame_sp[2]; duke@435: // The 2-nd arg of constructor is needed to stop iterating at java entry frame. duke@435: for (vframeStream vfs(java_thread, true); !vfs.at_end(); vfs.next()) { duke@435: methodHandle mh(current_thread, vfs.method()); duke@435: if (mh->is_native()) return(JVMTI_ERROR_OPAQUE_FRAME); duke@435: is_interpreted[frame_count] = vfs.is_interpreted_frame(); duke@435: frame_sp[frame_count] = vfs.frame_id(); duke@435: if (++frame_count > 1) break; duke@435: } duke@435: if (frame_count < 2) { duke@435: // We haven't found two adjacent non-native Java frames on the top. duke@435: // There can be two situations here: duke@435: // 1. There are no more java frames duke@435: // 2. Two top java frames are separated by non-java native frames duke@435: if(vframeFor(java_thread, 1) == NULL) { duke@435: return JVMTI_ERROR_NO_MORE_FRAMES; duke@435: } else { duke@435: // Intervening non-java native or VM frames separate java frames. duke@435: // Current implementation does not support this. See bug #5031735. duke@435: // In theory it is possible to pop frames in such cases. duke@435: return JVMTI_ERROR_OPAQUE_FRAME; duke@435: } duke@435: } duke@435: duke@435: // If any of the top 2 frames is a compiled one, need to deoptimize it duke@435: for (int i = 0; i < 2; i++) { duke@435: if (!is_interpreted[i]) { never@2260: Deoptimization::deoptimize_frame(java_thread, frame_sp[i]); duke@435: } duke@435: } duke@435: duke@435: // Update the thread state to reflect that the top frame is popped duke@435: // so that cur_stack_depth is maintained properly and all frameIDs duke@435: // are invalidated. duke@435: // The current frame will be popped later when the suspended thread duke@435: // is resumed and right before returning from VM to Java. duke@435: // (see call_VM_base() in assembler_.cpp). duke@435: duke@435: // It's fine to update the thread state here because no JVMTI events duke@435: // shall be posted for this PopFrame. duke@435: duke@435: state->update_for_pop_top_frame(); duke@435: java_thread->set_popframe_condition(JavaThread::popframe_pending_bit); duke@435: // Set pending step flag for this popframe and it is cleared when next duke@435: // step event is posted. duke@435: state->set_pending_step_for_popframe(); duke@435: } duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end PopFrame */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: // java_thread - unchecked duke@435: // depth - pre-checked as non-negative duke@435: // method_ptr - pre-checked for NULL duke@435: // location_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetFrameLocation(JavaThread* java_thread, jint depth, jmethodID* method_ptr, jlocation* location_ptr) { duke@435: jvmtiError err = JVMTI_ERROR_NONE; duke@435: uint32_t debug_bits = 0; duke@435: duke@435: if (is_thread_fully_suspended(java_thread, true, &debug_bits)) { duke@435: err = get_frame_location(java_thread, depth, method_ptr, location_ptr); duke@435: } else { duke@435: // JVMTI get java stack frame location at safepoint. duke@435: VM_GetFrameLocation op(this, java_thread, depth, method_ptr, location_ptr); duke@435: VMThread::execute(&op); duke@435: err = op.result(); duke@435: } duke@435: return err; duke@435: } /* end GetFrameLocation */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: // java_thread - unchecked duke@435: // depth - pre-checked as non-negative duke@435: jvmtiError duke@435: JvmtiEnv::NotifyFramePop(JavaThread* java_thread, jint depth) { duke@435: ResourceMark rm; duke@435: uint32_t debug_bits = 0; duke@435: dcubed@1044: JvmtiThreadState *state = JvmtiThreadState::state_for(java_thread); dcubed@1044: if (state == NULL) { dcubed@1044: return JVMTI_ERROR_THREAD_NOT_ALIVE; dcubed@1044: } dcubed@1044: duke@435: if (!JvmtiEnv::is_thread_fully_suspended(java_thread, true, &debug_bits)) { duke@435: return JVMTI_ERROR_THREAD_NOT_SUSPENDED; duke@435: } duke@435: duke@435: if (TraceJVMTICalls) { duke@435: JvmtiSuspendControl::print(); duke@435: } duke@435: duke@435: vframe *vf = vframeFor(java_thread, depth); duke@435: if (vf == NULL) { duke@435: return JVMTI_ERROR_NO_MORE_FRAMES; duke@435: } duke@435: duke@435: if (!vf->is_java_frame() || ((javaVFrame*) vf)->method()->is_native()) { duke@435: return JVMTI_ERROR_OPAQUE_FRAME; duke@435: } duke@435: duke@435: assert(vf->frame_pointer() != NULL, "frame pointer mustn't be NULL"); duke@435: duke@435: int frame_number = state->count_frames() - depth; duke@435: state->env_thread_state(this)->set_frame_pop(frame_number); duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end NotifyFramePop */ duke@435: duke@435: duke@435: // duke@435: // Force Early Return functions duke@435: // duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: jvmtiError duke@435: JvmtiEnv::ForceEarlyReturnObject(JavaThread* java_thread, jobject value) { duke@435: jvalue val; duke@435: val.l = value; duke@435: return force_early_return(java_thread, val, atos); duke@435: } /* end ForceEarlyReturnObject */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: jvmtiError duke@435: JvmtiEnv::ForceEarlyReturnInt(JavaThread* java_thread, jint value) { duke@435: jvalue val; duke@435: val.i = value; duke@435: return force_early_return(java_thread, val, itos); duke@435: } /* end ForceEarlyReturnInt */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: jvmtiError duke@435: JvmtiEnv::ForceEarlyReturnLong(JavaThread* java_thread, jlong value) { duke@435: jvalue val; duke@435: val.j = value; duke@435: return force_early_return(java_thread, val, ltos); duke@435: } /* end ForceEarlyReturnLong */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: jvmtiError duke@435: JvmtiEnv::ForceEarlyReturnFloat(JavaThread* java_thread, jfloat value) { duke@435: jvalue val; duke@435: val.f = value; duke@435: return force_early_return(java_thread, val, ftos); duke@435: } /* end ForceEarlyReturnFloat */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: jvmtiError duke@435: JvmtiEnv::ForceEarlyReturnDouble(JavaThread* java_thread, jdouble value) { duke@435: jvalue val; duke@435: val.d = value; duke@435: return force_early_return(java_thread, val, dtos); duke@435: } /* end ForceEarlyReturnDouble */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: jvmtiError duke@435: JvmtiEnv::ForceEarlyReturnVoid(JavaThread* java_thread) { duke@435: jvalue val; duke@435: val.j = 0L; duke@435: return force_early_return(java_thread, val, vtos); duke@435: } /* end ForceEarlyReturnVoid */ duke@435: duke@435: duke@435: // duke@435: // Heap functions duke@435: // duke@435: duke@435: // klass - NULL is a valid value, must be checked duke@435: // initial_object - NULL is a valid value, must be checked duke@435: // callbacks - pre-checked for NULL duke@435: // user_data - NULL is a valid value, must be checked duke@435: jvmtiError duke@435: JvmtiEnv::FollowReferences(jint heap_filter, jclass klass, jobject initial_object, const jvmtiHeapCallbacks* callbacks, const void* user_data) { duke@435: // check klass if provided coleenp@4037: Klass* k_oop = NULL; duke@435: if (klass != NULL) { duke@435: oop k_mirror = JNIHandles::resolve_external_guard(klass); duke@435: if (k_mirror == NULL) { duke@435: return JVMTI_ERROR_INVALID_CLASS; duke@435: } duke@435: if (java_lang_Class::is_primitive(k_mirror)) { duke@435: return JVMTI_ERROR_NONE; duke@435: } coleenp@4037: k_oop = java_lang_Class::as_Klass(k_mirror); duke@435: if (k_oop == NULL) { duke@435: return JVMTI_ERROR_INVALID_CLASS; duke@435: } duke@435: } duke@435: duke@435: Thread *thread = Thread::current(); duke@435: HandleMark hm(thread); duke@435: KlassHandle kh (thread, k_oop); duke@435: duke@435: TraceTime t("FollowReferences", TraceJVMTIObjectTagging); duke@435: JvmtiTagMap::tag_map_for(this)->follow_references(heap_filter, kh, initial_object, callbacks, user_data); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end FollowReferences */ duke@435: duke@435: duke@435: // klass - NULL is a valid value, must be checked duke@435: // callbacks - pre-checked for NULL duke@435: // user_data - NULL is a valid value, must be checked duke@435: jvmtiError duke@435: JvmtiEnv::IterateThroughHeap(jint heap_filter, jclass klass, const jvmtiHeapCallbacks* callbacks, const void* user_data) { duke@435: // check klass if provided coleenp@4037: Klass* k_oop = NULL; duke@435: if (klass != NULL) { duke@435: oop k_mirror = JNIHandles::resolve_external_guard(klass); duke@435: if (k_mirror == NULL) { duke@435: return JVMTI_ERROR_INVALID_CLASS; duke@435: } duke@435: if (java_lang_Class::is_primitive(k_mirror)) { duke@435: return JVMTI_ERROR_NONE; duke@435: } coleenp@4037: k_oop = java_lang_Class::as_Klass(k_mirror); duke@435: if (k_oop == NULL) { duke@435: return JVMTI_ERROR_INVALID_CLASS; duke@435: } duke@435: } duke@435: duke@435: Thread *thread = Thread::current(); duke@435: HandleMark hm(thread); duke@435: KlassHandle kh (thread, k_oop); duke@435: duke@435: TraceTime t("IterateThroughHeap", TraceJVMTIObjectTagging); duke@435: JvmtiTagMap::tag_map_for(this)->iterate_through_heap(heap_filter, kh, callbacks, user_data); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end IterateThroughHeap */ duke@435: duke@435: duke@435: // tag_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetTag(jobject object, jlong* tag_ptr) { duke@435: oop o = JNIHandles::resolve_external_guard(object); duke@435: NULL_CHECK(o, JVMTI_ERROR_INVALID_OBJECT); duke@435: *tag_ptr = JvmtiTagMap::tag_map_for(this)->get_tag(object); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetTag */ duke@435: duke@435: duke@435: jvmtiError duke@435: JvmtiEnv::SetTag(jobject object, jlong tag) { duke@435: oop o = JNIHandles::resolve_external_guard(object); duke@435: NULL_CHECK(o, JVMTI_ERROR_INVALID_OBJECT); duke@435: JvmtiTagMap::tag_map_for(this)->set_tag(object, tag); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end SetTag */ duke@435: duke@435: duke@435: // tag_count - pre-checked to be greater than or equal to 0 duke@435: // tags - pre-checked for NULL duke@435: // count_ptr - pre-checked for NULL duke@435: // object_result_ptr - NULL is a valid value, must be checked duke@435: // tag_result_ptr - NULL is a valid value, must be checked duke@435: jvmtiError duke@435: JvmtiEnv::GetObjectsWithTags(jint tag_count, const jlong* tags, jint* count_ptr, jobject** object_result_ptr, jlong** tag_result_ptr) { duke@435: TraceTime t("GetObjectsWithTags", TraceJVMTIObjectTagging); duke@435: return JvmtiTagMap::tag_map_for(this)->get_objects_with_tags((jlong*)tags, tag_count, count_ptr, object_result_ptr, tag_result_ptr); duke@435: } /* end GetObjectsWithTags */ duke@435: duke@435: duke@435: jvmtiError duke@435: JvmtiEnv::ForceGarbageCollection() { duke@435: Universe::heap()->collect(GCCause::_jvmti_force_gc); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end ForceGarbageCollection */ duke@435: duke@435: duke@435: // duke@435: // Heap (1.0) functions duke@435: // duke@435: duke@435: // object_reference_callback - pre-checked for NULL duke@435: // user_data - NULL is a valid value, must be checked duke@435: jvmtiError duke@435: JvmtiEnv::IterateOverObjectsReachableFromObject(jobject object, jvmtiObjectReferenceCallback object_reference_callback, const void* user_data) { duke@435: oop o = JNIHandles::resolve_external_guard(object); duke@435: NULL_CHECK(o, JVMTI_ERROR_INVALID_OBJECT); duke@435: JvmtiTagMap::tag_map_for(this)->iterate_over_objects_reachable_from_object(object, object_reference_callback, user_data); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end IterateOverObjectsReachableFromObject */ duke@435: duke@435: duke@435: // heap_root_callback - NULL is a valid value, must be checked duke@435: // stack_ref_callback - NULL is a valid value, must be checked duke@435: // object_ref_callback - NULL is a valid value, must be checked duke@435: // user_data - NULL is a valid value, must be checked duke@435: jvmtiError duke@435: JvmtiEnv::IterateOverReachableObjects(jvmtiHeapRootCallback heap_root_callback, jvmtiStackReferenceCallback stack_ref_callback, jvmtiObjectReferenceCallback object_ref_callback, const void* user_data) { duke@435: TraceTime t("IterateOverReachableObjects", TraceJVMTIObjectTagging); duke@435: JvmtiTagMap::tag_map_for(this)->iterate_over_reachable_objects(heap_root_callback, stack_ref_callback, object_ref_callback, user_data); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end IterateOverReachableObjects */ duke@435: duke@435: duke@435: // heap_object_callback - pre-checked for NULL duke@435: // user_data - NULL is a valid value, must be checked duke@435: jvmtiError duke@435: JvmtiEnv::IterateOverHeap(jvmtiHeapObjectFilter object_filter, jvmtiHeapObjectCallback heap_object_callback, const void* user_data) { duke@435: TraceTime t("IterateOverHeap", TraceJVMTIObjectTagging); duke@435: Thread *thread = Thread::current(); duke@435: HandleMark hm(thread); duke@435: JvmtiTagMap::tag_map_for(this)->iterate_over_heap(object_filter, KlassHandle(), heap_object_callback, user_data); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end IterateOverHeap */ duke@435: duke@435: duke@435: // k_mirror - may be primitive, this must be checked duke@435: // heap_object_callback - pre-checked for NULL duke@435: // user_data - NULL is a valid value, must be checked duke@435: jvmtiError duke@435: JvmtiEnv::IterateOverInstancesOfClass(oop k_mirror, jvmtiHeapObjectFilter object_filter, jvmtiHeapObjectCallback heap_object_callback, const void* user_data) { duke@435: if (java_lang_Class::is_primitive(k_mirror)) { duke@435: // DO PRIMITIVE CLASS PROCESSING duke@435: return JVMTI_ERROR_NONE; duke@435: } coleenp@4037: Klass* k_oop = java_lang_Class::as_Klass(k_mirror); duke@435: if (k_oop == NULL) { duke@435: return JVMTI_ERROR_INVALID_CLASS; duke@435: } duke@435: Thread *thread = Thread::current(); duke@435: HandleMark hm(thread); duke@435: KlassHandle klass (thread, k_oop); duke@435: TraceTime t("IterateOverInstancesOfClass", TraceJVMTIObjectTagging); duke@435: JvmtiTagMap::tag_map_for(this)->iterate_over_heap(object_filter, klass, heap_object_callback, user_data); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end IterateOverInstancesOfClass */ duke@435: duke@435: duke@435: // duke@435: // Local Variable functions duke@435: // duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: // java_thread - unchecked duke@435: // depth - pre-checked as non-negative duke@435: // value_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetLocalObject(JavaThread* java_thread, jint depth, jint slot, jobject* value_ptr) { duke@435: JavaThread* current_thread = JavaThread::current(); duke@435: // rm object is created to clean up the javaVFrame created in duke@435: // doit_prologue(), but after doit() is finished with it. duke@435: ResourceMark rm(current_thread); duke@435: duke@435: VM_GetOrSetLocal op(java_thread, current_thread, depth, slot); duke@435: VMThread::execute(&op); duke@435: jvmtiError err = op.result(); duke@435: if (err != JVMTI_ERROR_NONE) { duke@435: return err; duke@435: } else { duke@435: *value_ptr = op.value().l; duke@435: return JVMTI_ERROR_NONE; duke@435: } duke@435: } /* end GetLocalObject */ duke@435: kamg@2361: // Threads_lock NOT held, java_thread not protected by lock kamg@2361: // java_thread - pre-checked kamg@2361: // java_thread - unchecked kamg@2361: // depth - pre-checked as non-negative kamg@2361: // value - pre-checked for NULL kamg@2361: jvmtiError phh@2423: JvmtiEnv::GetLocalInstance(JavaThread* java_thread, jint depth, jobject* value_ptr){ kamg@2361: JavaThread* current_thread = JavaThread::current(); kamg@2361: // rm object is created to clean up the javaVFrame created in kamg@2361: // doit_prologue(), but after doit() is finished with it. kamg@2361: ResourceMark rm(current_thread); kamg@2361: kamg@2361: VM_GetReceiver op(java_thread, current_thread, depth); kamg@2361: VMThread::execute(&op); kamg@2361: jvmtiError err = op.result(); kamg@2361: if (err != JVMTI_ERROR_NONE) { kamg@2361: return err; kamg@2361: } else { phh@2423: *value_ptr = op.value().l; kamg@2361: return JVMTI_ERROR_NONE; kamg@2361: } kamg@2361: } /* end GetLocalInstance */ kamg@2361: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: // java_thread - unchecked duke@435: // depth - pre-checked as non-negative duke@435: // value_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetLocalInt(JavaThread* java_thread, jint depth, jint slot, jint* value_ptr) { duke@435: // rm object is created to clean up the javaVFrame created in duke@435: // doit_prologue(), but after doit() is finished with it. duke@435: ResourceMark rm; duke@435: duke@435: VM_GetOrSetLocal op(java_thread, depth, slot, T_INT); duke@435: VMThread::execute(&op); duke@435: *value_ptr = op.value().i; duke@435: return op.result(); duke@435: } /* end GetLocalInt */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: // java_thread - unchecked duke@435: // depth - pre-checked as non-negative duke@435: // value_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetLocalLong(JavaThread* java_thread, jint depth, jint slot, jlong* value_ptr) { duke@435: // rm object is created to clean up the javaVFrame created in duke@435: // doit_prologue(), but after doit() is finished with it. duke@435: ResourceMark rm; duke@435: duke@435: VM_GetOrSetLocal op(java_thread, depth, slot, T_LONG); duke@435: VMThread::execute(&op); duke@435: *value_ptr = op.value().j; duke@435: return op.result(); duke@435: } /* end GetLocalLong */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: // java_thread - unchecked duke@435: // depth - pre-checked as non-negative duke@435: // value_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetLocalFloat(JavaThread* java_thread, jint depth, jint slot, jfloat* value_ptr) { duke@435: // rm object is created to clean up the javaVFrame created in duke@435: // doit_prologue(), but after doit() is finished with it. duke@435: ResourceMark rm; duke@435: duke@435: VM_GetOrSetLocal op(java_thread, depth, slot, T_FLOAT); duke@435: VMThread::execute(&op); duke@435: *value_ptr = op.value().f; duke@435: return op.result(); duke@435: } /* end GetLocalFloat */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: // java_thread - unchecked duke@435: // depth - pre-checked as non-negative duke@435: // value_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetLocalDouble(JavaThread* java_thread, jint depth, jint slot, jdouble* value_ptr) { duke@435: // rm object is created to clean up the javaVFrame created in duke@435: // doit_prologue(), but after doit() is finished with it. duke@435: ResourceMark rm; duke@435: duke@435: VM_GetOrSetLocal op(java_thread, depth, slot, T_DOUBLE); duke@435: VMThread::execute(&op); duke@435: *value_ptr = op.value().d; duke@435: return op.result(); duke@435: } /* end GetLocalDouble */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: // java_thread - unchecked duke@435: // depth - pre-checked as non-negative duke@435: jvmtiError duke@435: JvmtiEnv::SetLocalObject(JavaThread* java_thread, jint depth, jint slot, jobject value) { duke@435: // rm object is created to clean up the javaVFrame created in duke@435: // doit_prologue(), but after doit() is finished with it. duke@435: ResourceMark rm; duke@435: jvalue val; duke@435: val.l = value; duke@435: VM_GetOrSetLocal op(java_thread, depth, slot, T_OBJECT, val); duke@435: VMThread::execute(&op); duke@435: return op.result(); duke@435: } /* end SetLocalObject */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: // java_thread - unchecked duke@435: // depth - pre-checked as non-negative duke@435: jvmtiError duke@435: JvmtiEnv::SetLocalInt(JavaThread* java_thread, jint depth, jint slot, jint value) { duke@435: // rm object is created to clean up the javaVFrame created in duke@435: // doit_prologue(), but after doit() is finished with it. duke@435: ResourceMark rm; duke@435: jvalue val; duke@435: val.i = value; duke@435: VM_GetOrSetLocal op(java_thread, depth, slot, T_INT, val); duke@435: VMThread::execute(&op); duke@435: return op.result(); duke@435: } /* end SetLocalInt */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: // java_thread - unchecked duke@435: // depth - pre-checked as non-negative duke@435: jvmtiError duke@435: JvmtiEnv::SetLocalLong(JavaThread* java_thread, jint depth, jint slot, jlong value) { duke@435: // rm object is created to clean up the javaVFrame created in duke@435: // doit_prologue(), but after doit() is finished with it. duke@435: ResourceMark rm; duke@435: jvalue val; duke@435: val.j = value; duke@435: VM_GetOrSetLocal op(java_thread, depth, slot, T_LONG, val); duke@435: VMThread::execute(&op); duke@435: return op.result(); duke@435: } /* end SetLocalLong */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: // java_thread - unchecked duke@435: // depth - pre-checked as non-negative duke@435: jvmtiError duke@435: JvmtiEnv::SetLocalFloat(JavaThread* java_thread, jint depth, jint slot, jfloat value) { duke@435: // rm object is created to clean up the javaVFrame created in duke@435: // doit_prologue(), but after doit() is finished with it. duke@435: ResourceMark rm; duke@435: jvalue val; duke@435: val.f = value; duke@435: VM_GetOrSetLocal op(java_thread, depth, slot, T_FLOAT, val); duke@435: VMThread::execute(&op); duke@435: return op.result(); duke@435: } /* end SetLocalFloat */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: // java_thread - unchecked duke@435: // depth - pre-checked as non-negative duke@435: jvmtiError duke@435: JvmtiEnv::SetLocalDouble(JavaThread* java_thread, jint depth, jint slot, jdouble value) { duke@435: // rm object is created to clean up the javaVFrame created in duke@435: // doit_prologue(), but after doit() is finished with it. duke@435: ResourceMark rm; duke@435: jvalue val; duke@435: val.d = value; duke@435: VM_GetOrSetLocal op(java_thread, depth, slot, T_DOUBLE, val); duke@435: VMThread::execute(&op); duke@435: return op.result(); duke@435: } /* end SetLocalDouble */ duke@435: duke@435: duke@435: // duke@435: // Breakpoint functions duke@435: // duke@435: duke@435: // method_oop - pre-checked for validity, but may be NULL meaning obsolete method duke@435: jvmtiError coleenp@4037: JvmtiEnv::SetBreakpoint(Method* method_oop, jlocation location) { duke@435: NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); duke@435: if (location < 0) { // simple invalid location check first duke@435: return JVMTI_ERROR_INVALID_LOCATION; duke@435: } duke@435: // verify that the breakpoint is not past the end of the method duke@435: if (location >= (jlocation) method_oop->code_size()) { duke@435: return JVMTI_ERROR_INVALID_LOCATION; duke@435: } duke@435: duke@435: ResourceMark rm; duke@435: JvmtiBreakpoint bp(method_oop, location); duke@435: JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints(); duke@435: if (jvmti_breakpoints.set(bp) == JVMTI_ERROR_DUPLICATE) duke@435: return JVMTI_ERROR_DUPLICATE; duke@435: duke@435: if (TraceJVMTICalls) { duke@435: jvmti_breakpoints.print(); duke@435: } duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end SetBreakpoint */ duke@435: duke@435: duke@435: // method_oop - pre-checked for validity, but may be NULL meaning obsolete method duke@435: jvmtiError coleenp@4037: JvmtiEnv::ClearBreakpoint(Method* method_oop, jlocation location) { duke@435: NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); duke@435: duke@435: if (location < 0) { // simple invalid location check first duke@435: return JVMTI_ERROR_INVALID_LOCATION; duke@435: } duke@435: duke@435: // verify that the breakpoint is not past the end of the method duke@435: if (location >= (jlocation) method_oop->code_size()) { duke@435: return JVMTI_ERROR_INVALID_LOCATION; duke@435: } duke@435: duke@435: JvmtiBreakpoint bp(method_oop, location); duke@435: duke@435: JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints(); duke@435: if (jvmti_breakpoints.clear(bp) == JVMTI_ERROR_NOT_FOUND) duke@435: return JVMTI_ERROR_NOT_FOUND; duke@435: duke@435: if (TraceJVMTICalls) { duke@435: jvmti_breakpoints.print(); duke@435: } duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end ClearBreakpoint */ duke@435: duke@435: duke@435: // duke@435: // Watched Field functions duke@435: // duke@435: duke@435: jvmtiError duke@435: JvmtiEnv::SetFieldAccessWatch(fieldDescriptor* fdesc_ptr) { duke@435: // make sure we haven't set this watch before duke@435: if (fdesc_ptr->is_field_access_watched()) return JVMTI_ERROR_DUPLICATE; duke@435: fdesc_ptr->set_is_field_access_watched(true); duke@435: duke@435: JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_ACCESS, true); duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end SetFieldAccessWatch */ duke@435: duke@435: duke@435: jvmtiError duke@435: JvmtiEnv::ClearFieldAccessWatch(fieldDescriptor* fdesc_ptr) { duke@435: // make sure we have a watch to clear duke@435: if (!fdesc_ptr->is_field_access_watched()) return JVMTI_ERROR_NOT_FOUND; duke@435: fdesc_ptr->set_is_field_access_watched(false); duke@435: duke@435: JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_ACCESS, false); duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end ClearFieldAccessWatch */ duke@435: duke@435: duke@435: jvmtiError duke@435: JvmtiEnv::SetFieldModificationWatch(fieldDescriptor* fdesc_ptr) { duke@435: // make sure we haven't set this watch before duke@435: if (fdesc_ptr->is_field_modification_watched()) return JVMTI_ERROR_DUPLICATE; duke@435: fdesc_ptr->set_is_field_modification_watched(true); duke@435: duke@435: JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_MODIFICATION, true); duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end SetFieldModificationWatch */ duke@435: duke@435: duke@435: jvmtiError duke@435: JvmtiEnv::ClearFieldModificationWatch(fieldDescriptor* fdesc_ptr) { duke@435: // make sure we have a watch to clear duke@435: if (!fdesc_ptr->is_field_modification_watched()) return JVMTI_ERROR_NOT_FOUND; duke@435: fdesc_ptr->set_is_field_modification_watched(false); duke@435: duke@435: JvmtiEventController::change_field_watch(JVMTI_EVENT_FIELD_MODIFICATION, false); duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end ClearFieldModificationWatch */ duke@435: duke@435: // duke@435: // Class functions duke@435: // duke@435: duke@435: duke@435: // k_mirror - may be primitive, this must be checked duke@435: // signature_ptr - NULL is a valid value, must be checked duke@435: // generic_ptr - NULL is a valid value, must be checked duke@435: jvmtiError duke@435: JvmtiEnv::GetClassSignature(oop k_mirror, char** signature_ptr, char** generic_ptr) { duke@435: ResourceMark rm; duke@435: bool isPrimitive = java_lang_Class::is_primitive(k_mirror); coleenp@4037: Klass* k = NULL; duke@435: if (!isPrimitive) { coleenp@4037: k = java_lang_Class::as_Klass(k_mirror); duke@435: NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); duke@435: } duke@435: if (signature_ptr != NULL) { duke@435: char* result = NULL; duke@435: if (isPrimitive) { duke@435: char tchar = type2char(java_lang_Class::primitive_type(k_mirror)); duke@435: result = (char*) jvmtiMalloc(2); duke@435: result[0] = tchar; duke@435: result[1] = '\0'; duke@435: } else { hseigel@4278: const char* class_sig = k->signature_name(); duke@435: result = (char *) jvmtiMalloc(strlen(class_sig)+1); duke@435: strcpy(result, class_sig); duke@435: } duke@435: *signature_ptr = result; duke@435: } duke@435: if (generic_ptr != NULL) { duke@435: *generic_ptr = NULL; hseigel@4278: if (!isPrimitive && k->oop_is_instance()) { coleenp@4037: Symbol* soo = InstanceKlass::cast(k)->generic_signature(); duke@435: if (soo != NULL) { duke@435: const char *gen_sig = soo->as_C_string(); duke@435: if (gen_sig != NULL) { duke@435: char* gen_result; duke@435: jvmtiError err = allocate(strlen(gen_sig) + 1, duke@435: (unsigned char **)&gen_result); duke@435: if (err != JVMTI_ERROR_NONE) { duke@435: return err; duke@435: } duke@435: strcpy(gen_result, gen_sig); duke@435: *generic_ptr = gen_result; duke@435: } duke@435: } duke@435: } duke@435: } duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetClassSignature */ duke@435: duke@435: duke@435: // k_mirror - may be primitive, this must be checked duke@435: // status_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetClassStatus(oop k_mirror, jint* status_ptr) { duke@435: jint result = 0; duke@435: if (java_lang_Class::is_primitive(k_mirror)) { duke@435: result |= JVMTI_CLASS_STATUS_PRIMITIVE; duke@435: } else { coleenp@4037: Klass* k = java_lang_Class::as_Klass(k_mirror); duke@435: NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); hseigel@4278: result = k->jvmti_class_status(); duke@435: } duke@435: *status_ptr = result; duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetClassStatus */ duke@435: duke@435: duke@435: // k_mirror - may be primitive, this must be checked duke@435: // source_name_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetSourceFileName(oop k_mirror, char** source_name_ptr) { duke@435: if (java_lang_Class::is_primitive(k_mirror)) { duke@435: return JVMTI_ERROR_ABSENT_INFORMATION; duke@435: } coleenp@4037: Klass* k_klass = java_lang_Class::as_Klass(k_mirror); duke@435: NULL_CHECK(k_klass, JVMTI_ERROR_INVALID_CLASS); duke@435: hseigel@4278: if (!k_klass->oop_is_instance()) { duke@435: return JVMTI_ERROR_ABSENT_INFORMATION; duke@435: } duke@435: coleenp@4037: Symbol* sfnOop = InstanceKlass::cast(k_klass)->source_file_name(); duke@435: NULL_CHECK(sfnOop, JVMTI_ERROR_ABSENT_INFORMATION); duke@435: { duke@435: JavaThread* current_thread = JavaThread::current(); duke@435: ResourceMark rm(current_thread); duke@435: const char* sfncp = (const char*) sfnOop->as_C_string(); duke@435: *source_name_ptr = (char *) jvmtiMalloc(strlen(sfncp)+1); duke@435: strcpy(*source_name_ptr, sfncp); duke@435: } duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetSourceFileName */ duke@435: duke@435: duke@435: // k_mirror - may be primitive, this must be checked duke@435: // modifiers_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetClassModifiers(oop k_mirror, jint* modifiers_ptr) { duke@435: JavaThread* current_thread = JavaThread::current(); duke@435: jint result = 0; duke@435: if (!java_lang_Class::is_primitive(k_mirror)) { coleenp@4037: Klass* k = java_lang_Class::as_Klass(k_mirror); duke@435: NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); hseigel@4278: result = k->compute_modifier_flags(current_thread); duke@435: JavaThread* THREAD = current_thread; // pass to macros duke@435: if (HAS_PENDING_EXCEPTION) { duke@435: CLEAR_PENDING_EXCEPTION; duke@435: return JVMTI_ERROR_INTERNAL; duke@435: }; duke@435: duke@435: // Reset the deleted ACC_SUPER bit ( deleted in compute_modifier_flags()). hseigel@4278: if(k->is_super()) { duke@435: result |= JVM_ACC_SUPER; duke@435: } duke@435: } else { duke@435: result = (JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC); duke@435: } duke@435: *modifiers_ptr = result; duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetClassModifiers */ duke@435: duke@435: duke@435: // k_mirror - may be primitive, this must be checked duke@435: // method_count_ptr - pre-checked for NULL duke@435: // methods_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetClassMethods(oop k_mirror, jint* method_count_ptr, jmethodID** methods_ptr) { duke@435: JavaThread* current_thread = JavaThread::current(); duke@435: HandleMark hm(current_thread); duke@435: duke@435: if (java_lang_Class::is_primitive(k_mirror)) { duke@435: *method_count_ptr = 0; duke@435: *methods_ptr = (jmethodID*) jvmtiMalloc(0 * sizeof(jmethodID)); duke@435: return JVMTI_ERROR_NONE; duke@435: } coleenp@4037: Klass* k = java_lang_Class::as_Klass(k_mirror); duke@435: NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); duke@435: duke@435: // Return CLASS_NOT_PREPARED error as per JVMTI spec. hseigel@4278: if (!(k->jvmti_class_status() & (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY) )) { duke@435: return JVMTI_ERROR_CLASS_NOT_PREPARED; duke@435: } duke@435: hseigel@4278: if (!k->oop_is_instance()) { duke@435: *method_count_ptr = 0; duke@435: *methods_ptr = (jmethodID*) jvmtiMalloc(0 * sizeof(jmethodID)); duke@435: return JVMTI_ERROR_NONE; duke@435: } duke@435: instanceKlassHandle instanceK_h(current_thread, k); duke@435: // Allocate the result and fill it in duke@435: int result_length = instanceK_h->methods()->length(); duke@435: jmethodID* result_list = (jmethodID*)jvmtiMalloc(result_length * sizeof(jmethodID)); duke@435: int index; duke@435: if (JvmtiExport::can_maintain_original_method_order()) { duke@435: // Use the original method ordering indices stored in the class, so we can emit duke@435: // jmethodIDs in the order they appeared in the class file duke@435: for (index = 0; index < result_length; index++) { coleenp@4037: Method* m = instanceK_h->methods()->at(index); coleenp@4037: int original_index = instanceK_h->method_ordering()->at(index); duke@435: assert(original_index >= 0 && original_index < result_length, "invalid original method index"); duke@435: jmethodID id = m->jmethod_id(); duke@435: result_list[original_index] = id; duke@435: } duke@435: } else { duke@435: // otherwise just copy in any order duke@435: for (index = 0; index < result_length; index++) { coleenp@4037: Method* m = instanceK_h->methods()->at(index); duke@435: jmethodID id = m->jmethod_id(); duke@435: result_list[index] = id; duke@435: } duke@435: } duke@435: // Fill in return value. duke@435: *method_count_ptr = result_length; duke@435: *methods_ptr = result_list; duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetClassMethods */ duke@435: duke@435: duke@435: // k_mirror - may be primitive, this must be checked duke@435: // field_count_ptr - pre-checked for NULL duke@435: // fields_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetClassFields(oop k_mirror, jint* field_count_ptr, jfieldID** fields_ptr) { duke@435: if (java_lang_Class::is_primitive(k_mirror)) { duke@435: *field_count_ptr = 0; duke@435: *fields_ptr = (jfieldID*) jvmtiMalloc(0 * sizeof(jfieldID)); duke@435: return JVMTI_ERROR_NONE; duke@435: } duke@435: JavaThread* current_thread = JavaThread::current(); duke@435: HandleMark hm(current_thread); coleenp@4037: Klass* k = java_lang_Class::as_Klass(k_mirror); duke@435: NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); duke@435: duke@435: // Return CLASS_NOT_PREPARED error as per JVMTI spec. hseigel@4278: if (!(k->jvmti_class_status() & (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY) )) { duke@435: return JVMTI_ERROR_CLASS_NOT_PREPARED; duke@435: } duke@435: hseigel@4278: if (!k->oop_is_instance()) { duke@435: *field_count_ptr = 0; duke@435: *fields_ptr = (jfieldID*) jvmtiMalloc(0 * sizeof(jfieldID)); duke@435: return JVMTI_ERROR_NONE; duke@435: } duke@435: duke@435: duke@435: instanceKlassHandle instanceK_h(current_thread, k); duke@435: duke@435: int result_count = 0; duke@435: // First, count the fields. duke@435: FilteredFieldStream flds(instanceK_h, true, true); duke@435: result_count = flds.field_count(); duke@435: duke@435: // Allocate the result and fill it in duke@435: jfieldID* result_list = (jfieldID*) jvmtiMalloc(result_count * sizeof(jfieldID)); duke@435: // The JVMTI spec requires fields in the order they occur in the class file, duke@435: // this is the reverse order of what FieldStream hands out. duke@435: int id_index = (result_count - 1); duke@435: duke@435: for (FilteredFieldStream src_st(instanceK_h, true, true); !src_st.eos(); src_st.next()) { duke@435: result_list[id_index--] = jfieldIDWorkaround::to_jfieldID( duke@435: instanceK_h, src_st.offset(), duke@435: src_st.access_flags().is_static()); duke@435: } duke@435: assert(id_index == -1, "just checking"); duke@435: // Fill in the results duke@435: *field_count_ptr = result_count; duke@435: *fields_ptr = result_list; duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetClassFields */ duke@435: duke@435: duke@435: // k_mirror - may be primitive, this must be checked duke@435: // interface_count_ptr - pre-checked for NULL duke@435: // interfaces_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetImplementedInterfaces(oop k_mirror, jint* interface_count_ptr, jclass** interfaces_ptr) { duke@435: { duke@435: if (java_lang_Class::is_primitive(k_mirror)) { duke@435: *interface_count_ptr = 0; duke@435: *interfaces_ptr = (jclass*) jvmtiMalloc(0 * sizeof(jclass)); duke@435: return JVMTI_ERROR_NONE; duke@435: } duke@435: JavaThread* current_thread = JavaThread::current(); duke@435: HandleMark hm(current_thread); coleenp@4037: Klass* k = java_lang_Class::as_Klass(k_mirror); duke@435: NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); duke@435: duke@435: // Return CLASS_NOT_PREPARED error as per JVMTI spec. hseigel@4278: if (!(k->jvmti_class_status() & (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY) )) duke@435: return JVMTI_ERROR_CLASS_NOT_PREPARED; duke@435: hseigel@4278: if (!k->oop_is_instance()) { duke@435: *interface_count_ptr = 0; duke@435: *interfaces_ptr = (jclass*) jvmtiMalloc(0 * sizeof(jclass)); duke@435: return JVMTI_ERROR_NONE; duke@435: } duke@435: coleenp@4037: Array* interface_list = InstanceKlass::cast(k)->local_interfaces(); coleenp@4037: const int result_length = (interface_list == NULL ? 0 : interface_list->length()); duke@435: jclass* result_list = (jclass*) jvmtiMalloc(result_length * sizeof(jclass)); duke@435: for (int i_index = 0; i_index < result_length; i_index += 1) { coleenp@4037: Klass* klass_at = interface_list->at(i_index); coleenp@4037: assert(klass_at->is_klass(), "interfaces must be Klass*s"); hseigel@4278: assert(klass_at->is_interface(), "interfaces must be interfaces"); hseigel@4278: oop mirror_at = klass_at->java_mirror(); duke@435: Handle handle_at = Handle(current_thread, mirror_at); duke@435: result_list[i_index] = (jclass) jni_reference(handle_at); duke@435: } duke@435: *interface_count_ptr = result_length; duke@435: *interfaces_ptr = result_list; duke@435: } duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetImplementedInterfaces */ duke@435: duke@435: duke@435: // k_mirror - may be primitive, this must be checked duke@435: // minor_version_ptr - pre-checked for NULL duke@435: // major_version_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetClassVersionNumbers(oop k_mirror, jint* minor_version_ptr, jint* major_version_ptr) { duke@435: if (java_lang_Class::is_primitive(k_mirror)) { duke@435: return JVMTI_ERROR_ABSENT_INFORMATION; duke@435: } coleenp@4037: Klass* k_oop = java_lang_Class::as_Klass(k_mirror); duke@435: Thread *thread = Thread::current(); duke@435: HandleMark hm(thread); duke@435: KlassHandle klass(thread, k_oop); duke@435: duke@435: jint status = klass->jvmti_class_status(); duke@435: if (status & (JVMTI_CLASS_STATUS_ERROR)) { duke@435: return JVMTI_ERROR_INVALID_CLASS; duke@435: } duke@435: if (status & (JVMTI_CLASS_STATUS_ARRAY)) { duke@435: return JVMTI_ERROR_ABSENT_INFORMATION; duke@435: } duke@435: duke@435: instanceKlassHandle ik(thread, k_oop); duke@435: *minor_version_ptr = ik->minor_version(); duke@435: *major_version_ptr = ik->major_version(); duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetClassVersionNumbers */ duke@435: duke@435: duke@435: // k_mirror - may be primitive, this must be checked duke@435: // constant_pool_count_ptr - pre-checked for NULL duke@435: // constant_pool_byte_count_ptr - pre-checked for NULL duke@435: // constant_pool_bytes_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetConstantPool(oop k_mirror, jint* constant_pool_count_ptr, jint* constant_pool_byte_count_ptr, unsigned char** constant_pool_bytes_ptr) { duke@435: if (java_lang_Class::is_primitive(k_mirror)) { duke@435: return JVMTI_ERROR_ABSENT_INFORMATION; duke@435: } duke@435: coleenp@4037: Klass* k_oop = java_lang_Class::as_Klass(k_mirror); duke@435: Thread *thread = Thread::current(); duke@435: HandleMark hm(thread); duke@435: ResourceMark rm(thread); duke@435: KlassHandle klass(thread, k_oop); duke@435: duke@435: jint status = klass->jvmti_class_status(); duke@435: if (status & (JVMTI_CLASS_STATUS_ERROR)) { duke@435: return JVMTI_ERROR_INVALID_CLASS; duke@435: } duke@435: if (status & (JVMTI_CLASS_STATUS_ARRAY)) { duke@435: return JVMTI_ERROR_ABSENT_INFORMATION; duke@435: } duke@435: duke@435: instanceKlassHandle ikh(thread, k_oop); duke@435: constantPoolHandle constants(thread, ikh->constants()); iklam@5971: MonitorLockerEx ml(constants->lock()); // lock constant pool while we query it duke@435: duke@435: JvmtiConstantPoolReconstituter reconstituter(ikh); duke@435: if (reconstituter.get_error() != JVMTI_ERROR_NONE) { duke@435: return reconstituter.get_error(); duke@435: } duke@435: duke@435: unsigned char *cpool_bytes; duke@435: int cpool_size = reconstituter.cpool_size(); duke@435: if (reconstituter.get_error() != JVMTI_ERROR_NONE) { duke@435: return reconstituter.get_error(); duke@435: } duke@435: jvmtiError res = allocate(cpool_size, &cpool_bytes); duke@435: if (res != JVMTI_ERROR_NONE) { duke@435: return res; duke@435: } duke@435: reconstituter.copy_cpool_bytes(cpool_bytes); duke@435: if (reconstituter.get_error() != JVMTI_ERROR_NONE) { duke@435: return reconstituter.get_error(); duke@435: } duke@435: duke@435: *constant_pool_count_ptr = constants->length(); duke@435: *constant_pool_byte_count_ptr = cpool_size; duke@435: *constant_pool_bytes_ptr = cpool_bytes; duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetConstantPool */ duke@435: duke@435: duke@435: // k_mirror - may be primitive, this must be checked duke@435: // is_interface_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::IsInterface(oop k_mirror, jboolean* is_interface_ptr) { duke@435: { duke@435: bool result = false; duke@435: if (!java_lang_Class::is_primitive(k_mirror)) { coleenp@4037: Klass* k = java_lang_Class::as_Klass(k_mirror); hseigel@4278: if (k != NULL && k->is_interface()) { duke@435: result = true; duke@435: } duke@435: } duke@435: *is_interface_ptr = result; duke@435: } duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end IsInterface */ duke@435: duke@435: duke@435: // k_mirror - may be primitive, this must be checked duke@435: // is_array_class_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::IsArrayClass(oop k_mirror, jboolean* is_array_class_ptr) { duke@435: { duke@435: bool result = false; duke@435: if (!java_lang_Class::is_primitive(k_mirror)) { coleenp@4037: Klass* k = java_lang_Class::as_Klass(k_mirror); hseigel@4278: if (k != NULL && k->oop_is_array()) { duke@435: result = true; duke@435: } duke@435: } duke@435: *is_array_class_ptr = result; duke@435: } duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end IsArrayClass */ duke@435: duke@435: duke@435: // k_mirror - may be primitive, this must be checked duke@435: // classloader_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetClassLoader(oop k_mirror, jobject* classloader_ptr) { duke@435: { duke@435: if (java_lang_Class::is_primitive(k_mirror)) { duke@435: *classloader_ptr = (jclass) jni_reference(Handle()); duke@435: return JVMTI_ERROR_NONE; duke@435: } duke@435: JavaThread* current_thread = JavaThread::current(); duke@435: HandleMark hm(current_thread); coleenp@4037: Klass* k = java_lang_Class::as_Klass(k_mirror); duke@435: NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); duke@435: hseigel@4278: oop result_oop = k->class_loader(); duke@435: if (result_oop == NULL) { duke@435: *classloader_ptr = (jclass) jni_reference(Handle()); duke@435: return JVMTI_ERROR_NONE; duke@435: } duke@435: Handle result_handle = Handle(current_thread, result_oop); duke@435: jclass result_jnihandle = (jclass) jni_reference(result_handle); duke@435: *classloader_ptr = result_jnihandle; duke@435: } duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetClassLoader */ duke@435: duke@435: duke@435: // k_mirror - may be primitive, this must be checked duke@435: // source_debug_extension_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetSourceDebugExtension(oop k_mirror, char** source_debug_extension_ptr) { duke@435: { duke@435: if (java_lang_Class::is_primitive(k_mirror)) { duke@435: return JVMTI_ERROR_ABSENT_INFORMATION; duke@435: } coleenp@4037: Klass* k = java_lang_Class::as_Klass(k_mirror); duke@435: NULL_CHECK(k, JVMTI_ERROR_INVALID_CLASS); hseigel@4278: if (!k->oop_is_instance()) { duke@435: return JVMTI_ERROR_ABSENT_INFORMATION; duke@435: } coleenp@4037: char* sde = InstanceKlass::cast(k)->source_debug_extension(); fparain@3906: NULL_CHECK(sde, JVMTI_ERROR_ABSENT_INFORMATION); duke@435: duke@435: { fparain@3906: *source_debug_extension_ptr = (char *) jvmtiMalloc(strlen(sde)+1); fparain@3906: strcpy(*source_debug_extension_ptr, sde); duke@435: } duke@435: } duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetSourceDebugExtension */ duke@435: duke@435: // duke@435: // Object functions duke@435: // duke@435: duke@435: // hash_code_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetObjectHashCode(jobject object, jint* hash_code_ptr) { duke@435: oop mirror = JNIHandles::resolve_external_guard(object); duke@435: NULL_CHECK(mirror, JVMTI_ERROR_INVALID_OBJECT); duke@435: NULL_CHECK(hash_code_ptr, JVMTI_ERROR_NULL_POINTER); duke@435: duke@435: { duke@435: jint result = (jint) mirror->identity_hash(); duke@435: *hash_code_ptr = result; duke@435: } duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetObjectHashCode */ duke@435: duke@435: duke@435: // info_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetObjectMonitorUsage(jobject object, jvmtiMonitorUsage* info_ptr) { duke@435: JavaThread* calling_thread = JavaThread::current(); duke@435: jvmtiError err = get_object_monitor_usage(calling_thread, object, info_ptr); duke@435: if (err == JVMTI_ERROR_THREAD_NOT_SUSPENDED) { duke@435: // Some of the critical threads were not suspended. go to a safepoint and try again duke@435: VM_GetObjectMonitorUsage op(this, calling_thread, object, info_ptr); duke@435: VMThread::execute(&op); duke@435: err = op.result(); duke@435: } duke@435: return err; duke@435: } /* end GetObjectMonitorUsage */ duke@435: duke@435: duke@435: // duke@435: // Field functions duke@435: // duke@435: duke@435: // name_ptr - NULL is a valid value, must be checked duke@435: // signature_ptr - NULL is a valid value, must be checked duke@435: // generic_ptr - NULL is a valid value, must be checked duke@435: jvmtiError duke@435: JvmtiEnv::GetFieldName(fieldDescriptor* fdesc_ptr, char** name_ptr, char** signature_ptr, char** generic_ptr) { duke@435: JavaThread* current_thread = JavaThread::current(); duke@435: ResourceMark rm(current_thread); duke@435: if (name_ptr == NULL) { duke@435: // just don't return the name duke@435: } else { duke@435: const char* fieldName = fdesc_ptr->name()->as_C_string(); duke@435: *name_ptr = (char*) jvmtiMalloc(strlen(fieldName) + 1); duke@435: if (*name_ptr == NULL) duke@435: return JVMTI_ERROR_OUT_OF_MEMORY; duke@435: strcpy(*name_ptr, fieldName); duke@435: } duke@435: if (signature_ptr== NULL) { duke@435: // just don't return the signature duke@435: } else { duke@435: const char* fieldSignature = fdesc_ptr->signature()->as_C_string(); duke@435: *signature_ptr = (char*) jvmtiMalloc(strlen(fieldSignature) + 1); duke@435: if (*signature_ptr == NULL) duke@435: return JVMTI_ERROR_OUT_OF_MEMORY; duke@435: strcpy(*signature_ptr, fieldSignature); duke@435: } duke@435: if (generic_ptr != NULL) { duke@435: *generic_ptr = NULL; coleenp@2497: Symbol* soop = fdesc_ptr->generic_signature(); duke@435: if (soop != NULL) { duke@435: const char* gen_sig = soop->as_C_string(); duke@435: if (gen_sig != NULL) { duke@435: jvmtiError err = allocate(strlen(gen_sig) + 1, (unsigned char **)generic_ptr); duke@435: if (err != JVMTI_ERROR_NONE) { duke@435: return err; duke@435: } duke@435: strcpy(*generic_ptr, gen_sig); duke@435: } duke@435: } duke@435: } duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetFieldName */ duke@435: duke@435: duke@435: // declaring_class_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetFieldDeclaringClass(fieldDescriptor* fdesc_ptr, jclass* declaring_class_ptr) { duke@435: duke@435: *declaring_class_ptr = get_jni_class_non_null(fdesc_ptr->field_holder()); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetFieldDeclaringClass */ duke@435: duke@435: duke@435: // modifiers_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetFieldModifiers(fieldDescriptor* fdesc_ptr, jint* modifiers_ptr) { duke@435: duke@435: AccessFlags resultFlags = fdesc_ptr->access_flags(); duke@435: jint result = resultFlags.as_int(); duke@435: *modifiers_ptr = result; duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetFieldModifiers */ duke@435: duke@435: duke@435: // is_synthetic_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::IsFieldSynthetic(fieldDescriptor* fdesc_ptr, jboolean* is_synthetic_ptr) { duke@435: *is_synthetic_ptr = fdesc_ptr->is_synthetic(); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end IsFieldSynthetic */ duke@435: duke@435: duke@435: // duke@435: // Method functions duke@435: // duke@435: duke@435: // method_oop - pre-checked for validity, but may be NULL meaning obsolete method duke@435: // name_ptr - NULL is a valid value, must be checked duke@435: // signature_ptr - NULL is a valid value, must be checked duke@435: // generic_ptr - NULL is a valid value, must be checked duke@435: jvmtiError coleenp@4037: JvmtiEnv::GetMethodName(Method* method_oop, char** name_ptr, char** signature_ptr, char** generic_ptr) { duke@435: NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); duke@435: JavaThread* current_thread = JavaThread::current(); duke@435: duke@435: ResourceMark rm(current_thread); // get the utf8 name and signature duke@435: if (name_ptr == NULL) { duke@435: // just don't return the name duke@435: } else { duke@435: const char* utf8_name = (const char *) method_oop->name()->as_utf8(); duke@435: *name_ptr = (char *) jvmtiMalloc(strlen(utf8_name)+1); duke@435: strcpy(*name_ptr, utf8_name); duke@435: } duke@435: if (signature_ptr == NULL) { duke@435: // just don't return the signature duke@435: } else { duke@435: const char* utf8_signature = (const char *) method_oop->signature()->as_utf8(); duke@435: *signature_ptr = (char *) jvmtiMalloc(strlen(utf8_signature) + 1); duke@435: strcpy(*signature_ptr, utf8_signature); duke@435: } duke@435: duke@435: if (generic_ptr != NULL) { duke@435: *generic_ptr = NULL; coleenp@2497: Symbol* soop = method_oop->generic_signature(); duke@435: if (soop != NULL) { duke@435: const char* gen_sig = soop->as_C_string(); duke@435: if (gen_sig != NULL) { duke@435: jvmtiError err = allocate(strlen(gen_sig) + 1, (unsigned char **)generic_ptr); duke@435: if (err != JVMTI_ERROR_NONE) { duke@435: return err; duke@435: } duke@435: strcpy(*generic_ptr, gen_sig); duke@435: } duke@435: } duke@435: } duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetMethodName */ duke@435: duke@435: duke@435: // method_oop - pre-checked for validity, but may be NULL meaning obsolete method duke@435: // declaring_class_ptr - pre-checked for NULL duke@435: jvmtiError coleenp@4037: JvmtiEnv::GetMethodDeclaringClass(Method* method_oop, jclass* declaring_class_ptr) { duke@435: NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); duke@435: (*declaring_class_ptr) = get_jni_class_non_null(method_oop->method_holder()); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetMethodDeclaringClass */ duke@435: duke@435: duke@435: // method_oop - pre-checked for validity, but may be NULL meaning obsolete method duke@435: // modifiers_ptr - pre-checked for NULL duke@435: jvmtiError coleenp@4037: JvmtiEnv::GetMethodModifiers(Method* method_oop, jint* modifiers_ptr) { duke@435: NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); duke@435: (*modifiers_ptr) = method_oop->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS; duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetMethodModifiers */ duke@435: duke@435: duke@435: // method_oop - pre-checked for validity, but may be NULL meaning obsolete method duke@435: // max_ptr - pre-checked for NULL duke@435: jvmtiError coleenp@4037: JvmtiEnv::GetMaxLocals(Method* method_oop, jint* max_ptr) { duke@435: NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); duke@435: // get max stack duke@435: (*max_ptr) = method_oop->max_locals(); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetMaxLocals */ duke@435: duke@435: duke@435: // method_oop - pre-checked for validity, but may be NULL meaning obsolete method duke@435: // size_ptr - pre-checked for NULL duke@435: jvmtiError coleenp@4037: JvmtiEnv::GetArgumentsSize(Method* method_oop, jint* size_ptr) { duke@435: NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); duke@435: // get size of arguments duke@435: duke@435: (*size_ptr) = method_oop->size_of_parameters(); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetArgumentsSize */ duke@435: duke@435: duke@435: // method_oop - pre-checked for validity, but may be NULL meaning obsolete method duke@435: // entry_count_ptr - pre-checked for NULL duke@435: // table_ptr - pre-checked for NULL duke@435: jvmtiError coleenp@4037: JvmtiEnv::GetLineNumberTable(Method* method_oop, jint* entry_count_ptr, jvmtiLineNumberEntry** table_ptr) { duke@435: NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); duke@435: if (!method_oop->has_linenumber_table()) { duke@435: return (JVMTI_ERROR_ABSENT_INFORMATION); duke@435: } duke@435: duke@435: // The line number table is compressed so we don't know how big it is until decompressed. duke@435: // Decompression is really fast so we just do it twice. duke@435: duke@435: // Compute size of table duke@435: jint num_entries = 0; duke@435: CompressedLineNumberReadStream stream(method_oop->compressed_linenumber_table()); duke@435: while (stream.read_pair()) { duke@435: num_entries++; duke@435: } duke@435: jvmtiLineNumberEntry *jvmti_table = duke@435: (jvmtiLineNumberEntry *)jvmtiMalloc(num_entries * (sizeof(jvmtiLineNumberEntry))); duke@435: duke@435: // Fill jvmti table duke@435: if (num_entries > 0) { duke@435: int index = 0; duke@435: CompressedLineNumberReadStream stream(method_oop->compressed_linenumber_table()); duke@435: while (stream.read_pair()) { duke@435: jvmti_table[index].start_location = (jlocation) stream.bci(); duke@435: jvmti_table[index].line_number = (jint) stream.line(); duke@435: index++; duke@435: } duke@435: assert(index == num_entries, "sanity check"); duke@435: } duke@435: duke@435: // Set up results duke@435: (*entry_count_ptr) = num_entries; duke@435: (*table_ptr) = jvmti_table; duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetLineNumberTable */ duke@435: duke@435: duke@435: // method_oop - pre-checked for validity, but may be NULL meaning obsolete method duke@435: // start_location_ptr - pre-checked for NULL duke@435: // end_location_ptr - pre-checked for NULL duke@435: jvmtiError coleenp@4037: JvmtiEnv::GetMethodLocation(Method* method_oop, jlocation* start_location_ptr, jlocation* end_location_ptr) { duke@435: duke@435: NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); duke@435: // get start and end location duke@435: (*end_location_ptr) = (jlocation) (method_oop->code_size() - 1); duke@435: if (method_oop->code_size() == 0) { duke@435: // there is no code so there is no start location duke@435: (*start_location_ptr) = (jlocation)(-1); duke@435: } else { duke@435: (*start_location_ptr) = (jlocation)(0); duke@435: } duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetMethodLocation */ duke@435: duke@435: duke@435: // method_oop - pre-checked for validity, but may be NULL meaning obsolete method duke@435: // entry_count_ptr - pre-checked for NULL duke@435: // table_ptr - pre-checked for NULL duke@435: jvmtiError coleenp@4037: JvmtiEnv::GetLocalVariableTable(Method* method_oop, jint* entry_count_ptr, jvmtiLocalVariableEntry** table_ptr) { duke@435: duke@435: NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); duke@435: JavaThread* current_thread = JavaThread::current(); duke@435: duke@435: // does the klass have any local variable information? coleenp@4251: InstanceKlass* ik = method_oop->method_holder(); duke@435: if (!ik->access_flags().has_localvariable_table()) { duke@435: return (JVMTI_ERROR_ABSENT_INFORMATION); duke@435: } duke@435: coleenp@4037: ConstantPool* constants = method_oop->constants(); duke@435: NULL_CHECK(constants, JVMTI_ERROR_ABSENT_INFORMATION); duke@435: duke@435: // in the vm localvariable table representation, 6 consecutive elements in the table duke@435: // represent a 6-tuple of shorts duke@435: // [start_pc, length, name_index, descriptor_index, signature_index, index] duke@435: jint num_entries = method_oop->localvariable_table_length(); duke@435: jvmtiLocalVariableEntry *jvmti_table = (jvmtiLocalVariableEntry *) duke@435: jvmtiMalloc(num_entries * (sizeof(jvmtiLocalVariableEntry))); duke@435: duke@435: if (num_entries > 0) { duke@435: LocalVariableTableElement* table = method_oop->localvariable_table_start(); duke@435: for (int i = 0; i < num_entries; i++) { duke@435: // get the 5 tuple information from the vm table duke@435: jlocation start_location = (jlocation) table[i].start_bci; duke@435: jint length = (jint) table[i].length; duke@435: int name_index = (int) table[i].name_cp_index; duke@435: int signature_index = (int) table[i].descriptor_cp_index; duke@435: int generic_signature_index = (int) table[i].signature_cp_index; duke@435: jint slot = (jint) table[i].slot; duke@435: duke@435: // get utf8 name and signature duke@435: char *name_buf = NULL; duke@435: char *sig_buf = NULL; duke@435: char *gen_sig_buf = NULL; duke@435: { duke@435: ResourceMark rm(current_thread); duke@435: duke@435: const char *utf8_name = (const char *) constants->symbol_at(name_index)->as_utf8(); duke@435: name_buf = (char *) jvmtiMalloc(strlen(utf8_name)+1); duke@435: strcpy(name_buf, utf8_name); duke@435: duke@435: const char *utf8_signature = (const char *) constants->symbol_at(signature_index)->as_utf8(); duke@435: sig_buf = (char *) jvmtiMalloc(strlen(utf8_signature)+1); duke@435: strcpy(sig_buf, utf8_signature); duke@435: duke@435: if (generic_signature_index > 0) { duke@435: const char *utf8_gen_sign = (const char *) duke@435: constants->symbol_at(generic_signature_index)->as_utf8(); duke@435: gen_sig_buf = (char *) jvmtiMalloc(strlen(utf8_gen_sign)+1); duke@435: strcpy(gen_sig_buf, utf8_gen_sign); duke@435: } duke@435: } duke@435: duke@435: // fill in the jvmti local variable table duke@435: jvmti_table[i].start_location = start_location; duke@435: jvmti_table[i].length = length; duke@435: jvmti_table[i].name = name_buf; duke@435: jvmti_table[i].signature = sig_buf; duke@435: jvmti_table[i].generic_signature = gen_sig_buf; duke@435: jvmti_table[i].slot = slot; duke@435: } duke@435: } duke@435: duke@435: // set results duke@435: (*entry_count_ptr) = num_entries; duke@435: (*table_ptr) = jvmti_table; duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetLocalVariableTable */ duke@435: duke@435: duke@435: // method_oop - pre-checked for validity, but may be NULL meaning obsolete method duke@435: // bytecode_count_ptr - pre-checked for NULL duke@435: // bytecodes_ptr - pre-checked for NULL duke@435: jvmtiError coleenp@4037: JvmtiEnv::GetBytecodes(Method* method_oop, jint* bytecode_count_ptr, unsigned char** bytecodes_ptr) { duke@435: NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); duke@435: duke@435: HandleMark hm; duke@435: methodHandle method(method_oop); duke@435: jint size = (jint)method->code_size(); duke@435: jvmtiError err = allocate(size, bytecodes_ptr); duke@435: if (err != JVMTI_ERROR_NONE) { duke@435: return err; duke@435: } duke@435: duke@435: (*bytecode_count_ptr) = size; duke@435: // get byte codes duke@435: JvmtiClassFileReconstituter::copy_bytecodes(method, *bytecodes_ptr); duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetBytecodes */ duke@435: duke@435: duke@435: // method_oop - pre-checked for validity, but may be NULL meaning obsolete method duke@435: // is_native_ptr - pre-checked for NULL duke@435: jvmtiError coleenp@4037: JvmtiEnv::IsMethodNative(Method* method_oop, jboolean* is_native_ptr) { duke@435: NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); duke@435: (*is_native_ptr) = method_oop->is_native(); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end IsMethodNative */ duke@435: duke@435: duke@435: // method_oop - pre-checked for validity, but may be NULL meaning obsolete method duke@435: // is_synthetic_ptr - pre-checked for NULL duke@435: jvmtiError coleenp@4037: JvmtiEnv::IsMethodSynthetic(Method* method_oop, jboolean* is_synthetic_ptr) { duke@435: NULL_CHECK(method_oop, JVMTI_ERROR_INVALID_METHODID); duke@435: (*is_synthetic_ptr) = method_oop->is_synthetic(); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end IsMethodSynthetic */ duke@435: duke@435: duke@435: // method_oop - pre-checked for validity, but may be NULL meaning obsolete method duke@435: // is_obsolete_ptr - pre-checked for NULL duke@435: jvmtiError coleenp@4037: JvmtiEnv::IsMethodObsolete(Method* method_oop, jboolean* is_obsolete_ptr) { dcubed@1556: if (use_version_1_0_semantics() && dcubed@1556: get_capabilities()->can_redefine_classes == 0) { dcubed@1556: // This JvmtiEnv requested version 1.0 semantics and this function dcubed@1556: // requires the can_redefine_classes capability in version 1.0 so dcubed@1556: // we need to return an error here. dcubed@1556: return JVMTI_ERROR_MUST_POSSESS_CAPABILITY; dcubed@1556: } dcubed@1556: duke@435: if (method_oop == NULL || method_oop->is_obsolete()) { duke@435: *is_obsolete_ptr = true; duke@435: } else { duke@435: *is_obsolete_ptr = false; duke@435: } duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end IsMethodObsolete */ duke@435: duke@435: // duke@435: // Raw Monitor functions duke@435: // duke@435: duke@435: // name - pre-checked for NULL duke@435: // monitor_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::CreateRawMonitor(const char* name, jrawMonitorID* monitor_ptr) { duke@435: JvmtiRawMonitor* rmonitor = new JvmtiRawMonitor(name); duke@435: NULL_CHECK(rmonitor, JVMTI_ERROR_OUT_OF_MEMORY); duke@435: duke@435: *monitor_ptr = (jrawMonitorID)rmonitor; duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end CreateRawMonitor */ duke@435: duke@435: duke@435: // rmonitor - pre-checked for validity duke@435: jvmtiError duke@435: JvmtiEnv::DestroyRawMonitor(JvmtiRawMonitor * rmonitor) { duke@435: if (Threads::number_of_threads() == 0) { duke@435: // Remove this monitor from pending raw monitors list duke@435: // if it has entered in onload or start phase. duke@435: JvmtiPendingMonitors::destroy(rmonitor); duke@435: } else { duke@435: Thread* thread = Thread::current(); duke@435: if (rmonitor->is_entered(thread)) { duke@435: // The caller owns this monitor which we are about to destroy. duke@435: // We exit the underlying synchronization object so that the duke@435: // "delete monitor" call below can work without an assertion duke@435: // failure on systems that don't like destroying synchronization duke@435: // objects that are locked. duke@435: int r; duke@435: intptr_t recursion = rmonitor->recursions(); duke@435: for (intptr_t i=0; i <= recursion; i++) { duke@435: r = rmonitor->raw_exit(thread); duke@435: assert(r == ObjectMonitor::OM_OK, "raw_exit should have worked"); duke@435: if (r != ObjectMonitor::OM_OK) { // robustness duke@435: return JVMTI_ERROR_INTERNAL; duke@435: } duke@435: } duke@435: } duke@435: if (rmonitor->owner() != NULL) { duke@435: // The caller is trying to destroy a monitor that is locked by duke@435: // someone else. While this is not forbidden by the JVMTI duke@435: // spec, it will cause an assertion failure on systems that don't duke@435: // like destroying synchronization objects that are locked. duke@435: // We indicate a problem with the error return (and leak the duke@435: // monitor's memory). duke@435: return JVMTI_ERROR_NOT_MONITOR_OWNER; duke@435: } duke@435: } duke@435: duke@435: delete rmonitor; duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end DestroyRawMonitor */ duke@435: duke@435: duke@435: // rmonitor - pre-checked for validity duke@435: jvmtiError duke@435: JvmtiEnv::RawMonitorEnter(JvmtiRawMonitor * rmonitor) { duke@435: if (Threads::number_of_threads() == 0) { duke@435: // No JavaThreads exist so ObjectMonitor enter cannot be duke@435: // used, add this raw monitor to the pending list. duke@435: // The pending monitors will be actually entered when duke@435: // the VM is setup. duke@435: // See transition_pending_raw_monitors in create_vm() duke@435: // in thread.cpp. duke@435: JvmtiPendingMonitors::enter(rmonitor); duke@435: } else { duke@435: int r; duke@435: Thread* thread = Thread::current(); duke@435: duke@435: if (thread->is_Java_thread()) { duke@435: JavaThread* current_thread = (JavaThread*)thread; duke@435: duke@435: #ifdef PROPER_TRANSITIONS duke@435: // Not really unknown but ThreadInVMfromNative does more than we want duke@435: ThreadInVMfromUnknown __tiv; duke@435: { duke@435: ThreadBlockInVM __tbivm(current_thread); duke@435: r = rmonitor->raw_enter(current_thread); duke@435: } duke@435: #else duke@435: /* Transition to thread_blocked without entering vm state */ duke@435: /* This is really evil. Normally you can't undo _thread_blocked */ duke@435: /* transitions like this because it would cause us to miss a */ duke@435: /* safepoint but since the thread was already in _thread_in_native */ duke@435: /* the thread is not leaving a safepoint safe state and it will */ duke@435: /* block when it tries to return from native. We can't safepoint */ duke@435: /* block in here because we could deadlock the vmthread. Blech. */ duke@435: duke@435: JavaThreadState state = current_thread->thread_state(); duke@435: assert(state == _thread_in_native, "Must be _thread_in_native"); duke@435: // frame should already be walkable since we are in native duke@435: assert(!current_thread->has_last_Java_frame() || duke@435: current_thread->frame_anchor()->walkable(), "Must be walkable"); duke@435: current_thread->set_thread_state(_thread_blocked); duke@435: duke@435: r = rmonitor->raw_enter(current_thread); duke@435: // restore state, still at a safepoint safe state duke@435: current_thread->set_thread_state(state); duke@435: duke@435: #endif /* PROPER_TRANSITIONS */ duke@435: assert(r == ObjectMonitor::OM_OK, "raw_enter should have worked"); duke@435: } else { duke@435: if (thread->is_VM_thread() || thread->is_ConcurrentGC_thread()) { duke@435: r = rmonitor->raw_enter(thread); duke@435: } else { duke@435: ShouldNotReachHere(); duke@435: } duke@435: } duke@435: duke@435: if (r != ObjectMonitor::OM_OK) { // robustness duke@435: return JVMTI_ERROR_INTERNAL; duke@435: } duke@435: } duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end RawMonitorEnter */ duke@435: duke@435: duke@435: // rmonitor - pre-checked for validity duke@435: jvmtiError duke@435: JvmtiEnv::RawMonitorExit(JvmtiRawMonitor * rmonitor) { duke@435: jvmtiError err = JVMTI_ERROR_NONE; duke@435: duke@435: if (Threads::number_of_threads() == 0) { duke@435: // No JavaThreads exist so just remove this monitor from the pending list. duke@435: // Bool value from exit is false if rmonitor is not in the list. duke@435: if (!JvmtiPendingMonitors::exit(rmonitor)) { duke@435: err = JVMTI_ERROR_NOT_MONITOR_OWNER; duke@435: } duke@435: } else { duke@435: int r; duke@435: Thread* thread = Thread::current(); duke@435: duke@435: if (thread->is_Java_thread()) { duke@435: JavaThread* current_thread = (JavaThread*)thread; duke@435: #ifdef PROPER_TRANSITIONS duke@435: // Not really unknown but ThreadInVMfromNative does more than we want duke@435: ThreadInVMfromUnknown __tiv; duke@435: #endif /* PROPER_TRANSITIONS */ duke@435: r = rmonitor->raw_exit(current_thread); duke@435: } else { duke@435: if (thread->is_VM_thread() || thread->is_ConcurrentGC_thread()) { duke@435: r = rmonitor->raw_exit(thread); duke@435: } else { duke@435: ShouldNotReachHere(); duke@435: } duke@435: } duke@435: duke@435: if (r == ObjectMonitor::OM_ILLEGAL_MONITOR_STATE) { duke@435: err = JVMTI_ERROR_NOT_MONITOR_OWNER; duke@435: } else { duke@435: assert(r == ObjectMonitor::OM_OK, "raw_exit should have worked"); duke@435: if (r != ObjectMonitor::OM_OK) { // robustness duke@435: err = JVMTI_ERROR_INTERNAL; duke@435: } duke@435: } duke@435: } duke@435: return err; duke@435: } /* end RawMonitorExit */ duke@435: duke@435: duke@435: // rmonitor - pre-checked for validity duke@435: jvmtiError duke@435: JvmtiEnv::RawMonitorWait(JvmtiRawMonitor * rmonitor, jlong millis) { duke@435: int r; duke@435: Thread* thread = Thread::current(); duke@435: duke@435: if (thread->is_Java_thread()) { duke@435: JavaThread* current_thread = (JavaThread*)thread; duke@435: #ifdef PROPER_TRANSITIONS duke@435: // Not really unknown but ThreadInVMfromNative does more than we want duke@435: ThreadInVMfromUnknown __tiv; duke@435: { duke@435: ThreadBlockInVM __tbivm(current_thread); duke@435: r = rmonitor->raw_wait(millis, true, current_thread); duke@435: } duke@435: #else duke@435: /* Transition to thread_blocked without entering vm state */ duke@435: /* This is really evil. Normally you can't undo _thread_blocked */ duke@435: /* transitions like this because it would cause us to miss a */ duke@435: /* safepoint but since the thread was already in _thread_in_native */ duke@435: /* the thread is not leaving a safepoint safe state and it will */ duke@435: /* block when it tries to return from native. We can't safepoint */ duke@435: /* block in here because we could deadlock the vmthread. Blech. */ duke@435: duke@435: JavaThreadState state = current_thread->thread_state(); duke@435: assert(state == _thread_in_native, "Must be _thread_in_native"); duke@435: // frame should already be walkable since we are in native duke@435: assert(!current_thread->has_last_Java_frame() || duke@435: current_thread->frame_anchor()->walkable(), "Must be walkable"); duke@435: current_thread->set_thread_state(_thread_blocked); duke@435: duke@435: r = rmonitor->raw_wait(millis, true, current_thread); duke@435: // restore state, still at a safepoint safe state duke@435: current_thread->set_thread_state(state); duke@435: duke@435: #endif /* PROPER_TRANSITIONS */ duke@435: } else { duke@435: if (thread->is_VM_thread() || thread->is_ConcurrentGC_thread()) { duke@435: r = rmonitor->raw_wait(millis, true, thread); duke@435: } else { duke@435: ShouldNotReachHere(); duke@435: } duke@435: } duke@435: duke@435: switch (r) { duke@435: case ObjectMonitor::OM_INTERRUPTED: duke@435: return JVMTI_ERROR_INTERRUPT; duke@435: case ObjectMonitor::OM_ILLEGAL_MONITOR_STATE: duke@435: return JVMTI_ERROR_NOT_MONITOR_OWNER; duke@435: } duke@435: assert(r == ObjectMonitor::OM_OK, "raw_wait should have worked"); duke@435: if (r != ObjectMonitor::OM_OK) { // robustness duke@435: return JVMTI_ERROR_INTERNAL; duke@435: } duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end RawMonitorWait */ duke@435: duke@435: duke@435: // rmonitor - pre-checked for validity duke@435: jvmtiError duke@435: JvmtiEnv::RawMonitorNotify(JvmtiRawMonitor * rmonitor) { duke@435: int r; duke@435: Thread* thread = Thread::current(); duke@435: duke@435: if (thread->is_Java_thread()) { duke@435: JavaThread* current_thread = (JavaThread*)thread; duke@435: // Not really unknown but ThreadInVMfromNative does more than we want duke@435: ThreadInVMfromUnknown __tiv; duke@435: r = rmonitor->raw_notify(current_thread); duke@435: } else { duke@435: if (thread->is_VM_thread() || thread->is_ConcurrentGC_thread()) { duke@435: r = rmonitor->raw_notify(thread); duke@435: } else { duke@435: ShouldNotReachHere(); duke@435: } duke@435: } duke@435: duke@435: if (r == ObjectMonitor::OM_ILLEGAL_MONITOR_STATE) { duke@435: return JVMTI_ERROR_NOT_MONITOR_OWNER; duke@435: } duke@435: assert(r == ObjectMonitor::OM_OK, "raw_notify should have worked"); duke@435: if (r != ObjectMonitor::OM_OK) { // robustness duke@435: return JVMTI_ERROR_INTERNAL; duke@435: } duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end RawMonitorNotify */ duke@435: duke@435: duke@435: // rmonitor - pre-checked for validity duke@435: jvmtiError duke@435: JvmtiEnv::RawMonitorNotifyAll(JvmtiRawMonitor * rmonitor) { duke@435: int r; duke@435: Thread* thread = Thread::current(); duke@435: duke@435: if (thread->is_Java_thread()) { duke@435: JavaThread* current_thread = (JavaThread*)thread; duke@435: ThreadInVMfromUnknown __tiv; duke@435: r = rmonitor->raw_notifyAll(current_thread); duke@435: } else { duke@435: if (thread->is_VM_thread() || thread->is_ConcurrentGC_thread()) { duke@435: r = rmonitor->raw_notifyAll(thread); duke@435: } else { duke@435: ShouldNotReachHere(); duke@435: } duke@435: } duke@435: duke@435: if (r == ObjectMonitor::OM_ILLEGAL_MONITOR_STATE) { duke@435: return JVMTI_ERROR_NOT_MONITOR_OWNER; duke@435: } duke@435: assert(r == ObjectMonitor::OM_OK, "raw_notifyAll should have worked"); duke@435: if (r != ObjectMonitor::OM_OK) { // robustness duke@435: return JVMTI_ERROR_INTERNAL; duke@435: } duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end RawMonitorNotifyAll */ duke@435: duke@435: duke@435: // duke@435: // JNI Function Interception functions duke@435: // duke@435: duke@435: duke@435: // function_table - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::SetJNIFunctionTable(const jniNativeInterface* function_table) { duke@435: // Copy jni function table at safepoint. duke@435: VM_JNIFunctionTableCopier copier(function_table); duke@435: VMThread::execute(&copier); duke@435: duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end SetJNIFunctionTable */ duke@435: duke@435: duke@435: // function_table - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetJNIFunctionTable(jniNativeInterface** function_table) { duke@435: *function_table=(jniNativeInterface*)jvmtiMalloc(sizeof(jniNativeInterface)); duke@435: if (*function_table == NULL) duke@435: return JVMTI_ERROR_OUT_OF_MEMORY; duke@435: memcpy(*function_table,(JavaThread::current())->get_jni_functions(),sizeof(jniNativeInterface)); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetJNIFunctionTable */ duke@435: duke@435: duke@435: // duke@435: // Event Management functions duke@435: // duke@435: duke@435: jvmtiError duke@435: JvmtiEnv::GenerateEvents(jvmtiEvent event_type) { duke@435: // can only generate two event types duke@435: if (event_type != JVMTI_EVENT_COMPILED_METHOD_LOAD && duke@435: event_type != JVMTI_EVENT_DYNAMIC_CODE_GENERATED) { duke@435: return JVMTI_ERROR_ILLEGAL_ARGUMENT; duke@435: } duke@435: duke@435: // for compiled_method_load events we must check that the environment duke@435: // has the can_generate_compiled_method_load_events capability. duke@435: if (event_type == JVMTI_EVENT_COMPILED_METHOD_LOAD) { duke@435: if (get_capabilities()->can_generate_compiled_method_load_events == 0) { duke@435: return JVMTI_ERROR_MUST_POSSESS_CAPABILITY; duke@435: } duke@435: return JvmtiCodeBlobEvents::generate_compiled_method_load_events(this); duke@435: } else { duke@435: return JvmtiCodeBlobEvents::generate_dynamic_code_events(this); duke@435: } duke@435: duke@435: } /* end GenerateEvents */ duke@435: duke@435: duke@435: // duke@435: // Extension Mechanism functions duke@435: // duke@435: duke@435: // extension_count_ptr - pre-checked for NULL duke@435: // extensions - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetExtensionFunctions(jint* extension_count_ptr, jvmtiExtensionFunctionInfo** extensions) { duke@435: return JvmtiExtensions::get_functions(this, extension_count_ptr, extensions); duke@435: } /* end GetExtensionFunctions */ duke@435: duke@435: duke@435: // extension_count_ptr - pre-checked for NULL duke@435: // extensions - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetExtensionEvents(jint* extension_count_ptr, jvmtiExtensionEventInfo** extensions) { duke@435: return JvmtiExtensions::get_events(this, extension_count_ptr, extensions); duke@435: } /* end GetExtensionEvents */ duke@435: duke@435: duke@435: // callback - NULL is a valid value, must be checked duke@435: jvmtiError duke@435: JvmtiEnv::SetExtensionEventCallback(jint extension_event_index, jvmtiExtensionEvent callback) { duke@435: return JvmtiExtensions::set_event_callback(this, extension_event_index, callback); duke@435: } /* end SetExtensionEventCallback */ duke@435: duke@435: // duke@435: // Timers functions duke@435: // duke@435: duke@435: // info_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetCurrentThreadCpuTimerInfo(jvmtiTimerInfo* info_ptr) { duke@435: os::current_thread_cpu_time_info(info_ptr); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetCurrentThreadCpuTimerInfo */ duke@435: duke@435: duke@435: // nanos_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetCurrentThreadCpuTime(jlong* nanos_ptr) { duke@435: *nanos_ptr = os::current_thread_cpu_time(); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetCurrentThreadCpuTime */ duke@435: duke@435: duke@435: // info_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetThreadCpuTimerInfo(jvmtiTimerInfo* info_ptr) { duke@435: os::thread_cpu_time_info(info_ptr); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetThreadCpuTimerInfo */ duke@435: duke@435: duke@435: // Threads_lock NOT held, java_thread not protected by lock duke@435: // java_thread - pre-checked duke@435: // nanos_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetThreadCpuTime(JavaThread* java_thread, jlong* nanos_ptr) { duke@435: *nanos_ptr = os::thread_cpu_time(java_thread); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetThreadCpuTime */ duke@435: duke@435: duke@435: // info_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetTimerInfo(jvmtiTimerInfo* info_ptr) { duke@435: os::javaTimeNanos_info(info_ptr); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetTimerInfo */ duke@435: duke@435: duke@435: // nanos_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetTime(jlong* nanos_ptr) { duke@435: *nanos_ptr = os::javaTimeNanos(); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetTime */ duke@435: duke@435: duke@435: // processor_count_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetAvailableProcessors(jint* processor_count_ptr) { duke@435: *processor_count_ptr = os::active_processor_count(); duke@435: return JVMTI_ERROR_NONE; duke@435: } /* end GetAvailableProcessors */ duke@435: duke@435: // duke@435: // System Properties functions duke@435: // duke@435: duke@435: // count_ptr - pre-checked for NULL duke@435: // property_ptr - pre-checked for NULL duke@435: jvmtiError duke@435: JvmtiEnv::GetSystemProperties(jint* count_ptr, char*** property_ptr) { duke@435: jvmtiError err = JVMTI_ERROR_NONE; duke@435: duke@435: *count_ptr = Arguments::PropertyList_count(Arguments::system_properties()); duke@435: duke@435: err = allocate(*count_ptr * sizeof(char *), (unsigned char **)property_ptr); duke@435: if (err != JVMTI_ERROR_NONE) { duke@435: return err; duke@435: } duke@435: int i = 0 ; duke@435: for (SystemProperty* p = Arguments::system_properties(); p != NULL && i < *count_ptr; p = p->next(), i++) { duke@435: const char *key = p->key(); duke@435: char **tmp_value = *property_ptr+i; duke@435: err = allocate((strlen(key)+1) * sizeof(char), (unsigned char**)tmp_value); duke@435: if (err == JVMTI_ERROR_NONE) { duke@435: strcpy(*tmp_value, key); duke@435: } else { duke@435: // clean up previously allocated memory. duke@435: for (int j=0; jnext()) { duke@435: if (strcmp(property, p->key()) == 0) { phh@2423: if (p->set_value((char *)value_ptr)) { duke@435: err = JVMTI_ERROR_NONE; duke@435: } duke@435: } duke@435: } duke@435: return err; duke@435: } /* end SetSystemProperty */