Oops~ 今天写下今天遇到的问题,相信众位程序员一定也有遇到的--linux下shutdown关闭不掉tomcat问题。
首先描述下遇到的情况。当多次启动tomcat后,发现在系统下有类似于这样的日志文件或者输入任何命令都会抛出一堆balabala的东西,打开日志会发现报告内存不足等乱七八糟的东西(造成的原因有不少,其中内存不够用应该是大多数遇到的情况),输入free -m 后,如果你发现是内存不够用了,当然这时候你可能还不知道是因为tomcat未关闭造成的原因,你会一个一个排查,然并卵。如果你的机子上有运行过或正在运行的tomcat,那么不妨输入ps -ef|grep tomcat,你可能会发现有N个未关闭 的tomcat进程,ok一个一个kill掉就好,那么接下来的问题又来了,每次都手动kill掉会很不爽,接下来就是本文要解决的问题了。上面说了一堆废话,O(∩_∩)O哈哈哈~,不爽请喷。
解决问题的办法:
方法一:从tomcat下项目入手,一般造成这种原因是因为项目中有非守护线程的存在。那么怎么找到改线程呢,请看下面:
12126即为pid,继续输入jstack 12126会看到如下一堆balabala的东西:
你可能会遇到下面的状况(俺遇到的不是,下面的状况是从别人那转过来的)
其中主线程不是daemon的,所以是这样:
"main" prio=10 tid=0xb6d05000 nid=0x5ea runnable [0xb6ee9000]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:408)
- locked <0x871644a8> (a java.net.SocksSocketImpl)
at java.net.ServerSocket.implAccept(ServerSocket.java:462)
at java.net.ServerSocket.accept(ServerSocket.java:430)
at org.apache.catalina.core.StandardServer.await(StandardServer.java:431)
at org.apache.catalina.startup.Catalina.await(Catalina.java:676)
at org.apache.catalina.startup.Catalina.start(Catalina.java:628)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)
在"main" 后没有daemon,看到这样的线程状态,顺藤摸瓜,找到对应new Thread的地方setDaemon(true)就可以,痛痛快快的shutdown了:)
你也可能会看到类似下面的状况(我遇到的就是这种情况):
如果你看到类似于"DestroyJavaVM" prio=10 balabala的东西,那么恭喜你,你的程序可能出现了死锁,关于死锁方面的资料可以看着这篇文章点击打开链接看下,这里就不多做介绍了。继续往下看如果发现有waiting on condition等字样说明你的程序如果发现有大量的线程都在处在 Wait on condition,从线程 stack看, 正等待网络读写,这可能是一个网络瓶颈的征兆。因为网络阻塞导致线程无法执行。一种情况是网络非常忙,几乎消耗了所有的带宽,仍然有大量数据等待网络读写;另一种情况也可能是网络空闲,但由于路由等问题,导致包无法正常的到达。所以要结合系统的一些性能观察工具来综合分析,比如 netstat统计单位时间的发送包的数目,如果很明显超过了所在网络带宽的限制 ; 观察 cpu的利用率,如果系统态的 CPU时间,相对于用户态的 CPU时间比例较高;如果程序运行在 Solaris 10平台上,可以用 dtrace工具看系统调用的情况,如果观察到 read/write的系统调用的次数或者运行时间遥遥领先;这些都指向由于网络带宽所限导致的网络瓶颈。另外一种出现 Wait on condition的常见情况是该线程在 sleep,等待 sleep的时间到了时候,将被唤醒。 前面蓝色字体是度娘百出来的结果。详细请点击打开链接。好既然已找到问题所在了,那么接下来就叫给你自己解决了。
ok,上面的办法肯定可以解决也是最应该用的办法,但是我相信很对于很多人尤其是入行不太久的看到这里,应该还是乱乱的,尝试还是解决不掉。没有关系,下面再介绍一种强制关闭tomcat的方法:
方法二:基本原理为启动tomcat时记录启动tomcat的进程id(pid),关闭时强制杀死该进程
1.找到tomcat下bin/catalina.sh文件,vi进去添加点东西,主要是记录tomcat的pid,如下:
大概在第125行左右,添加如下代码
#设置CATALINA_PID(后加)
if [ -z "$CATALINA_PID" ]; then
CATALINA_PID=$PRGDIR/CATALINA_PID
cat $CATALINA_PID
fi
保存即可。
2.vi进shutdown.sh文件,在最后一行如下红圈-force:
保存即可.
ok,好了上面即为强制关闭tomcat。希望能帮到你。