成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Java開源工具在linux上的源碼分析(二):信號處理

開發 后端
當java虛擬機啟動的時候,會啟動很多內部的線程,這些線程主要在thread.cpp里的create_vm方法體里實現。而在thread.cpp里主要起了2個線程來處理信號相關的。詳細請看下文

當java虛擬機啟動的時候,會啟動很多內部的線程,這些線程主要在thread.cpp里的create_vm方法體里實現。

而在thread.cpp里主要起了2個線程來處理信號相關的:

  1. JvmtiExport::enter_live_phase();  
  2.  
  3. // Signal Dispatcher needs to be started before VMInit event is posted  
  4. os::signal_init();  
  5.  
  6. // Start Attach Listener if +StartAttachListener or it can't be started lazily  
  7. if (!DisableAttachMechanism) {  
  8.   if (StartAttachListener || AttachListener::init_at_startup()) {  
  9.     AttachListener::init();  
  10.   }  

1. Signal Dispatcher 線程

在os.cpp中的signal_init()函數中,啟動了signal dispatcher 線程,對signal dispather 線程主要是用于處理信號,等待信號并且分發處理,可以詳細看signal_thread_entry的方法:

  1. static void signal_thread_entry(JavaThread* thread, TRAPS) {  
  2.   os::set_priority(thread, NearMaxPriority);  
  3.   while (true) {  
  4.     int sig;  
  5.     {  
  6.       // FIXME : Currently we have not decieded what should be the status  
  7.       //         for this java thread blocked here. Once we decide about  
  8.       //         that we should fix this.  
  9.       sig = os::signal_wait();  
  10.     }  
  11.     if (sig == os::sigexitnum_pd()) {  
  12.        // Terminate the signal thread  
  13.        return;  
  14.     }  
  15.  
  16.     switch (sig) {  
  17.       case SIGBREAK: {  
  18.         // Check if the signal is a trigger to start the Attach Listener - in that  
  19.         // case don't print stack traces.  
  20.         if (!DisableAttachMechanism && AttachListener::is_init_trigger()) {  
  21.           continue;  
  22.         }  
  23.         // Print stack traces  
  24.         // Any SIGBREAK operations added here should make sure to flush  
  25.         // the output stream (e.g. tty->flush()) after output.  See 4803766.  
  26.         // Each module also prints an extra carriage return after its output.  
  27.         VM_PrintThreads op;  
  28.         VMThread::execute(&op);  
  29.         VM_PrintJNI jni_op;  
  30.         VMThread::execute(&jni_op);  
  31.         VM_FindDeadlocks op1(tty);  
  32.         VMThread::execute(&op1);  
  33.         Universe::print_heap_at_SIGBREAK();  
  34.         if (PrintClassHistogram) {  
  35.           VM_GC_HeapInspection op1(gclog_or_tty, true /* force full GC before heap inspection */,  
  36.                                    true /* need_prologue */);  
  37.           VMThread::execute(&op1);  
  38.         }  
  39.         if (JvmtiExport::should_post_data_dump()) {  
  40.           JvmtiExport::post_data_dump();  
  41.         }  
  42.         break;  
  43.       }  
  44.       default: {  
  45.         // Dispatch the signal to java  
  46.         HandleMark hm(THREAD);  
  47.         klassOop k = SystemDictionary::resolve_or_null(vmSymbolHandles::sun_misc_Signal(), THREAD);  
  48.         KlassHandle klass (THREAD, k);  
  49.         if (klass.not_null()) {  
  50.           JavaValue result(T_VOID);  
  51.           JavaCallArguments args;  
  52.           args.push_int(sig);  
  53.           JavaCalls::call_static(  
  54.             &result,  
  55.             klass,  
  56.             vmSymbolHandles::dispatch_name(),  
  57.             vmSymbolHandles::int_void_signature(),  
  58.             &args,  
  59.             THREAD  
  60.           );  
  61.         }  
  62.         if (HAS_PENDING_EXCEPTION) {  
  63.           // tty is initialized early so we don't expect it to be null, but  
  64.           // if it is we can't risk doing an initialization that might  
  65.           // trigger additional out-of-memory conditions  
  66.           if (tty != NULL) {  
  67.             char klass_name[256];  
  68.             char tmp_sig_name[16];  
  69.             const char* sig_name = "UNKNOWN";  
  70.             instanceKlass::cast(PENDING_EXCEPTION->klass())->  
  71.               name()->as_klass_external_name(klass_name, 256);  
  72.             if (os::exception_name(sig, tmp_sig_name, 16) != NULL)  
  73.               sig_name = tmp_sig_name;  
  74.             warning("Exception %s occurred dispatching signal %s to handler" 
  75.                     "- the VM may need to be forcibly terminated",  
  76.                     klass_name, sig_name );  
  77.           }  
  78.           CLEAR_PENDING_EXCEPTION;  
  79.         }  
  80.       }  
  81.     }  
  82.   }  

可以看到通過os::signal_wait();等待信號,而在linux里是通過sem_wait()來實現,接受到SIGBREAK(linux 中的QUIT)信號的時候(關于信號處理請參考筆者的另一篇博客:java 中關于信號的處理在linux下的實現),***次通過調用 AttachListener::is_init_trigger()初始化attach listener線程,詳細見2.Attach Listener 線程。

***次收到信號,會開始初始化,當初始化成功,將會直接返回,而且不返回任何線程stack的信息(通過socket file的操作返回),并且第二次將不在需要初始化。如果初始化不成功,將直接在控制臺的outputstream中打印線程棧信息。
第二次收到信號,如果已經初始化過,將直接在控制臺中打印線程的棧信息。如果沒有初始化,繼續初始化,走和***次相同的流程。

2. Attach Listener 線程

Attach Listener 線程是負責接收到外部的命令,而對該命令進行執行的并且吧結果返回給發送者。在jvm啟動的時候,如果沒有指定+StartAttachListener,該線程是不會啟動的,剛才我們討論到了在接受到quit信號之后,會調用 AttachListener::is_init_trigger()通過調用用AttachListener::init()啟動了Attach Listener 線程,同時在不同的操作系統下初始化,在linux中 是在attachListener_Linux.cpp文件中實現的。

在linux中如果發現文件.attach_pid#pid存在,才會啟動attach listener線程,同時初始化了socket 文件,也就是通常jmap,jstack tool干的事情,先創立attach_pid#pid文件,然后發quit信號,通過這種方式暗式的啟動了Attach Listener線程(見博客:http://blog.csdn.net/raintungli/article/details/7023092)。

線程的實現在 attach_listener_thread_entry 方法體中實現:

  1. static void attach_listener_thread_entry(JavaThread* thread, TRAPS) {  
  2.   os::set_priority(thread, NearMaxPriority);  
  3.  
  4.   if (AttachListener::pd_init() != 0) {  
  5.     return;  
  6.   }  
  7.   AttachListener::set_initialized();  
  8.  
  9.   for (;;) {  
  10.     AttachOperation* op = AttachListener::dequeue();    
  11.      if (op == NULL) {  
  12.       return;   // dequeue failed or shutdown  
  13.     }  
  14.  
  15.     ResourceMark rm;  
  16.     bufferedStream st;  
  17.     jint res = JNI_OK;  
  18.  
  19.     // handle special detachall operation  
  20.     if (strcmp(op->name(), AttachOperation::detachall_operation_name()) == 0) {  
  21.       AttachListener::detachall();  
  22.     } else {  
  23.       // find the function to dispatch too  
  24.       AttachOperationFunctionInfo* info = NULL;  
  25.       for (int i=0; funcs[i].name != NULL; i++) {  
  26.         const char* name = funcs[i].name;  
  27.         assert(strlen(name) <= AttachOperation::name_length_max, "operation <= name_length_max");  
  28.         if (strcmp(op->name(), name) == 0) {  
  29.           info = &(funcs[i]);  
  30.           break;  
  31.         }  
  32.       }  
  33.  
  34.       // check for platform dependent attach operation  
  35.       if (info == NULL) {  
  36.         info = AttachListener::pd_find_operation(op->name());  
  37.       }  
  38.  
  39.       if (info != NULL) {  
  40.         // dispatch to the function that implements this operation  
  41.         res = (info->func)(op, &st);  
  42.       } else {  
  43.         st.print("Operation %s not recognized!", op->name());  
  44.         res = JNI_ERR;  
  45.       }  
  46.     }  
  47.  
  48.     // operation complete - send result and output to client  
  49.     op->complete(res, &st);  
  50.   }  

在AttachListener::dequeue(); 在liunx里的實現就是監聽剛才創建的socket的文件,如果有請求進來,找到請求對應的操作,調用操作得到結果并把結果寫到這個socket的文件,如果你把socket的文件刪除,jstack/jmap會出現錯誤信息 unable to open socket file:........

 

我們經常使用 kill -3 pid的操作打印出線程棧信息,我們可以看到具體的實現是在Signal Dispatcher 線程中完成的,因為kill -3 pid 并不會創建.attach_pid#pid文件,所以一直初始化不成功,從而線程的棧信息被打印到控制臺中。

原文鏈接:http://blog.csdn.net/raintungli/article/details/7034005

【系列文章】

  1. Java開源工具在linux上的源碼分析(一):跟蹤方式
  2. Java開源工具在linux上的源碼分析(三):執行的線程vm thread
  3. Java開源工具在linux上的源碼分析(四):safe point
  4. Java開源工具在linux上的源碼分析(五):-F參數的bug
  5. Java開源工具在linux上的源碼分析(六):符號表的讀取
責任編輯:林師授 來源: raintungli的博客
相關推薦

2012-03-02 12:14:19

JavaJstackJmap

2012-03-02 12:31:50

Javajmapjstack

2012-03-02 12:25:07

Javajmapjstack

2012-03-02 12:38:49

Javajmapjstack

2012-03-02 13:29:38

Javajmapjstack

2022-06-26 18:09:43

Linux開源

2019-10-16 17:00:51

LinuxUbuntuVMware

2020-05-06 09:51:37

二進制Linux命令行工具

2020-05-09 12:01:40

Linux開源軟件SDN

2010-01-27 09:58:59

Linuxunix程序日志

2024-01-03 10:17:51

Linux通信

2021-03-09 11:25:04

Linux開源工具服務器

2021-09-07 07:53:42

Semaphore 信號量源碼

2019-08-01 09:52:46

LinuxNetData性能監控工具

2012-05-22 00:28:21

JavaJava開源開源工具

2025-06-25 06:18:46

Linux多線程機制

2021-08-31 09:41:57

LinuxiPhone開源工具

2021-09-01 09:47:25

Linux 工具 開發

2017-01-16 15:05:17

Linux信號機制分析

2017-01-16 14:48:42

Linux信號機制分析
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品国产91| 久久精品一级 | 日本不卡一区 | 在线免费观看成年人视频 | 99re热精品视频 | 亚洲国产精久久久久久久 | 国产成人一区二区三区 | 久草在线免费资源 | 国产高清视频一区 | 国产区在线观看 | 欧美精品第三页 | 中文字幕精品一区久久久久 | 国产成人免费视频网站视频社区 | 97国产精品| 欧美性猛交 | 综合久久网 | 狠狠撸在线视频 | 亚洲视频网 | 大学生a级毛片免费视频 | 国产香蕉视频在线播放 | 成人精品一区二区三区 | 在线日韩欧美 | 狠狠爱视频 | 国产一区二区影院 | 久久国产成人精品国产成人亚洲 | 亚洲国产精品日本 | 中文字字幕一区二区三区四区五区 | 日韩亚洲一区二区 | 日韩视频在线一区 | 99re热精品视频国产免费 | 日韩高清国产一区在线 | 国产精品久久久久久久午夜 | 国产99久久久国产精品 | 成人av免费在线观看 | 九九伦理电影 | 亚洲欧美一区二区三区视频 | 99热播放| 奇米av| 无码一区二区三区视频 | 中文字幕 欧美 日韩 | 久久久精品网 |