问题记录---java程序内存溢出

来源:互联网 发布:mathematics软件安卓 编辑:程序博客网 时间:2024/04/24 00:37

    前段时间公司更新了新版本的业务系统,并进行了并发测试,并发数仅为20人左右,测试跑到3天左右,系统就开始奔溃了,查看日志信息。错误如下:

 

系统使用了thrift框架来进行服务的发布,从日志中可以看出由于java.lang.OutOfMemoryError: GC overhead limit exceeded原因导致了thrift服务端负责select线程的异常退出,服务端无法接受到请求。出现异常的thrift的源码如下:


   通过查找资料得出,GC overhead limit exceeded 是JVM定义的一个策略,通过统计GC时间来预测是否要OOM了,提前抛出异常,防止OOM发生。因为GC发生在堆区,所以得出结论为,Java堆区内存溢出导致程序异常。所以当天早上9点重新启动项目进行并发测试,并使用了jvisualvm工具(jvisualvm工具为jdk自带的图形化的jvm性能监控工具)对程序JVM的内存区域进行了监控。发现随着时间的增长,其堆内存增长迅速,在当天下午7点的时候堆内容已经从开始的50M左右增长到600多M。经过对比分析不同时间生成的堆转储文件,发现内存中存在持续增长且不被回收的String[]类型的数据,后期甚至占据堆内存的85%以上。对系统的代码进行分析发现,原本计划只在应用启动时加载一次的元素为String[]的List,由于程序的疏忽(懒加载未赋值,重复判空),导致随请求数被重复加载,List为static变量,被不断的add数据,却不能被回收,导致其占据大量的堆内存。对程序进行修改后,再重新进行测试,堆内存的占用一直稳定在60M上下,且未发现体积异常未被回收的对象。





















0 0
原创粉丝点击