当前位置: 首页 > news >正文

内存溢出的预防及解决汇总

内存溢出是一个非常隐式的问题,经过相关资料的查询,先总结一下内存溢出的关键字:what(溢出表现)、origin(内存分配及回收)、where(溢出类型)、why(泄露原因)、how(预防及解决方案)。
 
一、what(溢出表现)
1. 服务器内存长期不合理占用,内存经常处于高位占用,很难回收到低位;
2. 服务器极为不稳定,几乎每两天重新启动一次,有时甚至每天重新启动一次;
3. 服务器经常做 Full GC(Garbage Collection),而且时间很长,大约需要 30-40秒,应用服务器在做 Full GC的时候是不响应客户的交易请求的,非常影响系统性能。
4. 服务器的内存占用不是锯齿形波动,而是趋势向上,最后宕机。
 
二、origin(起源)
1. 内存溢出是指无法回收的内存积攒过多或者正在使用的内存过多,最终导致程序运行需要的内存大于虚拟机所能提供的最大内存,从而导致内存溢出。
因此,为了解决这个问题,从抽丝剥茧的角度来看,首先第一步需要明白起源,即明白内存分配以及回收的方式:
“在Java中,内存的分配是由程序完成的,而内存的释放是由垃圾收集器(Garbage Collection,GC)完成的,程序员不需要通过调用GC函数来释放内存,因为不同的JVM实现者可能使用不同的算法管理GC,有的是内存使用到达一定程度时,GC才开始工作,也有定时执行的,有的是中断式执行GC。但GC只能回收无用并且不再被其它对象引用的那些对象所占用的空间。Java的内存垃圾回收机制是从程序的主要运行对象开始检查引用链,当遍历一遍后发现没有被引用的孤立对象就作为垃圾回收。” --引用
我觉得这一段话说的比较准确,总结起来就是:1.内存的分配及回收基本都可以交由程序静默进行,释放不了的核心在于引用还在。
2. 那么什么时候进行垃圾回收(分为Scavenge GC 跟 Full GC)呢?
2.1 Scavenge GC 主要集中在 Eden 园区,一般情况下,当新对象生成,并且在Eden申请空间失败时,就会触发Scavenge GC,对Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区。然后整理Survivor的两个区。这种方式的GC是对年轻代的Eden区进行,不会影响到年老代。
2.2 Full GC。速度很慢,对整个堆进行整理,包括Young、Tenured和Perm。引起 Full GC 的方式有:老年代被写满,持久代被写满以及System.gc()被显示调用。
 
三、where(主要溢出类型)
下一步我们继续关注主要在什么位置有可能内存溢出:
1. java.lang.OutOfMemoryError: Java heap space (堆溢出)
堆是垃圾回收关注的重点,如果在垃圾回收之间 Java 虚拟机创建了过多的对象,虚拟机分配到堆内存的空间已经满了,那么就会报这个错误。
2. Java.lang.OutOfMemoryError: PermGen space (永久区溢出)
如果说堆是给我们程序员使用的话,那么非堆就是给JVM自己使用的,非堆主要存在类的基本信息,他与堆的不同之处在于非堆中在运行期间GC不会释放空间。按照该异常的原义,指的是程序中使用了大量的jar或class,使java虚拟机装载类的空间不够(注意这时候是MaxPermSize较小)。
 
四、why(泄漏原因)
根据时间顺序,我们大致可以总结如下:
1. 启动参数内存值设定的过小,无法加载过大的包;
2. 内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
3. 集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
4. 代码中存在死循环或循环产生过多重复的对象实体;
5. 使用的第三方软件中的BUG;
6. 注意其他不健壮的代码原因;
6.1 注意无引用对象的及时释放;
6.2 无法避免的大量字符串处理,尽量使用 StringBuffer 而非 String,原因是每一个 String 都需要占用一块内存空间;
6.3 注意静态变量的使用,因为静态变量是全局变量,不会被回收;
6.4 注意大对象的创建及使用,注意显示声明极大的数组对象;
6.5 注意循环体体内的对象创建;
6.6 注意是否一次性查询出来大量的数据;
6.7 检查List及Map是否有对象的引用一直存在;
 
