src/hotspot/share/jfr/jni/jfrJavaSupport.cpp
changeset 58863 c16ac7a2eba4
parent 55302 686dedba1d9a
child 59259 127ca611f19b
equal deleted inserted replaced
58861:2c3cc4b01880 58863:c16ac7a2eba4
    21  * questions.
    21  * questions.
    22  *
    22  *
    23  */
    23  */
    24 
    24 
    25 #include "precompiled.hpp"
    25 #include "precompiled.hpp"
    26 #include "jni.h"
       
    27 #include "classfile/javaClasses.inline.hpp"
    26 #include "classfile/javaClasses.inline.hpp"
    28 #include "classfile/modules.hpp"
    27 #include "classfile/modules.hpp"
    29 #include "classfile/symbolTable.hpp"
    28 #include "classfile/symbolTable.hpp"
    30 #include "classfile/systemDictionary.hpp"
    29 #include "classfile/systemDictionary.hpp"
    31 #include "classfile/vmSymbols.hpp"
    30 #include "classfile/vmSymbols.hpp"
    40 #include "oops/objArrayOop.inline.hpp"
    39 #include "oops/objArrayOop.inline.hpp"
    41 #include "runtime/handles.inline.hpp"
    40 #include "runtime/handles.inline.hpp"
    42 #include "runtime/fieldDescriptor.inline.hpp"
    41 #include "runtime/fieldDescriptor.inline.hpp"
    43 #include "runtime/java.hpp"
    42 #include "runtime/java.hpp"
    44 #include "runtime/jniHandles.inline.hpp"
    43 #include "runtime/jniHandles.inline.hpp"
       
    44 #include "runtime/semaphore.inline.hpp"
    45 #include "runtime/synchronizer.hpp"
    45 #include "runtime/synchronizer.hpp"
    46 #include "runtime/thread.inline.hpp"
    46 #include "runtime/thread.inline.hpp"
    47 #include "runtime/threadSMR.hpp"
    47 #include "runtime/threadSMR.hpp"
       
    48 #include "utilities/growableArray.hpp"
    48 
    49 
    49 #ifdef ASSERT
    50 #ifdef ASSERT
    50 void JfrJavaSupport::check_java_thread_in_vm(Thread* t) {
    51 void JfrJavaSupport::check_java_thread_in_vm(Thread* t) {
    51   assert(t != NULL, "invariant");
    52   assert(t != NULL, "invariant");
    52   assert(t->is_Java_thread(), "invariant");
    53   assert(t->is_Java_thread(), "invariant");
    56 void JfrJavaSupport::check_java_thread_in_native(Thread* t) {
    57 void JfrJavaSupport::check_java_thread_in_native(Thread* t) {
    57   assert(t != NULL, "invariant");
    58   assert(t != NULL, "invariant");
    58   assert(t->is_Java_thread(), "invariant");
    59   assert(t->is_Java_thread(), "invariant");
    59   assert(((JavaThread*)t)->thread_state() == _thread_in_native, "invariant");
    60   assert(((JavaThread*)t)->thread_state() == _thread_in_native, "invariant");
    60 }
    61 }
       
    62 
       
    63 static void check_new_unstarted_java_thread(Thread* t) {
       
    64   assert(t != NULL, "invariant");
       
    65   assert(t->is_Java_thread(), "invariant");
       
    66   assert(((JavaThread*)t)->thread_state() == _thread_new, "invariant");
       
    67 }
    61 #endif
    68 #endif
    62 
    69 
    63 /*
    70 /*
    64  *  Handles and references
    71  *  Handles and references
    65  */
    72  */
    89   return obj == NULL ? NULL : global_jni_handle(obj, t);
    96   return obj == NULL ? NULL : global_jni_handle(obj, t);
    90 }
    97 }
    91 
    98 
    92 void JfrJavaSupport::destroy_global_jni_handle(jobject handle) {
    99 void JfrJavaSupport::destroy_global_jni_handle(jobject handle) {
    93   JNIHandles::destroy_global(handle);
   100   JNIHandles::destroy_global(handle);
       
   101 }
       
   102 
       
   103 jweak JfrJavaSupport::global_weak_jni_handle(const oop obj, Thread* t) {
       
   104   DEBUG_ONLY(check_java_thread_in_vm(t));
       
   105   HandleMark hm(t);
       
   106   return JNIHandles::make_weak_global(Handle(t, obj));
       
   107 }
       
   108 
       
   109 jweak JfrJavaSupport::global_weak_jni_handle(const jobject handle, Thread* t) {
       
   110   const oop obj = JNIHandles::resolve(handle);
       
   111   return obj == NULL ? NULL : global_weak_jni_handle(obj, t);
       
   112 }
       
   113 
       
   114 void JfrJavaSupport::destroy_global_weak_jni_handle(jweak handle) {
       
   115   JNIHandles::destroy_weak_global(handle);
    94 }
   116 }
    95 
   117 
    96 oop JfrJavaSupport::resolve_non_null(jobject obj) {
   118 oop JfrJavaSupport::resolve_non_null(jobject obj) {
    97   return JNIHandles::resolve_non_null(obj);
   119   return JNIHandles::resolve_non_null(obj);
    98 }
   120 }
   601     return false;
   623     return false;
   602   }
   624   }
   603   return true;
   625   return true;
   604 }
   626 }
   605 
   627 
   606 jlong JfrJavaSupport::jfr_thread_id(jobject target_thread) {
   628 class ThreadExclusionListAccess : public StackObj {
       
   629  private:
       
   630   static Semaphore _mutex_semaphore;
       
   631  public:
       
   632   ThreadExclusionListAccess() { _mutex_semaphore.wait(); }
       
   633   ~ThreadExclusionListAccess() { _mutex_semaphore.signal(); }
       
   634 };
       
   635 
       
   636 Semaphore ThreadExclusionListAccess::_mutex_semaphore(1);
       
   637 static GrowableArray<jweak>* exclusion_list = NULL;
       
   638 
       
   639 static bool equals(const jweak excluded_thread, Handle target_thread) {
       
   640   return JfrJavaSupport::resolve_non_null(excluded_thread) == target_thread();
       
   641 }
       
   642 
       
   643 static int find_exclusion_thread_idx(Handle thread) {
       
   644   if (exclusion_list != NULL) {
       
   645     for (int i = 0; i < exclusion_list->length(); ++i) {
       
   646       if (equals(exclusion_list->at(i), thread)) {
       
   647         return i;
       
   648       }
       
   649     }
       
   650   }
       
   651   return -1;
       
   652 }
       
   653 
       
   654 static Handle as_handle(jobject thread) {
       
   655   return Handle(Thread::current(), JfrJavaSupport::resolve_non_null(thread));
       
   656 }
       
   657 
       
   658 static bool thread_is_not_excluded(Handle thread) {
       
   659   return -1 == find_exclusion_thread_idx(thread);
       
   660 }
       
   661 
       
   662 static bool thread_is_not_excluded(jobject thread) {
       
   663   return thread_is_not_excluded(as_handle(thread));
       
   664 }
       
   665 
       
   666 static bool is_thread_excluded(jobject thread) {
       
   667   return !thread_is_not_excluded(thread);
       
   668 }
       
   669 
       
   670 #ifdef ASSERT
       
   671 static bool is_thread_excluded(Handle thread) {
       
   672   return !thread_is_not_excluded(thread);
       
   673 }
       
   674 #endif // ASSERT
       
   675 
       
   676 static int add_thread_to_exclusion_list(jobject thread) {
       
   677   ThreadExclusionListAccess lock;
       
   678   if (exclusion_list == NULL) {
       
   679     exclusion_list = new (ResourceObj::C_HEAP, mtTracing) GrowableArray<jweak>(10, true, mtTracing);
       
   680   }
       
   681   assert(exclusion_list != NULL, "invariant");
       
   682   assert(thread_is_not_excluded(thread), "invariant");
       
   683   jweak ref = JfrJavaSupport::global_weak_jni_handle(thread, Thread::current());
       
   684   const int idx = exclusion_list->append(ref);
       
   685   assert(is_thread_excluded(thread), "invariant");
       
   686   return idx;
       
   687 }
       
   688 
       
   689 static void remove_thread_from_exclusion_list(Handle thread) {
       
   690   assert(exclusion_list != NULL, "invariant");
       
   691   assert(is_thread_excluded(thread), "invariant");
       
   692   assert(exclusion_list != NULL, "invariant");
       
   693   const int idx = find_exclusion_thread_idx(thread);
       
   694   assert(idx >= 0, "invariant");
       
   695   assert(idx < exclusion_list->length(), "invariant");
       
   696   JfrJavaSupport::destroy_global_weak_jni_handle(exclusion_list->at(idx));
       
   697   exclusion_list->delete_at(idx);
       
   698   assert(thread_is_not_excluded(thread), "invariant");
       
   699   if (0 == exclusion_list->length()) {
       
   700     delete exclusion_list;
       
   701     exclusion_list = NULL;
       
   702   }
       
   703 }
       
   704 
       
   705 static void remove_thread_from_exclusion_list(jobject thread) {
       
   706   ThreadExclusionListAccess lock;
       
   707   remove_thread_from_exclusion_list(as_handle(thread));
       
   708 }
       
   709 
       
   710 // includes removal
       
   711 static bool check_exclusion_state_on_thread_start(JavaThread* jt) {
       
   712   Handle h_obj(jt, jt->threadObj());
       
   713   ThreadExclusionListAccess lock;
       
   714   if (thread_is_not_excluded(h_obj)) {
       
   715     return false;
       
   716   }
       
   717   remove_thread_from_exclusion_list(h_obj);
       
   718   return true;
       
   719 }
       
   720 
       
   721 jlong JfrJavaSupport::jfr_thread_id(jobject thread) {
   607   ThreadsListHandle tlh;
   722   ThreadsListHandle tlh;
   608   JavaThread* native_thread = NULL;
   723   JavaThread* native_thread = NULL;
   609   (void)tlh.cv_internal_thread_to_JavaThread(target_thread, &native_thread, NULL);
   724   (void)tlh.cv_internal_thread_to_JavaThread(thread, &native_thread, NULL);
   610   return native_thread != NULL ? JFR_THREAD_ID(native_thread) : 0;
   725   return native_thread != NULL ? JFR_THREAD_ID(native_thread) : 0;
   611 }
   726 }
       
   727 
       
   728 void JfrJavaSupport::exclude(jobject thread) {
       
   729   HandleMark hm;
       
   730   ThreadsListHandle tlh;
       
   731   JavaThread* native_thread = NULL;
       
   732   (void)tlh.cv_internal_thread_to_JavaThread(thread, &native_thread, NULL);
       
   733   if (native_thread != NULL) {
       
   734     JfrThreadLocal::exclude(native_thread);
       
   735   } else {
       
   736     // not started yet, track the thread oop
       
   737     add_thread_to_exclusion_list(thread);
       
   738   }
       
   739 }
       
   740 
       
   741 void JfrJavaSupport::include(jobject thread) {
       
   742   HandleMark hm;
       
   743   ThreadsListHandle tlh;
       
   744   JavaThread* native_thread = NULL;
       
   745   (void)tlh.cv_internal_thread_to_JavaThread(thread, &native_thread, NULL);
       
   746   if (native_thread != NULL) {
       
   747     JfrThreadLocal::include(native_thread);
       
   748   } else {
       
   749     // not started yet, untrack the thread oop
       
   750     remove_thread_from_exclusion_list(thread);
       
   751   }
       
   752 }
       
   753 
       
   754 bool JfrJavaSupport::is_excluded(jobject thread) {
       
   755   HandleMark hm;
       
   756   ThreadsListHandle tlh;
       
   757   JavaThread* native_thread = NULL;
       
   758   (void)tlh.cv_internal_thread_to_JavaThread(thread, &native_thread, NULL);
       
   759   return native_thread != NULL ? native_thread->jfr_thread_local()->is_excluded() : is_thread_excluded(thread);
       
   760 }
       
   761 
       
   762 void JfrJavaSupport::on_thread_start(Thread* t) {
       
   763   assert(t != NULL, "invariant");
       
   764   assert(Thread::current() == t, "invariant");
       
   765   if (!t->is_Java_thread()) {
       
   766     return;
       
   767   }
       
   768   DEBUG_ONLY(check_new_unstarted_java_thread(t);)
       
   769   HandleMark hm;
       
   770   if (check_exclusion_state_on_thread_start((JavaThread*)t)) {
       
   771     JfrThreadLocal::exclude(t);
       
   772   }
       
   773 }