java是否存在内存泄漏

来源:互联网 发布:python 遍历字符串 编辑:程序博客网 时间:2024/05/20 02:53

内存泄露是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成的内存空间的浪费称为内存泄露。内存泄露有时不严重且不易察觉,这样开发者就不知道存在内存泄露,但有时也会很严重,会提示你Out of memory。
那么,Java内存泄露根本原因是什么呢?长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收,这就是java中内存泄露的发生场景。具体主要有如下几大类:
1、静态集合类引起内存泄露:
像HashMap、Vector等的使用最容易出现内存泄露,这些静态变量的生命周期和应用程序一致,他们所引用的所有的对象Object也不能被释放,因为他们也将一直被Vector等引用着。
例:
Static Vector v = new Vector(10);
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、当集合里面的对象属性被修改后,再调用remove()方法时不起作用。

例:
public static void main(String[] args)
{
Set set = new HashSet();
Person p1 = new Person(“唐僧”,”pwd1”,25);
Person p2 = new Person(“孙悟空”,”pwd2”,26);
Person p3 = new Person(“猪八戒”,”pwd3”,27);
set.add(p1);
set.add(p2);
set.add(p3);
System.out.println(“总共有:”+set.size()+” 个元素!”); //结果:总共有:3 个元素!
p3.setAge(2); //修改p3的年龄,此时p3元素对应的hashcode值发生改变
set.remove(p3); //此时remove不掉,造成内存泄漏

set.add(p3); //重新添加,居然添加成功
System.out.println(“总共有:”+set.size()+” 个元素!”); //结果:总共有:4 个元素!
for (Person person : set)
{
System.out.println(person);
}
}

3、监听器
在java 编程中,我们都需要和监听器打交道,通常一个应用当中会用到很多监听器,我们会调用一个控件的诸如addXXXListener()等方法来增加监听器,但往往在释放对象的时候却没有记住去删除这些监听器,从而增加了内存泄漏的机会。

4、各种连接
比如数据库连接(dataSourse.getConnection()),网络连接(socket)和io连接,除非其显式的调用了其close()方法将其连接关闭,否则是不会自动被GC 回收的。对于Resultset 和Statement 对象可以不进行显式回收,但Connection 一定要显式回收,因为Connection 在任何时候都无法自动回收,而Connection一旦回收,Resultset 和Statement 对象就会立即为NULL。但是如果使用连接池,情况就不一样了,除了要显式地关闭连接,还必须显式地关闭Resultset Statement 对象(关闭其中一个,另外一个也会关闭),否则就会造成大量的Statement 对象无法释放,从而引起内存泄漏。这种情况下一般都会在try里面去的连接,在finally里面释放连接。

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

6、单例模式
不正确使用单例模式是引起内存泄露的一个常见问题,单例对象在被初始化后将在JVM的整个生命周期中存在(以静态变量的方式),如果单例对象持有外部对象的引用,那么这个外部对象将不能被jvm正常回收,导致内存泄露,考虑下面的例子:
class A{
public A(){
B.getInstance().setA(this);
}
….
}
//B类采用单例模式
class B{
private A a;
private static B instance=new B();
public B(){}
public static B getInstance(){
return instance;
}
public void setA(A a){
this.a=a;
}
//getter…
}
显然B采用singleton模式,它持有一个A对象的引用,而这个A类的对象将不能被回收。想象下如果A是个比较复杂的对象或者集合类型会发生什么情况

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 婴儿成蛋蛋的皮好长怎么办 丈夫总要害自己该怎么办 脚背踢肿了怎么办很疼 踢沙袋脚背伤了怎么办 脚y子烂了怎么办 掐喉咙那会痒会咳嗽怎么办 掐到婴儿脖子了怎么办 孩子胳膊不小心烫破皮了怎么办 孩子嘴角磕破了怎么办 电话不小心拒接了怎么办 手机微信不小心碰到语言英文怎么办 手机微信不小心碰到英文说话怎么办 不小心碰到宝宝卤门怎么办 不小心碰到婴儿头顶囟门怎么办 重要部位被踢了怎么办 吃了带刺的葡萄怎么办 小孩子老是去厕所大便怎么办 家人偷了我的钱怎么办 小孩打闹踢到要害怎么办 腿上汗毛孔没开都是点点怎么办 脸蛋澡巾擦破了怎么办 婴儿后背用擦澡巾擦红了怎么办 搓澡皮肤搓破了怎么办 搓背搓的脖子红痒怎么办 上班迟到1个小时怎么办 想家想的都哭怎么办 想学手艺被骗学费怎么办 小腿肚后面筋和肌肉压痛怎么办 尿道囗和屁股眼中间长疮怎么办? 2个多月的宝宝蛋蛋上有个包怎么办 幼儿园睡觉自己摸下身玩怎么办 猫猫打喷嚏有透明液体怎么办 夏季穿运动鞋出了脚气怎么办 脚底长了刺瘊子怎么办 凉鞋前面踢破了怎么办 尖头鞋前面折了怎么办 月子里宝宝蛋蛋破皮怎么办 军人在训练时想上侧所怎么办 被白蚂蚁咬了怎么办 被蚂蚁咬了起包怎么办 脚踢了石头肿了怎么办