src/share/vm/prims/jvmtiExport.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File hotspot Sdiff src/share/vm/prims

src/share/vm/prims/jvmtiExport.cpp

Print this page




 570     MutexLocker mu(JvmtiThreadState_lock);
 571     return JvmtiEnvBase::get_all_native_method_prefixes(count_ptr);
 572   }
 573 }
 574 
 575 class JvmtiClassFileLoadHookPoster : public StackObj {
 576  private:
 577   Symbol*            _h_name;
 578   Handle               _class_loader;
 579   Handle               _h_protection_domain;
 580   unsigned char **     _data_ptr;
 581   unsigned char **     _end_ptr;
 582   JavaThread *         _thread;
 583   jint                 _curr_len;
 584   unsigned char *      _curr_data;
 585   JvmtiEnv *           _curr_env;
 586   JvmtiCachedClassFileData ** _cached_class_file_ptr;
 587   JvmtiThreadState *   _state;
 588   KlassHandle *        _h_class_being_redefined;
 589   JvmtiClassLoadKind   _load_kind;

 590 
 591  public:
 592   inline JvmtiClassFileLoadHookPoster(Symbol* h_name, Handle class_loader,
 593                                       Handle h_protection_domain,
 594                                       unsigned char **data_ptr, unsigned char **end_ptr,
 595                                       JvmtiCachedClassFileData **cache_ptr) {
 596     _h_name = h_name;
 597     _class_loader = class_loader;
 598     _h_protection_domain = h_protection_domain;
 599     _data_ptr = data_ptr;
 600     _end_ptr = end_ptr;
 601     _thread = JavaThread::current();
 602     _curr_len = *end_ptr - *data_ptr;
 603     _curr_data = *data_ptr;
 604     _curr_env = NULL;
 605     _cached_class_file_ptr = cache_ptr;

 606 
 607     _state = _thread->jvmti_thread_state();
 608     if (_state != NULL) {
 609       _h_class_being_redefined = _state->get_class_being_redefined();
 610       _load_kind = _state->get_class_load_kind();
 611       Klass* klass = (_h_class_being_redefined == NULL) ? NULL : (*_h_class_being_redefined)();
 612       if (_load_kind != jvmti_class_load_kind_load && klass != NULL) {
 613         ModuleEntry* module_entry = InstanceKlass::cast(klass)->module();
 614         assert(module_entry != NULL, "module_entry should always be set");
 615         if (module_entry->is_named() &&
 616             module_entry->module() != NULL &&
 617             !module_entry->has_default_read_edges()) {
 618           if (!module_entry->set_has_default_read_edges()) {
 619             // We won a potential race.
 620             // Add read edges to the unnamed modules of the bootstrap and app class loaders
 621             Handle class_module(_thread, JNIHandles::resolve(module_entry->module())); // Obtain j.l.r.Module
 622             JvmtiExport::add_default_read_edges(class_module, _thread);
 623           }
 624         }
 625       }
 626       // Clear class_being_redefined flag here. The action
 627       // from agent handler could generate a new class file load
 628       // hook event and if it is not cleared the new event generated
 629       // from regular class file load could have this stale redefined
 630       // class handle info.
 631       _state->clear_class_being_redefined();
 632     } else {
 633       // redefine and retransform will always set the thread state
 634       _h_class_being_redefined = (KlassHandle *) NULL;
 635       _load_kind = jvmti_class_load_kind_load;
 636     }
 637   }
 638 
 639   void post() {
 640     post_all_envs();
 641     copy_modified_data();
 642   }
 643 


 644  private:
 645   void post_all_envs() {
 646     if (_load_kind != jvmti_class_load_kind_retransform) {
 647       // for class load and redefine,
 648       // call the non-retransformable agents
 649       JvmtiEnvIterator it;
 650       for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
 651         if (!env->is_retransformable() && env->is_enabled(JVMTI_EVENT_CLASS_FILE_LOAD_HOOK)) {
 652           // non-retransformable agents cannot retransform back,
 653           // so no need to cache the original class file bytes
 654           post_to_env(env, false);
 655         }
 656       }
 657     }
 658     JvmtiEnvIterator it;
 659     for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
 660       // retransformable agents get all events
 661       if (env->is_retransformable() && env->is_enabled(JVMTI_EVENT_CLASS_FILE_LOAD_HOOK)) {
 662         // retransformable agents need to cache the original class file
 663         // bytes if changes are made via the ClassFileLoadHook


 670     if (env->phase() == JVMTI_PHASE_PRIMORDIAL && !env->early_class_hook_env()) {
 671       return;
 672     }
 673     unsigned char *new_data = NULL;
 674     jint new_len = 0;
 675     JvmtiClassFileLoadEventMark jem(_thread, _h_name, _class_loader,
 676                                     _h_protection_domain,
 677                                     _h_class_being_redefined);
 678     JvmtiJavaThreadEventTransition jet(_thread);
 679     jvmtiEventClassFileLoadHook callback = env->callbacks()->ClassFileLoadHook;
 680     if (callback != NULL) {
 681       (*callback)(env->jvmti_external(), jem.jni_env(),
 682                   jem.class_being_redefined(),
 683                   jem.jloader(), jem.class_name(),
 684                   jem.protection_domain(),
 685                   _curr_len, _curr_data,
 686                   &new_len, &new_data);
 687     }
 688     if (new_data != NULL) {
 689       // this agent has modified class data.

 690       if (caching_needed && *_cached_class_file_ptr == NULL) {
 691         // data has been changed by the new retransformable agent
 692         // and it hasn't already been cached, cache it
 693         JvmtiCachedClassFileData *p;
 694         p = (JvmtiCachedClassFileData *)os::malloc(
 695           offset_of(JvmtiCachedClassFileData, data) + _curr_len, mtInternal);
 696         if (p == NULL) {
 697           vm_exit_out_of_memory(offset_of(JvmtiCachedClassFileData, data) + _curr_len,
 698             OOM_MALLOC_ERROR,
 699             "unable to allocate cached copy of original class bytes");
 700         }
 701         p->length = _curr_len;
 702         memcpy(p->data, _curr_data, _curr_len);
 703         *_cached_class_file_ptr = p;
 704       }
 705 
 706       if (_curr_data != *_data_ptr) {
 707         // curr_data is previous agent modified class data.
 708         // And this has been changed by the new agent so
 709         // we can delete it now.


 717       // memory allocated by this agent.
 718       _curr_env = env;
 719     }
 720   }
 721 
 722   void copy_modified_data() {
 723     // if one of the agent has modified class file data.
 724     // Copy modified class data to new resources array.
 725     if (_curr_data != *_data_ptr) {
 726       *_data_ptr = NEW_RESOURCE_ARRAY(u1, _curr_len);
 727       memcpy(*_data_ptr, _curr_data, _curr_len);
 728       *_end_ptr = *_data_ptr + _curr_len;
 729       _curr_env->Deallocate(_curr_data);
 730     }
 731   }
 732 };
 733 
 734 bool JvmtiExport::_should_post_class_file_load_hook = false;
 735 
 736 // this entry is for class file load hook on class load, redefine and retransform
 737 void JvmtiExport::post_class_file_load_hook(Symbol* h_name,
 738                                             Handle class_loader,
 739                                             Handle h_protection_domain,
 740                                             unsigned char **data_ptr,
 741                                             unsigned char **end_ptr,
 742                                             JvmtiCachedClassFileData **cache_ptr) {
 743   if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) {
 744     return;
 745   }
 746 
 747   JvmtiClassFileLoadHookPoster poster(h_name, class_loader,
 748                                       h_protection_domain,
 749                                       data_ptr, end_ptr,
 750                                       cache_ptr);
 751   poster.post();

 752 }
 753 
 754 void JvmtiExport::report_unsupported(bool on) {
 755   // If any JVMTI service is turned on, we need to exit before native code
 756   // tries to access nonexistant services.
 757   if (on) {
 758     vm_exit_during_initialization("Java Kernel does not support JVMTI.");
 759   }
 760 }
 761 
 762 
 763 static inline Klass* oop_to_klass(oop obj) {
 764   Klass* k = obj->klass();
 765 
 766   // if the object is a java.lang.Class then return the java mirror
 767   if (k == SystemDictionary::Class_klass()) {
 768     if (!java_lang_Class::is_primitive(obj)) {
 769       k = java_lang_Class::as_Klass(obj);
 770       assert(k != NULL, "class for non-primitive mirror must exist");
 771     }




 570     MutexLocker mu(JvmtiThreadState_lock);
 571     return JvmtiEnvBase::get_all_native_method_prefixes(count_ptr);
 572   }
 573 }
 574 
 575 class JvmtiClassFileLoadHookPoster : public StackObj {
 576  private:
 577   Symbol*            _h_name;
 578   Handle               _class_loader;
 579   Handle               _h_protection_domain;
 580   unsigned char **     _data_ptr;
 581   unsigned char **     _end_ptr;
 582   JavaThread *         _thread;
 583   jint                 _curr_len;
 584   unsigned char *      _curr_data;
 585   JvmtiEnv *           _curr_env;
 586   JvmtiCachedClassFileData ** _cached_class_file_ptr;
 587   JvmtiThreadState *   _state;
 588   KlassHandle *        _h_class_being_redefined;
 589   JvmtiClassLoadKind   _load_kind;
 590   bool                 _has_been_modified;
 591 
 592  public:
 593   inline JvmtiClassFileLoadHookPoster(Symbol* h_name, Handle class_loader,
 594                                       Handle h_protection_domain,
 595                                       unsigned char **data_ptr, unsigned char **end_ptr,
 596                                       JvmtiCachedClassFileData **cache_ptr) {
 597     _h_name = h_name;
 598     _class_loader = class_loader;
 599     _h_protection_domain = h_protection_domain;
 600     _data_ptr = data_ptr;
 601     _end_ptr = end_ptr;
 602     _thread = JavaThread::current();
 603     _curr_len = *end_ptr - *data_ptr;
 604     _curr_data = *data_ptr;
 605     _curr_env = NULL;
 606     _cached_class_file_ptr = cache_ptr;
 607     _has_been_modified = false;
 608 
 609     _state = _thread->jvmti_thread_state();
 610     if (_state != NULL) {
 611       _h_class_being_redefined = _state->get_class_being_redefined();
 612       _load_kind = _state->get_class_load_kind();
 613       Klass* klass = (_h_class_being_redefined == NULL) ? NULL : (*_h_class_being_redefined)();
 614       if (_load_kind != jvmti_class_load_kind_load && klass != NULL) {
 615         ModuleEntry* module_entry = InstanceKlass::cast(klass)->module();
 616         assert(module_entry != NULL, "module_entry should always be set");
 617         if (module_entry->is_named() &&
 618             module_entry->module() != NULL &&
 619             !module_entry->has_default_read_edges()) {
 620           if (!module_entry->set_has_default_read_edges()) {
 621             // We won a potential race.
 622             // Add read edges to the unnamed modules of the bootstrap and app class loaders
 623             Handle class_module(_thread, JNIHandles::resolve(module_entry->module())); // Obtain j.l.r.Module
 624             JvmtiExport::add_default_read_edges(class_module, _thread);
 625           }
 626         }
 627       }
 628       // Clear class_being_redefined flag here. The action
 629       // from agent handler could generate a new class file load
 630       // hook event and if it is not cleared the new event generated
 631       // from regular class file load could have this stale redefined
 632       // class handle info.
 633       _state->clear_class_being_redefined();
 634     } else {
 635       // redefine and retransform will always set the thread state
 636       _h_class_being_redefined = (KlassHandle *) NULL;
 637       _load_kind = jvmti_class_load_kind_load;
 638     }
 639   }
 640 
 641   void post() {
 642     post_all_envs();
 643     copy_modified_data();
 644   }
 645 
 646   bool has_been_modified() { return _has_been_modified; }
 647 
 648  private:
 649   void post_all_envs() {
 650     if (_load_kind != jvmti_class_load_kind_retransform) {
 651       // for class load and redefine,
 652       // call the non-retransformable agents
 653       JvmtiEnvIterator it;
 654       for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
 655         if (!env->is_retransformable() && env->is_enabled(JVMTI_EVENT_CLASS_FILE_LOAD_HOOK)) {
 656           // non-retransformable agents cannot retransform back,
 657           // so no need to cache the original class file bytes
 658           post_to_env(env, false);
 659         }
 660       }
 661     }
 662     JvmtiEnvIterator it;
 663     for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
 664       // retransformable agents get all events
 665       if (env->is_retransformable() && env->is_enabled(JVMTI_EVENT_CLASS_FILE_LOAD_HOOK)) {
 666         // retransformable agents need to cache the original class file
 667         // bytes if changes are made via the ClassFileLoadHook


 674     if (env->phase() == JVMTI_PHASE_PRIMORDIAL && !env->early_class_hook_env()) {
 675       return;
 676     }
 677     unsigned char *new_data = NULL;
 678     jint new_len = 0;
 679     JvmtiClassFileLoadEventMark jem(_thread, _h_name, _class_loader,
 680                                     _h_protection_domain,
 681                                     _h_class_being_redefined);
 682     JvmtiJavaThreadEventTransition jet(_thread);
 683     jvmtiEventClassFileLoadHook callback = env->callbacks()->ClassFileLoadHook;
 684     if (callback != NULL) {
 685       (*callback)(env->jvmti_external(), jem.jni_env(),
 686                   jem.class_being_redefined(),
 687                   jem.jloader(), jem.class_name(),
 688                   jem.protection_domain(),
 689                   _curr_len, _curr_data,
 690                   &new_len, &new_data);
 691     }
 692     if (new_data != NULL) {
 693       // this agent has modified class data.
 694       _has_been_modified = true;
 695       if (caching_needed && *_cached_class_file_ptr == NULL) {
 696         // data has been changed by the new retransformable agent
 697         // and it hasn't already been cached, cache it
 698         JvmtiCachedClassFileData *p;
 699         p = (JvmtiCachedClassFileData *)os::malloc(
 700           offset_of(JvmtiCachedClassFileData, data) + _curr_len, mtInternal);
 701         if (p == NULL) {
 702           vm_exit_out_of_memory(offset_of(JvmtiCachedClassFileData, data) + _curr_len,
 703             OOM_MALLOC_ERROR,
 704             "unable to allocate cached copy of original class bytes");
 705         }
 706         p->length = _curr_len;
 707         memcpy(p->data, _curr_data, _curr_len);
 708         *_cached_class_file_ptr = p;
 709       }
 710 
 711       if (_curr_data != *_data_ptr) {
 712         // curr_data is previous agent modified class data.
 713         // And this has been changed by the new agent so
 714         // we can delete it now.


 722       // memory allocated by this agent.
 723       _curr_env = env;
 724     }
 725   }
 726 
 727   void copy_modified_data() {
 728     // if one of the agent has modified class file data.
 729     // Copy modified class data to new resources array.
 730     if (_curr_data != *_data_ptr) {
 731       *_data_ptr = NEW_RESOURCE_ARRAY(u1, _curr_len);
 732       memcpy(*_data_ptr, _curr_data, _curr_len);
 733       *_end_ptr = *_data_ptr + _curr_len;
 734       _curr_env->Deallocate(_curr_data);
 735     }
 736   }
 737 };
 738 
 739 bool JvmtiExport::_should_post_class_file_load_hook = false;
 740 
 741 // this entry is for class file load hook on class load, redefine and retransform
 742 bool JvmtiExport::post_class_file_load_hook(Symbol* h_name,
 743                                             Handle class_loader,
 744                                             Handle h_protection_domain,
 745                                             unsigned char **data_ptr,
 746                                             unsigned char **end_ptr,
 747                                             JvmtiCachedClassFileData **cache_ptr) {
 748   if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) {
 749     return false;
 750   }
 751 
 752   JvmtiClassFileLoadHookPoster poster(h_name, class_loader,
 753                                       h_protection_domain,
 754                                       data_ptr, end_ptr,
 755                                       cache_ptr);
 756   poster.post();
 757   return poster.has_been_modified();
 758 }
 759 
 760 void JvmtiExport::report_unsupported(bool on) {
 761   // If any JVMTI service is turned on, we need to exit before native code
 762   // tries to access nonexistant services.
 763   if (on) {
 764     vm_exit_during_initialization("Java Kernel does not support JVMTI.");
 765   }
 766 }
 767 
 768 
 769 static inline Klass* oop_to_klass(oop obj) {
 770   Klass* k = obj->klass();
 771 
 772   // if the object is a java.lang.Class then return the java mirror
 773   if (k == SystemDictionary::Class_klass()) {
 774     if (!java_lang_Class::is_primitive(obj)) {
 775       k = java_lang_Class::as_Klass(obj);
 776       assert(k != NULL, "class for non-primitive mirror must exist");
 777     }


src/share/vm/prims/jvmtiExport.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File