1、JVM正常关闭
直接看代码吧,
`public class Test { public void start(){ Runtime.getRuntime().addShutdownHook(new Thread(()-> System.out.println("钩子函数被执行,可以在这里关闭资源") )); } public static void main(String[] args) throws Exception{ new Test().start(); System.out.println("主应用程序在执行"); } } //控制台输出 //主应用程序在执行 //钩子函数被执行,可以在这里关闭资源 看控制台打印,可以发现,主应用程序执行完之后就会调用钩子函数,接下来就会正式的关闭JVM。 ### 2、异常关闭 还是直接看代码演示,这里我们演示异常关闭的第二种OOM的情况,我们可以先设置堆的大小为20M,然后在代码中创建一个500M的对象,这样就会OOM。参数是`-Xmx20M`;`public class Test { public void start(){ Runtime.getRuntime().addShutdownHook(new Thread(()-> System.out.println("钩子函数被执行,可以在这里关闭资源") )); } public static void main(String[] args) throws Exception{ new Test().start(); System.out.println("主应用程序在执行"); Runtime.getRuntime().halt(1); byte[] b = new byte[500*1024*1024]; } } //控制台输出 //主应用程序在执行 //钩子函数被执行,可以在这里关闭资源 从控制台可以看出,钩子函数在异常关闭的时候依然会被调用。 ### 3、强制关闭 这里我们使用`Runtime.getRuntime().halt()`来演示强势关闭。这个方法和`System.exit`的区别是,`System.exit`会执行钩子函数,但是`Runtime.getRuntime().halt()`不会。`public class Test { public void start(){ Runtime.getRuntime().addShutdownHook(new Thread(()-> System.out.println("钩子函数被执行,可以在这里关闭资源" > **《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》** > > **【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享** ) )); } public static void main(String[] args) throws Exception{ new Test().start(); System.out.println("主应用程序在执行"); Runtime.getRuntime().halt(1); } } //控制台输出 //主应用程序在执行 从上面代码的输出可以看出,调用了`Runtime.getRuntime().halt(1)`就会强制关闭JVM,钩子函数来不及执行就关闭了。而使用`System.exit`依然会执行。所以一般使用`System.exit`来关闭JVM。 ### 4、移除钩子函数 上面演示了钩子函数的作用,有时候我们想移除也比较简单。`public class Test { public static void main(String[] args) throws Exception{ //new Test().start(); Thread willNotRun = new Thread(() -> System.out.println("Won't run!")); Runtime.getRuntime().addShutdownHook(willNotRun); System.out.println("主应用程序在执行"); Runtime.getRuntime().removeShutdownHook(willNotRun); } } //控制台输出 //主应用程序在执行 OK,钩子函数的基本操作就写到这,使用起来比较简单,不过我之前看过Spring的启动流程,所以又去那个启动流程看了一波,发现也使用到了钩子函数。 ## 二、典型应用场景 ### 1、Spring使用 Spring在关闭上下文的时候,可以使用钩子函数来关闭残留的资源。方法是使用`ApplicationContext`注册一个钩子函数即可。`ApplicationContext.registerShutdownHook(); //上面的这句代码可以分析进去看看