今天在做定時任務的時候,遇到了一個比較難搞的問題,這個問題也比較有意思,現在給大家分享一下,這個定時任務的調用入口是這樣的。 // 進行 ldap同步 public void runLdapSyncJob(){ try { ldapSyncService.syncLdap(); } catch (E ...
今天在做定時任務的時候,遇到了一個比較難搞的問題,這個問題也比較有意思,現在給大家分享一下,這個定時任務的調用入口是這樣的。
// 進行 ldap同步
public void runLdapSyncJob(){
try {
ldapSyncService.syncLdap();
} catch (Exception e) {
e.printStackTrace();
}
}
這個方法ldapSyncService.syncLdap()向外拋出異常,這個方法內部會調用另一個方法
/**
* 創建部門目錄並返回部門cn
* @param departmentDtoMap
* @param targetDepartId
* @param rootCn
* @return
* @throws Exception
*/
public String creatStaffDepartCN(Map<Long,DepartmentDto> departmentDtoMap ,long targetDepartId,String rootCn, Set<String> ldapDUSet ) throws Exception {}
但是傳入的參數中,第二個參數傳入的是Long類型,而且是null,一開始沒排查出來,因為一直加日誌,在調用處,數據返回處,數據驗證處都加日誌了,但是通過定時任務管理平臺執行任務之後方法執行到一定行數就什麼也沒有了,也沒有日誌,懷疑是可能有死迴圈(程式里寫了while)結果top一下,發現cpu,記憶體都很正常,結合之前遇到的這種情況也看了下這個定時任務的進程中線程狀態,看看有沒有blocked或者死鎖(單線程操作應該不會有死鎖),發現也沒有。
這就尷尬了,於是想到了可能異常被框架或者jvm吃掉了,於是在上面兩個方法里都加了try,catch
ldapSyncService.syncLdap() throws Exception{
try{
......
}catch(Exception e){
e.print();
}
}
creatStaffDepartCN() throws Exception{
try{
......
}catch(Exception e){
e.print();
}
}
再次部署執行之後發現確實有異常了,然後拋出了空指針,這裡我恍然大悟,因為creatStaffDepartCN這個方法的第二個入參確實沒有值傳進去的。然後懷疑是否是因為自動裝箱和拆箱過程中即使出現異常也會被jvm吃掉。本地簡單寫了一個demo,運行發現會報空指針。
這裡沒有列印異常我判斷有下麵幾種可能
1.定時任務框架沒有幫忙拋出。
2.最外層的try,catch沒有生效
3.jvm把異常吃掉了
下麵總結一下遇到程式日誌停止滾動之後我們可以做的一些操作
1.top看是否由於FGC等問題導致的服務停止響應
2.jstack -l pid看一下進程內線程是否大量有blocked狀態的線程
3.在日誌停止滾動的代碼上下文增加try,catch語句嘗試捕獲異常。
本文由博客一文多發平臺 OpenWrite 發佈!
架構設計@工程設計@服務穩定性之路