帧的对象引用,这个引用指向了被操作线程对象。这样就可以获得一个显式线程切换的上下文信息,可以被描述为:<Thread-A, start, Thread-B>、<Thread-B, resume, Thread-C> 等等。
清单 2. 监控显式线程切换
static void JNICALL callbackMethodEntry(jvmtiEnv *jvmti_env, JNIEnv* env,
jthread thr, jmethodID method) {
gb_jvmti->RawMonitorEnter(gb_lock);
if (strcmp(name,"start")==0||strcmp(name,"interrupt")==0||
strcmp(name,"join")==0||strcmp(name,"stop")==0||
strcmp(name,"suspend")==0||strcmp(name,"resume")==0){
gb_jvmti->GetLocalObject(thr,0,0,&thd_ptr);
gb_jvmti->GetObjectHashCode(thd_ptr, &hash_code);
}
gb_jvmti->RawMonitorExit(gb_lock);
}
监控隐式线程切换
隐式线程切换的监控通过捕获 wait()/notify()/notifyAll() 方法调用前和调用后的等待集信息来实现。
以 notify() 方法为例,当 notify() 方法即将被调用时,在 callbackMethodEntry() 方法中首先使用 GetOwnedMonitorInfo() 方法获取当前操作线程所拥有的监视器,然后用 GetObjectMonitorUsage() 方法获取每个监视器上等待的线程对象,并将它们保存在隐式线程切换信息链表中等待分析,主要代码片段如清单 3 所示。
清单 3. 获取 notify 方法调用前的等待集
static void JNICALL callbackMethodEntry(jvmtiEnv *jvmti_env, JNIEnv* env,
jthread thr, jmethodID method){
if(strcmp(name,"notify")==0||strcmp(name,"notifyAll")==0) {
gb_jvmti->GetOwnedMonitorInfo(thr,&owned_monitor_count,&owned_monitors_ptr);
for(int index=0;index<owned_monitor_count;index++){
jvmtiMonitorUsage *info_ptr=NULL;
info_ptr=(jvmtiMonitorUsage*)malloc(sizeof(jvmtiMonitorUsage));
gb_jvmti->GetObjectMonitorUsage(*(owned_monitors_ptr+index),info_ptr);
insertElem(&inf_head,&inf_tail,info_ptr);
}
}
}
基于JVMTI实现Java线程的监控(5)
时间:2011-02-06 IBM 李凌
当 notify() 方法即将完成调用时,在 callbackMethodExit() 方法中,同样获取当前操作线程的等待集(notify_waiters),然后与之前记录的等待集进行比较,其中有差异的对象即为被操作线程对象。这样就能确定隐式线程切换的上下文信息,它可以被描述为:<Thread-A, notify, Thread-B>。其主要代码片段如清单 4 所示。
清单 4. 分析 notify 方法调用前后的等待集
static void JNICALL callbackMethodExit(jvmtiEnv *jvmti_env, JNIEnv* env,
jthread thr, jmethodID method){
//compare the two wait pools
if(info_ptr->notify_waiter_count!=inf_head->info_ptr->notify_waiter_count){
for(int i=0;i<inf_head->info_ptr->notify_waiter_count;i++){
for(int j=0;j<info_ptr->notify_waiter_count;j++){
if(inf_head->info_ptr->notify_waiters+i!=info_ptr->notify_waiters+j){
isObj=false;
break;
}
}
if(isObj==true) {
GetObjectHashCode(*(inf_head->info_ptr->notify_waiters+i), &hash_code);
|