一、基本概念
内存溢出:简单地说内存溢出就是指程序运行过程中申请的内存大于系统能够提供的内存,导致无法申请到足够的内存,于是就发生了内存溢出 。
内存泄漏:内存泄漏指程序运行过程中分配内存给临时变量 , 用完之后却没有被GC回收,始终占用着内存,既不能被使用也不能分配给其他程序,于是就发生了内存泄漏 。
【什么叫内存溢出?内存泄漏的定义又是什么?使用中如何避免?】内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用 , 出现out of memory;
内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略 , 但内存泄露堆积后果很严重,无论多少内存,迟早会被占光 。
memory leak会最终会导致out of memory!
内存泄露是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成的内存空间的浪费称为内存泄露 。内存泄露有时不严重且不易察觉 , 这样开发者就不知道存在内存泄露,但有时也会很严重,会提示你Out of memory 。
二、内存溢出的常见情况
内存溢出有以下几种常见的情况:
1、java.lang.OutOfMemoryError: PermGen space (持久带溢出)
我们知道jvm通过持久带实现了java虚拟机规范中的方法区,而运行时常量池就是保存在方法区中的,因此发生这种溢出可能是运行时常量池溢出,或是由于程序中使用了大量的jar或class,使得方法区中保存的class对象没有被及时回收或者class信息占用的内存超过了配置的大小 。
2、java.lang.OutOfMemoryError: Java heap space (堆溢出)
发生这种溢出的原因一般是创建的对象太多,在进行垃圾回收之前对象数量达到了最大堆的容量限制 。
解决这个区域异常的方法一般是通过内存映像分析工具对Dump出来的堆转储快照进行分析,看到底是内存溢出还是内存泄漏 。如果是内存泄漏,可进一步通过工具查看泄漏对象到GC Roots的引用链,定位出泄漏代码的位置,修改程序或算法;如果不存在泄漏,就是说内存中的对象确实都还必须存活 , 那就应该检查虚拟机的堆参数-Xmx(最大堆大小)和-Xms(初始堆大小),与机器物理内存对比看是否可以调大 。
3、虚拟机栈和本地方法栈溢出
如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError 。
如果虚拟机在扩展栈时无法申请到足够的内存空间 , 则抛出OutOfMemoryError 。
三、内存泄漏
内存泄漏的根本原因是长生命周期的对象持有短生命周期对象的引用,尽管短生命周期的对象已经不再需要,但由于长生命周期对象持有它的引用而导致不能被回收 。
以发生的方式来分类,内存泄漏可以分为4类:
1、常发性内存泄漏 。发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏 。
2、偶发性内存泄漏 。发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生 。常发性和偶发性是相对的 。对于特定的环境,偶发性的也许就变成了常发性的 。所以测试环境和测试方法对检测内存泄漏至关重要 。
3、一次性内存泄漏 。发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷 , 导致总会有一块仅且一块内存发生泄漏 。比如,在类的构造函数中分配内存 , 在析构函数中却没有释放该内存,所以内存泄漏只会发生一次 。
4、隐式内存泄漏 。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存 。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存 。但是对于一个服务器程序,需要运行几天,几周甚至几个月 , 不及时释放内存也可能导致最终耗尽系统的所有内存 。所以,我们称这类内存泄漏为隐式内存泄漏 。
从用户使用程序的角度来看,内存泄漏本身不会产生什么危害,作为一般的用户 , 根本感觉不到内存泄漏的存在 。真正有危害的是内存泄漏的堆积,这会最终消耗尽系统所有的内存 。从这个角度来说,一次性内存泄漏并没有什么危害,因为它不会堆积 , 而隐式内存泄漏危害性则非常大,因为较之于常发性和偶发性内存泄漏它更难被检测到 。
下面总结几种常见的内存泄漏:
1、静态集合类引起的内存泄漏:
像HashMap、Vector等的使用最容易出现内存泄露,这些静态变量的生命周期和应用程序一致 , 他们所引用的所有的对象Object也不能被释放,从而造成内存泄漏,因为他们也将一直被Vector等引用着 。
Vector<Object> v=new Vector<Object>(100);
for (int i = 1; i<100; i++)
{
Object o = new Object();
v.add(o);
o = null;
}
在这个例子中 , 循环申请Object 对象,并将所申请的对象放入一个Vector 中,如果仅仅释放引用本身(o=null),那么Vector 仍然引用该对象 , 所以这个对象对GC 来说是不可回收的 。因此,如果对象加入到Vector 后,还必须从Vector 中删除,最简单的方法就是将Vector对象设置为null 。
2、修改HashSet中对象的参数值,且参数是计算哈希值的字段
当一个对象被存储到HashSet集合中
以上就是朝夕生活(www.30zx.com)关于“什么叫内存溢出?内存泄漏的定义又是什么?使用中如何避免?”的详细内容 , 希望对大家有所帮助!
猜你喜欢
- 内存溢出和内存泄漏的区别、产生原因以及解决方案
- 红米Note9突然黑屏不开机的原因以及解决办法
- 红米开机黑屏怎么办
- 红米手机不开机的几种原因以及解决方法
- 我的红米现在打开手机就黑屏,程序也运行不了,手点一下就黑屏,有时候
- 手机黑屏的4种类型,对应4种解决方法
- 蓝色协议服务器崩溃/无法连接服务器/服务器报错/解决步骤
- 腾讯与360大战始末
- 域名被劫持应该如何处理