首先,以后碰到任何jvm的错误,先看日志!!!!!!!!
web项目在tomcat目录下的log里,或者自己设定的errorfile目录下。总之,找到一切可以运用的日志,比如crash日志,coredump日志等,可以快速确定问题所在。
不过这次调查奇怪的很,不管是jvm还是tomcat,都没有任何错误日志报出。真让人难受。
经过学习,得知有一个linux命令可以助我一臂之力(感谢此命令) 那就是万能的sudo dmesg -T | grep "java"。果然,命令一出,效果空前,发现一条类似这样的错误。
localhost kernel: java: segfault at ip sp error 7 in libjvm.so
作为一个优秀的垃圾,我表示不懂这是啥(后来才知道,这就足够了啊。。。。),这条信息大概的意思如下。libjvm.so(共享动态库)运行时出现段错误。我就在想,这个error 7是什么意思?解读如下:
段错误中(segfault error),7是要解读为二进制的,即111 这个111每位对应如下:
1: 表示是用户态程序内存访问越界,值为0表示是内核态程序内存访问越界。
1: 表示是写操作导致内存访问越界,值为0表示是读操作导致内存访问越界。
0: 表示访问的非法地址根本没有对应的页面,也就是无效地址,值为1表示没有足够的权限访问非法地址的内容。
所以我的问题就是:用户态程序内存访问越界,写操作导致内存访问越界,没有足够的权限访问非法地址的内容。
好,问题放这里,开始我的吐槽。
从别人手中接手一个项目,起初说是不稳定,只要一运行某个程序,tomcat会直接死掉。然后这个人交给我后就跑路了,天真的我以为是个小活,因为以前只是有过一些jvm的基础知识,虽然这是第一次碰到真实情景,但是我垃圾人胆大(领导都说交给我了,我能不做?)所以我就欣(bei)然(po)接受了。
首先我阅读代码,理解业务逻辑。边理解代码边改动代码(边改边骂,这是魔鬼写的代码吗,错误太多,用法奇葩,即便不是后来发现的主要原因,程序原有的错误也真让人脑袋大)。
一天半以后,理解的差不多了,改的也差不多了,就开始我的头大之路。首先我怀疑是内存泄漏(所以说,一定要找到所有可用日志再去解决问题,唉,没经验),渣渣的我只想到了jconsole工具,好巧不巧的是,测试了两次,程序当掉的时候还都是survivor区炸掉。所以我就开始了调优。
同时jvm是被linux主动杀死的,接受了11信号,网上很多说有时候是因为程序内存占用过大导致系统自我保护而杀死进程,所以我深信不疑是内存问题了(当然了,搞了半天都白搞了)。如果有需要的可以看看,程序运行时的参数如下:-Xms128m -Xmx128m。然后还不行,还是会死,那我想啊,我的机器到底还剩了多少内存了?执行free -h 嘿嘿嘿 只剩下79M了。。。。
所以啊,我打算继续调优eclipse,毕竟开了eclipse之后,内存从1.2G锐减到79M。在eclipse的安装目录里,有个eclipse.ini配置文件,加入参数如下:
-Xms128m
-Xmx128m
-XX:PermSize=128m
-XX:MaxPermSize=128m
-XX:+UseParallelGC
进入eclipse后,进入window->preferences->general->startupandshutdown->取消所有启动项(如果只是简单的开发java及javaee)。
配置完之后发现,有点用,有效内存剩了300M了,同时启动好像也快了一点哦。(这并非最优配置,且不说每个机器配置不一样,我这个128m分配就很随意,等好好了解了我再更新)。
还是没有解决问题,嘿嘿嘿。怎么办呢,一行一行测试!是的,就是注释入口的所有代码,从第一行开始一行一行解注释,并且每次解注释运行2000次。办法虽笨,还真管用,最后定位到一个so动态库。
让c的小伙伴好好查错并重新生成,问题解决。。。。。。。
再贡献一点点
实在没有任何日志,可以进行如下办法:
(1)开启linux 的core文件生成,Core文件其实就是内存的映像,当程序崩溃时,存储内存的相应信息,主用用于对程序进行调试。
当程序崩溃时便会产生core文件,其实准确的应该说是core dump 文件,默认生成位置与可执行程序位于同一目录下,文件名为core.***,其中***是某一数字。
ulimit -c 0 关闭core生成
开启步骤:sudo vim /etc/profile 在末尾添加 ulimit -S -c unlimited >/dev/null 2>&1
(2)当程序意外被kill后,在程序目录或者根目录 会生成生成core.***文件。用 gdb java core.***进行调试。