安全发布之Jvm友好关闭


声明:本文转载自https://my.oschina.net/qixiaobo025/blog/1031140,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

小伙伴们一定很熟悉kill -9 来杀某个进程了,其实这样做在生产系统中是存在安全隐患的。

我们知道线程分为守护线程和用户线程。如果是系统中存在的均是守护线程,那么调用JVM的关闭讲课以关闭否则(存在至少一个用户线程)是无法正常关闭的。

因此代码能否响应中断是一个很重要的标志。

我们熟悉的Java的GC线程

就是一个很典型的守护线程。

各位在关闭tomcat时,在使用到线程池时经常会碰到调用tomcat的关闭脚本无法正常关闭就是因为系统中存在一些非守护线程导致无法正常退出导致。

那么各位可能想了,我将所有的线程池起的线程都设置为守护线程那么在调用shutdown的时候是否时就会正常关闭呢?

thread.setDaemon(true);

答案是肯定的,但是带来一个其他的问题===》如果此时代码只执行了一半那么怎么处理呢?比如你消费了一个jms的消息,但是没有消费完成,然后‘砰’所有的线程灰飞烟灭,恰巧这个消息里面是个1000w的大单……

严重: The web application [] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.  2013-1-8 15:02:53 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads  严重: The web application [] appears to have started a thread named [Thread-2] but has failed to stop it. This is very likely to create a memory leak.  2013-1-8 15:02:53 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads  严重: The web application [] appears to have started a thread named [thread-snatch-picture] but has failed to stop it. This is very likely to create a memory leak.  2013-1-8 15:02:53 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads  严重: The web application [] appears to have started a thread named [Xmemcached-Reactor-0] but has failed to stop it. This is very likely to create a memory leak.  2013-1-8 15:02:53 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads  严重: The web application [] appears to have started a thread named [Xmemcached-Reactor-1] but has failed to stop it. This is very likely to create a memory leak.  2013-1-8 15:02:53 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads  严重: The web application [] appears to have started a thread named [Xmemcached-Reactor-2] but has failed to stop it. This is very likely to create a memory leak.  2013-1-8 15:02:53 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads  严重: The web application [] appears to have started a thread named [Xmemcached-Reactor-3] but has failed to stop it. This is very likely to create a memory leak.  

通常我们调用tomcat关闭脚本如果没有关闭那么log重可能吐出类似下面的日志

某些小伙伴还可能看到如下的log

Exception in thread "Xmemcached-Reactor-3" java.lang.NoClassDefFoundError: org/apache/log4j/spi/ThrowableInformation  at org.apache.log4j.spi.LoggingEvent.(LoggingEvent.java:159)  at org.apache.log4j.Category.forcedLog(Category.java:391)  at org.apache.log4j.Category.log(Category.java:856)  at org.slf4j.impl.Log4jLoggerAdapter.info(Log4jLoggerAdapter.java:382)  at com.captaindebug.longpoll.service.DeferredResultService.run(DeferredResultService.java:75)  at java.lang.Thread.run(Thread.java:722) Caused by: java.lang.ClassNotFoundException: org.apache.log4j.spi.ThrowableInformation  at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1714)  at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)  ... 6 more

上述的原因是由于出现类卸载之后使用了一些已经不存在类加载器的类导致报错

小伙伴可能觉得太Easy了,怎么能难道有一定经验的开发小伙伴呢?

kill -9 `ps -ef|grep <tomcat>|awk '{print $2}'`

当然下次启动时没有问题了,但是可能就导致某些消费没有完成。

本篇重点来了 ShutDownHook 顾名思义这是在Jvm关闭时的钩子函数

“一个shutdown hook就是一个初始化但没有启动的线程。 当虚拟机开始执行关闭程序时,它会启动所有已注册的shutdown hook(不按先后顺序)并且并发执行。”

比如我们查看一下tomcat的shutdownhook

/**  * Start a new server instance.  */ public void start() {       if (getServer() == null) {         load();     }       if (getServer() == null) {         log.fatal("Cannot start server. Server instance is not configured.");         return;     }       long t1 = System.nanoTime();       // Start the new server     try {         getServer().start();     } catch (LifecycleException e) {         log.fatal(sm.getString("catalina.serverStartFail"), e);         try {             getServer().destroy();         } catch (LifecycleException e1) {             log.debug("destroy() failed for failed Server ", e1);         }         return;     }       long t2 = System.nanoTime();     if(log.isInfoEnabled()) {         log.info("Server startup in " + ((t2 - t1) / 1000000) + " ms");     }       // Register shutdown hook     if (useShutdownHook) {         if (shutdownHook == null) {             shutdownHook = new CatalinaShutdownHook();         }         Runtime.getRuntime().addShutdownHook(shutdownHook);           // If JULI is being used, disable JULI's shutdown hook since         // shutdown hooks run in parallel and log messages may be lost         // if JULI's hook completes before the CatalinaShutdownHook()         LogManager logManager = LogManager.getLogManager();         if (logManager instanceof ClassLoaderLogManager) {             ((ClassLoaderLogManager) logManager).setUseShutdownHook(                     false);         }     }       if (await) {         await();         stop();     } }

再比如Dubbo中各个组件中

static {     Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {         public void run() {             if (logger.isInfoEnabled()) {                 logger.info("Run shutdown hook now.");             }             ProtocolConfig.destroyAll();         }     }, "DubboShutdownHook")); }

我们可以在对应使用清理Hook

本文发表于2017年06月27日 12:36
(c)注:本文转载自https://my.oschina.net/qixiaobo025/blog/1031140,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 2222 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1