JVM中垃圾回收线程的创建



本文描述了垃圾回收线程的创建过程,和在gc过程中,垃圾回收线程的任务分配



垃圾回收线程是在代回收堆GenCollectedHeap的父类SharedHeap的构造方法中创建的,可见代码



\hotspot\src\share\vm\memory\shareHeap.cpp



    构造方法:    SharedHeap::SharedHeap(CollectorPolicy policy_)



                    代码:    FlexibleWorkGang _workers = new FlexibleWorkGang(“Parallel GC Threads”, ParallelGCThreads,true,false);



                    代码:    _workers->initialize_workers();







    FlexibleWorkGang中即为垃圾回收线程的创建



    构造方法:    FlexibleWorkGang    设置_active_workers数量为ParallelGCThreads,默认为0,但是会根据gc策略和CPU数量进行修改参见函数Abstract_VM_Version::nof_parallel_worker_threads



                     父类构造方法:    WorkGang    设置_total_workers = workers;



                                            父类构造方法:    AbstractWorkGang::AbstractWorkGang



                                                                   _monitor = new Monitor(Mutex::leaf,”WorkGroup monitor”,are_GC_task_threads);



                                                                   _terminate = false;



                                                                   _task = NULL;



                                                                   _sequence_number = 0;



                                                                   _started_workers = 0;



                                                                   _finished_workers = 0;



    在_workers->initialize_workers();中即为worker的初始化,参见代码\hotspot\src\share\vm\utilities\Workgroup.cpp



        调用:    WorkGang::initialize_workers()



                    代码:    if (are_ConcurrentGC_threads()) {

                                    worker_type = os::cgc_thread;            判断是并发垃圾回收线程

                                } else {

                                    worker_type = os::pgc_thread;            判断是否是并行垃圾回收线程

                                }



                    代码:    for (int worker = 0; worker < total_workers(); worker += 1) {

                                    GangWorker new_worker = allocate_worker(worker);            申请一个worker内存




                                                代码:    GangWorker new_worker = new GangWorker(this, which);




                                    _gang_workers[worker] = new_worker;



                                    os::create_thread(new_worker, worker_type)                        创建一个worker线程




                                        代码:    \hotspot\src\os\linux\vm\Os_linux.cpp




                                                    代码:    OSThread osthread = new OSThread(NULL, NULL);



                                                    代码:    osthread->set_thread_type(thr_type);



                                                    代码:    thread->set_osthread(osthread);



                                                    代码:    pthread_t tid;



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



                                                               



                    代码:    os::start_thread(new_worker);



                                代码:    OSThread osthread = thread->osthread();



                                代码:    osthread->set_state(RUNNABLE);



                                代码:    pd_start_thread(thread);



                                            代码:    sync_with_child->notify();        触发os函数,即    java_start函数






                                                        调用:    static void java_start(Thread thread)



                                                                   代码:    thread->run();                    此处的thread是在上步骤生成的GangWorker



                                                                              调用:    GangWorker.run()




                                                                                         调用:    initialize();        初始化一些信息



                                                                                         调用:    loop();             循环操作




                                                                                                    代码:    WorkData data;



                                                                                                    代码:    gang()->internal_worker_poll(&data);            此处的gang()是指FlexibleWorkGang,AbstractWorkGang::internal_worker_poll(WorkData data)




                                                                                                                      data->set_terminate(terminate());



                                                                                                                      data->set_task(task());                        此处的task为AbstractGangTask的子类,但是FlexibleWorkGang在构造的时候,没有指定task,因此为空



                                                                                                                      data->set_sequence_number(sequence_number());




                                                                                                     代码:    data.task()->work(part);                               此处的task为AbstractGangTask的子类,



                                                                                                                     包括:CMConcurrentMarkingTask、G1ParFinalCountTask、G1ParNoteEndTask、G1ParScrubRemSetTask、CMRemarkTask、



                                                                                                                            CMSParRemarkTask、CMSRefEnqueueTaskProxy、ParRebuildRSTask、G1ParVerifyTask、G1ParTask、



                                                                                                                            G1ParCleanupCTTask、ParKnownGarbageTask、ParNewRefProcTaskProxy、ParNewRefEnqueueTaskProxy、ParNewGenTask




                                                                                                                     在concurrentmarksweep中使用的是CMSParRemarkTask和CMSRefEnqueueTaskProxy



                                                                                                                     在parnew中使用的是ParNewRefProcTaskProxy、ParNewRefEnqueueTaskProxy、ParNewGenTask










                    CMSParRemarkTask任务的位置



                    入口    CMSCollector::collect(bool   full, bool   clear_all_soft_refs, size_t size, bool   tlab)




                                调用:    CMSCollector::acquire_control_and_collect(bool full, bool clear_all_soft_refs)或者

                                            调用:    
CMSCollector::do_mark_sweep_work(bool clear_all_soft_refs, CollectorState first_state, bool should_start_over) 或者 VM_CMS_Initial_Mark::doit()



                                                        调用:    CMSCollector::collect_in_foreground(bool clear_all_soft_refs)        或者CMSCollector::do_CMS_operation(CMS_op_type op)




                                                                    调用:    CMSCollector::checkpointRootsFinal(bool asynch,bool clear_all_soft_refs, bool init_mark_was_synchronous)




                                                                                调用:    CMSCollector::checkpointRootsFinalWork(bool asynch,bool clear_all_soft_refs, bool init_mark_was_synchronous)




                                                                                            调用:    CMSCollector::do_remark_parallel()



                                                                                                        代码:    CMSParRemarkTask tsk(this,cms_space, perm_space,n_workers, workers, task_queues());



                                                                                                        代码:    workers->run_task(&tsk);



                                                                                                        代码:    tsk.work(0);




                从上可知,由某个操作,例如内存分配,触发一个收集内存垃圾的动作,进而调用了属于该堆的worker的runtask函数,将task进行执行操作,调用work函数。




              



               我们从更细节的角度来看一下gc的触发与执行




               从$$23123!@#$%^&@#$%^&(%$^&*()                        –》发生了惨剧,作者写了三个小时的内容,因为一个随意的关闭,丢失了一部分从java.c启动到创建VMTHREAD,到VMTHREAD的安全点通知,到执行collect_as_vm_thread到do_collection,到安全点的恢复……….的文档……




               已经晚上12:54,还在等待隔壁的不靠谱系统发版,没有心情写了,听一会儿歌,明天写VMTHREAD的启动过程和垃圾回收过程。………………….