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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 希望多多 中级黑马   /  2014-3-15 08:19  /  1017 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

请问java存在内存泄漏的问题吗,举个例子?

3 个回复

正序浏览
我认为,如果简单说“Java 存在内存泄漏问题”,那是在有意或无意地混淆视听。

首先要明确什么是“内存泄漏”。恐怕大多数人的概念里,“内存泄漏”指的是 C/C++ 里那种“分配了一块内存,用完后没有释放,也不再有指针指向这块内存”。程序执行到这,后面的程序再没有任何办法使用这块内存,却也永远无法释放它(除非程序终止)。

可以肯定地说,Java 中是不会出现上面这种情况的!

所谓“Java 的内存泄漏问题”,其实指的是另一种完全不同的情况,即所谓的“无意识保留”。也就是说,当程序执行到某处时,某个对象从程序逻辑上已经不再需要了,但从程序语法上却还保留着(被某个变量所引用),造成 GC 无法对其进行回收。这种所谓的“泄漏”,其危害程度相对比较小,而且往往能够“自愈”。

我们讨论“Java 是否存在内存泄漏问题”的时候,不要停留在得到一个“存在”或者“不存在”的结论,而是要搞清楚它的实际含义,这样才能真正对我们的软件开发工作有所助益。

评分

参与人数 1技术分 +1 收起 理由
菜小徐 + 1

查看全部评分

回复 使用道具 举报
java导致内存泄露的原因很明确:长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收,这就是java中内存泄露的发生场景。
    1.集合类,集合类仅仅有添加元素的方法,而没有相应的删除机制,导致内存被占用。这一点其实也不明确,这个集合类如果仅仅是局部变量,根本不会造成内存泄露,在方法栈退出后就没有引用了会被jvm正常回收。而如果这个集合类是全局性的变量(比如类中的静态属性,全局性的map等即有静态引用或final一直指向它),那么没有相应的删除机制,很可能导致集合所占用的内存只增不减,因此提供这样的删除机制或者定期清除策略非常必要。
   2.单例模式。不正确使用单例模式是引起内存泄露的一个常见问题,单例对象在被初始化后将在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是个比较大的对象或者集合类型会发生什么情况。
   上面所讲的这些也启发我们如何去查找内存泄露问题,在代码复审的时候关注长生命周期对象:全局性的集合、单例模式的使用、类的static变量等等。在Java的实现过程中,也要考虑其对象释放,最好的方法是在不使用某对象时,显式地将此对象赋空。最好遵循谁创建谁释放的原则。

评分

参与人数 1技术分 +1 收起 理由
菜小徐 + 1

查看全部评分

回复 使用道具 举报 1 0
本帖最后由 黄飞1991 于 2014-3-15 09:44 编辑

java不存在内存泄漏的问题,因为java中的垃圾回收都是由java虚拟机自动进行的,这也是java相对于C和C++(存在内存泄漏,需自己手动回收垃圾内存)的好处。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马