1. 定义
1、内存泄漏:一般可以理解为系统资源(各方面的资源,堆、栈、线程等)在错误使用的情况下,导致使用完毕的资源无法回收(或没有回收),从而造成那部分内存不可用的情况。
2、内存溢出:指内存不够使用而抛出异常,内存泄露是其形成的原因之一。
2. 危害
会导致新的资源分配请求无法完成,引起系统错误,最后导致系统崩溃。
3. 内存泄漏分类
类型 |
描述 |
常发性内存泄漏 |
发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏 |
偶发性内存泄漏 |
发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的 |
一次性内存泄漏 |
发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。比如,在类的构造函数中分配内存,在析构函数中却没有释放该内存,所以内存泄漏只会发生一次 |
隐式内存泄漏 |
程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏 |
4. 内存泄露/溢出发生的区域
内存区域 |
发生情况 |
备注 |
程序计数器 |
不可能 |
|
虚拟机栈<VM Stack> |
Y |
|
本地方法栈 |
Y |
|
非堆内存 |
Y |
即方法区、持久代 |
运行时常量池< Runtime Constant Pool > |
Y |
|
本机直接内存< Direct Memory > |
Y |
|
堆内存 |
Y |
|
5. 内存溢出异常
内存区域 |
异常 |
虚拟机栈<VM Stack> |
java.lang.StackOverflowError |
本地方法栈 |
java.lang.OutOfMemoryError: unable to create new native thread |
非堆内存 |
java.lang.OutOfMemoryError:PermGen space |
运行时常量池< Runtime Constant Pool > |
java.lang.OutOfMemoryError: PermGen space |
本机直接内存< Direct Memory > |
java.lang.OutOfMemoryError |
堆内存 |
java.lang.OutOfMemoryError: Java heap space |
6. 内存溢出常见原因
异常 |
常见原因 |
解决办法 |
java.lang.StackOverflowError |
线程栈的溢出,要么是方法调用层次过多(比如存在无限递归调用),要么是线程栈太小 |
|
java.lang.OutOfMemoryError: unable to create new native thread |
Stack空间不足以创建额外的线程,要么是创建的线程过多,要么是Stack空间确实小 |
1.通过-Xss启动参数减少单个线程栈大小,这样便能开更多线程(当然不能太小,太小会出现StackOverflowError) 2.通过-Xms -Xmx 两参数减少Heap大小,将内存让给Stack(前提是保证Heap空间够用) |
java.lang.OutOfMemoryError:PermGen space |
Permanent Generation空间不足,不能加载额外的类,可能为运行时常量池溢出或持久代溢出。 大量动态反射生成的类不断被加载可导致此错误 |
调整PermGen内存 |
java.lang.OutOfMemoryError |
有可能本机直接内存不够用 |
|
java.lang.OutOfMemoryError: Java heap space |
1、内存泄露 2、堆内存分配不合理引起溢出 3、创建一个占用内存过大的对象 |
1、调整堆内存 2、根据垃圾回收前后情况对比,同时根据对象引用情况(常见的集合对象引用)分析,基本都可以找到泄漏点,然后修改程序错误 |