本篇内容介绍了“Java开源工具在linux上执行的线程是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
创新互联致力于互联网品牌建设与网络营销,包括网站设计制作、成都网站制作、SEO优化、网络推广、整站优化营销策划推广、电子商务、移动互联网营销等。创新互联为不同类型的客户提供良好的互联网应用定制及解决方案,创新互联核心团队十年专注互联网开发,积累了丰富的网站经验,为广大企业客户提供一站式企业网站建设服务,在网站建设行业内树立了良好口碑。
Attach Listener 线程都只是操作socket文件,并没有去执行比如stack 分析,或者heap的分析,真正的工作线程其实是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中启动线程,是调用:
int pthread_create((pthread_t *__thread, __const pthread_attr_t *__attr,void *(*__start_routine) (void *), void *__arg));
而在java里却增加了os:create_thread --初始化线程 和os:start_thread--启动线程。
我们去看一下jvm里面是如何在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); .... }
继续看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先设置了当前线程的状态是Initialized, 然后notify所有的线程,
while (osthread->get_state() == INITIALIZED) { sync->wait(Mutex::_no_safepoint_check_flag); }
不停的查看线程的当前状态是不是Initialized, 如果是的话,调用了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); }
这时候设置了线程的状态为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了线程,因为这时候的线程的状态是RUNNABLE, 方法java_start继续往下执行,于是调用了thread->run()的方法。
对于线程vm Thread 也就是调用了vmthread::run方法。
vmThread.cpp
void VMThread::run() { ... this->loop(); ... }
调用了loop函数,处理了VM_Operation 的queue
(二)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(); };
当调用VMThread::execute()也就是将VM_PrintThreads 放入了_vm_queue中,交给vm thread 处理,对vm thread来说取出queue里的VM_Operation,并且调用doit方法。
在jstack里,attach listener 的线程产生了VM_PrintThreads,VM_PrintJNI,VM_FindDeadlocks 3个operations,交给了vm thread 的线程处理。
“Java开源工具在linux上执行的线程是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注创新互联网站,小编将为大家输出更多高质量的实用文章!