JVM中的线程详解



在JVM的\hotsopt\src\share\vm\runtime\Thread.hpp中可以看到关于THREAD的子类结构



// Class hierarchy

// - Thread

//   - NamedThread

//     - VMThread

//     - ConcurrentGCThread

//     - WorkerThread

//       - GangWorker

//       - GCTaskThread

//   - JavaThread



//     - LowMemoryDetectorThread



//     - CompilerThread



//   - WatcherThread

Thread是最基础的基类



重要属性如下:



OSThread _osthread;        



        在OSThread内部set_thread_id方法可以设置为操作系统级的线程ID  pthreadid



        在JVM的线程管理中,THREAD是一个数据结构,THREAD中含有抽象的OSThread数据结构,OSThread中的pthreadid或者threadid指向的是操作系统内核级别的线程id



        关于操作系统内核级别的线程,大家可以阅读原生C语言的多线程编程接口POSIX threads 简称pthread库



重要函数如下:



virtual void run();    为最终的线程运行方法







此外有一个工具性质的类Threads



重要属性如下:



  static JavaThread _thread_list;

  static int         _number_of_threads;

  static int         _number_of_non_daemon_threads;

  static int         _return_code;



储存了所有正在运行的Java线程















————————————————————————————————————————————————————————————————



可以看到,线程粗分为三类:

NamedThread、JavaThread、WatcherThread



这三类中



NamedThread是一个大类







按照源码中的注释:



// Name support for threads.  non-JavaThread subclasses with multiple

// uniquely named instances should derive from this.

max_name_len = 64,最大名称长度为64个字符



重要属性为



char _name;



JavaThread _processed_thread;



也就是说NamedThread中可以有OSThread也可以有JavaThread










JavaThread是JAVA线程



重要属性如下:



JavaThread    _next;        // The next thread in the Threads list



oop            _threadObj;    // The Java level thread object



int _java_call_counter;      // java调用次数



JavaFrameAnchor _anchor; // JavaFrame锚点



ThreadFunction _entry_point;



JNIEnv        _jni_environment;



vframeArray  _vframe_array_head;



vframeArray  _vframe_array_last;



GrowableArray<jvmtiDeferredLocalVariableSet> _deferred_locals_updates;    本地变量表



oop           _vm_result;    // Used to pass back an oop result into Java code, GC-preserved



oop           _vm_result_2;  // Used to pass back an oop result into Java code, GC-preserved



ThreadSafepointState _safepoint_state;



address               _saved_exception_pc;



volatile oop     _exception_oop;



volatile address _exception_pc;



volatile address _exception_handler_pc;



volatile int     _exception_stack_size;



volatile int     _is_method_handle_return;







重要方法如下:



void java_suspend();



void java_resume();



int  java_suspend_self();



virtual void run();



WatcherThread是用来模拟时间中断



重要属性如下:



static WatcherThread _watcher_thread;



volatile static bool _should_terminate;



————————————————————————————————————————————————————————————————




//   - NamedThread

//     - VMThread

//     - ConcurrentGCThread

//     - WorkerThread

//       - GangWorker

//       - GCTaskThread



NameThread下分为三大类VMThread,ConcurrentGCThread,WorkerThread



首先看VMThread



VMThread位于\hotspot\src\share\vm\runtime\vmThread.hpp中



重要属性如下:



static VM_Operation     _cur_vm_operation;        当前正在执行的VM操作



static VMOperationQueue _vm_queue;                所有VM操作的对象



static VMThread     _vm_thread;                        单例模式的VMThread



重要方法如下:



void evaluate_operation(VM_Operation op);        执行一个VM操作



bool is_VM_thread() const                      { return true; }        //默认为VMThread

bool is_GC_thread() const                      { return true; }        //默认为GCThread



与VMThread配套使用的是VMOperationQueue和VM_Operation



VMOperationQueue位于\hotspot\src\share\vm\runtime\vmThread.hpp中



重要属性如下:



int           _queue_length[nof_priorities];



VM_Operation _queue       [nof_priorities];



int           _queue_counter;



VM_Operation _drain_list;



VM_Operation位于\hotspot\src\share\vm\runtime\Vm_operations.hpp中



重要属性如下:



Thread         _calling_thread;



VM_Operation   _next;



VM_Operation   _prev;



void evaluate();



virtual void doit()



virtual bool doit_prologue()



virtual void doit_epilogue()



VM_ThreadStop位于\hotspot\src\share\vm\runtime\Vm_operations.hpp中



重要属性如下



oop     _thread;



oop     _throwable;



此外和VMThread相关联的VM_Operation还有



VM_ForceSafepoint



VM_ForceAsyncSafepoint



VM_Deoptimize



VM_DeoptimizeFrame



VM_HandleFullCodeCache



VM_DeoptimizeAll



VM_ZombieAll



VM_Verify



VM_PrintThreads



VM_PrintJNI



VM_FindDeadlocks



VM_ThreadDump



VM_Exit



可从名称中看到其用途



举个简单的栗子,VM_PrintJNI



void VM_Operation::evaluate() {

  ResourceMark rm;

  if (TraceVMOperation) {

    tty->print(“[“);

    NOT_PRODUCT(print();)

  }

  doit();

  if (TraceVMOperation) {

    tty->print_cr(“]”);

  }

}




void VM_PrintJNI::doit() {

  JNIHandles::print_on(_out);

}



—————————————————————-



ConcurrentGCThread位于\hotspot\src\share\vm\gc_implementation\shared\concurrentGCThread.hpp中



