SharedHeap的结构如下,在结构中含有成员FlexibleWorkGang* _workers;
class SharedHeap : public CollectedHeap { friend class VMStructs; friend class VM_GC_Operation; friend class VM_CGC_Operation; private: // For claiming strong_roots tasks. SubTasksDone* _process_strong_tasks; protected: …… // If we're doing parallel GC, use this gang of threads. FlexibleWorkGang* _workers; …… };
FlexibleWorkGang的继承关系如下
class FlexibleWorkGang: public WorkGang { …… }; class WorkGang: public AbstractWorkGang { …… Void run_task(AbstractGangTask* task); …… }; class AbstractWorkGang: public CHeapObj { // Here's the public interface to this class. public: // Constructor and destructor. AbstractWorkGang(const char* name, bool are_GC_task_threads, bool are_ConcurrentGC_threads); ~AbstractWorkGang(); // Run a task, returns when the task is done (or terminated). virtual void run_task(AbstractGangTask* task) = 0; // Stop and terminate all workers. virtual void stop(); public: // Debugging. const char* name() const; protected: // Initialize only instance data. const bool _are_GC_task_threads; const bool _are_ConcurrentGC_threads; // Printing support. const char* _name; // The monitor which protects these data, // and notifies of changes in it. Monitor* _monitor; // The count of the number of workers in the gang. int _total_workers; // Whether the workers should terminate. bool _terminate; // The array of worker threads for this gang. // This is only needed for cleaning up. GangWorker** _gang_workers; // The task for this gang. AbstractGangTask* _task; // A sequence number for the current task. int _sequence_number; // The number of started workers. int _started_workers; // The number of finished workers. int _finished_workers; };
GangWorker的结构如下
class GangWorker: public WorkerThread { public: // Constructors and destructor. GangWorker(AbstractWorkGang* gang, uint id); // The only real method: run a task for the gang. virtual void run(); // Predicate for Thread virtual bool is_GC_task_thread() const; virtual bool is_ConcurrentGC_thread() const; // Printing void print_on(outputStream* st) const; virtual void print() const { print_on(tty); } protected: AbstractWorkGang* _gang; virtual void initialize(); virtual void loop(); public: AbstractWorkGang* gang() const { return _gang; } };
GangWorker就是GC线程,那么它是如何创建起来的呢?
当虚拟机启动的时候,会进行一些初始化操作,我们看一看是通过怎样的路径创建GangWorker的。Trace信息如下所示
#0 0x00002adb4964bace in FlexibleWorkGang (this=0x48, name=0xb00000000 <Address 0xb00000000 out of bounds>, workers=10971, are_GC_task_threads=8, are_ConcurrentGC_threads=false) at /home/chengtao/hotspot20/src/share/vm/utilities/workgroup.hpp:280 #1 0x00002adb4998e403 in SharedHeap (this=0x5903a430, policy_=0x5903a2f0) at /home/chengtao/hotspot20/src/share/vm/memory/sharedHeap.cpp:76 #2 0x00002adb49731331 in GenCollectedHeap (this=0x5903a430, policy=0x5903a2f0) at /home/chengtao/hotspot20/src/share/vm/memory/genCollectedHeap.cpp:76 #3 0x00002adb49a23f95 in Universe::initialize_heap () at /home/chengtao/hotspot20/src/share/vm/memory/universe.cpp:921 #4 0x00002adb49a243f8 in universe_init () at /home/chengtao/hotspot20/src/share/vm/memory/universe.cpp:781 #5 0x00002adb49767a52 in init_globals () at /home/chengtao/hotspot20/src/share/vm/runtime/init.cpp:98 #6 0x00002adb49a0e56a in Threads::create_vm (args=0x41964080, canTryAgain=0x4196405b) at /home/chengtao/hotspot20/src/share/vm/runtime/thread.cpp:3092 #7 0x00002adb497a181c in JNI_CreateJavaVM (vm=0x419640e0, penv=0x419640e8, args=0x41964080) at /home/chengtao/hotspot20/src/share/vm/prims/jni.cpp:3344 #8 0x00000000400035f8 in InitializeJVM () #9 0x000000004000206e in JavaMain ()
在WorkGang进行完成构造以后,会进行初始化,调用_workers->initialize_workers();在这个函数中,进行创建GangWorker,具体如下
//创建保存GangWork的指针数组 _gang_workers = NEW_C_HEAP_ARRAY(GangWorker*, total_workers());
// 创建_total_workers个GangWorker,实际上_total_workers是与ParallelGCThreads相等的,ParallelGCThreads这个值是根据cpu core计算出来的一个值 //每创建一个GangWorker就会立即启动这个线程 for (int worker = 0; worker < total_workers(); worker += 1) { GangWorker* new_worker = allocate_worker(worker); assert(new_worker != NULL, "Failed to allocate GangWorker"); _gang_workers[worker] = new_worker; if (new_worker == NULL || !os::create_thread(new_worker, worker_type)) { vm_exit_out_of_memory(0, "Cannot create worker GC thread. Out of system resources."); return false; } if (!DisableStartThread) { os::start_thread(new_worker); } }
到此,Parallel GC线程就被创建完了,并启动。
我们来看一下GangWorker的一些函数,可以看到,当GC线程被创建以后,首先会进行一些初始化工作,然后就进入到了loop函数中。仔细分析这个loop函数,可以发现,刚开始GC线程是进入wait状态的,等待被唤醒然后进行GC,接下来我们看一看GC线程是如何被唤醒的。
void GangWorker::run() { initialize(); loop(); } void GangWorker::initialize() { this->initialize_thread_local_storage(); assert(_gang != NULL, "No gang to run in"); os::set_priority(this, NearMaxPriority); if (TraceWorkGang) { tty->print_cr("Running gang worker for gang %s id %d", gang()->name(), id()); } // The VM thread should not execute here because MutexLocker's are used // as (opposed to MutexLockerEx's). assert(!Thread::current()->is_VM_thread(), "VM thread should not be part" " of a work gang"); } void GangWorker::loop() { int previous_sequence_number = 0; Monitor* gang_monitor = gang()->monitor(); for ( ; /* !terminate() */; ) { WorkData data; int part; // Initialized below. { // Grab the gang mutex. MutexLocker ml(gang_monitor); // Wait for something to do. // Polling outside the while { wait } avoids missed notifies // in the outer loop. gang()->internal_worker_poll(&data); if (TraceWorkGang) { tty->print("Polled outside for work in gang %s worker %d", gang()->name(), id()); tty->print(" terminate: %s", data.terminate() ? "true" : "false"); tty->print(" sequence: %d (prev: %d)", data.sequence_number(), previous_sequence_number); if (data.task() != NULL) { tty->print(" task: %s", data.task()->name()); } else { tty->print(" task: NULL"); } tty->cr(); } for ( ; /* break or return */; ) { // Terminate if requested. if (data.terminate()) { gang()->internal_note_finish(); gang_monitor->notify_all(); return; } // Check for new work. if ((data.task() != NULL) && (data.sequence_number() != previous_sequence_number)) { gang()->internal_note_start(); gang_monitor->notify_all(); part = gang()->started_workers() - 1; break; } // Nothing to do. gang_monitor->wait(/* no_safepoint_check */ true); gang()->internal_worker_poll(&data); if (TraceWorkGang) { tty->print("Polled inside for work in gang %s worker %d", gang()->name(), id()); tty->print(" terminate: %s", data.terminate() ? "true" : "false"); tty->print(" sequence: %d (prev: %d)", data.sequence_number(), previous_sequence_number); if (data.task() != NULL) { tty->print(" task: %s", data.task()->name()); } else { tty->print(" task: NULL"); } tty->cr(); } } // Drop gang mutex. } if (TraceWorkGang) { tty->print("Work for work gang %s id %d task %s part %d", gang()->name(), id(), data.task()->name(), part); } assert(data.task() != NULL, "Got null task"); data.task()->work(part); { if (TraceWorkGang) { tty->print("Finish for work gang %s id %d task %s part %d", gang()->name(), id(), data.task()->name(), part); } // Grab the gang mutex. MutexLocker ml(gang_monitor); gang()->internal_note_finish(); // Tell the gang you are done. gang_monitor->notify_all(); // Drop the gang mutex. } previous_sequence_number = data.sequence_number(); } }
当需要进行GC的时候,以ParNew为例,会进入到ParNewGeneration::collect这个函数,这个函数中有这样一段代码
if (n_workers > 1) { GenCollectedHeap::StrongRootsScope srs(gch); workers->run_task(&tsk); } else { GenCollectedHeap::StrongRootsScope srs(gch); tsk.work(0); }
进行Parallel GC的时候,就会进入到workers->run_task(&tsk)这个函数中了。函数原型就是void WorkGang::run_task(AbstractGangTask* task);
在这个函数中有这样一段代码
// Initialize. _task = task; _sequence_number += 1; _started_workers = 0; _finished_workers = 0; // Tell the workers to get to work. monitor()->notify_all(); // Wait for them to be finished while (finished_workers() < total_workers()) { if (TraceWorkGang) { tty->print_cr("Waiting in work gang %s: %d/%d finished sequence %d", name(), finished_workers(), total_workers(), _sequence_number); } monitor()->wait(/* no_safepoint_check */ true); } _task = NULL;
从代码中我们可以发现,monitor()->notify_all();就可以唤醒GC线程了,然后进入到wait状态,等待所有GC线程完成GC任务结束,然后退出。
总结起来很简单,就是初始时,WorkGang创建ParallelGCThreads个GC线程(GangWorker),这些GC线程处于wait状态。当进行Paralel GC的时候,WorkGang就会唤醒wait的GC线程,进行Parallel GC。WorkGang等待Parallel GC完成后返回。