• jvm安全退出


    很多时候我们需要在退出的时候能够保证内存中的数据得到处理,比如在写文件的时候程序要退出,此时如果直接退出的话会造成部分数据还没有持久化到文件中,从而造成数据丢失。为了解决这个问题,我们需要在程序退出的时候能够捕获到该消息,然后做一些数据清理操作,目前有两种方案:

    一种是采用SignalHandler类来进行相应的处理

    另外一种是在JVM里注册一个“关闭钩子”(shutdown hook)

    1、关于第一种方法,我们来看一个例子,代码如下:

    /**
     * 信号注册及捕捉处理类
     * @author xiaoxiao
     */
    @Component
    public class SignalHelper implements SignalHandler {
    
    	private Log log = LogFactory.getLog(getClass());
    	
    	@PostConstruct
    	public void registSignal() {
            //注意这里并不是什么消息都能捕获,像kill -9或者断电等退出操作就捕获不了,所以尽量少用kill -9
    		Signal.handle(new Signal("TERM"), this); //kill -15
    		Signal.handle(new Signal("INT"), this); //CRTL+C
    		log.info("注册信号成功");
    	}
    	
    	@Override
    	public void handle(Signal signal) { //捕捉信号,使程序优雅地退出
    		log.info("捕捉到信号:" + signal.getName());
    		new CleanerTask().run();
    		System.exit(0); //捕捉到终止信号若不调用exit方法,则程序不会退出
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    其中CleanerTask就是一个线程类,它里面会进行相应的数据清理操作,这个根据具体业务做相应操作,在程序启动的时候务必要执行registSignal函数,如果有退出信号,例如kill -15,此时就会执行handle函数。

    2、关于第二种方法,注册"关闭钩子",代码如下:

    AbstractApplicationContext ctx;
    // 加载spring配置文件
    ctx = new FileSystemXmlApplicationContext("mybean.xml");
    //为了在非web环境下让spring容器优雅的关闭
    ctx.registerShutdownHook();
    ctx.start();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这里之所以用钩子,主要是用来在程序退出的时候将IOC容器资源释放掉,像web程序中自动会进行IOC容器资源释放,所以不需要我们做任何释放操作,但是在非web程序中,就不会自动释放spring中的IOC容器资源,所以需要我们手动进行释放资源。

    当然我们也可以实现自己的关闭钩子(关闭钩子可以有多个),示例代码如下:

    public class JVMHook {
    
     public static void start(){
      System.out.println("The JVM is started");
      Runtime.getRuntime().addShutdownHook(new Thread(){
       public void run(){
        try{
         //do something
         System.out.println("The JVM Hook is execute");
        }catch (Exception e) {
         e.printStackTrace();
        }
       }
      });
     }
     
     public static void main(String[] args) {
      start();
      System.out.println("The Application is doing something");  
      try {
       Thread.sleep(3000);
      } catch (InterruptedException e) {
       e.printStackTrace();
      }
     }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    执行结果为:

    The JVM is started
    The Application is doing something
    The JVM Hook is execute

    参考文章:

    文章1

    文章2

  • 相关阅读:
    企业在数字化转型中可以实现的7个目标
    linux文件查看和文件查找
    LeetCode-102.题: 二叉树的层序遍历(原创)
    每日一练<4>
    springcloud14:gateway总结
    Mockito单元测试
    【MPU6050_DMP】dmp初始化校准设置,取消上电零度
    6763个gb2312汉字笔画分析
    [原创]九点标定工具之机械手头部相机标定
    Linux ARM平台开发系列讲解(摄像头V4L2子系统) 2.12.2 摄像头V4L2出图框架介绍
  • 原文地址:https://blog.csdn.net/m0_67401228/article/details/126744537