内存泄露

2019-03-07  本文已影响0人  Zero_a67b

内存溢出 out of memory,是指程序在申请内存时,没足够的内存空间供其使用,出现Out of memory

内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内训,迟早被占光

内存泄露可以分为4种

1..常发性内存泄露:发生泄露的代码会被多次执行,每次被执行的时候都会导致一块内存泄露

2.偶发性内存泄露:发生内存泄露的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的,对于特定的环境,偶发性也许就变成了常发性的,所以在测试环境和测试方法对检测内存泄露至关重要

3.一次性内存泄露:发生内存泄露的代码只会被执行一次,或者由于算法的缺陷,导致总会有一块仅一块内存发生泄露,比如在类的构造函数中分配内存,在析构函数中却没有释放该内部才能,所以内存泄露只会发生一次

4.隐藏性内存泄露:程序在运行过程中那个不停的分配内存,但是知道结束的时候才释放内存,严格的说这里并没有发生内存泄露,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所有我们称这类内存泄露为隐式内存泄露

从用户使用程序的角度来看,内存泄漏本身不会产生什么危害,作为一般的用户,根本感觉不到内存泄漏的存在。真正有危害的是内存泄漏的堆积,这会最终消耗尽系统所有的内存。从这个角度来说,一次性内存泄漏并没有什么危害,因为它不会堆积,而隐式内存泄漏危害性则非常大,因为较之于常发性和偶发性内存泄漏它更难被检测到

一java内存回收机制

java中对象是采用new或者反射的方法创建的,这些对象的创建都是在堆中分配的,所有对象的回收都是java雪泥机通过垃圾回收机制完成的。GC为了能够正确的释放对象,会监控每个对象的运行状况,对他们的申请、引用、被引用、赋值等状况进行监控,java会使用 有向图 的方法进行管理内部才能,十四岁监控对象是否可以达到,如果不可达到,则就其回收

二java内存泄露引起原因

内存泄露是指 无用对象持续占用内存或无用对象得不到及时释放,从而造成内存空间的浪费称为内存泄露。内存泄露有时不严重且不易察觉,这样开发者就不知道存在内存泄露,但有时也会很严重,会提示你Out of memory

根本原因:长生命周期的对象持有短生命周期对象的引用就很可能发送内存泄露,金光短生命周期对象以及不在需要,但是因为长生命周期对象持有它的引用而导致不能被回收,这就是Java内存泄露的发生场景。主要有如下几大类

1.静态集合类引起内存泄露

像HashMap,Vector等的使用最容易出现内存泄露。这些将就这些静态变量的生命周期和应用程序一直,他们所引用的所有对象Object也不能被释放,因为他们也将一直被Vector等引用着

2.当集合里面的对象属性被修改后,在调用remove方法时不起作用

3.监听器。在在一个应用当中会用到很多监听器,我们会调用一个控件的诸如addXXXLister()等方法来添加监听器,但往往在释放对象的时候却没有记得删除这些监听器,从而增加了内部才能泄露的机会

4各种连接,如数据库连接,网络连接和o连接除非显示的调用close方法将其关闭,否则不会自动被GC回收。

5、内部类和外部模块的引用

  内部类的引用是比较容易遗忘的一种,而且一旦没释放可能导致一系列的后继类对象没有释放。此外程序员还要小心外部模块不经意的引用,例如程序员A 负责A 模块,调用了B 模块的一个方法如: public void registerMsg(Object b); 这种调用就要非常小心了,传入了一个对象,很可能模块B就保持了对该对象的引用,这时候就需要注意模块B 是否提供相应的操作去除引用

6、单例模式

如果单例对象持有外部对象的引用,那么这个外部对象将不能被jvm正常回收,导致内存泄露。

如果单例对象持有外部对象的引用,那么这个外部对象将不能被jvm正常回收,导致内存泄露

不正确使用单例模式是引起内存泄露的一个常见问题,单例对象在被初始化后将在JVM的整个生命周期中存在(以静态变量的方式),如果单例对象持有外部对象的引用,那么这个外部对象将不能被jvm正常回收,导致内存泄露,考虑下面的例

上一篇下一篇

猜你喜欢

热点阅读