Skip to content

Commit

Permalink
g1-gc-init 1
Browse files Browse the repository at this point in the history
  • Loading branch information
yoa1226 committed Oct 17, 2024
1 parent b3c48da commit b4db401
Showing 1 changed file with 256 additions and 5 deletions.
261 changes: 256 additions & 5 deletions _posts/2024-08-10-g1-gc-init.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ date: 2024-08-10 11:00:00 +0200
tags: [GC, G1]
---

[前文](https://yoa1226.github.io/2024/08/05/g1-gc-important-component.html) 介绍了 G1 非常重要多的重要概念,并介绍了相关的源码,这些概念在后续文章中会重复的提到。了解完成上述概念以后,本文将开始介绍堆初始化相关的内容。
[前文](https://yoa1226.github.io/2024/08/05/g1-gc-important-component.html) 介绍了 G1 非常重要多的重要概念,并介绍了相关的源码,这些概念在后续文章中会重复提到。本文将开始介绍堆初始化相关的内容,介绍 G1 中重要的组件

## 启动 JVM

Expand Down Expand Up @@ -95,7 +95,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
//omit
}
```
### Java 堆创建
## Java 堆创建
接着看找到 JVM 堆创建的代码
Expand All @@ -112,7 +112,7 @@ jint Universe::initialize_heap() {
G1CollectedHeap::initialize();
```

#### GC 类型选择
### GC 类型选择

未指定 GC 的情况下,JVM 通过 `select_gc_ergonomically` 函数在服务端模式默认选择 G1。

Expand All @@ -138,8 +138,259 @@ void GCConfig::select_gc_ergonomically() {
} else { /*omit*/ }
}
```
### G1CollectedHeap()
G1 堆属性很多,仅枚举比较重要的,具体逻辑使用时再次介绍。
```cpp
// Handle G1 NUMA support. 与 G1 numa 优化有关,
//详情见 JEP 345: NUMA-Aware Memory Allocation for G1
G1NUMA* _numa;
// The sequence of all heap regions in the heap.
//负责对堆中所有 region 进行管理
G1HeapRegionManager _hrm;
// Manages all allocations with regions except humongous object allocations.
// 分配器
G1Allocator* _allocator;
// The young region list.
G1EdenRegions _eden;
G1SurvivorRegions _survivor;
//cset
G1CollectionSet _collection_set;
//年轻代共享的记忆集
G1CardSet _young_regions_cardset;
//收集策略,回收过程保存一下统计信息,用于预测回收时间
G1Policy* _policy;
//GC 线程数
ParallelGCThreads;
//全局任务队列
_task_queues
```

## G1 堆初始化

## G1 堆组件
`initialize()` 初始化内部组件,此处只是枚举重要属性,特别重要的会在单独的小节介绍。

```cpp
//全局卡表,前面的文章介绍过
G1CardTable* ct = new G1CardTable(heap_rs.region());

//写屏障相关操作
G1BarrierSet* bs = new G1BarrierSet(ct);

//遍历记忆集相关
_rem_set = new G1RemSet(this, _card_table);

//GC 工作线程
_workers = new WorkerThreads("GC Thread", ParallelGCThreads);

//并发标记相关
_cm = new G1ConcurrentMark(this, bitmap_storage);
_cm_thread = _cm->cm_thread();

//GC 策略相关初始化
policy()->init(this, &_collection_set);

//处理 dirty card 线程
jint ecode = initialize_concurrent_refinement();

//负责协调异步任务的执行和后台的维护操作
ecode = initialize_service_thread();
_service_thread->register_task(_periodic_gc_task);
_service_thread->register_task(_free_arena_memory_task);

```
## G1 组件
### WorkerThreads
处理特定任务的线程池,用于 GC 收集和 并发标记。`_workers` 是实际的线程数据。
```cpp
_workers = new WorkerThreads("GC Thread", ParallelGCThreads);
_concurrent_workers = new WorkerThreads("G1 Conc", _max_concurrent_workers)
uint WorkerThreads::set_active_workers(uint num_workers) {
while (_created_workers < num_workers) {
WorkerThread* const worker = create_worker(_created_workers);
_workers[_created_workers] = worker;
}
}
```

`WorkerThread` 被创建完成以后就会执行 `run` 方法,阻塞在 `_start_semaphore` 等待被唤醒。

当任务执行完成则换醒分发任务的线程。

```cpp
void WorkerThread::run() {
while (true) { _dispatcher->worker_run_task(); }
}

