Linux下优雅关闭Java程序

最近用maven工程的形式打jar包写一个小型服务器,于是希望提供脚本的形式启动和关闭服务器。

网上浏览到一些文章,基本思路是:

1.在start.sh中启动Java程序,保存pid到文件server.pid

2.在shutdown.sh中使用 kill -9 pid 的形式杀死Java进程

问题是:kill -9 pid 会强制杀死进程,而我的需求是,在程序退出前,执行一些清理操作,比如将缓存存库。

下面来介绍如何实现“优雅”地关闭Java程序。

基于信号的进程通知机制

不难理解,我们要关闭的Java程序,就是操作系统中的一个进程。在杀死进程前,我们要执行一些操作,所以涉及到进程通信的问题。

信号是进程通信的一种手段,可以理解为事件机制,当进程接受到一个特定类型的信号,就会执行相应的逻辑处理。

Linux的信号类型如下:

Linux下优雅关闭Java程序_第1张图片

通过相应的信号,通知相应的Java程序进程(一个jvm实例),从而Java程序可以在程序终止前执行一些逻辑处理。

如何使用信号:

Linux环境下 kill -12 pid  会发送SIGUSR2类型的信号到pid对应的进程

Java代码响应信号

为了响应信号,我们要用到两个类:

sun.misc.Signal:代表信号

sun.misc.SignalHandler:响应信号的接口

这两个类来自sun.misc包,这个包下的类是设计被jdk类库使用的,所以代码提示不会出现这两个类,需要手动import,并且编译器会发出警告。

示例代码:


Linux下优雅关闭Java程序_第2张图片

Linux下优雅关闭Java程序_第3张图片

关于ShutdownHook

在上面的handle方法中,我执行了exit()方法,是为了触发ShowdownHook线程。

jdk提供了一个钩子方法,从而在程序终止时,在一个独立的线程中执行终止逻辑。注册ShowdownHook方式如下:


然后当执行System.exit(),或其他非强制方式去关闭Java程序时,该方法会被执行。

测试Signal

通过maven打jar包,我的jar包名称是:

Linux下优雅关闭Java程序_第4张图片

测试过程:

1.后台模式启动Java程序,重定向输出到test.log


可以看到进程启动成功,pid为45393

2.kill -12 45393 ,和Java进程进行信号通信,从而触发SignalHandler执行


可以看到ShutdownHook线程中代码被执行,程序优雅终止完成!

当然,还有最后一步,写shell脚本,完成程序启动和优雅关闭,关于这点,可以看下面的参考文章,结合上述优雅终止的方式,写出相应的shell脚本。

参考:

signal:

https://blog.csdn.net/u011001084/article/details/73480432

https://blog.csdn.net/carlislelee/article/details/52688693

maven:

https://blog.csdn.net/xiao__gui/article/details/47341385

shell脚本:

https://blog.csdn.net/e_wsq/article/details/51767165

https://blog.csdn.net/clerk0324/article/details/50593882

你可能感兴趣的:(Java基础,Linux)