GC回收周期包括如下11个子阶段:
出于回收效率的考虑,remap过程放在下一个回收周期的并发标记子阶段进行。
ZGC的入口在ZCollectedHeap collect方法
zCollectedHeap.cpp
void ZCollectedHeap::collect(GCCause::Cause cause) {
_driver->collect(cause);
}
根据传入的GCCause,判断使用同步消息还是异步消息。
zDriver.cpp
void ZDriver::collect(GCCause::Cause cause) {
switch (cause) {
case GCCause::_wb_young_gc:
case GCCause::_wb_conc_mark:
case GCCause::_wb_full_gc:
case GCCause::_dcmd_gc_run:
case GCCause::_java_lang_system_gc:
case GCCause::_full_gc_alot:
case GCCause::_scavenge_alot:
case GCCause::_jvmti_force_gc:
case GCCause::_metadata_GC_clear_soft_refs:
// Start synchronous GC
_gc_cycle_port.send_sync(cause);
break;
case GCCause::_z_timer:
case GCCause::_z_warmup:
case GCCause::_z_allocation_rate:
case GCCause::_z_allocation_stall:
case GCCause::_z_proactive:
case GCCause::_metadata_GC_threshold:
// Start asynchronous GC
_gc_cycle_port.send_async(cause);
break;
case GCCause::_gc_locker:
// Restart VM operation previously blocked by the GC locker
_gc_locker_port.signal();
break;
default:
// Other causes not supported
fatal("Unsupported GC cause (%s)", GCCause::to_string(cause));
break;
}
}
ZGC使用ZMessagePort类传递消息,ZMessagePort内部使用了ZList队列。
zMessagePort.hpp
class ZMessagePort {
private:
typedef ZMessageRequest Request;
Monitor _monitor;
bool _has_message;
T _message;
uint64_t _seqnum;
ZList _queue;
public:
ZMessagePort();
void send_sync(T message);
void send_async(T message);
T receive();
void ack();
};
同步消息逻辑如下:
zMessagePort.inline.hpp
template
inline void ZMessagePort::send_sync(T message) {
Request request;
{
// Enqueue message
MonitorLockerEx ml(&_monitor, Monitor::_no_safepoint_check_flag);
request.initialize(message, _seqnum);
_queue.insert_last(&request);
ml.notify();
}
// Wait for completion
request.wait();
{
// Guard deletion of underlying semaphore. This is a workaround for a
// bug in sem_post() in glibc < 2.21, where it's not safe to destroy
// the semaphore immediately after returning from sem_wait(). The
// reason is that sem_post() can touch the semaphore after a waiting
// thread have returned from sem_wait(). To avoid this race we are
// forcing the waiting thread to acquire/release the lock held by the
// posting thread. https://sourceware.org/bugzilla/show_bug.cgi?id=12674
MonitorLockerEx ml(&_monitor, Monitor::_no_safepoint_check_flag);
}
}
消息消费者负责消费队列中的消息,如果是异步消息,则直接读取类变量_message。
zMessagePort.inline.hpp
template
inline T ZMessagePort::receive() {
MonitorLockerEx ml(&_monitor, Monitor::_no_safepoint_check_flag);
// Wait for message
while (!_has_message && _queue.is_empty()) {
ml.wait(Monitor::_no_safepoint_check_flag);
}
// Increment request sequence number
_seqnum++;
if (!_has_message) {
// Message available in the queue
_message = _queue.first()->message();
_has_message = true;
}
return _message;
}
ZDriver启动一个线程,死循环判断是否应该启动gc cycle
zDriver.cpp
void ZDriver::run_service() {
// Main loop
while (!should_terminate()) {
const GCCause::Cause cause = start_gc_cycle();
if (cause != GCCause::_no_gc) {
run_gc_cycle(cause);
end_gc_cycle();
}
}
}
GCCause::Cause ZDriver::start_gc_cycle() {
// Wait for GC request
return _gc_cycle_port.receive();
}
void ZDriver::end_gc_cycle() {
// Notify GC cycle completed
_gc_cycle_port.ack();
// Check for out of memory condition
ZHeap::heap()->check_out_of_memory();
}
run_gc_cycle中,顺序执行GC的11个子阶段。
zDriver.cpp
void ZDriver::run_gc_cycle(GCCause::Cause cause) {
ZDriverCycleScope scope(cause);
// Phase 1: Pause Mark Start
{
ZMarkStartClosure cl;
vm_operation(&cl);
}
// Phase 2: Concurrent Mark
{
ZStatTimer timer(ZPhaseConcurrentMark);
ZHeap::heap()->mark(true /* initial */);
}
// Phase 3: Pause Mark End
{
ZMarkEndClosure cl;
while (!vm_operation(&cl)) {
// Phase 3.5: Concurrent Mark Continue
ZStatTimer timer(ZPhaseConcurrentMarkContinue);
ZHeap::heap()->mark(false /* initial */);
}
}
// Phase 4: Concurrent Process Non-Strong References
{
ZStatTimer timer(ZPhaseConcurrentProcessNonStrongReferences);
ZHeap::heap()->process_non_strong_references();
}
// Phase 5: Concurrent Reset Relocation Set
{
ZStatTimer timer(ZPhaseConcurrentResetRelocationSet);
ZHeap::heap()->reset_relocation_set();
}
// Phase 6: Concurrent Destroy Detached Pages
{
ZStatTimer timer(ZPhaseConcurrentDestroyDetachedPages);
ZHeap::heap()->destroy_detached_pages();
}
// Phase 7: Pause Verify
if (VerifyBeforeGC || VerifyDuringGC || VerifyAfterGC) {
ZVerifyClosure cl;
vm_operation(&cl);
}
// Phase 8: Concurrent Select Relocation Set
{
ZStatTimer timer(ZPhaseConcurrentSelectRelocationSet);
ZHeap::heap()->select_relocation_set();
}
// Phase 9: Concurrent Prepare Relocation Set
{
ZStatTimer timer(ZPhaseConcurrentPrepareRelocationSet);
ZHeap::heap()->prepare_relocation_set();
}
// Phase 10: Pause Relocate Start
{
ZRelocateStartClosure cl;
vm_operation(&cl);
}
// Phase 11: Concurrent Relocate
{
ZStatTimer timer(ZPhaseConcurrentRelocated);
ZHeap::heap()->relocate();
}
}
OpenJDK 12 源代码