問題描述面試
如上圖所示程序,按道理,子線程會經過 num++ 操做破壞 while 循環的條件,從而終止循環,執行最後的輸出操做。但在個人屢次運行中,偶爾會出現 while 循環一直不結束的場合。像我截圖同樣,程序一直不終止,JDK七、JDK8 均已試驗,均能偶然觸發。
回覆segmentfault
[西湖の風]:變量前加個 volatile。緩存
[csyangchsh]:volatile 使用讀寫屏障強制刷新緩存,若是不加就由 CPU 決定什麼時候刷新。jvm
[sofkyle]:由 CPU 決定什麼時候刷新,那麼能夠認爲,終會有一個時機會去刷新,可是while卡在那一直不刷新。優化
[你假笨]:和 jit 也是有必定關係的,-Xint 設定解釋執行,也能夠只關閉 OSR 看看,-XX:-UseOnStackReplacement。ui
問題描述
咱們線上應用提供的服務接口忽然超時(dubbo服務接口調用耗時最大限制1s),發現gc.log在對應的時間進入了STW,耗時1.526s查看對應的vm.log發如今相對飲的時間有一個no vm operation提示,請教下:no vm operation,這個類型vm具體在作什麼操做啊?如何優化?lua
回覆spa
[你假笨]:safepoint並非必定要發生了某個VM_OP纔會進入的,VMThread自己的執行,就是不斷循環,看是否有必要進入safepoint,或者是否要執行一些VM_OP,能夠看下這塊代碼。線程
while (!should_terminate() && _cur_vm_operation == NULL) { // wait with a timeout to guarantee safepoints at regular intervals bool timedout = VMOperationQueue_lock->wait(Mutex::_no_safepoint_check_flag, GuaranteedSafepointInterval); // Support for self destruction if ((SelfDestructTimer != 0) && !is_error_reported() && (os::elapsedTime() > SelfDestructTimer * 60)) { tty->print_cr("VM self-destructed"); exit(-1); } if (timedout && (SafepointALot || SafepointSynchronize::is_cleanup_needed())) { MutexUnlockerEx mul(VMOperationQueue_lock, Mutex::_no_safepoint_check_flag); // Force a safepoint since we have not had one for at least // 'GuaranteedSafepointInterval' milliseconds. This will run all // the clean-up processing that needs to be done regularly at a // safepoint SafepointSynchronize::begin(); #ifdef ASSERT if (GCALotAtAllSafepoints) InterfaceSupport::check_gc_alot(); #endif SafepointSynchronize::end(); } _cur_vm_operation = _vm_queue->remove_next(); // If we are at a safepoint we will evaluate all the operations that // follow that also require a safepoint if (_cur_vm_operation != NULL && _cur_vm_operation->evaluate_at_safepoint()) { safepoint_ops = _vm_queue->drain_at_safepoint_priority(); } }
幾個關鍵的點,GuaranteedSafepointInterval,timedout,SafepointSynchronize::is_cleanup_needed()
若是上面條件知足,就會發生 no vm operation 的 safepoint 操做。code
問題描述
-XX:+UseCompressedOops -Xms5g -Xmx5g -XX:PermSize=256M -XX:MaxPermSize=1024m -XX:NewSize=3g -XX:MaxNewSize=3g -XX:+UseCMSInitiatingOccupancyOnly -XX:+PerfDataSaveToFile -XX:SurvivorRatio=10 -Xloggc:/data/dataLogs/gc/gc.log -verbose:gc -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:+CMSClassUnloadingEnabled -XX:+DisableExplicitGC -XX:CMSInitiatingOccupancyFraction=80 -XX:+HeapDumpOnOutOfMemoryError
如題,這是個人 jvm 參數,jstat採集到的ygc次數與mxbean是一致的,fgc的數量大概是mxbean統計到的兩倍,可是不到兩倍。
對於耗時,jstat採集到的不管是ygc仍是fgc均小於mxbean統計到的數據。
回覆
[Rookie_267692]:這是由於CMS收集器在MXBean是在每次發生FGC時只會在Sweeping統計一次,而jstat會在InitialMark階段統計一次,FinalMark階段統計一次,這樣發生一次CMS gc時就會統計兩次,因此次數不一致。
gc時間在MXBen中統計的是整個gc從開始到結束時間,jstat統計的是gc在每一個階段實際耗費的時間。
推薦閱讀 ZGC何時會進行垃圾回收
推薦閱讀 GC一些長時間停頓問題排查及解決辦法