java内存泄漏原因及编程建议

一、Java内存回收机制
不论哪种语言的内存分配方式,都需要返回所分配内存的真实地址,也就是返回一个指针到内存块的首地址。Java中对象是采用new或者反射的方法创建的,这些对象的创建都是在堆(Heap)中分配的,所有对象的回收都是由Java虚拟机通过垃圾回收机制完成的。GC为了能够正确释放对象,会监控每个对象的运行状况,对他们的申请、引用、被引用、赋值等状况进行监控,Java会使用有向图的方法进行管理内存,实时监控对象是否可以达到,如果不可到达,则就将其回收,这样也可以消除引用循环的问题。在Java语言中,判断一个内存空间是否符合垃圾收集标准有两个:一个是给对象赋予了空值null,以下再没有调用过,另一个是给对象赋予了新值,这样重新分配了内存空间。

二、Java内存泄露引起原因
首先,什么是内存泄露?经常听人谈起内存泄露,但要问什么是内存泄露,没几个说得清楚。内存泄露是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成的内存空间的浪费称为内存泄露。内存泄露有时不严重且不易察觉,这样开发者就不知道存在内存泄露,但有时也会很严重,会提示你Out of memory。
那么,Java内存泄露根本原因是什么呢?长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收,这就是java中内存泄露的发生场景。具体主要有如下几大类:

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

2、内部类和外部类的引用容易出现内存泄露的问题

3、监听器的使用,java中往往会使用到监听器,在释放对象的同时没有相应删除监听器的时候也可能导致内存泄露。

4、大量临时变量的使用,没有及时将对象设置为null也可能导致内存的泄露

5、数据库的连接没有关闭情况,包括连接池方法连接数据库,如果没有关闭ResultSet等也都可能出现内存泄露的问题。

举例一个内存泄露的例子:

Vector v = new Vector(10);

for (int i = 1; i<100; i++){

    Object o = new Object();

    v.add(o);

    o = null;

}

别以为o对象被回收了,实际上v引用了这些对象,还被引用的对象GC是没有办法回收的,这样就很可能导致内存的泄露。


三、编程建议

1、尽早释放无用对象的引用。特别是大对象和集合对象,通过置为null,暗示垃圾收集器来收集该对象,防止发生内存泄露。

2、尽量少用静态变量,因为静态变量是全局的, GC 不会回收的;

3、避免集中创建对象尤其是大对象, JVM 会突然需要大量内存,这时必然会触发 GC 优化系统内存环境;显示的声明数组空间,而且申请数量还极大。

4、尽量运用对象池技术以提高系统性能;生命周期长的对象拥有生命周期短的对象时容易引发内存泄漏,例如大集合对象拥有大数据量的业务对象的时候,可以考虑分块进行处理,然后解决一块释放一块的策略。

5、不要在经常调用的方法中创建对象,尤其是忌讳在循环中创建对象。可以适当的使用 hashtable,vector 创建一组对象容器,然后从容器中去取那些对象,而不用每次 new 之后又丢弃。

6、一般都是发生在开启大型文件或跟数据库一次拿了太多的数据,造成 Out Of Memory Error 的状况,这时就大概要计算一下数据量的最大值是多少,并且设定所需最小及最大的内存空间值。

7、尽量避免在类的默认构造器中创建、初始化大量的对象,防止在调用其自类的构造器时造成不必要的内存资源浪费。

8、尽量避免强制系统做垃圾内存的回收,增长系统做垃圾回收的最终时间。

9、代码中是否有死循环或递归调用

10、是否有大循环重复产生新对象实体。

11、检查List、Map等集合对象是否有使用完后,未清除的问题。List、Map等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收。

12、当复制大量数据时,使用System.arraycopy();





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值