Java開源工具在linux上的源碼分析(三):執(zhí)行的線程
在前面的博客中(http://blog.csdn.net/raintungli/article/details/7034005)所提到的信號轉(zhuǎn)發(fā)線程,Attach Listener 線程都只是操作socket文件,并沒有去執(zhí)行比如stack 分析,或者h(yuǎn)eap的分析,真正的工作線程其實是vm thread.
(一)啟動vm thread
- jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
 - ...
 - // Create the VMThread
 - { TraceTime timer("Start VMThread", TraceStartupTime);
 - VMThread::create();
 - Thread* vmthread = VMThread::vm_thread();
 - if (!os::create_thread(vmthread, os::vm_thread))
 - vm_exit_during_initialization("Cannot create VM thread. Out of system resources.");
 - // Wait for the VM thread to become ready, and VMThread::run to initialize
 - // Monitors can have spurious returns, must always check another state flag
 - {
 - MutexLocker ml(Notify_lock);
 - os::start_thread(vmthread);
 - while (vmthread->active_handles() == NULL) {
 - Notify_lock->wait();
 - }
 - }
 - }
 - ...
 - }
 
我們可以看到,在thread.cpp里啟動了線程vm thread,在這里我們同時也稍微的略帶的講一下jvm在linux里如何啟動線程的。
通常在linux中啟動線程,是調(diào)用:
- int pthread_create((pthread_t *__thread, __const pthread_attr_t *__attr,void *(*__start_routine) (void *), void *__arg));
 
而在java里卻增加了os:create_thread --初始化線程 和os:start_thread--啟動線程。
我們?nèi)タ匆幌耲vm里面是如何在linux里做到的。
在os_linux.cpp中來看create_thread的方法:
- bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {
 - ....
 - int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread);
 - ....
 - }
 
繼續(xù)看java_start方法:
- static void *java_start(Thread *thread) {
 - ....
 - // handshaking with parent thread
 - {
 - MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag);
 - // notify parent thread
 - osthread->set_state(INITIALIZED);
 - sync->notify_all();
 - // wait until os::start_thread()
 - while (osthread->get_state() == INITIALIZED) {
 - sync->wait(Mutex::_no_safepoint_check_flag);
 - }
 - }
 - // call one more level start routine
 - thread->run();
 - return 0;
 - }
 
首先jvm先設(shè)置了當(dāng)前線程的狀態(tài)是Initialized, 然后notify所有的線程,
- while (osthread->get_state() == INITIALIZED) {
 - sync->wait(Mutex::_no_safepoint_check_flag);
 - }
 
不停的查看線程的當(dāng)前狀態(tài)是不是Initialized, 如果是的話,調(diào)用了sync->wait()的方法等待。
來看os:start_thread的方法 os.cpp
- void os::start_thread(Thread* thread) {
 - // guard suspend/resume
 - MutexLockerEx ml(thread->SR_lock(), Mutex::_no_safepoint_check_flag);
 - OSThread* osthread = thread->osthread();
 - osthread->set_state(RUNNABLE);
 - pd_start_thread(thread);
 - }
 
這時候設(shè)置了線程的狀態(tài)為runnable,但沒有notify線程。
在 pd_start_thread(thread)中, os_linux.cpp中:
- void os::pd_start_thread(Thread* thread) {
 - OSThread * osthread = thread->osthread();
 - assert(osthread->get_state() != INITIALIZED, "just checking");
 - Monitor* sync_with_child = osthread->startThread_lock();
 - MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag);
 - sync_with_child->notify();
 - }
 
這時候我們看到了notify 線程的操作,也就是這時候notify了線程,因為這時候的線程的狀態(tài)是RUNNABLE, 方法java_start繼續(xù)往下執(zhí)行,于是調(diào)用了thread->run()的方法。
對于線程vm Thread 也就是調(diào)用了vmthread::run方法。
vmThread.cpp
- void VMThread::run() {
 - ...
 - this->loop();
 - ...
 - }
 
調(diào)用了loop函數(shù),處理了VM_Operation 的queue 關(guān)于queue的級別和優(yōu)先級處理算法:可以參考 另一篇博客:http://blog.csdn.net/raintungli/article/details/6553337
(二)Jstack 運行在vm thread里的VM_Operation
jstack 處理也就是在前面博客所提到的attach Listener 線程所做的 operation
- static jint thread_dump(AttachOperation* op, outputStream* out) {
 - bool print_concurrent_locks = false;
 - if (op->arg(0) != NULL && strcmp(op->arg(0), "-l") == 0) {
 - print_concurrent_locks = true;
 - }
 - // thread stacks
 - VM_PrintThreads op1(out, print_concurrent_locks);
 - VMThread::execute(&op1);
 - // JNI global handles
 - VM_PrintJNI op2(out);
 - VMThread::execute(&op2);
 - // Deadlock detection
 - VM_FindDeadlocks op3(out);
 - VMThread::execute(&op3);
 - return JNI_OK;
 - }
 
簡單看一下類VM_PrintThreads 它 繼承了VM_Operation
- class VM_PrintThreads: public VM_Operation {
 - private:
 - outputStream* _out;
 - bool _print_concurrent_locks;
 - public:
 - VM_PrintThreads() { _out = tty; _print_concurrent_locks = PrintConcurrentLocks; }
 - VM_PrintThreads(outputStream* out, bool print_concurrent_locks) { _out = out; _print_concurrent_locks = print_concurrent_locks; }
 - VMOp_Type type() const { return VMOp_PrintThreads; }
 - void doit();
 - bool doit_prologue();
 - void doit_epilogue();
 - };
 
當(dāng)調(diào)用VMThread::execute()也就是將VM_PrintThreads 放入了_vm_queue中,交給vm thread 處理,對vm thread來說取出queue里的VM_Operation,并且調(diào)用doit方法。
在jstack里,attach listener 的線程產(chǎn)生了VM_PrintThreads,VM_PrintJNI,VM_FindDeadlocks 3個operations,交給了vm thread 的線程處理。
原文鏈接:http://blog.csdn.net/raintungli/article/details/7045024
【系列文章】















 
 
 



 
 
 
 