含义如其名称,并发垃圾回收线程













WorkerThread有两个子类:GangWorker、GCTaskThread



子类极多。启动过程有很大区别,例如



GangWorker在WorkGang::initialize_workers()中GangWorker new_worker = allocate_worker(worker);中创建



        例如FlexibleWorkGang   _workers->initialize_workers();




GCTaskThread的初始化与启动在



ParallelScavengeHeap::initialize()



_gc_task_manager = GCTaskManager::create(ParallelGCThreads);



在构造函数中调用:initialize();




GCTaskManager::initialize()



    set_thread(t, GCTaskThread::create(this, t, processor_assignment[t]));



        new GCTaskThread(manager, which, processor_id)



            os::create_thread(this, os::pgc_thread)



                osthread->set_thread_type(thr_type);




                    thread->run();



                        GCTaskThread->run();




                            GCTask task = manager()->get_task(which());        即:任何一个进程,只要在manager的任务队列中放入task,后续将会立刻执行



                            task->do_it(manager(), which());       




从这段描述中可以看到,WorkerThread本身即为垃圾回收线程,大致分为两类:



1、GangWorker,作用于SharedHeap,在ShareHeap创建成功后,等待AbstractWorkGang->AbstractGangTask _task中获取到task,然后执行



2、GCTaskThread,作用于parallelscavenge,在ParallelScavengeHeap创建成功后,生成GCTaskManager,进而生成任务队列SynchronizedGCTaskQueue  _queue,等待有程序将任务放入队列,然后执行







—————————————————————-



下文我们来看一下VMThread的启动过程



VMThread是用于JVM虚拟机操作



其启动过程为随着JVM虚拟机java.c一起启动



调用堆栈序列为:



java.c:main->javaMain->InitializeJVM->CreateJavaVM->JNI_CreateJavaVM->Threads::create_vm



    VMThread::create();        生成单例模式的_vm_thread



        _vm_thread = new VMThread();



        _vm_queue = new VMOperationQueue();



    os::create_thread(vmthread, os::vm_thread)    给VMThread创建真实线程



        OSThread osthread = new OSThread(NULL, NULL);



                pd_initialize();



                    _startThread_lock = new Monitor(Mutex::event, “startThread_lock”, true);          锁监视器,第一个和第三个参数均没有用,只有第二个参数会作为Monitor的名名称



                            内部具有_LockWord关键字,同时具有CASPTR宏Atomic::cmpxchg_ptr用来对数据进行原子性操作,底层采用AMD64汇编指令cmpxchgq来完成原子性操作




                            Monitor::Monitor() { ClearMonitor(this); }



                            void Monitor::ClearMonitor (Monitor m, const char name) {

                                  m->_owner             = NULL ;

                                  m->_snuck             = false ;

                                  if (name == NULL) {

                                    strcpy(m->_name, “UNKNOWN”) ;

                                  } else {

                                    strncpy(m->_name, name, MONITOR_NAME_LEN - 1);

                                    m->_name[MONITOR_NAME_LEN - 1] = ‘\0’;

                                  }

                                  m->_LockWord.FullWord = 0 ;

                                  m->_EntryList         = NULL ;

                                  m->_OnDeck            = NULL ;

                                  m->_WaitSet           = NULL ;

                                  m->_WaitLock[0]       = 0 ;

                                }

                            可看到锁的初始值是m->_LockWord.FullWord = 0 ;



                                此处需要注意:Monitor中的lockWord为SplitWord



                                    union SplitWord {   // full-word with separately addressable LSB

                                          volatile intptr_t FullWord ;

                                          volatile void Address ;

                                          volatile jbyte Bytes [sizeof(intptr_t)] ;

                                    }



                                因此,lockWord初始值为0



                                而ILock中代码如下intptr_t v = CASPTR (&_LockWord, 0, _LBIT) ;



                                锁定后_LockWord = 1,解锁后_LockWord = 0;



                                初始值为未锁定0




        vmthread->set_osthread(osthread);




        pthread_t tid;



        int ret = pthread_create(&tid, &attr, (void ()(void)) java_start, thread);



        osthread->set_pthread_id(tid);



        在java_start函数中




            while (osthread->get_state() == INITIALIZED) {



                sync->wait(Mutex::_no_safepoint_check_flag);            开始等待




                    等待函数的写法如下:




                            Thread const Self = Thread::current() ;



                            set_owner(NULL);



                            wait_status = IWait (Self, timeout) ;            开始等待–>内部实现细节需要研究




                            set_owner (Self) ;




            }




            thread->run();            开始调用thread->run函数



    os::start_thread(vmthread);    



            调用:    pd_start_thread(thread);




                    调用:    Monitor* sync_with_child = osthread->startThread_lock();



                    调用:    MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag);



                    调用:    sync_with_child->notify();            通知java_start继续运行




                                调用:    thread->run()




                                        调用:    this->loop();          




                                                    代码:    while(true)




                                                            代码:    _cur_vm_operation = _vm_queue->remove_next();



                                                            代码:    evaluate_operation(_cur_vm_operation);




                                                                    代码:    _cur_vm_operation->evaluate();




                                                                            代码:    _cur_vm_operation->doit();



                                    在最终的doit()函数中,即执行的是VM_Operation的操作。




            例如:




                    void VM_PrintThreads::doit() {

                      Threads::print_on(_out, true, false, _print_concurrent_locks);

                    }



    这个就是VMThread的执行步骤,以及最终调用函数的过程。