Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/prims/jvmtiExport.cpp
32285 views
/*1* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "classfile/systemDictionary.hpp"26#include "code/nmethod.hpp"27#include "code/pcDesc.hpp"28#include "code/scopeDesc.hpp"29#include "interpreter/interpreter.hpp"30#include "jvmtifiles/jvmtiEnv.hpp"31#include "memory/resourceArea.hpp"32#include "oops/objArrayKlass.hpp"33#include "oops/objArrayOop.hpp"34#include "prims/jvmtiCodeBlobEvents.hpp"35#include "prims/jvmtiEventController.hpp"36#include "prims/jvmtiEventController.inline.hpp"37#include "prims/jvmtiExport.hpp"38#include "prims/jvmtiImpl.hpp"39#include "prims/jvmtiManageCapabilities.hpp"40#include "prims/jvmtiRawMonitor.hpp"41#include "prims/jvmtiTagMap.hpp"42#include "prims/jvmtiThreadState.inline.hpp"43#include "prims/jvmtiRedefineClasses.hpp"44#include "runtime/arguments.hpp"45#include "runtime/handles.hpp"46#include "runtime/interfaceSupport.hpp"47#include "runtime/objectMonitor.hpp"48#include "runtime/objectMonitor.inline.hpp"49#include "runtime/thread.inline.hpp"50#include "runtime/vframe.hpp"51#include "services/attachListener.hpp"52#include "services/serviceUtil.hpp"53#include "utilities/macros.hpp"54#if INCLUDE_ALL_GCS55#include "gc_implementation/parallelScavenge/psMarkSweep.hpp"56#endif // INCLUDE_ALL_GCS5758PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC5960#ifdef JVMTI_TRACE61#define EVT_TRACE(evt,out) if ((JvmtiTrace::event_trace_flags(evt) & JvmtiTrace::SHOW_EVENT_SENT) != 0) { SafeResourceMark rm; tty->print_cr out; }62#define EVT_TRIG_TRACE(evt,out) if ((JvmtiTrace::event_trace_flags(evt) & JvmtiTrace::SHOW_EVENT_TRIGGER) != 0) { SafeResourceMark rm; tty->print_cr out; }63#else64#define EVT_TRIG_TRACE(evt,out)65#define EVT_TRACE(evt,out)66#endif6768///////////////////////////////////////////////////////////////69//70// JvmtiEventTransition71//72// TO DO --73// more handle purging7475// Use this for JavaThreads and state is _thread_in_vm.76class JvmtiJavaThreadEventTransition : StackObj {77private:78ResourceMark _rm;79ThreadToNativeFromVM _transition;80HandleMark _hm;8182public:83JvmtiJavaThreadEventTransition(JavaThread *thread) :84_rm(),85_transition(thread),86_hm(thread) {};87};8889// For JavaThreads which are not in _thread_in_vm state90// and other system threads use this.91class JvmtiThreadEventTransition : StackObj {92private:93ResourceMark _rm;94HandleMark _hm;95JavaThreadState _saved_state;96JavaThread *_jthread;9798public:99JvmtiThreadEventTransition(Thread *thread) : _rm(), _hm() {100if (thread->is_Java_thread()) {101_jthread = (JavaThread *)thread;102_saved_state = _jthread->thread_state();103if (_saved_state == _thread_in_Java) {104ThreadStateTransition::transition_from_java(_jthread, _thread_in_native);105} else {106ThreadStateTransition::transition(_jthread, _saved_state, _thread_in_native);107}108} else {109_jthread = NULL;110}111}112113~JvmtiThreadEventTransition() {114if (_jthread != NULL)115ThreadStateTransition::transition_from_native(_jthread, _saved_state);116}117};118119120///////////////////////////////////////////////////////////////121//122// JvmtiEventMark123//124125class JvmtiEventMark : public StackObj {126private:127JavaThread *_thread;128JNIEnv* _jni_env;129bool _exception_detected;130bool _exception_caught;131#if 0132JNIHandleBlock* _hblock;133#endif134135public:136JvmtiEventMark(JavaThread *thread) : _thread(thread),137_jni_env(thread->jni_environment()) {138#if 0139_hblock = thread->active_handles();140_hblock->clear_thoroughly(); // so we can be safe141#else142// we want to use the code above - but that needs the JNIHandle changes - later...143// for now, steal JNI push local frame code144JvmtiThreadState *state = thread->jvmti_thread_state();145// we are before an event.146// Save current jvmti thread exception state.147if (state != NULL) {148_exception_detected = state->is_exception_detected();149_exception_caught = state->is_exception_caught();150} else {151_exception_detected = false;152_exception_caught = false;153}154155JNIHandleBlock* old_handles = thread->active_handles();156JNIHandleBlock* new_handles = JNIHandleBlock::allocate_block(thread);157assert(new_handles != NULL, "should not be NULL");158new_handles->set_pop_frame_link(old_handles);159thread->set_active_handles(new_handles);160#endif161assert(thread == JavaThread::current(), "thread must be current!");162thread->frame_anchor()->make_walkable(thread);163};164165~JvmtiEventMark() {166#if 0167_hblock->clear(); // for consistency with future correct behavior168#else169// we want to use the code above - but that needs the JNIHandle changes - later...170// for now, steal JNI pop local frame code171JNIHandleBlock* old_handles = _thread->active_handles();172JNIHandleBlock* new_handles = old_handles->pop_frame_link();173assert(new_handles != NULL, "should not be NULL");174_thread->set_active_handles(new_handles);175// Note that we set the pop_frame_link to NULL explicitly, otherwise176// the release_block call will release the blocks.177old_handles->set_pop_frame_link(NULL);178JNIHandleBlock::release_block(old_handles, _thread); // may block179#endif180181JvmtiThreadState* state = _thread->jvmti_thread_state();182// we are continuing after an event.183if (state != NULL) {184// Restore the jvmti thread exception state.185if (_exception_detected) {186state->set_exception_detected();187}188if (_exception_caught) {189state->set_exception_caught();190}191}192}193194#if 0195jobject to_jobject(oop obj) { return obj == NULL? NULL : _hblock->allocate_handle_fast(obj); }196#else197// we want to use the code above - but that needs the JNIHandle changes - later...198// for now, use regular make_local199jobject to_jobject(oop obj) { return JNIHandles::make_local(_thread,obj); }200#endif201202jclass to_jclass(Klass* klass) { return (klass == NULL ? NULL : (jclass)to_jobject(klass->java_mirror())); }203204jmethodID to_jmethodID(methodHandle method) { return method->jmethod_id(); }205206JNIEnv* jni_env() { return _jni_env; }207};208209class JvmtiThreadEventMark : public JvmtiEventMark {210private:211jthread _jt;212213public:214JvmtiThreadEventMark(JavaThread *thread) :215JvmtiEventMark(thread) {216_jt = (jthread)(to_jobject(thread->threadObj()));217};218jthread jni_thread() { return _jt; }219};220221class JvmtiClassEventMark : public JvmtiThreadEventMark {222private:223jclass _jc;224225public:226JvmtiClassEventMark(JavaThread *thread, Klass* klass) :227JvmtiThreadEventMark(thread) {228_jc = to_jclass(klass);229};230jclass jni_class() { return _jc; }231};232233class JvmtiMethodEventMark : public JvmtiThreadEventMark {234private:235jmethodID _mid;236237public:238JvmtiMethodEventMark(JavaThread *thread, methodHandle method) :239JvmtiThreadEventMark(thread),240_mid(to_jmethodID(method)) {};241jmethodID jni_methodID() { return _mid; }242};243244class JvmtiLocationEventMark : public JvmtiMethodEventMark {245private:246jlocation _loc;247248public:249JvmtiLocationEventMark(JavaThread *thread, methodHandle method, address location) :250JvmtiMethodEventMark(thread, method),251_loc(location - method->code_base()) {};252jlocation location() { return _loc; }253};254255class JvmtiExceptionEventMark : public JvmtiLocationEventMark {256private:257jobject _exc;258259public:260JvmtiExceptionEventMark(JavaThread *thread, methodHandle method, address location, Handle exception) :261JvmtiLocationEventMark(thread, method, location),262_exc(to_jobject(exception())) {};263jobject exception() { return _exc; }264};265266class JvmtiClassFileLoadEventMark : public JvmtiThreadEventMark {267private:268const char *_class_name;269jobject _jloader;270jobject _protection_domain;271jclass _class_being_redefined;272273public:274JvmtiClassFileLoadEventMark(JavaThread *thread, Symbol* name,275Handle class_loader, Handle prot_domain, KlassHandle *class_being_redefined) : JvmtiThreadEventMark(thread) {276_class_name = name != NULL? name->as_utf8() : NULL;277_jloader = (jobject)to_jobject(class_loader());278_protection_domain = (jobject)to_jobject(prot_domain());279if (class_being_redefined == NULL) {280_class_being_redefined = NULL;281} else {282_class_being_redefined = (jclass)to_jclass((*class_being_redefined)());283}284};285const char *class_name() {286return _class_name;287}288jobject jloader() {289return _jloader;290}291jobject protection_domain() {292return _protection_domain;293}294jclass class_being_redefined() {295return _class_being_redefined;296}297};298299//////////////////////////////////////////////////////////////////////////////300301int JvmtiExport::_field_access_count = 0;302int JvmtiExport::_field_modification_count = 0;303304bool JvmtiExport::_can_access_local_variables = false;305bool JvmtiExport::_can_hotswap_or_post_breakpoint = false;306bool JvmtiExport::_can_modify_any_class = false;307bool JvmtiExport::_can_walk_any_space = false;308309bool JvmtiExport::_has_redefined_a_class = false;310bool JvmtiExport::_all_dependencies_are_recorded = false;311312//313// field access management314//315316// interpreter generator needs the address of the counter317address JvmtiExport::get_field_access_count_addr() {318// We don't grab a lock because we don't want to319// serialize field access between all threads. This means that a320// thread on another processor can see the wrong count value and321// may either miss making a needed call into post_field_access()322// or will make an unneeded call into post_field_access(). We pay323// this price to avoid slowing down the VM when we aren't watching324// field accesses.325// Other access/mutation safe by virtue of being in VM state.326return (address)(&_field_access_count);327}328329//330// field modification management331//332333// interpreter generator needs the address of the counter334address JvmtiExport::get_field_modification_count_addr() {335// We don't grab a lock because we don't336// want to serialize field modification between all threads. This337// means that a thread on another processor can see the wrong338// count value and may either miss making a needed call into339// post_field_modification() or will make an unneeded call into340// post_field_modification(). We pay this price to avoid slowing341// down the VM when we aren't watching field modifications.342// Other access/mutation safe by virtue of being in VM state.343return (address)(&_field_modification_count);344}345346347///////////////////////////////////////////////////////////////348// Functions needed by java.lang.instrument for starting up javaagent.349///////////////////////////////////////////////////////////////350351jint352JvmtiExport::get_jvmti_interface(JavaVM *jvm, void **penv, jint version) {353// The JVMTI_VERSION_INTERFACE_JVMTI part of the version number354// has already been validated in JNI GetEnv().355int major, minor, micro;356357// micro version doesn't matter here (yet?)358decode_version_values(version, &major, &minor, µ);359switch (major) {360case 1:361switch (minor) {362case 0: // version 1.0.<micro> is recognized363case 1: // version 1.1.<micro> is recognized364case 2: // version 1.2.<micro> is recognized365break;366367default:368return JNI_EVERSION; // unsupported minor version number369}370break;371default:372return JNI_EVERSION; // unsupported major version number373}374375if (JvmtiEnv::get_phase() == JVMTI_PHASE_LIVE) {376JavaThread* current_thread = (JavaThread*) ThreadLocalStorage::thread();377// transition code: native to VM378ThreadInVMfromNative __tiv(current_thread);379VM_ENTRY_BASE(jvmtiEnv*, JvmtiExport::get_jvmti_interface, current_thread)380debug_only(VMNativeEntryWrapper __vew;)381382JvmtiEnv *jvmti_env = JvmtiEnv::create_a_jvmti(version);383*penv = jvmti_env->jvmti_external(); // actual type is jvmtiEnv* -- not to be confused with JvmtiEnv*384return JNI_OK;385386} else if (JvmtiEnv::get_phase() == JVMTI_PHASE_ONLOAD) {387// not live, no thread to transition388JvmtiEnv *jvmti_env = JvmtiEnv::create_a_jvmti(version);389*penv = jvmti_env->jvmti_external(); // actual type is jvmtiEnv* -- not to be confused with JvmtiEnv*390return JNI_OK;391392} else {393// Called at the wrong time394*penv = NULL;395return JNI_EDETACHED;396}397}398399400void401JvmtiExport::decode_version_values(jint version, int * major, int * minor,402int * micro) {403*major = (version & JVMTI_VERSION_MASK_MAJOR) >> JVMTI_VERSION_SHIFT_MAJOR;404*minor = (version & JVMTI_VERSION_MASK_MINOR) >> JVMTI_VERSION_SHIFT_MINOR;405*micro = (version & JVMTI_VERSION_MASK_MICRO) >> JVMTI_VERSION_SHIFT_MICRO;406}407408void JvmtiExport::enter_primordial_phase() {409JvmtiEnvBase::set_phase(JVMTI_PHASE_PRIMORDIAL);410}411412void JvmtiExport::enter_start_phase() {413JvmtiManageCapabilities::recompute_always_capabilities();414JvmtiEnvBase::set_phase(JVMTI_PHASE_START);415}416417void JvmtiExport::enter_onload_phase() {418JvmtiEnvBase::set_phase(JVMTI_PHASE_ONLOAD);419}420421void JvmtiExport::enter_live_phase() {422JvmtiEnvBase::set_phase(JVMTI_PHASE_LIVE);423}424425//426// JVMTI events that the VM posts to the debugger and also startup agent427// and call the agent's premain() for java.lang.instrument.428//429430void JvmtiExport::post_vm_start() {431EVT_TRIG_TRACE(JVMTI_EVENT_VM_START, ("JVMTI Trg VM start event triggered" ));432433// can now enable some events434JvmtiEventController::vm_start();435436JvmtiEnvIterator it;437for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {438if (env->is_enabled(JVMTI_EVENT_VM_START)) {439EVT_TRACE(JVMTI_EVENT_VM_START, ("JVMTI Evt VM start event sent" ));440441JavaThread *thread = JavaThread::current();442JvmtiThreadEventMark jem(thread);443JvmtiJavaThreadEventTransition jet(thread);444jvmtiEventVMStart callback = env->callbacks()->VMStart;445if (callback != NULL) {446(*callback)(env->jvmti_external(), jem.jni_env());447}448}449}450}451452453void JvmtiExport::post_vm_initialized() {454EVT_TRIG_TRACE(JVMTI_EVENT_VM_INIT, ("JVMTI Trg VM init event triggered" ));455456// can now enable events457JvmtiEventController::vm_init();458459JvmtiEnvIterator it;460for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {461if (env->is_enabled(JVMTI_EVENT_VM_INIT)) {462EVT_TRACE(JVMTI_EVENT_VM_INIT, ("JVMTI Evt VM init event sent" ));463464JavaThread *thread = JavaThread::current();465JvmtiThreadEventMark jem(thread);466JvmtiJavaThreadEventTransition jet(thread);467jvmtiEventVMInit callback = env->callbacks()->VMInit;468if (callback != NULL) {469(*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread());470}471}472}473}474475476void JvmtiExport::post_vm_death() {477EVT_TRIG_TRACE(JVMTI_EVENT_VM_DEATH, ("JVMTI Trg VM death event triggered" ));478479JvmtiEnvIterator it;480for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {481if (env->is_enabled(JVMTI_EVENT_VM_DEATH)) {482EVT_TRACE(JVMTI_EVENT_VM_DEATH, ("JVMTI Evt VM death event sent" ));483484JavaThread *thread = JavaThread::current();485JvmtiEventMark jem(thread);486JvmtiJavaThreadEventTransition jet(thread);487jvmtiEventVMDeath callback = env->callbacks()->VMDeath;488if (callback != NULL) {489(*callback)(env->jvmti_external(), jem.jni_env());490}491}492}493494JvmtiEnvBase::set_phase(JVMTI_PHASE_DEAD);495JvmtiEventController::vm_death();496}497498char**499JvmtiExport::get_all_native_method_prefixes(int* count_ptr) {500// Have to grab JVMTI thread state lock to be sure environment doesn't501// go away while we iterate them. No locks during VM bring-up.502if (Threads::number_of_threads() == 0 || SafepointSynchronize::is_at_safepoint()) {503return JvmtiEnvBase::get_all_native_method_prefixes(count_ptr);504} else {505MutexLocker mu(JvmtiThreadState_lock);506return JvmtiEnvBase::get_all_native_method_prefixes(count_ptr);507}508}509510class JvmtiClassFileLoadHookPoster : public StackObj {511private:512Symbol* _h_name;513Handle _class_loader;514Handle _h_protection_domain;515unsigned char ** _data_ptr;516unsigned char ** _end_ptr;517JavaThread * _thread;518jint _curr_len;519unsigned char * _curr_data;520JvmtiEnv * _curr_env;521JvmtiCachedClassFileData ** _cached_class_file_ptr;522JvmtiThreadState * _state;523KlassHandle * _h_class_being_redefined;524JvmtiClassLoadKind _load_kind;525526public:527inline JvmtiClassFileLoadHookPoster(Symbol* h_name, Handle class_loader,528Handle h_protection_domain,529unsigned char **data_ptr, unsigned char **end_ptr,530JvmtiCachedClassFileData **cache_ptr) {531_h_name = h_name;532_class_loader = class_loader;533_h_protection_domain = h_protection_domain;534_data_ptr = data_ptr;535_end_ptr = end_ptr;536_thread = JavaThread::current();537_curr_len = *end_ptr - *data_ptr;538_curr_data = *data_ptr;539_curr_env = NULL;540_cached_class_file_ptr = cache_ptr;541542_state = _thread->jvmti_thread_state();543if (_state != NULL) {544_h_class_being_redefined = _state->get_class_being_redefined();545_load_kind = _state->get_class_load_kind();546// Clear class_being_redefined flag here. The action547// from agent handler could generate a new class file load548// hook event and if it is not cleared the new event generated549// from regular class file load could have this stale redefined550// class handle info.551_state->clear_class_being_redefined();552} else {553// redefine and retransform will always set the thread state554_h_class_being_redefined = (KlassHandle *) NULL;555_load_kind = jvmti_class_load_kind_load;556}557}558559void post() {560// EVT_TRIG_TRACE(JVMTI_EVENT_CLASS_FILE_LOAD_HOOK,561// ("JVMTI [%s] class file load hook event triggered",562// JvmtiTrace::safe_get_thread_name(_thread)));563post_all_envs();564copy_modified_data();565}566567private:568void post_all_envs() {569if (_load_kind != jvmti_class_load_kind_retransform) {570// for class load and redefine,571// call the non-retransformable agents572JvmtiEnvIterator it;573for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {574if (!env->is_retransformable() && env->is_enabled(JVMTI_EVENT_CLASS_FILE_LOAD_HOOK)) {575// non-retransformable agents cannot retransform back,576// so no need to cache the original class file bytes577post_to_env(env, false);578}579}580}581JvmtiEnvIterator it;582for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {583// retransformable agents get all events584if (env->is_retransformable() && env->is_enabled(JVMTI_EVENT_CLASS_FILE_LOAD_HOOK)) {585// retransformable agents need to cache the original class file586// bytes if changes are made via the ClassFileLoadHook587post_to_env(env, true);588}589}590}591592void post_to_env(JvmtiEnv* env, bool caching_needed) {593unsigned char *new_data = NULL;594jint new_len = 0;595// EVT_TRACE(JVMTI_EVENT_CLASS_FILE_LOAD_HOOK,596// ("JVMTI [%s] class file load hook event sent %s data_ptr = %d, data_len = %d",597// JvmtiTrace::safe_get_thread_name(_thread),598// _h_name == NULL ? "NULL" : _h_name->as_utf8(),599// _curr_data, _curr_len ));600JvmtiClassFileLoadEventMark jem(_thread, _h_name, _class_loader,601_h_protection_domain,602_h_class_being_redefined);603JvmtiJavaThreadEventTransition jet(_thread);604JNIEnv* jni_env = (JvmtiEnv::get_phase() == JVMTI_PHASE_PRIMORDIAL)?605NULL : jem.jni_env();606jvmtiEventClassFileLoadHook callback = env->callbacks()->ClassFileLoadHook;607if (callback != NULL) {608(*callback)(env->jvmti_external(), jni_env,609jem.class_being_redefined(),610jem.jloader(), jem.class_name(),611jem.protection_domain(),612_curr_len, _curr_data,613&new_len, &new_data);614}615if (new_data != NULL) {616// this agent has modified class data.617if (caching_needed && *_cached_class_file_ptr == NULL) {618// data has been changed by the new retransformable agent619// and it hasn't already been cached, cache it620JvmtiCachedClassFileData *p;621p = (JvmtiCachedClassFileData *)os::malloc(622offset_of(JvmtiCachedClassFileData, data) + _curr_len, mtInternal);623if (p == NULL) {624vm_exit_out_of_memory(offset_of(JvmtiCachedClassFileData, data) + _curr_len,625OOM_MALLOC_ERROR,626"unable to allocate cached copy of original class bytes");627}628p->length = _curr_len;629memcpy(p->data, _curr_data, _curr_len);630*_cached_class_file_ptr = p;631}632633if (_curr_data != *_data_ptr) {634// curr_data is previous agent modified class data.635// And this has been changed by the new agent so636// we can delete it now.637_curr_env->Deallocate(_curr_data);638}639640// Class file data has changed by the current agent.641_curr_data = new_data;642_curr_len = new_len;643// Save the current agent env we need this to deallocate the644// memory allocated by this agent.645_curr_env = env;646}647}648649void copy_modified_data() {650// if one of the agent has modified class file data.651// Copy modified class data to new resources array.652if (_curr_data != *_data_ptr) {653*_data_ptr = NEW_RESOURCE_ARRAY(u1, _curr_len);654memcpy(*_data_ptr, _curr_data, _curr_len);655*_end_ptr = *_data_ptr + _curr_len;656_curr_env->Deallocate(_curr_data);657}658}659};660661bool JvmtiExport::_should_post_class_file_load_hook = false;662663// this entry is for class file load hook on class load, redefine and retransform664void JvmtiExport::post_class_file_load_hook(Symbol* h_name,665Handle class_loader,666Handle h_protection_domain,667unsigned char **data_ptr,668unsigned char **end_ptr,669JvmtiCachedClassFileData **cache_ptr) {670JvmtiClassFileLoadHookPoster poster(h_name, class_loader,671h_protection_domain,672data_ptr, end_ptr,673cache_ptr);674poster.post();675}676677void JvmtiExport::report_unsupported(bool on) {678// If any JVMTI service is turned on, we need to exit before native code679// tries to access nonexistant services.680if (on) {681vm_exit_during_initialization("Java Kernel does not support JVMTI.");682}683}684685686static inline Klass* oop_to_klass(oop obj) {687Klass* k = obj->klass();688689// if the object is a java.lang.Class then return the java mirror690if (k == SystemDictionary::Class_klass()) {691if (!java_lang_Class::is_primitive(obj)) {692k = java_lang_Class::as_Klass(obj);693assert(k != NULL, "class for non-primitive mirror must exist");694}695}696return k;697}698699class JvmtiVMObjectAllocEventMark : public JvmtiClassEventMark {700private:701jobject _jobj;702jlong _size;703public:704JvmtiVMObjectAllocEventMark(JavaThread *thread, oop obj) : JvmtiClassEventMark(thread, oop_to_klass(obj)) {705_jobj = (jobject)to_jobject(obj);706_size = obj->size() * wordSize;707};708jobject jni_jobject() { return _jobj; }709jlong size() { return _size; }710};711712class JvmtiCompiledMethodLoadEventMark : public JvmtiMethodEventMark {713private:714jint _code_size;715const void *_code_data;716jint _map_length;717jvmtiAddrLocationMap *_map;718const void *_compile_info;719public:720JvmtiCompiledMethodLoadEventMark(JavaThread *thread, nmethod *nm, void* compile_info_ptr = NULL)721: JvmtiMethodEventMark(thread,methodHandle(thread, nm->method())) {722_code_data = nm->insts_begin();723_code_size = nm->insts_size();724_compile_info = compile_info_ptr; // Set void pointer of compiledMethodLoad Event. Default value is NULL.725JvmtiCodeBlobEvents::build_jvmti_addr_location_map(nm, &_map, &_map_length);726}727~JvmtiCompiledMethodLoadEventMark() {728FREE_C_HEAP_ARRAY(jvmtiAddrLocationMap, _map, mtInternal);729}730731jint code_size() { return _code_size; }732const void *code_data() { return _code_data; }733jint map_length() { return _map_length; }734const jvmtiAddrLocationMap* map() { return _map; }735const void *compile_info() { return _compile_info; }736};737738739740class JvmtiMonitorEventMark : public JvmtiThreadEventMark {741private:742jobject _jobj;743public:744JvmtiMonitorEventMark(JavaThread *thread, oop object)745: JvmtiThreadEventMark(thread){746_jobj = to_jobject(object);747}748jobject jni_object() { return _jobj; }749};750751///////////////////////////////////////////////////////////////752//753// pending CompiledMethodUnload support754//755756void JvmtiExport::post_compiled_method_unload(757jmethodID method, const void *code_begin) {758JavaThread* thread = JavaThread::current();759EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD,760("JVMTI [%s] method compile unload event triggered",761JvmtiTrace::safe_get_thread_name(thread)));762763// post the event for each environment that has this event enabled.764JvmtiEnvIterator it;765for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {766if (env->is_enabled(JVMTI_EVENT_COMPILED_METHOD_UNLOAD)) {767768EVT_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD,769("JVMTI [%s] class compile method unload event sent jmethodID " PTR_FORMAT,770JvmtiTrace::safe_get_thread_name(thread), method));771772ResourceMark rm(thread);773774JvmtiEventMark jem(thread);775JvmtiJavaThreadEventTransition jet(thread);776jvmtiEventCompiledMethodUnload callback = env->callbacks()->CompiledMethodUnload;777if (callback != NULL) {778(*callback)(env->jvmti_external(), method, code_begin);779}780}781}782}783784///////////////////////////////////////////////////////////////785//786// JvmtiExport787//788789void JvmtiExport::post_raw_breakpoint(JavaThread *thread, Method* method, address location) {790HandleMark hm(thread);791methodHandle mh(thread, method);792793JvmtiThreadState *state = thread->jvmti_thread_state();794if (state == NULL) {795return;796}797EVT_TRIG_TRACE(JVMTI_EVENT_BREAKPOINT, ("JVMTI [%s] Trg Breakpoint triggered",798JvmtiTrace::safe_get_thread_name(thread)));799JvmtiEnvThreadStateIterator it(state);800for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {801ets->compare_and_set_current_location(mh(), location, JVMTI_EVENT_BREAKPOINT);802if (!ets->breakpoint_posted() && ets->is_enabled(JVMTI_EVENT_BREAKPOINT)) {803ThreadState old_os_state = thread->osthread()->get_state();804thread->osthread()->set_state(BREAKPOINTED);805EVT_TRACE(JVMTI_EVENT_BREAKPOINT, ("JVMTI [%s] Evt Breakpoint sent %s.%s @ %d",806JvmtiTrace::safe_get_thread_name(thread),807(mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),808(mh() == NULL) ? "NULL" : mh()->name()->as_C_string(),809location - mh()->code_base() ));810811JvmtiEnv *env = ets->get_env();812JvmtiLocationEventMark jem(thread, mh, location);813JvmtiJavaThreadEventTransition jet(thread);814jvmtiEventBreakpoint callback = env->callbacks()->Breakpoint;815if (callback != NULL) {816(*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(),817jem.jni_methodID(), jem.location());818}819820ets->set_breakpoint_posted();821thread->osthread()->set_state(old_os_state);822}823}824}825826//////////////////////////////////////////////////////////////////////////////827828bool JvmtiExport::_can_get_source_debug_extension = false;829bool JvmtiExport::_can_maintain_original_method_order = false;830bool JvmtiExport::_can_post_interpreter_events = false;831bool JvmtiExport::_can_post_on_exceptions = false;832bool JvmtiExport::_can_post_breakpoint = false;833bool JvmtiExport::_can_post_field_access = false;834bool JvmtiExport::_can_post_field_modification = false;835bool JvmtiExport::_can_post_method_entry = false;836bool JvmtiExport::_can_post_method_exit = false;837bool JvmtiExport::_can_pop_frame = false;838bool JvmtiExport::_can_force_early_return = false;839840bool JvmtiExport::_should_post_single_step = false;841bool JvmtiExport::_should_post_field_access = false;842bool JvmtiExport::_should_post_field_modification = false;843bool JvmtiExport::_should_post_class_load = false;844bool JvmtiExport::_should_post_class_prepare = false;845bool JvmtiExport::_should_post_class_unload = false;846bool JvmtiExport::_should_post_thread_life = false;847bool JvmtiExport::_should_clean_up_heap_objects = false;848bool JvmtiExport::_should_post_native_method_bind = false;849bool JvmtiExport::_should_post_dynamic_code_generated = false;850bool JvmtiExport::_should_post_data_dump = false;851bool JvmtiExport::_should_post_compiled_method_load = false;852bool JvmtiExport::_should_post_compiled_method_unload = false;853bool JvmtiExport::_should_post_monitor_contended_enter = false;854bool JvmtiExport::_should_post_monitor_contended_entered = false;855bool JvmtiExport::_should_post_monitor_wait = false;856bool JvmtiExport::_should_post_monitor_waited = false;857bool JvmtiExport::_should_post_garbage_collection_start = false;858bool JvmtiExport::_should_post_garbage_collection_finish = false;859bool JvmtiExport::_should_post_object_free = false;860bool JvmtiExport::_should_post_resource_exhausted = false;861bool JvmtiExport::_should_post_vm_object_alloc = false;862bool JvmtiExport::_should_post_on_exceptions = false;863864////////////////////////////////////////////////////////////////////////////////////////////////865866867//868// JVMTI single step management869//870void JvmtiExport::at_single_stepping_point(JavaThread *thread, Method* method, address location) {871assert(JvmtiExport::should_post_single_step(), "must be single stepping");872873HandleMark hm(thread);874methodHandle mh(thread, method);875876// update information about current location and post a step event877JvmtiThreadState *state = thread->jvmti_thread_state();878if (state == NULL) {879return;880}881EVT_TRIG_TRACE(JVMTI_EVENT_SINGLE_STEP, ("JVMTI [%s] Trg Single Step triggered",882JvmtiTrace::safe_get_thread_name(thread)));883if (!state->hide_single_stepping()) {884if (state->is_pending_step_for_popframe()) {885state->process_pending_step_for_popframe();886}887if (state->is_pending_step_for_earlyret()) {888state->process_pending_step_for_earlyret();889}890JvmtiExport::post_single_step(thread, mh(), location);891}892}893894895void JvmtiExport::expose_single_stepping(JavaThread *thread) {896JvmtiThreadState *state = thread->jvmti_thread_state();897if (state != NULL) {898state->clear_hide_single_stepping();899}900}901902903bool JvmtiExport::hide_single_stepping(JavaThread *thread) {904JvmtiThreadState *state = thread->jvmti_thread_state();905if (state != NULL && state->is_enabled(JVMTI_EVENT_SINGLE_STEP)) {906state->set_hide_single_stepping();907return true;908} else {909return false;910}911}912913void JvmtiExport::post_class_load(JavaThread *thread, Klass* klass) {914HandleMark hm(thread);915KlassHandle kh(thread, klass);916917EVT_TRIG_TRACE(JVMTI_EVENT_CLASS_LOAD, ("JVMTI [%s] Trg Class Load triggered",918JvmtiTrace::safe_get_thread_name(thread)));919JvmtiThreadState* state = thread->jvmti_thread_state();920if (state == NULL) {921return;922}923JvmtiEnvThreadStateIterator it(state);924for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {925if (ets->is_enabled(JVMTI_EVENT_CLASS_LOAD)) {926EVT_TRACE(JVMTI_EVENT_CLASS_LOAD, ("JVMTI [%s] Evt Class Load sent %s",927JvmtiTrace::safe_get_thread_name(thread),928kh()==NULL? "NULL" : kh()->external_name() ));929930JvmtiEnv *env = ets->get_env();931JvmtiClassEventMark jem(thread, kh());932JvmtiJavaThreadEventTransition jet(thread);933jvmtiEventClassLoad callback = env->callbacks()->ClassLoad;934if (callback != NULL) {935(*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(), jem.jni_class());936}937}938}939}940941942void JvmtiExport::post_class_prepare(JavaThread *thread, Klass* klass) {943HandleMark hm(thread);944KlassHandle kh(thread, klass);945946EVT_TRIG_TRACE(JVMTI_EVENT_CLASS_PREPARE, ("JVMTI [%s] Trg Class Prepare triggered",947JvmtiTrace::safe_get_thread_name(thread)));948JvmtiThreadState* state = thread->jvmti_thread_state();949if (state == NULL) {950return;951}952JvmtiEnvThreadStateIterator it(state);953for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {954if (ets->is_enabled(JVMTI_EVENT_CLASS_PREPARE)) {955EVT_TRACE(JVMTI_EVENT_CLASS_PREPARE, ("JVMTI [%s] Evt Class Prepare sent %s",956JvmtiTrace::safe_get_thread_name(thread),957kh()==NULL? "NULL" : kh()->external_name() ));958959JvmtiEnv *env = ets->get_env();960JvmtiClassEventMark jem(thread, kh());961JvmtiJavaThreadEventTransition jet(thread);962jvmtiEventClassPrepare callback = env->callbacks()->ClassPrepare;963if (callback != NULL) {964(*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(), jem.jni_class());965}966}967}968}969970void JvmtiExport::post_class_unload(Klass* klass) {971Thread *thread = Thread::current();972HandleMark hm(thread);973KlassHandle kh(thread, klass);974975EVT_TRIG_TRACE(EXT_EVENT_CLASS_UNLOAD, ("JVMTI [?] Trg Class Unload triggered" ));976if (JvmtiEventController::is_enabled((jvmtiEvent)EXT_EVENT_CLASS_UNLOAD)) {977assert(thread->is_VM_thread(), "wrong thread");978979// get JavaThread for whom we are proxy980JavaThread *real_thread =981(JavaThread *)((VMThread *)thread)->vm_operation()->calling_thread();982983JvmtiEnvIterator it;984for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {985if (env->is_enabled((jvmtiEvent)EXT_EVENT_CLASS_UNLOAD)) {986EVT_TRACE(EXT_EVENT_CLASS_UNLOAD, ("JVMTI [?] Evt Class Unload sent %s",987kh()==NULL? "NULL" : kh()->external_name() ));988989// do everything manually, since this is a proxy - needs special care990JNIEnv* jni_env = real_thread->jni_environment();991jthread jt = (jthread)JNIHandles::make_local(real_thread, real_thread->threadObj());992jclass jk = (jclass)JNIHandles::make_local(real_thread, kh()->java_mirror());993994// Before we call the JVMTI agent, we have to set the state in the995// thread for which we are proxying.996JavaThreadState prev_state = real_thread->thread_state();997assert(((Thread *)real_thread)->is_ConcurrentGC_thread() ||998(real_thread->is_Java_thread() && prev_state == _thread_blocked),999"should be ConcurrentGCThread or JavaThread at safepoint");1000real_thread->set_thread_state(_thread_in_native);10011002jvmtiExtensionEvent callback = env->ext_callbacks()->ClassUnload;1003if (callback != NULL) {1004(*callback)(env->jvmti_external(), jni_env, jt, jk);1005}10061007assert(real_thread->thread_state() == _thread_in_native,1008"JavaThread should be in native");1009real_thread->set_thread_state(prev_state);10101011JNIHandles::destroy_local(jk);1012JNIHandles::destroy_local(jt);1013}1014}1015}1016}101710181019void JvmtiExport::post_thread_start(JavaThread *thread) {1020assert(thread->thread_state() == _thread_in_vm, "must be in vm state");10211022EVT_TRIG_TRACE(JVMTI_EVENT_THREAD_START, ("JVMTI [%s] Trg Thread Start event triggered",1023JvmtiTrace::safe_get_thread_name(thread)));10241025// do JVMTI thread initialization (if needed)1026JvmtiEventController::thread_started(thread);10271028// Do not post thread start event for hidden java thread.1029if (JvmtiEventController::is_enabled(JVMTI_EVENT_THREAD_START) &&1030!thread->is_hidden_from_external_view()) {1031JvmtiEnvIterator it;1032for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {1033if (env->is_enabled(JVMTI_EVENT_THREAD_START)) {1034EVT_TRACE(JVMTI_EVENT_THREAD_START, ("JVMTI [%s] Evt Thread Start event sent",1035JvmtiTrace::safe_get_thread_name(thread) ));10361037JvmtiThreadEventMark jem(thread);1038JvmtiJavaThreadEventTransition jet(thread);1039jvmtiEventThreadStart callback = env->callbacks()->ThreadStart;1040if (callback != NULL) {1041(*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread());1042}1043}1044}1045}1046}104710481049void JvmtiExport::post_thread_end(JavaThread *thread) {1050EVT_TRIG_TRACE(JVMTI_EVENT_THREAD_END, ("JVMTI [%s] Trg Thread End event triggered",1051JvmtiTrace::safe_get_thread_name(thread)));10521053JvmtiThreadState *state = thread->jvmti_thread_state();1054if (state == NULL) {1055return;1056}10571058// Do not post thread end event for hidden java thread.1059if (state->is_enabled(JVMTI_EVENT_THREAD_END) &&1060!thread->is_hidden_from_external_view()) {10611062JvmtiEnvThreadStateIterator it(state);1063for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {1064if (ets->is_enabled(JVMTI_EVENT_THREAD_END)) {1065EVT_TRACE(JVMTI_EVENT_THREAD_END, ("JVMTI [%s] Evt Thread End event sent",1066JvmtiTrace::safe_get_thread_name(thread) ));10671068JvmtiEnv *env = ets->get_env();1069JvmtiThreadEventMark jem(thread);1070JvmtiJavaThreadEventTransition jet(thread);1071jvmtiEventThreadEnd callback = env->callbacks()->ThreadEnd;1072if (callback != NULL) {1073(*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread());1074}1075}1076}1077}1078}10791080void JvmtiExport::post_object_free(JvmtiEnv* env, jlong tag) {1081assert(SafepointSynchronize::is_at_safepoint(), "must be executed at safepoint");1082assert(env->is_enabled(JVMTI_EVENT_OBJECT_FREE), "checking");10831084EVT_TRIG_TRACE(JVMTI_EVENT_OBJECT_FREE, ("JVMTI [?] Trg Object Free triggered" ));1085EVT_TRACE(JVMTI_EVENT_OBJECT_FREE, ("JVMTI [?] Evt Object Free sent"));10861087jvmtiEventObjectFree callback = env->callbacks()->ObjectFree;1088if (callback != NULL) {1089(*callback)(env->jvmti_external(), tag);1090}1091}10921093void JvmtiExport::post_resource_exhausted(jint resource_exhausted_flags, const char* description) {1094EVT_TRIG_TRACE(JVMTI_EVENT_RESOURCE_EXHAUSTED, ("JVMTI Trg resource exhausted event triggered" ));10951096JvmtiEnvIterator it;1097for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {1098if (env->is_enabled(JVMTI_EVENT_RESOURCE_EXHAUSTED)) {1099EVT_TRACE(JVMTI_EVENT_RESOURCE_EXHAUSTED, ("JVMTI Evt resource exhausted event sent" ));11001101JavaThread *thread = JavaThread::current();1102JvmtiThreadEventMark jem(thread);1103JvmtiJavaThreadEventTransition jet(thread);1104jvmtiEventResourceExhausted callback = env->callbacks()->ResourceExhausted;1105if (callback != NULL) {1106(*callback)(env->jvmti_external(), jem.jni_env(),1107resource_exhausted_flags, NULL, description);1108}1109}1110}1111}11121113void JvmtiExport::post_method_entry(JavaThread *thread, Method* method, frame current_frame) {1114HandleMark hm(thread);1115methodHandle mh(thread, method);11161117EVT_TRIG_TRACE(JVMTI_EVENT_METHOD_ENTRY, ("JVMTI [%s] Trg Method Entry triggered %s.%s",1118JvmtiTrace::safe_get_thread_name(thread),1119(mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),1120(mh() == NULL) ? "NULL" : mh()->name()->as_C_string() ));11211122JvmtiThreadState* state = thread->jvmti_thread_state();1123if (state == NULL || !state->is_interp_only_mode()) {1124// for any thread that actually wants method entry, interp_only_mode is set1125return;1126}11271128state->incr_cur_stack_depth();11291130if (state->is_enabled(JVMTI_EVENT_METHOD_ENTRY)) {1131JvmtiEnvThreadStateIterator it(state);1132for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {1133if (ets->is_enabled(JVMTI_EVENT_METHOD_ENTRY)) {1134EVT_TRACE(JVMTI_EVENT_METHOD_ENTRY, ("JVMTI [%s] Evt Method Entry sent %s.%s",1135JvmtiTrace::safe_get_thread_name(thread),1136(mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),1137(mh() == NULL) ? "NULL" : mh()->name()->as_C_string() ));11381139JvmtiEnv *env = ets->get_env();1140JvmtiMethodEventMark jem(thread, mh);1141JvmtiJavaThreadEventTransition jet(thread);1142jvmtiEventMethodEntry callback = env->callbacks()->MethodEntry;1143if (callback != NULL) {1144(*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(), jem.jni_methodID());1145}1146}1147}1148}1149}11501151void JvmtiExport::post_method_exit(JavaThread *thread, Method* method, frame current_frame) {1152HandleMark hm(thread);1153methodHandle mh(thread, method);11541155EVT_TRIG_TRACE(JVMTI_EVENT_METHOD_EXIT, ("JVMTI [%s] Trg Method Exit triggered %s.%s",1156JvmtiTrace::safe_get_thread_name(thread),1157(mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),1158(mh() == NULL) ? "NULL" : mh()->name()->as_C_string() ));11591160JvmtiThreadState *state = thread->jvmti_thread_state();1161if (state == NULL || !state->is_interp_only_mode()) {1162// for any thread that actually wants method exit, interp_only_mode is set1163return;1164}11651166// return a flag when a method terminates by throwing an exception1167// i.e. if an exception is thrown and it's not caught by the current method1168bool exception_exit = state->is_exception_detected() && !state->is_exception_caught();116911701171if (state->is_enabled(JVMTI_EVENT_METHOD_EXIT)) {1172Handle result;1173jvalue value;1174value.j = 0L;11751176// if the method hasn't been popped because of an exception then we populate1177// the return_value parameter for the callback. At this point we only have1178// the address of a "raw result" and we just call into the interpreter to1179// convert this into a jvalue.1180if (!exception_exit) {1181oop oop_result;1182BasicType type = current_frame.interpreter_frame_result(&oop_result, &value);1183if (type == T_OBJECT || type == T_ARRAY) {1184result = Handle(thread, oop_result);1185}1186}11871188JvmtiEnvThreadStateIterator it(state);1189for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {1190if (ets->is_enabled(JVMTI_EVENT_METHOD_EXIT)) {1191EVT_TRACE(JVMTI_EVENT_METHOD_EXIT, ("JVMTI [%s] Evt Method Exit sent %s.%s",1192JvmtiTrace::safe_get_thread_name(thread),1193(mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),1194(mh() == NULL) ? "NULL" : mh()->name()->as_C_string() ));11951196JvmtiEnv *env = ets->get_env();1197JvmtiMethodEventMark jem(thread, mh);1198if (result.not_null()) {1199value.l = JNIHandles::make_local(thread, result());1200}1201JvmtiJavaThreadEventTransition jet(thread);1202jvmtiEventMethodExit callback = env->callbacks()->MethodExit;1203if (callback != NULL) {1204(*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(),1205jem.jni_methodID(), exception_exit, value);1206}1207}1208}1209}12101211if (state->is_enabled(JVMTI_EVENT_FRAME_POP)) {1212JvmtiEnvThreadStateIterator it(state);1213for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {1214int cur_frame_number = state->cur_stack_depth();12151216if (ets->is_frame_pop(cur_frame_number)) {1217// we have a NotifyFramePop entry for this frame.1218// now check that this env/thread wants this event1219if (ets->is_enabled(JVMTI_EVENT_FRAME_POP)) {1220EVT_TRACE(JVMTI_EVENT_FRAME_POP, ("JVMTI [%s] Evt Frame Pop sent %s.%s",1221JvmtiTrace::safe_get_thread_name(thread),1222(mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),1223(mh() == NULL) ? "NULL" : mh()->name()->as_C_string() ));12241225// we also need to issue a frame pop event for this frame1226JvmtiEnv *env = ets->get_env();1227JvmtiMethodEventMark jem(thread, mh);1228JvmtiJavaThreadEventTransition jet(thread);1229jvmtiEventFramePop callback = env->callbacks()->FramePop;1230if (callback != NULL) {1231(*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(),1232jem.jni_methodID(), exception_exit);1233}1234}1235// remove the frame's entry1236ets->clear_frame_pop(cur_frame_number);1237}1238}1239}12401241#ifdef AARCH641242// FIXME: this is just a kludge to get JVMTI going. Compiled1243// MethodHandle code doesn't call the JVMTI notify routines, so the1244// stack depth we see here is wrong.1245state->invalidate_cur_stack_depth();1246#else1247state->decr_cur_stack_depth();1248#endif1249}125012511252// Todo: inline this for optimization1253void JvmtiExport::post_single_step(JavaThread *thread, Method* method, address location) {1254HandleMark hm(thread);1255methodHandle mh(thread, method);12561257JvmtiThreadState *state = thread->jvmti_thread_state();1258if (state == NULL) {1259return;1260}1261JvmtiEnvThreadStateIterator it(state);1262for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {1263ets->compare_and_set_current_location(mh(), location, JVMTI_EVENT_SINGLE_STEP);1264if (!ets->single_stepping_posted() && ets->is_enabled(JVMTI_EVENT_SINGLE_STEP)) {1265EVT_TRACE(JVMTI_EVENT_SINGLE_STEP, ("JVMTI [%s] Evt Single Step sent %s.%s @ %d",1266JvmtiTrace::safe_get_thread_name(thread),1267(mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),1268(mh() == NULL) ? "NULL" : mh()->name()->as_C_string(),1269location - mh()->code_base() ));12701271JvmtiEnv *env = ets->get_env();1272JvmtiLocationEventMark jem(thread, mh, location);1273JvmtiJavaThreadEventTransition jet(thread);1274jvmtiEventSingleStep callback = env->callbacks()->SingleStep;1275if (callback != NULL) {1276(*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(),1277jem.jni_methodID(), jem.location());1278}12791280ets->set_single_stepping_posted();1281}1282}1283}128412851286void JvmtiExport::post_exception_throw(JavaThread *thread, Method* method, address location, oop exception) {1287HandleMark hm(thread);1288methodHandle mh(thread, method);1289Handle exception_handle(thread, exception);12901291JvmtiThreadState *state = thread->jvmti_thread_state();1292if (state == NULL) {1293return;1294}12951296EVT_TRIG_TRACE(JVMTI_EVENT_EXCEPTION, ("JVMTI [%s] Trg Exception thrown triggered",1297JvmtiTrace::safe_get_thread_name(thread)));1298if (!state->is_exception_detected()) {1299state->set_exception_detected();1300JvmtiEnvThreadStateIterator it(state);1301for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {1302if (ets->is_enabled(JVMTI_EVENT_EXCEPTION) && (exception != NULL)) {13031304EVT_TRACE(JVMTI_EVENT_EXCEPTION,1305("JVMTI [%s] Evt Exception thrown sent %s.%s @ %d",1306JvmtiTrace::safe_get_thread_name(thread),1307(mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),1308(mh() == NULL) ? "NULL" : mh()->name()->as_C_string(),1309location - mh()->code_base() ));13101311JvmtiEnv *env = ets->get_env();1312JvmtiExceptionEventMark jem(thread, mh, location, exception_handle);13131314// It's okay to clear these exceptions here because we duplicate1315// this lookup in InterpreterRuntime::exception_handler_for_exception.1316EXCEPTION_MARK;13171318bool should_repeat;1319vframeStream st(thread);1320assert(!st.at_end(), "cannot be at end");1321Method* current_method = NULL;1322// A GC may occur during the Method::fast_exception_handler_bci_for()1323// call below if it needs to load the constraint class. Using a1324// methodHandle to keep the 'current_method' from being deallocated1325// if GC happens.1326methodHandle current_mh = methodHandle(thread, current_method);1327int current_bci = -1;1328do {1329current_method = st.method();1330current_mh = methodHandle(thread, current_method);1331current_bci = st.bci();1332do {1333should_repeat = false;1334KlassHandle eh_klass(thread, exception_handle()->klass());1335current_bci = Method::fast_exception_handler_bci_for(1336current_mh, eh_klass, current_bci, THREAD);1337if (HAS_PENDING_EXCEPTION) {1338exception_handle = Handle(thread, PENDING_EXCEPTION);1339CLEAR_PENDING_EXCEPTION;1340should_repeat = true;1341}1342} while (should_repeat && (current_bci != -1));1343st.next();1344} while ((current_bci < 0) && (!st.at_end()));13451346jmethodID catch_jmethodID;1347if (current_bci < 0) {1348catch_jmethodID = 0;1349current_bci = 0;1350} else {1351catch_jmethodID = jem.to_jmethodID(current_mh);1352}13531354JvmtiJavaThreadEventTransition jet(thread);1355jvmtiEventException callback = env->callbacks()->Exception;1356if (callback != NULL) {1357(*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(),1358jem.jni_methodID(), jem.location(),1359jem.exception(),1360catch_jmethodID, current_bci);1361}1362}1363}1364}13651366// frames may get popped because of this throw, be safe - invalidate cached depth1367state->invalidate_cur_stack_depth();1368}136913701371void JvmtiExport::notice_unwind_due_to_exception(JavaThread *thread, Method* method, address location, oop exception, bool in_handler_frame) {1372HandleMark hm(thread);1373methodHandle mh(thread, method);1374Handle exception_handle(thread, exception);13751376JvmtiThreadState *state = thread->jvmti_thread_state();1377if (state == NULL) {1378return;1379}1380EVT_TRIG_TRACE(JVMTI_EVENT_EXCEPTION_CATCH,1381("JVMTI [%s] Trg unwind_due_to_exception triggered %s.%s @ %s%d - %s",1382JvmtiTrace::safe_get_thread_name(thread),1383(mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),1384(mh() == NULL) ? "NULL" : mh()->name()->as_C_string(),1385location==0? "no location:" : "",1386location==0? 0 : location - mh()->code_base(),1387in_handler_frame? "in handler frame" : "not handler frame" ));13881389if (state->is_exception_detected()) {13901391state->invalidate_cur_stack_depth();1392if (!in_handler_frame) {1393// Not in exception handler.1394if(state->is_interp_only_mode()) {1395// method exit and frame pop events are posted only in interp mode.1396// When these events are enabled code should be in running in interp mode.1397JvmtiExport::post_method_exit(thread, method, thread->last_frame());1398// The cached cur_stack_depth might have changed from the1399// operations of frame pop or method exit. We are not 100% sure1400// the cached cur_stack_depth is still valid depth so invalidate1401// it.1402state->invalidate_cur_stack_depth();1403}1404} else {1405// In exception handler frame. Report exception catch.1406assert(location != NULL, "must be a known location");1407// Update cur_stack_depth - the frames above the current frame1408// have been unwound due to this exception:1409assert(!state->is_exception_caught(), "exception must not be caught yet.");1410state->set_exception_caught();14111412JvmtiEnvThreadStateIterator it(state);1413for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {1414if (ets->is_enabled(JVMTI_EVENT_EXCEPTION_CATCH) && (exception_handle() != NULL)) {1415EVT_TRACE(JVMTI_EVENT_EXCEPTION_CATCH,1416("JVMTI [%s] Evt ExceptionCatch sent %s.%s @ %d",1417JvmtiTrace::safe_get_thread_name(thread),1418(mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),1419(mh() == NULL) ? "NULL" : mh()->name()->as_C_string(),1420location - mh()->code_base() ));14211422JvmtiEnv *env = ets->get_env();1423JvmtiExceptionEventMark jem(thread, mh, location, exception_handle);1424JvmtiJavaThreadEventTransition jet(thread);1425jvmtiEventExceptionCatch callback = env->callbacks()->ExceptionCatch;1426if (callback != NULL) {1427(*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(),1428jem.jni_methodID(), jem.location(),1429jem.exception());1430}1431}1432}1433}1434}1435}14361437oop JvmtiExport::jni_GetField_probe(JavaThread *thread, jobject jobj, oop obj,1438Klass* klass, jfieldID fieldID, bool is_static) {1439if (*((int *)get_field_access_count_addr()) > 0 && thread->has_last_Java_frame()) {1440// At least one field access watch is set so we have more work1441// to do. This wrapper is used by entry points that allow us1442// to create handles in post_field_access_by_jni().1443post_field_access_by_jni(thread, obj, klass, fieldID, is_static);1444// event posting can block so refetch oop if we were passed a jobj1445if (jobj != NULL) return JNIHandles::resolve_non_null(jobj);1446}1447return obj;1448}14491450oop JvmtiExport::jni_GetField_probe_nh(JavaThread *thread, jobject jobj, oop obj,1451Klass* klass, jfieldID fieldID, bool is_static) {1452if (*((int *)get_field_access_count_addr()) > 0 && thread->has_last_Java_frame()) {1453// At least one field access watch is set so we have more work1454// to do. This wrapper is used by "quick" entry points that don't1455// allow us to create handles in post_field_access_by_jni(). We1456// override that with a ResetNoHandleMark.1457ResetNoHandleMark rnhm;1458post_field_access_by_jni(thread, obj, klass, fieldID, is_static);1459// event posting can block so refetch oop if we were passed a jobj1460if (jobj != NULL) return JNIHandles::resolve_non_null(jobj);1461}1462return obj;1463}14641465void JvmtiExport::post_field_access_by_jni(JavaThread *thread, oop obj,1466Klass* klass, jfieldID fieldID, bool is_static) {1467// We must be called with a Java context in order to provide reasonable1468// values for the klazz, method, and location fields. The callers of this1469// function don't make the call unless there is a Java context.1470assert(thread->has_last_Java_frame(), "must be called with a Java context");14711472ResourceMark rm;1473fieldDescriptor fd;1474// if get_field_descriptor finds fieldID to be invalid, then we just bail1475bool valid_fieldID = JvmtiEnv::get_field_descriptor(klass, fieldID, &fd);1476assert(valid_fieldID == true,"post_field_access_by_jni called with invalid fieldID");1477if (!valid_fieldID) return;1478// field accesses are not watched so bail1479if (!fd.is_field_access_watched()) return;14801481HandleMark hm(thread);1482KlassHandle h_klass(thread, klass);1483Handle h_obj;1484if (!is_static) {1485// non-static field accessors have an object, but we need a handle1486assert(obj != NULL, "non-static needs an object");1487h_obj = Handle(thread, obj);1488}1489post_field_access(thread,1490thread->last_frame().interpreter_frame_method(),1491thread->last_frame().interpreter_frame_bcp(),1492h_klass, h_obj, fieldID);1493}14941495void JvmtiExport::post_field_access(JavaThread *thread, Method* method,1496address location, KlassHandle field_klass, Handle object, jfieldID field) {14971498HandleMark hm(thread);1499methodHandle mh(thread, method);15001501JvmtiThreadState *state = thread->jvmti_thread_state();1502if (state == NULL) {1503return;1504}1505EVT_TRIG_TRACE(JVMTI_EVENT_FIELD_ACCESS, ("JVMTI [%s] Trg Field Access event triggered",1506JvmtiTrace::safe_get_thread_name(thread)));1507JvmtiEnvThreadStateIterator it(state);1508for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {1509if (ets->is_enabled(JVMTI_EVENT_FIELD_ACCESS)) {1510EVT_TRACE(JVMTI_EVENT_FIELD_ACCESS, ("JVMTI [%s] Evt Field Access event sent %s.%s @ %d",1511JvmtiTrace::safe_get_thread_name(thread),1512(mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),1513(mh() == NULL) ? "NULL" : mh()->name()->as_C_string(),1514location - mh()->code_base() ));15151516JvmtiEnv *env = ets->get_env();1517JvmtiLocationEventMark jem(thread, mh, location);1518jclass field_jclass = jem.to_jclass(field_klass());1519jobject field_jobject = jem.to_jobject(object());1520JvmtiJavaThreadEventTransition jet(thread);1521jvmtiEventFieldAccess callback = env->callbacks()->FieldAccess;1522if (callback != NULL) {1523(*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(),1524jem.jni_methodID(), jem.location(),1525field_jclass, field_jobject, field);1526}1527}1528}1529}15301531oop JvmtiExport::jni_SetField_probe(JavaThread *thread, jobject jobj, oop obj,1532Klass* klass, jfieldID fieldID, bool is_static,1533char sig_type, jvalue *value) {1534if (*((int *)get_field_modification_count_addr()) > 0 && thread->has_last_Java_frame()) {1535// At least one field modification watch is set so we have more work1536// to do. This wrapper is used by entry points that allow us1537// to create handles in post_field_modification_by_jni().1538post_field_modification_by_jni(thread, obj, klass, fieldID, is_static, sig_type, value);1539// event posting can block so refetch oop if we were passed a jobj1540if (jobj != NULL) return JNIHandles::resolve_non_null(jobj);1541}1542return obj;1543}15441545oop JvmtiExport::jni_SetField_probe_nh(JavaThread *thread, jobject jobj, oop obj,1546Klass* klass, jfieldID fieldID, bool is_static,1547char sig_type, jvalue *value) {1548if (*((int *)get_field_modification_count_addr()) > 0 && thread->has_last_Java_frame()) {1549// At least one field modification watch is set so we have more work1550// to do. This wrapper is used by "quick" entry points that don't1551// allow us to create handles in post_field_modification_by_jni(). We1552// override that with a ResetNoHandleMark.1553ResetNoHandleMark rnhm;1554post_field_modification_by_jni(thread, obj, klass, fieldID, is_static, sig_type, value);1555// event posting can block so refetch oop if we were passed a jobj1556if (jobj != NULL) return JNIHandles::resolve_non_null(jobj);1557}1558return obj;1559}15601561void JvmtiExport::post_field_modification_by_jni(JavaThread *thread, oop obj,1562Klass* klass, jfieldID fieldID, bool is_static,1563char sig_type, jvalue *value) {1564// We must be called with a Java context in order to provide reasonable1565// values for the klazz, method, and location fields. The callers of this1566// function don't make the call unless there is a Java context.1567assert(thread->has_last_Java_frame(), "must be called with Java context");15681569ResourceMark rm;1570fieldDescriptor fd;1571// if get_field_descriptor finds fieldID to be invalid, then we just bail1572bool valid_fieldID = JvmtiEnv::get_field_descriptor(klass, fieldID, &fd);1573assert(valid_fieldID == true,"post_field_modification_by_jni called with invalid fieldID");1574if (!valid_fieldID) return;1575// field modifications are not watched so bail1576if (!fd.is_field_modification_watched()) return;15771578HandleMark hm(thread);15791580Handle h_obj;1581if (!is_static) {1582// non-static field accessors have an object, but we need a handle1583assert(obj != NULL, "non-static needs an object");1584h_obj = Handle(thread, obj);1585}1586KlassHandle h_klass(thread, klass);1587post_field_modification(thread,1588thread->last_frame().interpreter_frame_method(),1589thread->last_frame().interpreter_frame_bcp(),1590h_klass, h_obj, fieldID, sig_type, value);1591}15921593void JvmtiExport::post_raw_field_modification(JavaThread *thread, Method* method,1594address location, KlassHandle field_klass, Handle object, jfieldID field,1595char sig_type, jvalue *value) {15961597if (sig_type == 'I' || sig_type == 'Z' || sig_type == 'B' || sig_type == 'C' || sig_type == 'S') {1598// 'I' instructions are used for byte, char, short and int.1599// determine which it really is, and convert1600fieldDescriptor fd;1601bool found = JvmtiEnv::get_field_descriptor(field_klass(), field, &fd);1602// should be found (if not, leave as is)1603if (found) {1604jint ival = value->i;1605// convert value from int to appropriate type1606switch (fd.field_type()) {1607case T_BOOLEAN:1608sig_type = 'Z';1609value->i = 0; // clear it1610value->z = (jboolean)ival;1611break;1612case T_BYTE:1613sig_type = 'B';1614value->i = 0; // clear it1615value->b = (jbyte)ival;1616break;1617case T_CHAR:1618sig_type = 'C';1619value->i = 0; // clear it1620value->c = (jchar)ival;1621break;1622case T_SHORT:1623sig_type = 'S';1624value->i = 0; // clear it1625value->s = (jshort)ival;1626break;1627case T_INT:1628// nothing to do1629break;1630default:1631// this is an integer instruction, should be one of above1632ShouldNotReachHere();1633break;1634}1635}1636}16371638assert(sig_type != '[', "array should have sig_type == 'L'");1639bool handle_created = false;16401641// convert oop to JNI handle.1642if (sig_type == 'L') {1643handle_created = true;1644value->l = (jobject)JNIHandles::make_local(thread, (oop)value->l);1645}16461647post_field_modification(thread, method, location, field_klass, object, field, sig_type, value);16481649// Destroy the JNI handle allocated above.1650if (handle_created) {1651JNIHandles::destroy_local(value->l);1652}1653}16541655void JvmtiExport::post_field_modification(JavaThread *thread, Method* method,1656address location, KlassHandle field_klass, Handle object, jfieldID field,1657char sig_type, jvalue *value_ptr) {16581659HandleMark hm(thread);1660methodHandle mh(thread, method);16611662JvmtiThreadState *state = thread->jvmti_thread_state();1663if (state == NULL) {1664return;1665}1666EVT_TRIG_TRACE(JVMTI_EVENT_FIELD_MODIFICATION,1667("JVMTI [%s] Trg Field Modification event triggered",1668JvmtiTrace::safe_get_thread_name(thread)));16691670JvmtiEnvThreadStateIterator it(state);1671for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {1672if (ets->is_enabled(JVMTI_EVENT_FIELD_MODIFICATION)) {1673EVT_TRACE(JVMTI_EVENT_FIELD_MODIFICATION,1674("JVMTI [%s] Evt Field Modification event sent %s.%s @ %d",1675JvmtiTrace::safe_get_thread_name(thread),1676(mh() == NULL) ? "NULL" : mh()->klass_name()->as_C_string(),1677(mh() == NULL) ? "NULL" : mh()->name()->as_C_string(),1678location - mh()->code_base() ));16791680JvmtiEnv *env = ets->get_env();1681JvmtiLocationEventMark jem(thread, mh, location);1682jclass field_jclass = jem.to_jclass(field_klass());1683jobject field_jobject = jem.to_jobject(object());1684JvmtiJavaThreadEventTransition jet(thread);1685jvmtiEventFieldModification callback = env->callbacks()->FieldModification;1686if (callback != NULL) {1687(*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(),1688jem.jni_methodID(), jem.location(),1689field_jclass, field_jobject, field, sig_type, *value_ptr);1690}1691}1692}1693}16941695void JvmtiExport::post_native_method_bind(Method* method, address* function_ptr) {1696JavaThread* thread = JavaThread::current();1697assert(thread->thread_state() == _thread_in_vm, "must be in vm state");16981699HandleMark hm(thread);1700methodHandle mh(thread, method);17011702EVT_TRIG_TRACE(JVMTI_EVENT_NATIVE_METHOD_BIND, ("JVMTI [%s] Trg Native Method Bind event triggered",1703JvmtiTrace::safe_get_thread_name(thread)));17041705if (JvmtiEventController::is_enabled(JVMTI_EVENT_NATIVE_METHOD_BIND)) {1706JvmtiEnvIterator it;1707for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {1708if (env->is_enabled(JVMTI_EVENT_NATIVE_METHOD_BIND)) {1709EVT_TRACE(JVMTI_EVENT_NATIVE_METHOD_BIND, ("JVMTI [%s] Evt Native Method Bind event sent",1710JvmtiTrace::safe_get_thread_name(thread) ));17111712JvmtiMethodEventMark jem(thread, mh);1713JvmtiJavaThreadEventTransition jet(thread);1714JNIEnv* jni_env = JvmtiEnv::get_phase() == JVMTI_PHASE_PRIMORDIAL? NULL : jem.jni_env();1715jvmtiEventNativeMethodBind callback = env->callbacks()->NativeMethodBind;1716if (callback != NULL) {1717(*callback)(env->jvmti_external(), jni_env, jem.jni_thread(),1718jem.jni_methodID(), (void*)(*function_ptr), (void**)function_ptr);1719}1720}1721}1722}1723}17241725// Returns a record containing inlining information for the given nmethod1726jvmtiCompiledMethodLoadInlineRecord* create_inline_record(nmethod* nm) {1727jint numstackframes = 0;1728jvmtiCompiledMethodLoadInlineRecord* record = (jvmtiCompiledMethodLoadInlineRecord*)NEW_RESOURCE_OBJ(jvmtiCompiledMethodLoadInlineRecord);1729record->header.kind = JVMTI_CMLR_INLINE_INFO;1730record->header.next = NULL;1731record->header.majorinfoversion = JVMTI_CMLR_MAJOR_VERSION_1;1732record->header.minorinfoversion = JVMTI_CMLR_MINOR_VERSION_0;1733record->numpcs = 0;1734for(PcDesc* p = nm->scopes_pcs_begin(); p < nm->scopes_pcs_end(); p++) {1735if(p->scope_decode_offset() == DebugInformationRecorder::serialized_null) continue;1736record->numpcs++;1737}1738record->pcinfo = (PCStackInfo*)(NEW_RESOURCE_ARRAY(PCStackInfo, record->numpcs));1739int scope = 0;1740for(PcDesc* p = nm->scopes_pcs_begin(); p < nm->scopes_pcs_end(); p++) {1741if(p->scope_decode_offset() == DebugInformationRecorder::serialized_null) continue;1742void* pc_address = (void*)p->real_pc(nm);1743assert(pc_address != NULL, "pc_address must be non-null");1744record->pcinfo[scope].pc = pc_address;1745numstackframes=0;1746for(ScopeDesc* sd = nm->scope_desc_at(p->real_pc(nm));sd != NULL;sd = sd->sender()) {1747numstackframes++;1748}1749assert(numstackframes != 0, "numstackframes must be nonzero.");1750record->pcinfo[scope].methods = (jmethodID *)NEW_RESOURCE_ARRAY(jmethodID, numstackframes);1751record->pcinfo[scope].bcis = (jint *)NEW_RESOURCE_ARRAY(jint, numstackframes);1752record->pcinfo[scope].numstackframes = numstackframes;1753int stackframe = 0;1754for(ScopeDesc* sd = nm->scope_desc_at(p->real_pc(nm));sd != NULL;sd = sd->sender()) {1755// sd->method() can be NULL for stubs but not for nmethods. To be completely robust, include an assert that we should never see a null sd->method()1756assert(sd->method() != NULL, "sd->method() cannot be null.");1757record->pcinfo[scope].methods[stackframe] = sd->method()->jmethod_id();1758record->pcinfo[scope].bcis[stackframe] = sd->bci();1759stackframe++;1760}1761scope++;1762}1763return record;1764}17651766void JvmtiExport::post_compiled_method_load(nmethod *nm) {1767JavaThread* thread = JavaThread::current();17681769EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD,1770("JVMTI [%s] method compile load event triggered",1771JvmtiTrace::safe_get_thread_name(thread)));17721773JvmtiEnvIterator it;1774for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {1775if (env->is_enabled(JVMTI_EVENT_COMPILED_METHOD_LOAD)) {17761777EVT_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD,1778("JVMTI [%s] class compile method load event sent %s.%s ",1779JvmtiTrace::safe_get_thread_name(thread),1780(nm->method() == NULL) ? "NULL" : nm->method()->klass_name()->as_C_string(),1781(nm->method() == NULL) ? "NULL" : nm->method()->name()->as_C_string()));1782ResourceMark rm(thread);1783HandleMark hm(thread);17841785// Add inlining information1786jvmtiCompiledMethodLoadInlineRecord* inlinerecord = create_inline_record(nm);1787// Pass inlining information through the void pointer1788JvmtiCompiledMethodLoadEventMark jem(thread, nm, inlinerecord);1789JvmtiJavaThreadEventTransition jet(thread);1790jvmtiEventCompiledMethodLoad callback = env->callbacks()->CompiledMethodLoad;1791if (callback != NULL) {1792(*callback)(env->jvmti_external(), jem.jni_methodID(),1793jem.code_size(), jem.code_data(), jem.map_length(),1794jem.map(), jem.compile_info());1795}1796}1797}1798}179918001801// post a COMPILED_METHOD_LOAD event for a given environment1802void JvmtiExport::post_compiled_method_load(JvmtiEnv* env, const jmethodID method, const jint length,1803const void *code_begin, const jint map_length,1804const jvmtiAddrLocationMap* map)1805{1806JavaThread* thread = JavaThread::current();1807EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD,1808("JVMTI [%s] method compile load event triggered (by GenerateEvents)",1809JvmtiTrace::safe_get_thread_name(thread)));1810if (env->is_enabled(JVMTI_EVENT_COMPILED_METHOD_LOAD)) {18111812EVT_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD,1813("JVMTI [%s] class compile method load event sent (by GenerateEvents), jmethodID=" PTR_FORMAT,1814JvmtiTrace::safe_get_thread_name(thread), method));18151816JvmtiEventMark jem(thread);1817JvmtiJavaThreadEventTransition jet(thread);1818jvmtiEventCompiledMethodLoad callback = env->callbacks()->CompiledMethodLoad;1819if (callback != NULL) {1820(*callback)(env->jvmti_external(), method,1821length, code_begin, map_length,1822map, NULL);1823}1824}1825}18261827void JvmtiExport::post_dynamic_code_generated_internal(const char *name, const void *code_begin, const void *code_end) {1828assert(name != NULL && name[0] != '\0', "sanity check");18291830JavaThread* thread = JavaThread::current();1831// In theory everyone coming thru here is in_vm but we need to be certain1832// because a callee will do a vm->native transition1833ThreadInVMfromUnknown __tiv;18341835EVT_TRIG_TRACE(JVMTI_EVENT_DYNAMIC_CODE_GENERATED,1836("JVMTI [%s] method dynamic code generated event triggered",1837JvmtiTrace::safe_get_thread_name(thread)));1838JvmtiEnvIterator it;1839for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {1840if (env->is_enabled(JVMTI_EVENT_DYNAMIC_CODE_GENERATED)) {1841EVT_TRACE(JVMTI_EVENT_DYNAMIC_CODE_GENERATED,1842("JVMTI [%s] dynamic code generated event sent for %s",1843JvmtiTrace::safe_get_thread_name(thread), name));1844JvmtiEventMark jem(thread);1845JvmtiJavaThreadEventTransition jet(thread);1846jint length = (jint)pointer_delta(code_end, code_begin, sizeof(char));1847jvmtiEventDynamicCodeGenerated callback = env->callbacks()->DynamicCodeGenerated;1848if (callback != NULL) {1849(*callback)(env->jvmti_external(), name, (void*)code_begin, length);1850}1851}1852}1853}18541855void JvmtiExport::post_dynamic_code_generated(const char *name, const void *code_begin, const void *code_end) {1856jvmtiPhase phase = JvmtiEnv::get_phase();1857if (phase == JVMTI_PHASE_PRIMORDIAL || phase == JVMTI_PHASE_START) {1858post_dynamic_code_generated_internal(name, code_begin, code_end);1859} else {1860// It may not be safe to post the event from this thread. Defer all1861// postings to the service thread so that it can perform them in a safe1862// context and in-order.1863MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);1864JvmtiDeferredEvent event = JvmtiDeferredEvent::dynamic_code_generated_event(1865name, code_begin, code_end);1866JvmtiDeferredEventQueue::enqueue(event);1867}1868}186918701871// post a DYNAMIC_CODE_GENERATED event for a given environment1872// used by GenerateEvents1873void JvmtiExport::post_dynamic_code_generated(JvmtiEnv* env, const char *name,1874const void *code_begin, const void *code_end)1875{1876JavaThread* thread = JavaThread::current();1877EVT_TRIG_TRACE(JVMTI_EVENT_DYNAMIC_CODE_GENERATED,1878("JVMTI [%s] dynamic code generated event triggered (by GenerateEvents)",1879JvmtiTrace::safe_get_thread_name(thread)));1880if (env->is_enabled(JVMTI_EVENT_DYNAMIC_CODE_GENERATED)) {1881EVT_TRACE(JVMTI_EVENT_DYNAMIC_CODE_GENERATED,1882("JVMTI [%s] dynamic code generated event sent for %s",1883JvmtiTrace::safe_get_thread_name(thread), name));1884JvmtiEventMark jem(thread);1885JvmtiJavaThreadEventTransition jet(thread);1886jint length = (jint)pointer_delta(code_end, code_begin, sizeof(char));1887jvmtiEventDynamicCodeGenerated callback = env->callbacks()->DynamicCodeGenerated;1888if (callback != NULL) {1889(*callback)(env->jvmti_external(), name, (void*)code_begin, length);1890}1891}1892}18931894// post a DynamicCodeGenerated event while holding locks in the VM.1895void JvmtiExport::post_dynamic_code_generated_while_holding_locks(const char* name,1896address code_begin, address code_end)1897{1898// register the stub with the current dynamic code event collector1899JvmtiThreadState* state = JvmtiThreadState::state_for(JavaThread::current());1900// state can only be NULL if the current thread is exiting which1901// should not happen since we're trying to post an event1902guarantee(state != NULL, "attempt to register stub via an exiting thread");1903JvmtiDynamicCodeEventCollector* collector = state->get_dynamic_code_event_collector();1904guarantee(collector != NULL, "attempt to register stub without event collector");1905collector->register_stub(name, code_begin, code_end);1906}19071908// Collect all the vm internally allocated objects which are visible to java world1909void JvmtiExport::record_vm_internal_object_allocation(oop obj) {1910Thread* thread = ThreadLocalStorage::thread();1911if (thread != NULL && thread->is_Java_thread()) {1912// Can not take safepoint here.1913No_Safepoint_Verifier no_sfpt;1914// Can not take safepoint here so can not use state_for to get1915// jvmti thread state.1916JvmtiThreadState *state = ((JavaThread*)thread)->jvmti_thread_state();1917if (state != NULL ) {1918// state is non NULL when VMObjectAllocEventCollector is enabled.1919JvmtiVMObjectAllocEventCollector *collector;1920collector = state->get_vm_object_alloc_event_collector();1921if (collector != NULL && collector->is_enabled()) {1922// Don't record classes as these will be notified via the ClassLoad1923// event.1924if (obj->klass() != SystemDictionary::Class_klass()) {1925collector->record_allocation(obj);1926}1927}1928}1929}1930}19311932void JvmtiExport::post_garbage_collection_finish() {1933Thread *thread = Thread::current(); // this event is posted from VM-Thread.1934EVT_TRIG_TRACE(JVMTI_EVENT_GARBAGE_COLLECTION_FINISH,1935("JVMTI [%s] garbage collection finish event triggered",1936JvmtiTrace::safe_get_thread_name(thread)));1937JvmtiEnvIterator it;1938for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {1939if (env->is_enabled(JVMTI_EVENT_GARBAGE_COLLECTION_FINISH)) {1940EVT_TRACE(JVMTI_EVENT_GARBAGE_COLLECTION_FINISH,1941("JVMTI [%s] garbage collection finish event sent ",1942JvmtiTrace::safe_get_thread_name(thread)));1943JvmtiThreadEventTransition jet(thread);1944// JNIEnv is NULL here because this event is posted from VM Thread1945jvmtiEventGarbageCollectionFinish callback = env->callbacks()->GarbageCollectionFinish;1946if (callback != NULL) {1947(*callback)(env->jvmti_external());1948}1949}1950}1951}19521953void JvmtiExport::post_garbage_collection_start() {1954Thread* thread = Thread::current(); // this event is posted from vm-thread.1955EVT_TRIG_TRACE(JVMTI_EVENT_GARBAGE_COLLECTION_START,1956("JVMTI [%s] garbage collection start event triggered",1957JvmtiTrace::safe_get_thread_name(thread)));1958JvmtiEnvIterator it;1959for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {1960if (env->is_enabled(JVMTI_EVENT_GARBAGE_COLLECTION_START)) {1961EVT_TRACE(JVMTI_EVENT_GARBAGE_COLLECTION_START,1962("JVMTI [%s] garbage collection start event sent ",1963JvmtiTrace::safe_get_thread_name(thread)));1964JvmtiThreadEventTransition jet(thread);1965// JNIEnv is NULL here because this event is posted from VM Thread1966jvmtiEventGarbageCollectionStart callback = env->callbacks()->GarbageCollectionStart;1967if (callback != NULL) {1968(*callback)(env->jvmti_external());1969}1970}1971}1972}19731974void JvmtiExport::post_data_dump() {1975Thread *thread = Thread::current();1976EVT_TRIG_TRACE(JVMTI_EVENT_DATA_DUMP_REQUEST,1977("JVMTI [%s] data dump request event triggered",1978JvmtiTrace::safe_get_thread_name(thread)));1979JvmtiEnvIterator it;1980for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {1981if (env->is_enabled(JVMTI_EVENT_DATA_DUMP_REQUEST)) {1982EVT_TRACE(JVMTI_EVENT_DATA_DUMP_REQUEST,1983("JVMTI [%s] data dump request event sent ",1984JvmtiTrace::safe_get_thread_name(thread)));1985JvmtiThreadEventTransition jet(thread);1986// JNIEnv is NULL here because this event is posted from VM Thread1987jvmtiEventDataDumpRequest callback = env->callbacks()->DataDumpRequest;1988if (callback != NULL) {1989(*callback)(env->jvmti_external());1990}1991}1992}1993}19941995void JvmtiExport::post_monitor_contended_enter(JavaThread *thread, ObjectMonitor *obj_mntr) {1996oop object = (oop)obj_mntr->object();1997if (!ServiceUtil::visible_oop(object)) {1998// Ignore monitor contended enter for vm internal object.1999return;2000}2001JvmtiThreadState *state = thread->jvmti_thread_state();2002if (state == NULL) {2003return;2004}20052006HandleMark hm(thread);2007Handle h(thread, object);20082009EVT_TRIG_TRACE(JVMTI_EVENT_MONITOR_CONTENDED_ENTER,2010("JVMTI [%s] montior contended enter event triggered",2011JvmtiTrace::safe_get_thread_name(thread)));20122013JvmtiEnvThreadStateIterator it(state);2014for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {2015if (ets->is_enabled(JVMTI_EVENT_MONITOR_CONTENDED_ENTER)) {2016EVT_TRACE(JVMTI_EVENT_MONITOR_CONTENDED_ENTER,2017("JVMTI [%s] monitor contended enter event sent",2018JvmtiTrace::safe_get_thread_name(thread)));2019JvmtiMonitorEventMark jem(thread, h());2020JvmtiEnv *env = ets->get_env();2021JvmtiThreadEventTransition jet(thread);2022jvmtiEventMonitorContendedEnter callback = env->callbacks()->MonitorContendedEnter;2023if (callback != NULL) {2024(*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(), jem.jni_object());2025}2026}2027}2028}20292030void JvmtiExport::post_monitor_contended_entered(JavaThread *thread, ObjectMonitor *obj_mntr) {2031oop object = (oop)obj_mntr->object();2032if (!ServiceUtil::visible_oop(object)) {2033// Ignore monitor contended entered for vm internal object.2034return;2035}2036JvmtiThreadState *state = thread->jvmti_thread_state();2037if (state == NULL) {2038return;2039}20402041HandleMark hm(thread);2042Handle h(thread, object);20432044EVT_TRIG_TRACE(JVMTI_EVENT_MONITOR_CONTENDED_ENTERED,2045("JVMTI [%s] montior contended entered event triggered",2046JvmtiTrace::safe_get_thread_name(thread)));20472048JvmtiEnvThreadStateIterator it(state);2049for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {2050if (ets->is_enabled(JVMTI_EVENT_MONITOR_CONTENDED_ENTERED)) {2051EVT_TRACE(JVMTI_EVENT_MONITOR_CONTENDED_ENTERED,2052("JVMTI [%s] monitor contended enter event sent",2053JvmtiTrace::safe_get_thread_name(thread)));2054JvmtiMonitorEventMark jem(thread, h());2055JvmtiEnv *env = ets->get_env();2056JvmtiThreadEventTransition jet(thread);2057jvmtiEventMonitorContendedEntered callback = env->callbacks()->MonitorContendedEntered;2058if (callback != NULL) {2059(*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(), jem.jni_object());2060}2061}2062}2063}20642065void JvmtiExport::post_monitor_wait(JavaThread *thread, oop object,2066jlong timeout) {2067JvmtiThreadState *state = thread->jvmti_thread_state();2068if (state == NULL) {2069return;2070}20712072HandleMark hm(thread);2073Handle h(thread, object);20742075EVT_TRIG_TRACE(JVMTI_EVENT_MONITOR_WAIT,2076("JVMTI [%s] montior wait event triggered",2077JvmtiTrace::safe_get_thread_name(thread)));20782079JvmtiEnvThreadStateIterator it(state);2080for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {2081if (ets->is_enabled(JVMTI_EVENT_MONITOR_WAIT)) {2082EVT_TRACE(JVMTI_EVENT_MONITOR_WAIT,2083("JVMTI [%s] monitor wait event sent ",2084JvmtiTrace::safe_get_thread_name(thread)));2085JvmtiMonitorEventMark jem(thread, h());2086JvmtiEnv *env = ets->get_env();2087JvmtiThreadEventTransition jet(thread);2088jvmtiEventMonitorWait callback = env->callbacks()->MonitorWait;2089if (callback != NULL) {2090(*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(),2091jem.jni_object(), timeout);2092}2093}2094}2095}20962097void JvmtiExport::post_monitor_waited(JavaThread *thread, ObjectMonitor *obj_mntr, jboolean timed_out) {2098oop object = (oop)obj_mntr->object();2099if (!ServiceUtil::visible_oop(object)) {2100// Ignore monitor waited for vm internal object.2101return;2102}2103JvmtiThreadState *state = thread->jvmti_thread_state();2104if (state == NULL) {2105return;2106}21072108HandleMark hm(thread);2109Handle h(thread, object);21102111EVT_TRIG_TRACE(JVMTI_EVENT_MONITOR_WAITED,2112("JVMTI [%s] montior waited event triggered",2113JvmtiTrace::safe_get_thread_name(thread)));21142115JvmtiEnvThreadStateIterator it(state);2116for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {2117if (ets->is_enabled(JVMTI_EVENT_MONITOR_WAITED)) {2118EVT_TRACE(JVMTI_EVENT_MONITOR_WAITED,2119("JVMTI [%s] monitor waited event sent ",2120JvmtiTrace::safe_get_thread_name(thread)));2121JvmtiMonitorEventMark jem(thread, h());2122JvmtiEnv *env = ets->get_env();2123JvmtiThreadEventTransition jet(thread);2124jvmtiEventMonitorWaited callback = env->callbacks()->MonitorWaited;2125if (callback != NULL) {2126(*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(),2127jem.jni_object(), timed_out);2128}2129}2130}2131}213221332134void JvmtiExport::post_vm_object_alloc(JavaThread *thread, oop object) {2135EVT_TRIG_TRACE(JVMTI_EVENT_VM_OBJECT_ALLOC, ("JVMTI [%s] Trg vm object alloc triggered",2136JvmtiTrace::safe_get_thread_name(thread)));2137if (object == NULL) {2138return;2139}2140HandleMark hm(thread);2141Handle h(thread, object);2142JvmtiEnvIterator it;2143for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {2144if (env->is_enabled(JVMTI_EVENT_VM_OBJECT_ALLOC)) {2145EVT_TRACE(JVMTI_EVENT_VM_OBJECT_ALLOC, ("JVMTI [%s] Evt vmobject alloc sent %s",2146JvmtiTrace::safe_get_thread_name(thread),2147object==NULL? "NULL" : java_lang_Class::as_Klass(object)->external_name()));21482149JvmtiVMObjectAllocEventMark jem(thread, h());2150JvmtiJavaThreadEventTransition jet(thread);2151jvmtiEventVMObjectAlloc callback = env->callbacks()->VMObjectAlloc;2152if (callback != NULL) {2153(*callback)(env->jvmti_external(), jem.jni_env(), jem.jni_thread(),2154jem.jni_jobject(), jem.jni_class(), jem.size());2155}2156}2157}2158}21592160////////////////////////////////////////////////////////////////////////////////////////////////21612162void JvmtiExport::cleanup_thread(JavaThread* thread) {2163assert(JavaThread::current() == thread, "thread is not current");2164MutexLocker mu(JvmtiThreadState_lock);21652166if (thread->jvmti_thread_state() != NULL) {2167// This has to happen after the thread state is removed, which is2168// why it is not in post_thread_end_event like its complement2169// Maybe both these functions should be rolled into the posts?2170JvmtiEventController::thread_ended(thread);2171}2172}21732174void JvmtiExport::clear_detected_exception(JavaThread* thread) {2175assert(JavaThread::current() == thread, "thread is not current");21762177JvmtiThreadState* state = thread->jvmti_thread_state();2178if (state != NULL) {2179state->clear_exception_detected();2180}2181}21822183void JvmtiExport::oops_do(OopClosure* f) {2184JvmtiCurrentBreakpoints::oops_do(f);2185JvmtiVMObjectAllocEventCollector::oops_do_for_all_threads(f);2186}21872188void JvmtiExport::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {2189JvmtiTagMap::weak_oops_do(is_alive, f);2190}21912192void JvmtiExport::gc_epilogue() {2193JvmtiCurrentBreakpoints::gc_epilogue();2194}21952196// Onload raw monitor transition.2197void JvmtiExport::transition_pending_onload_raw_monitors() {2198JvmtiPendingMonitors::transition_raw_monitors();2199}22002201////////////////////////////////////////////////////////////////////////////////////////////////22022203// type for the Agent_OnAttach entry point2204extern "C" {2205typedef jint (JNICALL *OnAttachEntry_t)(JavaVM*, char *, void *);2206}22072208jint JvmtiExport::load_agent_library(AttachOperation* op, outputStream* st) {2209char ebuf[1024];2210char buffer[JVM_MAXPATHLEN];2211void* library = NULL;2212jint result = JNI_ERR;2213const char *on_attach_symbols[] = AGENT_ONATTACH_SYMBOLS;2214size_t num_symbol_entries = ARRAY_SIZE(on_attach_symbols);22152216// get agent name and options2217const char* agent = op->arg(0);2218const char* absParam = op->arg(1);2219const char* options = op->arg(2);22202221// The abs paramter should be "true" or "false"2222bool is_absolute_path = (absParam != NULL) && (strcmp(absParam,"true")==0);22232224// Initially marked as invalid. It will be set to valid if we can find the agent2225AgentLibrary *agent_lib = new AgentLibrary(agent, options, is_absolute_path, NULL);22262227// Check for statically linked in agent. If not found then if the path is2228// absolute we attempt to load the library. Otherwise we try to load it2229// from the standard dll directory.22302231if (!os::find_builtin_agent(agent_lib, on_attach_symbols, num_symbol_entries)) {2232if (is_absolute_path) {2233library = os::dll_load(agent, ebuf, sizeof ebuf);2234} else {2235// Try to load the agent from the standard dll directory2236if (os::dll_build_name(buffer, sizeof(buffer), Arguments::get_dll_dir(),2237agent)) {2238library = os::dll_load(buffer, ebuf, sizeof ebuf);2239}2240if (library == NULL) {2241// not found - try local path2242char ns[1] = {0};2243if (os::dll_build_name(buffer, sizeof(buffer), ns, agent)) {2244library = os::dll_load(buffer, ebuf, sizeof ebuf);2245}2246}2247}2248if (library != NULL) {2249agent_lib->set_os_lib(library);2250agent_lib->set_valid();2251}2252}2253// If the library was loaded then we attempt to invoke the Agent_OnAttach2254// function2255if (agent_lib->valid()) {2256// Lookup the Agent_OnAttach function2257OnAttachEntry_t on_attach_entry = NULL;2258on_attach_entry = CAST_TO_FN_PTR(OnAttachEntry_t,2259os::find_agent_function(agent_lib, false, on_attach_symbols, num_symbol_entries));2260if (on_attach_entry == NULL) {2261// Agent_OnAttach missing - unload library2262if (!agent_lib->is_static_lib()) {2263os::dll_unload(library);2264}2265delete agent_lib;2266} else {2267// Invoke the Agent_OnAttach function2268JavaThread* THREAD = JavaThread::current();2269{2270extern struct JavaVM_ main_vm;2271JvmtiThreadEventMark jem(THREAD);2272JvmtiJavaThreadEventTransition jet(THREAD);22732274result = (*on_attach_entry)(&main_vm, (char*)options, NULL);2275}22762277// Agent_OnAttach may have used JNI2278if (HAS_PENDING_EXCEPTION) {2279CLEAR_PENDING_EXCEPTION;2280}22812282// If OnAttach returns JNI_OK then we add it to the list of2283// agent libraries so that we can call Agent_OnUnload later.2284if (result == JNI_OK) {2285Arguments::add_loaded_agent(agent_lib);2286} else {2287delete agent_lib;2288}22892290// Agent_OnAttach executed so completion status is JNI_OK2291st->print_cr("%d", result);2292result = JNI_OK;2293}2294}2295return result;2296}22972298////////////////////////////////////////////////////////////////////////////////////////////////22992300// Setup current current thread for event collection.2301void JvmtiEventCollector::setup_jvmti_thread_state() {2302// set this event collector to be the current one.2303JvmtiThreadState* state = JvmtiThreadState::state_for(JavaThread::current());2304// state can only be NULL if the current thread is exiting which2305// should not happen since we're trying to configure for event collection2306guarantee(state != NULL, "exiting thread called setup_jvmti_thread_state");2307if (is_vm_object_alloc_event()) {2308_prev = state->get_vm_object_alloc_event_collector();2309state->set_vm_object_alloc_event_collector((JvmtiVMObjectAllocEventCollector *)this);2310} else if (is_dynamic_code_event()) {2311_prev = state->get_dynamic_code_event_collector();2312state->set_dynamic_code_event_collector((JvmtiDynamicCodeEventCollector *)this);2313}2314}23152316// Unset current event collection in this thread and reset it with previous2317// collector.2318void JvmtiEventCollector::unset_jvmti_thread_state() {2319JvmtiThreadState* state = JavaThread::current()->jvmti_thread_state();2320if (state != NULL) {2321// restore the previous event collector (if any)2322if (is_vm_object_alloc_event()) {2323if (state->get_vm_object_alloc_event_collector() == this) {2324state->set_vm_object_alloc_event_collector((JvmtiVMObjectAllocEventCollector *)_prev);2325} else {2326// this thread's jvmti state was created during the scope of2327// the event collector.2328}2329} else {2330if (is_dynamic_code_event()) {2331if (state->get_dynamic_code_event_collector() == this) {2332state->set_dynamic_code_event_collector((JvmtiDynamicCodeEventCollector *)_prev);2333} else {2334// this thread's jvmti state was created during the scope of2335// the event collector.2336}2337}2338}2339}2340}23412342// create the dynamic code event collector2343JvmtiDynamicCodeEventCollector::JvmtiDynamicCodeEventCollector() : _code_blobs(NULL) {2344if (JvmtiExport::should_post_dynamic_code_generated()) {2345setup_jvmti_thread_state();2346}2347}23482349// iterate over any code blob descriptors collected and post a2350// DYNAMIC_CODE_GENERATED event to the profiler.2351JvmtiDynamicCodeEventCollector::~JvmtiDynamicCodeEventCollector() {2352assert(!JavaThread::current()->owns_locks(), "all locks must be released to post deferred events");2353// iterate over any code blob descriptors that we collected2354if (_code_blobs != NULL) {2355for (int i=0; i<_code_blobs->length(); i++) {2356JvmtiCodeBlobDesc* blob = _code_blobs->at(i);2357JvmtiExport::post_dynamic_code_generated(blob->name(), blob->code_begin(), blob->code_end());2358FreeHeap(blob);2359}2360delete _code_blobs;2361}2362unset_jvmti_thread_state();2363}23642365// register a stub2366void JvmtiDynamicCodeEventCollector::register_stub(const char* name, address start, address end) {2367if (_code_blobs == NULL) {2368_code_blobs = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<JvmtiCodeBlobDesc*>(1,true);2369}2370_code_blobs->append(new JvmtiCodeBlobDesc(name, start, end));2371}23722373// Setup current thread to record vm allocated objects.2374JvmtiVMObjectAllocEventCollector::JvmtiVMObjectAllocEventCollector() : _allocated(NULL) {2375if (JvmtiExport::should_post_vm_object_alloc()) {2376_enable = true;2377setup_jvmti_thread_state();2378} else {2379_enable = false;2380}2381}23822383// Post vm_object_alloc event for vm allocated objects visible to java2384// world.2385JvmtiVMObjectAllocEventCollector::~JvmtiVMObjectAllocEventCollector() {2386if (_allocated != NULL) {2387set_enabled(false);2388for (int i = 0; i < _allocated->length(); i++) {2389oop obj = _allocated->at(i);2390if (ServiceUtil::visible_oop(obj)) {2391JvmtiExport::post_vm_object_alloc(JavaThread::current(), obj);2392}2393}2394delete _allocated;2395}2396unset_jvmti_thread_state();2397}23982399void JvmtiVMObjectAllocEventCollector::record_allocation(oop obj) {2400assert(is_enabled(), "VM object alloc event collector is not enabled");2401if (_allocated == NULL) {2402_allocated = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<oop>(1, true);2403}2404_allocated->push(obj);2405}24062407// GC support.2408void JvmtiVMObjectAllocEventCollector::oops_do(OopClosure* f) {2409if (_allocated != NULL) {2410for(int i=_allocated->length() - 1; i >= 0; i--) {2411if (_allocated->at(i) != NULL) {2412f->do_oop(_allocated->adr_at(i));2413}2414}2415}2416}24172418void JvmtiVMObjectAllocEventCollector::oops_do_for_all_threads(OopClosure* f) {2419// no-op if jvmti not enabled2420if (!JvmtiEnv::environments_might_exist()) {2421return;2422}24232424// Runs at safepoint. So no need to acquire Threads_lock.2425for (JavaThread *jthr = Threads::first(); jthr != NULL; jthr = jthr->next()) {2426JvmtiThreadState *state = jthr->jvmti_thread_state();2427if (state != NULL) {2428JvmtiVMObjectAllocEventCollector *collector;2429collector = state->get_vm_object_alloc_event_collector();2430while (collector != NULL) {2431collector->oops_do(f);2432collector = (JvmtiVMObjectAllocEventCollector *)collector->get_prev();2433}2434}2435}2436}243724382439// Disable collection of VMObjectAlloc events2440NoJvmtiVMObjectAllocMark::NoJvmtiVMObjectAllocMark() : _collector(NULL) {2441// a no-op if VMObjectAlloc event is not enabled2442if (!JvmtiExport::should_post_vm_object_alloc()) {2443return;2444}2445Thread* thread = ThreadLocalStorage::thread();2446if (thread != NULL && thread->is_Java_thread()) {2447JavaThread* current_thread = (JavaThread*)thread;2448JvmtiThreadState *state = current_thread->jvmti_thread_state();2449if (state != NULL) {2450JvmtiVMObjectAllocEventCollector *collector;2451collector = state->get_vm_object_alloc_event_collector();2452if (collector != NULL && collector->is_enabled()) {2453_collector = collector;2454_collector->set_enabled(false);2455}2456}2457}2458}24592460// Re-Enable collection of VMObjectAlloc events (if previously enabled)2461NoJvmtiVMObjectAllocMark::~NoJvmtiVMObjectAllocMark() {2462if (was_enabled()) {2463_collector->set_enabled(true);2464}2465};24662467JvmtiGCMarker::JvmtiGCMarker() {2468// if there aren't any JVMTI environments then nothing to do2469if (!JvmtiEnv::environments_might_exist()) {2470return;2471}24722473if (JvmtiExport::should_post_garbage_collection_start()) {2474JvmtiExport::post_garbage_collection_start();2475}24762477if (SafepointSynchronize::is_at_safepoint()) {2478// Do clean up tasks that need to be done at a safepoint2479JvmtiEnvBase::check_for_periodic_clean_up();2480}2481}24822483JvmtiGCMarker::~JvmtiGCMarker() {2484// if there aren't any JVMTI environments then nothing to do2485if (!JvmtiEnv::environments_might_exist()) {2486return;2487}24882489// JVMTI notify gc finish2490if (JvmtiExport::should_post_garbage_collection_finish()) {2491JvmtiExport::post_garbage_collection_finish();2492}2493}249424952496