代碼圖片來自:https://blog.csdn.net/qq_31865983/article/details/103788358
VM_Thread 就是大家平時說的 JVM線程,只有一個實例,也就是虛擬機創建過程中只會被創建一次(C++層面),並且在虛擬機銷毀的時候被銷毀
具體的作用是 開啟一個無限循環(while (true)), 然后不斷地從一個 VM_Operation 隊列中取出 VM_Operation 並且執行,如果沒有 VM_Operation 就等待一會
VM_Operation 是通過其他線程 放入到隊列中的,所以類似 生產者-消費者 模式。VM_Operation 有許多種,大概有四類
從注釋上看,應該都是一些堆內存的分配操作?
細分的話,具體操作如下:

#define VM_OP_ENUM(type) VMOp_##type, // Note: When new VM_XXX comes up, add 'XXX' to the template table. #define VM_OPS_DO(template) \ template(Dummy) \ template(ThreadStop) \ template(ThreadDump) \ template(PrintThreads) \ template(FindDeadlocks) \ template(ForceSafepoint) \ template(ForceAsyncSafepoint) \ template(Deoptimize) \ template(DeoptimizeFrame) \ template(DeoptimizeAll) \ template(ZombieAll) \ template(UnlinkSymbols) \ template(Verify) \ template(PrintJNI) \ template(HeapDumper) \ template(DeoptimizeTheWorld) \ template(CollectForMetadataAllocation) \ template(GC_HeapInspection) \ template(GenCollectFull) \ template(GenCollectFullConcurrent) \ template(GenCollectForAllocation) \ template(ParallelGCFailedAllocation) \ template(ParallelGCSystemGC) \ template(CGC_Operation) \ template(CMS_Initial_Mark) \ template(CMS_Final_Remark) \ template(G1CollectFull) \ template(G1CollectForAllocation) \ template(G1IncCollectionPause) \ template(DestroyAllocationContext) \ template(EnableBiasedLocking) \ template(RevokeBias) \ template(BulkRevokeBias) \ template(PopulateDumpSharedSpace) \ template(JNIFunctionTableCopier) \ template(RedefineClasses) \ template(GetOwnedMonitorInfo) \ template(GetObjectMonitorUsage) \ template(GetCurrentContendedMonitor) \ template(GetStackTrace) \ template(GetMultipleStackTraces) \ template(GetAllStackTraces) \ template(GetThreadListStackTraces) \ template(GetFrameCount) \ template(GetFrameLocation) \ template(ChangeBreakpoints) \ template(GetOrSetLocal) \ template(GetCurrentLocation) \ template(EnterInterpOnlyMode) \ template(ChangeSingleStep) \ template(HeapWalkOperation) \ template(HeapIterateOperation) \ template(ReportJavaOutOfMemory) \ template(JFRCheckpoint) \ template(Exit) \ template(LinuxDllLoad) \ template(RotateGCLog) \ template(WhiteBoxOperation) \ template(ClassLoaderStatsOperation) \
比較值得注意的是 加載Linux 的 動態鏈接庫:
比較重要的就是GC操作:
每個線程通過 VMThread::execute 把 VM_Operation 放入隊列的之前會通過doit_prologue方法做檢查,檢查是否能把這個 VM_Operation 放入隊列。
因為VM_Operation有可能會被多個Java線程入隊,但是實際上只用一個入隊就夠了。
有一種比較典型的情況就是GC操作可能會被多個Java線程入隊,但實際只用GC一次就夠了。
實際執行 VM_Operation 是在 VM_Operation::evaluate 中
具體過程偽代碼:
Java方法投遞該VM_operation
VMThread::execute (VM_Operation op)
不是 VM_Thread來執行投遞方法:
if (op::doit_prologue()) {
enqueue(op);
op::doit_epilogue();
}
如果是VM_Thread的話,可以直接執行evaluate方法

void VMThread::execute(VM_Operation* op) { Thread* t = Thread::current(); if (!t->is_VM_thread()) { SkipGCALot sgcalot(t); // avoid re-entrant attempts to gc-a-lot // JavaThread or WatcherThread bool concurrent = op->evaluate_concurrently(); // only blocking VM operations need to verify the caller's safepoint state: if (!concurrent) { t->check_for_valid_safepoint_state(true); } // New request from Java thread, evaluate prologue if (!op->doit_prologue()) { return; // op was cancelled } // Setup VM_operations for execution op->set_calling_thread(t, Thread::get_priority(t)); // It does not make sense to execute the epilogue, if the VM operation object is getting // deallocated by the VM thread. bool execute_epilog = !op->is_cheap_allocated(); assert(!concurrent || op->is_cheap_allocated(), "concurrent => cheap_allocated"); // Get ticket number for non-concurrent VM operations int ticket = 0; if (!concurrent) { ticket = t->vm_operation_ticket(); } // Add VM operation to list of waiting threads. We are guaranteed not to block while holding the // VMOperationQueue_lock, so we can block without a safepoint check. This allows vm operation requests // to be queued up during a safepoint synchronization. { VMOperationQueue_lock->lock_without_safepoint_check(); bool ok = _vm_queue->add(op); op->set_timestamp(os::javaTimeMillis()); VMOperationQueue_lock->notify(); VMOperationQueue_lock->unlock(); // VM_Operation got skipped if (!ok) { assert(concurrent, "can only skip concurrent tasks"); if (op->is_cheap_allocated()) delete op; return; } } if (!concurrent) { // Wait for completion of request (non-concurrent) // Note: only a JavaThread triggers the safepoint check when locking MutexLocker mu(VMOperationRequest_lock); while(t->vm_operation_completed_count() < ticket) { VMOperationRequest_lock->wait(!t->is_Java_thread()); } } if (execute_epilog) { op->doit_epilogue(); } } else { // invoked by VM thread; usually nested VM operation assert(t->is_VM_thread(), "must be a VM thread"); VM_Operation* prev_vm_operation = vm_operation(); if (prev_vm_operation != NULL) { // Check the VM operation allows nested VM operation. This normally not the case, e.g., the compiler // does not allow nested scavenges or compiles. if (!prev_vm_operation->allow_nested_vm_operations()) { fatal(err_msg("Nested VM operation %s requested by operation %s", op->name(), vm_operation()->name())); } op->set_calling_thread(prev_vm_operation->calling_thread(), prev_vm_operation->priority()); } EventMark em("Executing %s VM operation: %s", prev_vm_operation ? "nested" : "", op->name()); // Release all internal handles after operation is evaluated HandleMark hm(t); _cur_vm_operation = op; if (op->evaluate_at_safepoint() && !SafepointSynchronize::is_at_safepoint()) { SafepointSynchronize::begin(); op->evaluate(); SafepointSynchronize::end(); } else { op->evaluate(); } // Free memory if needed if (op->is_cheap_allocated()) delete op; _cur_vm_operation = prev_vm_operation; } }
進入隊列之后的 op 們,會在 VM_Thread run方法 的 loop 循環中被取出執行,當然,這個隊列被取出時要加鎖 MutexLockerEx(具體通過pthread_cond_wait等pthread庫函數實現)
run方法是在新的操作系統線程中執行的。
具體在Threads::create_vm中體現:
具體os是怎么開始run方法的?
起始是有一個 叫 java_start 的方法,調用了 run 方法
然后 os_start 調用 pthread_start 創建一個操作系統層面的線程去執行 java_start