Java中,通过“垃圾回收”机制虽然能够将
无用的对象从内存中删除,但前提是仅当该对象不再被引用时才会被统计为无用的。
内存泄漏的常见表现:
·日志中频繁出现“OutOfMemoryException”内存溢出错误;
·系统不时宕机;
·使用分析工具发现↓
内存回收低位点不断升高(以每次内存回收的最低点连成一条直线,那么它是一条上升线);
内存回收的频率也越来越高,内存占用也越来越高,最终出现"OutOfMemoryException"的系统异常。
内存泄漏的原因:
java把内存分两种:一种是栈内存,另一种是堆内存
1.在函数中定义的基本类型变量和对象的引用变量都在函数的栈内存中分配;
2.堆内存用来存放由new创建的对象和数组;
在函数(代码块)中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量所分配的内存空间;
在堆中分配的内存由java虚拟机的自动垃圾回收器来管理。
堆的优势是可以动态分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的。缺点就是要在运行时动态分配内存,存取速度较慢;
栈的优势是存取速度比堆要快,缺点是存在栈中的数据大小与生存期必须是确定的无灵活性。
如何分析:
1.代码走查和分析,找出程序中潜在的问题代码;
2.使用专门的内存泄漏测试工具找出内存泄漏发生的位置;
工具的使用↓
·抓取不同时刻的内存快照;
·捕获堆上的数据;
·强制执行GC,以便观察受怀疑的类实例是否会被作为垃圾收集;
·能显示出类实例的引用链;
推荐使用Eclipse的插件MAT(Memory Analyzer Tool)来帮助迅速,准确地分析内存泄漏;
一般说来,一个正常的系统在其运行稳定后其内存的占用量是基本稳定的,不应该是无限制的增长的,同样,
对任何一个类的对象的使用个数也有一个相对稳定的上限,不应该是持续增长的。根据这样的基本假设,我
们可以持续地观察系统运行时使用的内存的大小和各实例的个数,如果内存的大小持续地增长,则说明系统
存在内存泄漏,如果某个类的实例的个数持续地增长,则说明这个类的实例可能存在泄漏情况。
分析步骤:
·使用内存快照进行数据收集;
·初步分析,判断是否存在内存泄漏;
·分析定位,找到被泄漏的对象;
·修正错误再测试验证;