void WorkerTaskDispatcher::worker_run_task() {
_start_semaphore.wait();

// Get and set worker id.
const uint worker_id = Atomic::fetch_then_add(&_started, 1u);
WorkerThread::set_worker_id(worker_id);

// Run task.
GCIdMark gc_id_mark(_task->gc_id()); //保存到工作线程,这里就是在日志中看到第几轮 GC 编号。

_task->work(worker_id);
const uint not_finished = Atomic::sub(&_not_finished, 1u);
if (not_finished == 0) { _end_semaphore.signal(); /*任务执行完成,唤醒分发任务的线程。*/ }
}
```

`coordinator_distribute_task` 负责任务的分发,唤醒任务线程,并且等待任务执行完成。

```cpp
void WorkerTaskDispatcher::coordinator_distribute_task(WorkerTask* task, uint num_workers) {
_task = task;
_not_finished = num_workers;

_start_semaphore.signal(num_workers);//唤醒任务线程
_end_semaphore.wait(); //等待任务执行完成

_task = nullptr;
_started = 0;
}
```
### WorkerTask
`WorkerTask` 是顶级接口,几乎所有的 GC 任务都继承它,并且重写 `work` 方法。
后续阅读源码时,可直接查看 `work` 方法的逻辑。
```cpp
class WorkerTask : public CHeapObj<mtInternal> {
const char* _name;
const uint _gc_id;
virtual void work(uint worker_id) = 0;
}
```

### G1ConcurrentMark

此类主要用于发标记阶段。

```cpp
G1ConcurrentMarkThread* _cm_thread; // The thread doing the work
// Concurrent marking support structures
G1CMBitMap _mark_bitmap

G1CMTask** _tasks; // Task queue array (max_worker_id length)
G1CMTaskQueueSet* _task_queues; // Task queue se

WorkerThreads* _concurrent_workers;
uint _num_concurrent_workers; // The number of marking worker threads we're using
uint _max_concurrent_workers; // Maximum number of marking worker thread>
```

_mark_bitmap:存储标记结果的 bitMap,1 bit 标记 8 bytes,它额外消耗堆内存的 1.5%(1/64)。
_concurrent_workers:工作线程前文已经说过。

#### G1ConcurrentMarkThread

负责并发标记的整体调度、任务分发

```cpp
//继承树 oncurrentGCThread<-NamedThread<-NonJavaThread<-Thread<-ThreadShadow
class G1ConcurrentMarkThread: public ConcurrentGCThread {
void run_service();
}
class ConcurrentGCThread: public NamedThread {
void ConcurrentGCThread::run() { run_service(); }
}

void G1ConcurrentMarkThread::run_service() {

while (wait_for_next_cycle()) { //等待被唤醒
concurrent_cycle_start();
concurrent_mark_cycle_do();
concurrent_cycle_end(_state == FullMark && !_cm->has_aborted());
}
}
//唤醒代码
//-> do_collection_pause_at_safepoint_helper()
//->start_concurrent_cycle()->CGC_lock->notify()
```
### G1ConcurrentRefine
此类负责处理异步处理 `dirty card`,`do_refinement_step` 是入口函数。`_dcqs` 是 `dirty card` 集合。
```cpp
class G1ConcurrentRefine : public CHeapObj<mtGC> {
G1DirtyCardQueueSet& _dcqs
G1ConcurrentRefineThreadControl _thread_control;
}
//->G1ConcurrentRefineThreadControl::initialize
//->create_refinement_thread
//-> G1ConcurrentRefineThread::create(_cr, worker_id);
//crt = ->new (std::nothrow) G1PrimaryConcurrentRefineThread(cr);
//-> crt->create_and_start()
class G1ConcurrentRefineThread: public ConcurrentGCThread {
void G1ConcurrentRefineThread::run_service() {
while (wait_for_completed_buffers()) {
SuspendibleThreadSetJoiner sts_join;
G1ConcurrentRefineStats active_stats_start = _refinement_stats;
while (!should_terminate()) {
if (sts_join.should_yield()) {
} else if (maybe_deactivate()) { break; }
else {
do_refinement_step(); //处理 dirty card
} } } } }
```

### G1ServiceThread

此类负责协调异步任务的执行和后台的维护操作

```cpp
class G1ServiceThread: public ConcurrentGCThread {
G1ServiceTaskQueue _task_queue;

void G1ServiceThread::run_service() {
while (true) {
G1ServiceTask* task = wait_for_task();
run_task(task);
} } }
//注册任务
_service_thread->register_task(_periodic_gc_task);
_service_thread->register_task(_free_arena_memory_task);
```
## 总结
本文从 JVM 启动到 G1 堆,介绍了 G1 重要组件,G1 重要非常多,余下的后续使用时再介绍。
## 总结

0 comments on commit b4db401

Please sign in to comment.