五、how(解决方案及预防方案)
一般来说,系统稳定之后,内存的使用是保持在一定水平的,如果发现内存的使用随时间的增长而呈现线性的增长,那么就有可能说明正在内存泄露。
一般处理的思路,跟以上原因其实一一对应:
1. 增大JVM的启动内存,-Xms256m -Xmx256m -XX:MaxNewSize=256m -XX:MaxPermSize=256m;
2. 检查错误日志;
3. 代码层面的检查(参见第四大点的原因);
4. 使用检查工具,Optimizeit Profiler、JProbe Profiler等等。这些工具的主要点都会聚焦在追踪对象的申请、释放等动作,将内存管理的所有信息进行统计然后可视化,根据这些信息,可以追踪到上述三个步骤仍然无法检查到的泄露对象。
 
文章参考:
1.《jvm垃圾回收是什么时候触发的? 垃圾回收算法? 都有哪些垃圾回收器》 http://blog.csdn.net/sunny243788557/article/details/52797088
2.《Java内存溢出的详细解决方案》 http://blog.csdn.net/tototuzuoquan/article/details/25591923
3.《java中三种常见内存溢出错误的处理方法》 http://outofmemory.cn/java/OutOfMemoryError/PermGen-space-Java-heap-space-unable-create-new-native-thread
4.《Java中垃圾回收有什么目的?什么时候进行垃圾回收?》 https://zhidao.baidu.com/question/2204377803050672708.html
5.《 Java内存溢出详解及解决方案》 http://blog.csdn.net/xianmiao2009/article/details/49254391
 
 

转载于:https://www.cnblogs.com/Mr-Persist/p/6639896.html

相关文章:

  • linux 添加 swap
  • Win10系列:UWP界面布局进阶8
  • 使用Jenkins和Jmeter搭建性能测试平台
  • Android手机通过APN设置上网的方法
  • NSDate
  • 1
  • 电子测量
  • JS实现的图片预览功能
  • docker 安装centos 7
  • 深入理解计算机系统之存储器层次结构学习笔记
  • hihocoder offer收割编程练习赛12 C 矩形分割
  • css 样式表 基础 样式
  • 函数装饰器
  • 第二百一十节,jQuery EasyUI,SearchBox(搜索框)组件
  • UVa 10917 林中漫步
  • 「译」Node.js Streams 基础
  • Apache的80端口被占用以及访问时报错403
  • CentOS6 编译安装 redis-3.2.3
  • Django 博客开发教程 16 - 统计文章阅读量
  • echarts的各种常用效果展示
  • ES6简单总结(搭配简单的讲解和小案例)
  • hadoop入门学习教程--DKHadoop完整安装步骤
  • IP路由与转发
  • Javascript编码规范
  • JS专题之继承
  • React as a UI Runtime(五、列表)
  • SpiderData 2019年2月23日 DApp数据排行榜
  • 给github项目添加CI badge
  • 缓存与缓冲
  • 前端学习笔记之观察者模式
  • 让你的分享飞起来——极光推出社会化分享组件
  • 要让cordova项目适配iphoneX + ios11.4,总共要几步?三步
  • 阿里云服务器如何修改远程端口?
  • 曜石科技宣布获得千万级天使轮投资,全方面布局电竞产业链 ...
  • ​用户画像从0到100的构建思路
  • #常见电池型号介绍 常见电池尺寸是多少【详解】
  • #免费 苹果M系芯片Macbook电脑MacOS使用Bash脚本写入(读写)NTFS硬盘教程
  • $.extend({},旧的,新的);合并对象,后面的覆盖前面的
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (Repost) Getting Genode with TrustZone on the i.MX
  • (ZT)出版业改革:该死的死,该生的生
  • (二)换源+apt-get基础配置+搜狗拼音
  • (二十三)Flask之高频面试点
  • (二十一)devops持续集成开发——使用jenkins的Docker Pipeline插件完成docker项目的pipeline流水线发布
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (附源码)ssm考生评分系统 毕业设计 071114
  • (附源码)计算机毕业设计SSM智慧停车系统
  • (算法)前K大的和
  • (一)使用IDEA创建Maven项目和Maven使用入门(配图详解)
  • (转)PlayerPrefs在Windows下存到哪里去了?
  • **Java有哪些悲观锁的实现_乐观锁、悲观锁、Redis分布式锁和Zookeeper分布式锁的实现以及流程原理...
  • .NET CORE 3.1 集成JWT鉴权和授权2
  • .NET 将多个程序集合并成单一程序集的 4+3 种方法
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地中转一个自定义的弱事件(可让任意 CLR 事件成为弱事件)
  • .net遍历html中全部的中文,ASP.NET中遍历页面的所有button控件