本文介绍KVM的终止流程.其是在StartJVM方法中调用的.代码如下:
int StartJVM(int argc, char* argv[])
{
volatile int returnValue = 0;
/* Ensure that we have a class to run 必须提供要运行的类名 */
if (argc <= 0 || argv[0] == NULL) {
AlertUser(KVM_MSG_MUST_PROVIDE_CLASS_NAME);
return -1;
}
// 启动KVM
returnValue = KVM_Start(argc, argv);
KVM_Cleanup();
return returnValue;
}
而KVM_Cleanup的代码如下:
void KVM_Cleanup()
{
#if ENABLE_JAVA_DEBUGGER
if (vmDebugReady) {
setEvent_VMDeath();
CloseDebugger();
clearAllBreakpoints();
}
#endif
FinalizeVM();// 此处为宏
FinalizeInlineCaching(); // 释放InlineCache
FinalizeNativeCode(); // 释放本地代码,在unix环境为空方法
FinalizeJavaSystemClasses(); // 释放类
FinalizeClassLoading();// 释放ClassPathTable
FinalizeMemoryManagement();// 释放堆
DestroyROMImage();// 此处为宏
FinalizeHashtables(); // 释放UTFStringTable,InternStringTable,ClassTable
}
此处的有效步骤如下:
- 释放InlineCache,这点在kvm-inlineCache
- 释放类
- 释放ClassPathTable
- 释放堆
- 释放UTFStringTable,InternStringTable,ClassTable
释放类
代码如下:
void FinalizeJavaSystemClasses()
{
if (ROMIZING) {
FinalizeROMImage();
FOR_ALL_CLASSES(clazz)
/* Remove any class monitors */
if (OBJECT_HAS_MONITOR(clazz)) {// 1. 如果对象有锁,则清空锁对象
clearObjectMonitor((OBJECT)clazz);
}
if (!IS_ARRAY_CLASS(clazz)) {
/* Reset the state of the class to be its initial state.
* The ACC_ROM_NON_INIT_CLASS says that neither this class nor
* any of its superclasses has a <clinit> method
*/
INSTANCE_CLASS iclazz = ((INSTANCE_CLASS)clazz);
setClassInitialThread(iclazz, NULL); // 设置锁对象为Null
setClassStatus(iclazz,
(iclazz->clazz.accessFlags & ACC_ROM_NON_INIT_CLASS) ?
CLASS_READY : CLASS_VERIFIED); // 设置class状态
}
END_FOR_ALL_CLASSES
}
}
关于释放锁的详细内容,后续文章介绍.
释放ClassPathTable
代码如下:
void FinalizeClassLoading()
{
int paths = ClassPathTable->length;
int i;
for (i = 0; i < paths; i++) {
CLASS_PATH_ENTRY entry =
(CLASS_PATH_ENTRY)ClassPathTable->data[i].cellp;
if (entry->type == 'j') { // 如果是jar包,则需要关闭
closeJARFile(&entry->u.jarInfo);
}
}
}
void
closeJARFile(JAR_INFO entry)
{
#if JAR_FILES_USE_STDIO
fclose((FILE *)entry->u.jar.file);
#endif
}
关于这点,kvm中的class path支持目录,jar包.此处是对jar包的特殊处理.
释放堆
代码如下:
void FinalizeMemoryManagement(void) {
int i;
cellOrPointer *ptr, *endPtr;
/* When memory finalization is being performed */
/* the VM no longer has a CurrentThread. */
/* We need to fake it in order to support the */
/* code below. */
if (CurrentThread == NULL) {
CurrentThread = MainThread;
}
/* Check each known root to see if there are any instances
* to callback this callback (cb)
* 1. 调用finalizer方法
*/
for (i = CleanupRoots->length - 1; i >= 0; i--) {
WEAKPOINTERLIST list = (WEAKPOINTERLIST)CleanupRoots->data[i].cellp;
if (list != NULL) {
void (*finalizer)(INSTANCE_HANDLE) = list->finalizer;
if (finalizer != NULL) {// 调用finalizer方法
ptr = &list->data[0];
endPtr = ptr + list->length;
for ( ; ptr < endPtr; ptr++) {
INSTANCE object = (INSTANCE)(ptr->cellp);
if (object != NULL) {
/* 调用finalizer方法 */
finalizer((INSTANCE_HANDLE)&object);
}
}
/* Reset 'nativeLp' after calling all finalizers */
CurrentThread->nativeLp = NULL;
}
}
}
// 2. 清空GlobalRoots
ptr = &GlobalRoots[0];
endPtr = ptr + GlobalRootsLength;
for ( ; ptr < endPtr; ptr++) {
*(ptr->cellpp) = NULL;
}
// 3. 释放heap
FinalizeHeap();
if (USESTATIC) {// 此处默认不执行
FinalizeStaticMemory();
}
}
void FinalizeHeap(void)
{
freeHeap(TheHeap);
}
#define freeHeap(x) free(x)
同样,关于finalizer方法,也是后文介绍(此处有一处不解,故不敢乱写…).
释放UTFStringTable,InternStringTable,ClassTable
此处代码如下:
void FinalizeHashtables() {
if (!ROMIZING) {
UTFStringTable = NULL;
InternStringTable = NULL;
ClassTable = NULL;
}
}