今天在作定时任务的时候,遇到了一个比较难搞的问题,这个问题也比较有意思,如今给你们分享一下,这个定时任务的调用入口是这样的。架构
// 进行 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();
}
}jvm
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 发布!
架构设计@工程设计@服务稳定性之路指针