kvm垃圾收集-002

it2022-05-05  279

本文我们来介绍kvm中的垃圾收集器的实现.其算法为mark-and-sweep(含有压缩功能).其方法为garbageCollect.代码如下:

void garbageCollect(int moreMemory) { #if INCLUDEDEBUGCODE int beforeCollection = 0; int afterCollection = 0; #endif // 1. 如果gcInProgress 不等于0,就意味着当前正在gc中,如果循环调用gc是不允许的 if (gcInProgress != 0) { fatalVMError(KVM_MSG_CIRCULAR_GC_INVOCATION); } // 修改gc标记位 gcInProgress++; // 2. 等待异步线程执行完毕 RundownAsynchronousFunctions(); if (ENABLEPROFILING && INCLUDEDEBUGCODE) { checkHeap(); } #if INCLUDEDEBUGCODE if ((tracegarbagecollection || tracegarbagecollectionverbose) && !TERSE_MESSAGES) { Log->startGC(); } #endif #if INCLUDEDEBUGCODE if (ENABLEPROFILING || tracegarbagecollection || tracegarbagecollectionverbose) { beforeCollection = memoryFree(); } #endif MonitorCache = NULL; /* Clear any temporary monitors */ // 3. 在gc前 保存执行环境 if (CurrentThread) { storeExecutionEnvironment(CurrentThread); } // 4. 执行gc garbageCollectForReal(moreMemory); // 5. 在gc执行后,恢复执行环境 if (CurrentThread) { loadExecutionEnvironment(CurrentThread); } #if INCLUDEDEBUGCODE if (ENABLEPROFILING || tracegarbagecollection || tracegarbagecollectionverbose) { afterCollection = memoryFree(); #if ENABLEPROFILING GarbageCollectionCounter += 1; DynamicDeallocationCounter += (afterCollection - beforeCollection); #endif if (tracegarbagecollection || tracegarbagecollectionverbose) { Log->endGC(afterCollection - beforeCollection, afterCollection, getHeapSize()); } } #endif /* INCLUDEDEBUGCODE */ // 6. 重新启动异步线程 RestartAsynchronousFunctions(); // 7. 重置gc标记位 gcInProgress = 0; }

其中参数为垃圾收集后所期望的可用内存大小.

步骤如下:

如果gcInProgress 不等于0,就意味着当前正在gc中,如果循环调用gc是不允许的.并修改gc标记位.等待异步线程执行完毕在gc前 保存执行环境执行gc,关于此处,下文介绍在gc执行后,恢复执行环境重新启动异步线程重置gc标记位

其中第二步代码如下:

void RundownAsynchronousFunctions(void) { for (;;) { if (collectorIsRunning) { fatalError(KVM_MSG_COLLECTOR_RUNNING_IN_RUNDOWNASYNCHRONOUSFUNCTIONS); } START_CRITICAL_SECTION if (AsyncThreadCount == 0) { collectorIsRunning = TRUE; } END_CRITICAL_SECTION if (collectorIsRunning) { break; } /* Wait */ Yield_md(); } }

通过循环等待异步线程执行完毕.其中START_CRITICAL_SECTION, END_CRITICAL_SECTION为宏.定义如下:

void enterSystemCriticalSection(void); void exitSystemCriticalSection(void); #define START_CRITICAL_SECTION { enterSystemCriticalSection(); #define END_CRITICAL_SECTION exitSystemCriticalSection(); }

可见,此处是线程锁.关于这点,可以参考如下链接:

线程锁的概念函数EnterCriticalSection和LeaveCriticalSection的用法


在gc前保存执行环境的代码如下:

void storeExecutionEnvironment(THREAD thisThread) { // 将当前线程的执行环境(vm 所使用的寄存器)保存到THREAD中 thisThread->fpStore = getFP(); thisThread->spStore = getSP(); thisThread->ipStore = getIP(); }

与之所对应的就是恢复执行环境,其代码如下:

void loadExecutionEnvironment(THREAD thisThread) { // 恢复线程执行环境 setFP(thisThread->fpStore); setLP(FRAMELOCALS(getFP())); setCP(getFP()->thisMethod->ofClass->constPool); setSP(thisThread->spStore); setIP(thisThread->ipStore); }

重新启动异步线程的代码如下:

void RestartAsynchronousFunctions(void) { if (!collectorIsRunning) { fatalError(KVM_MSG_COLLECTOR_NOT_RUNNING_ON_ENTRY_TO_RESTARTASYNCHRONOUSFUNCTIONS); } collectorIsRunning = FALSE; }

最新回复(0)