20190304 记线上程序跑着跑着挂掉了

前言

公司线上的一个war程序,跑着跑着挂掉了。有点慌,因为找不到问题所在,也担心下次又出现这个问题。总不是每次都通过重启来解决吧?于是各种搜索,也因此了解到了一些新的东西,如visualVm。接触到内存溢出、dump文件分析、visualVm这些新东西,内心有点小激动,因此也记录一下。

问题——出现OutOfMemoryError

重启服务后,回头找问题。查看代码日志,发现报的错误是连接数据库出问题。没道理啊,怎么跑着跑着就访问不了数据库了呢。于是查看tomcat下的logs文件里的cataline日志和localhost日志,发现报的错误是:

03-Mar-2019 14:44:12.600 SEVERE [http-nio-8080-Acceptor-0] org.apache.tomcat.util.net.NioEndpoint$Acceptor.run 
 java.lang.OutOfMemoryError: Java heap space
	at java.nio.HeapByteBuffer.<init>(HeapByteBuffer.java:57)
	at java.nio.ByteBuffer.allocate(ByteBuffer.java:335)
	at org.apache.tomcat.util.net.NioEndpoint$NioBufferHandler.<init>(NioEndpoint.java:1432)
	at org.apache.tomcat.util.net.NioEndpoint.setSocketOptions(NioEndpoint.java:557)
	at org.apache.tomcat.util.net.NioEndpoint$Acceptor.run(NioEndpoint.java:707)
	at java.lang.Thread.run(Thread.java:748)

根据网上的资料,造成OutOfMemoryError:Java heap space异常的原因是Java堆上已经没有空闲的空间,JVM无法继续执行程序了。

引起堆内存不足的可能原因大概有这么些:

  1. 内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
  2. 集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
  3. 代码中存在死循环或循环产生过多重复的对象实体; 使用的第三方软件中的BUG; 启动参数内存值设定的过小;
  4. 使用的第三方软件中的BUG;
  5. 启动参数内存值设定的过小;
  6. 加载太多资源到内存,导致GC耗时较多加载太多资源到内存,导致GC耗时较多

dump文件

可是单凭日志的错误信息我也没法定位到问题,没法知道到底资源在哪里泄漏了。在网上查了一些资料,得知,可以设置jvm参数,当出现OutOfMemory异常的时候生成一个dump文件,然后再通过dump文件来定位问题。

于是在tomcat中进行了JVM参数的配置,这个也是借助网络的力量,才知道要怎么做的:
在/tomcat/bin/cataline.sh中,增加如下代码:

JAVA_OPTS="-server -Xms3072M -Xmx3072M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/tomcat/heapdump.hprof"

上面的配置表示设置初始堆为3g,最大堆为3g,并且设置了出现OutOfMemory错误时生成dump文件。这里也没写在哪个位置添加这串代码,参考文末的参考链接把。

然后重启tomcat服务。这样下次再出现这个错误的时候就会生成dump文件,就可以通过dump文件去定位问题了。

VisualVM工具

那么假设现在有dump文件了,该怎么去分析,怎么去定位?
在思考以及尝试解决这个问题的过程中,又了解到了visualVM这个工具。

对visualVm的初步认识,是通过这篇文章:
记一次解决OutOfMemoryError: Java heap space详细过程与解决思路(jvisualvm解决问题案例详细分析),作者写的有趣又有质量!!极力推荐!!!

VisualVM 是一款免费的,集成了多个 JDK 命令行工具的可视化工具,它能为您提供强大的分析能力,对 Java 应用程序做性能分析和调优。这些功能包括生成和分析海量数据、跟踪内存泄漏、监控垃圾回收器、执行内存和 CPU 分析。

首先,写一个可以触发OutOfMemory的代码:

public class MyTest1 {
    static class OOMObject {
    }
    public static void main(String[] args) {
        List<OOMObject> list = new ArrayList<OOMObject>();
        while (true) {//死循环
            list.add(new OOMObject());//循环往容器中添加对象,并且这些对象无法被释放
        }
    }
}

然后在idea中配置vm参数:

-Xms20M
-Xmx20M
-Xmn10M
-XX:+PrintGCDetails
-XX:SurvivorRatio=8
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=D:\heapdump.hprof

这里的vm配置,其实就是在服务器上的cataline.sh文件中配置一个道理,都是设置vm参数。

然后调用main方法,很快就会出现OutOfMemory错误了,同时也会得到一个dump文件。然后就可以通过visualVm去解析了。这里不对visualVm的使用进行讲述了,网上也有很多的教程。但我觉得最重要的还是自己去动手操作。通过dump文件,可以解析出最占用资源的是哪个对象,可以看出是不是某个对象特别特别的大,某类型的对象数量是不是高达几万个。

visualVm的功能不仅仅是可以分析dump文件,还可以访问远程服务器的jvm。通过在服务器进行一些与jstatd指令有关的配置并执行它。然后通过visualVm工具进行远程访问,这样,就可以远程查看服务器上jvm的堆内存使用的折线图了,十分的直观,也可以看到远程服务器上的vm参数。如下图所示:
在这里插入图片描述在这里插入图片描述
至于visualVm连接远程服务器jvm的操作流程,这里也不列出来了,操作流程也放在文末的链接中。我也是参考别人文章操作的。

最后

可能写的让人看的不知所云,觉得文章没有一个,既没有给出这次出现OutOfMemory的原因,也没有给出VisualVM的具体使用方法。

但其实想说的是,对于这种程序突然挂掉的问题,公司里也没谁可以帮忙解决没谁可以请教,只能自己去思考,自己去找解决。虽然,现在也还没解决掉这个问题,但是至少也有了一些相应的措施,如下次出现这个问题的时候可以分析dump去定位问题。另外,这些东西也是新的东西,之前也没接触到,因此内心也有点小激动,也因此认识了visualVm这个之前没听过的强大的工具,感觉很有意思。
也期待着下次这个问题再出现时自己能够把问题给解决!

参考链接

出现OutOfMemory的各种详细异常:https://blog.csdn.net/chen8238065/article/details/80860444
出现java heap space的根本原因:https://blog.csdn.net/esuom_gib/article/details/79942273
出现OutOfMemory可能的原因:https://blog.csdn.net/HBQandJAVA/article/details/80361900
tomcat如何设置jvm参数:https://www.cnblogs.com/101key/p/6876777.html
jvm各参数的含义参考:http://www.cnblogs.com/redcreen/archive/2011/05/04/2037057.html
jvm参数以及用法:https://www.cnblogs.com/z-sm/p/6253335.html
大神讲述他处理OutOfMemory的思路与操作:https://blog.csdn.net/lyflyyvip/article/details/82288719
写出OutOfMemory的代码:https://blog.csdn.net/wwd0501/article/details/78655942
visualVm的操作与使用:https://www.cnblogs.com/wangtao1993/p/6144183.html
visualVm的操作与使用:https://www.2cto.com/kf/201801/710669.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值