• 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

  • 相关阅读:
    【MindSpore易点通】网络构建经验总结中篇
    解决小程序中textarea ios端样式不兼容的方法
    主板与品牌电脑启动快捷键
    AAOS音频路由 问题分析
    盘点 | 好用的开发者IDE工具
    strongswan开源客户端项目排错运行
    Day09-尚品汇-路由传递参数结合会话存储
    devops-5:从0开始构建一条完成的CI CD流水线
    测试.net文字转语音模块System.Speech
    如何在 FastReport VCL 中通过 Outlook 发送和接收报告?
  • 原文地址:https://blog.csdn.net/m0_67401228/article/details/126744537