A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 尤圣回 中级黑马   /  2012-9-23 19:46  /  2007 人查看  /  8 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

java的内存泄露是错误还是异常?还有就是内存泄漏在什么情况下会出现,该怎么解救。谁能和我说说最好有例子代码说明。

评分

参与人数 1技术分 +1 收起 理由
滔哥 + 1

查看全部评分

8 个回复

倒序浏览
java中内存泄漏有两种情况。一是在堆中的分配的内存,在没有将其释放掉的时候,就将所有能访问这块内存的方式都删掉;另一种情况则是在内存对象明明已经不需要的时候,还仍然保留着这块内存和它的访问方式(引用)。在Java中已经由于垃圾回收机制的引入,第一种情况得到了很好的解决。所以,Java中的内存泄漏,主要指的是第二种情况。

Java的内存泄漏会导致程序效率低下、占用大量不需要的内存等问题。这将导致整个机器性能变差,内存泄露不是错误也不是异常,但是严重的话也会引起抛出OutOfMemoryError,导致程序崩溃。

评分

参与人数 1技术分 +1 收起 理由
滔哥 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 王海宇 于 2012-9-23 20:26 编辑

举例子的话,HashSet集合就是一个。哈希集合在保存元素的时候(存的是元素引用),会依据元素的hashcode值来将不同的元素放在不同的存储区域。当某个元素参与hashCode值计算的属性被修改,就会导致该元素的hashCode也发生变化,这样更改后的hashCode很可能就无法再匹配之前的那个区域,从而导致之前那个区域里存放的元素的引用再也无法被访问到,自然也就没法对它进行删除操作了。这样的后果就是,当外界再也没有哪个引用指向那个被修改的元素的时候,在哈希集合里面却仍然保存这这个不再被外界使用的元素的引用,而且也无法被外界访问到。这就造成了内存泄露(因为这个元素对象的引用还存储在集合中,所以Java虚拟机就认为这个元素还会有用处,就不会对其进行垃圾回收,即使在集合的外面已经不再使用这个元素对象。当这样的情况出现过多时,就会导致计算机内存大量被垃圾数据占用,最终导致内存溢出)

评分

参与人数 1技术分 +1 收起 理由
滔哥 + 1

查看全部评分

回复 使用道具 举报
找了点有用的 和大家分享一下:
网上关于java内存泄露的资料都过于玄乎,其实java导致内存泄露的原因很明确:长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收,这就是java中内存泄露的发生场景。作者在书中提到了3个场景:  

  1.流失监听器问题,在awt、swing编程中,给组件添加了事件监听器,这些组件的生命周期如果很长的话,监听器对象将不能被正确回收。关于GUI编程我不是很熟悉,这一点存有疑问,因为显然你触发一个按钮的事件,当然是一直期待同样的行为发生,如果删除了监听器或者使用弱引用让JVM回收不符合业务逻辑和用户体验。  

  2.集合类,集合类仅仅有添加元素的方法,而没有相应的删除机制,导致内存被占用。这一点其实也不明确,这个集合类如果仅仅是局部变量,根本不会造成内存泄露,在方法栈退出后就没有引用了会被jvm正常回收。而如果这个集合类是全局性的变量(比如类中的静态属性,全局性的map等),那么没有相应的删除机制,很可能导致集合所占用的内存只增不减,因此提供这样的删除机制或者定期清除策略非常必要。  

  3.单例模式。不正确使用单例模式是引起内存泄露的一个常见问题,单例对象在被初始化后将在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是个比较大的对象或者集合类型会发生什么情况。  

  上面所讲的这些也启发我们如何去查找内存泄露问题,第一选择当然是利用工具,比如jprofiler,第二就是在代码复审的时候关注长生命周期对象:全局性的集合、单例模式的使用、类的static变量等等。

评分

参与人数 1技术分 +1 收起 理由
滔哥 + 1

查看全部评分

回复 使用道具 举报
我也是看别人的,希望可以帮到你。{:soso_e121:}
回复 使用道具 举报
yangfengxiao 发表于 2012-9-23 20:42
我也是看别人的,希望可以帮到你。

:lol你是想叫版主给你加分吧
回复 使用道具 举报
是的,我想进黑马,所以需要你的帮忙。
回复 使用道具 举报
yangfengxiao 发表于 2012-9-23 20:52
是的,我想进黑马,所以需要你的帮忙。

这要看版主给你给你加咯 我也很无奈的
回复 使用道具 举报
你不是版主吗?
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马