精华内容
下载资源
问答
  • JAVA内存泄漏

    2018-09-29 03:53:36
    JAVA内存泄漏,内存的检测和检查相关步骤,必须要大大的看才行
  • java 内存泄漏

    2012-10-22 00:25:31
    java 内存泄漏
  • Java内存泄漏

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

    二、Java内存泄露引起原因 
    首先,什么是内存泄露?经常听人谈起内存泄露,但要问什么是内存泄露,没几个说得清楚。内存泄露是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成的内存空间的浪费称为内存泄露。内存泄露有时不严重且不易察觉,这样开发者就不知道存在内存泄露,但有时也会很严重,会提示你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<Person> set = new HashSet<Person>(); 
    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是个比较复杂的对象或者集合类型会发生什么情况
    展开全文
  • java内存泄漏

    2018-07-27 13:25:00
    java内存泄漏 Java内存泄漏引起的原因:  内存泄漏是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成内存空间的浪费称为内存泄漏。  长生命周期的对象持有短生命周期对象的...

    java内存泄漏

    • Java内存泄漏引起的原因:

      内存泄漏是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成内存空间的浪费称为内存泄漏。

      长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄漏,尽管短生命周期对象已经不再需要,但是因为长生命周期持有它的引用而导致不能被回收,这就是Java中内存泄漏的发生场景。

    • 造成内存泄漏的几种情况:

    • 1、静态集合类引起内存泄漏

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

    • 2、当集合里面的对象属性被修改后,再调用remove()方法时不起作用。

    • 3、监听器

      在释放对象的时候却没有去删除这些监听器,增加了内存泄漏的机会。

    • 4、各种连接

      比如数据库连接(dataSourse.getConnection()),网络连接(socket)和io连接,除非其显式的调用了其close()方法将其连接关闭,否则是不会自动被GC 回收的。

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

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

    • 6、单例模式

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

    转载于:https://www.cnblogs.com/renxiuxing/p/9377080.html

    展开全文
  • Java 内存泄漏

    2017-07-18 22:42:00
    与需手工管理内存的语言(C/C++)相比,Java 具有垃圾回收的功能,但 Java 编程中仍然可能发生内存泄漏,如果过期的对象引用等未被消除的话。Java 内存泄漏发生时,会更加隐蔽,更难debug,这就要求我们在编码阶段,...

    与需手工管理内存的语言(C/C++)相比,Java 具有垃圾回收的功能,但 Java 编程中仍然可能发生内存泄漏,如果过期的对象引用等未被消除的话。Java 内存泄漏发生时,会更加隐蔽,更难debug,这就要求我们在编码阶段,总结常见 Java 内存泄漏的情形,从源头加以避免。

    1. 过期的对象引用(obsolete reference)

    对于 Stack 类的 pop 方法:

    public Object pop() {
        if (size == 0) {
            return new EmptyStackException();
        }
        return elements[--size];
    }

    似乎没有什么问题。注意,如果一个栈是先增长,然后收缩,则从栈中弹出来的对象就不会被当做垃圾回收。修改也十分简单:

    public Object pop() {
        if (size == 0) {
            return new EmptyStackException();
        }
        Object result = elements[--size];
        elements[size] = null;        // 消除过期引用
        return result;
    }

    转载于:https://www.cnblogs.com/mtcnn/p/9421311.html

    展开全文
  • JAVA内存泄漏原因和内存泄漏检测工具摘要虽然Java虚拟机(JVM)及其垃圾收集器(garbage collector,GC)负责管理大多数的内存任务,Java软件程序中还是有可能出现内存泄漏。实际上,这在大型项目中是一个常见的问题。...

    JAVA内存泄漏原因和内存泄漏检测工具

    摘要

    虽然Java

    虚拟机(JVM)及其垃圾收

    集器(garbage collector,GC)负责管理大多数的内存任务,Java

    软件程序中还是有可能出现内

    存泄漏。实际上,这在大型项目中是一个常见的问题。避免内存泄漏的第一步是要弄清楚它是如何发生的。本文介绍了编写Java代码的一些常见的内存泄漏陷

    阱,以及编写不泄漏代码的一些最佳实践。一旦发生了内存泄漏,要指出造成泄漏的代码是非常困难的。因此本文还介绍了一种新工具,用来诊断泄漏并指出根本原

    因。该工具的开销非常小,因此可以使用它来寻找处于生产中的系统的内存泄漏。

    垃圾收集器的作用

    虽然垃圾收集器处理了大多数内存管理问题,从而使编程人员的生活变得更轻松了,但是编程人员还是

    可能犯错而导致出现内存问题。简单地说,GC循环地跟踪所有来自“根”对象(堆栈对象、静态对象、JNI句柄指向的对象,诸如此类)的引用,并将所有它所

    能到达的对象标记为活动的。程序只可以操纵这些对象;其他的对象都被删除了。因为GC使程序不可能到达已被删除的对象,这么做就是安全

    的。

    虽然内存管理可以说是自动化的,但是这并不能使编程人员免受思考内存管理问题之苦。例如,分配

    (以及释放)内存总会有开销,虽然这种开销对编程人员来说是不可见的。创建了太多对象的程序将会比完成同样的功能而创建的对象却比较少的程序更慢一些(在

    其他条件相同的情况下)。

    而且,与本文更为密切相关的是,如果忘记“释放”先前分配的内存,就可能造成内存泄漏。如果程序

    保留对永远不再使用的对象的引用,这些对象将会占用并耗尽内存,这是因为自动化的垃圾收集器无法证明这些对象将不再使用。正如我们先前所说的,如果存在一

    个对对象的引用,对象就被定义为活动的,因此不能删除。为了确保能回收对象占用的内存,编程人员必须确保该对象不能到达。这通常是通过将对象字段设置为

    null或者从集合(collection)中移除对象而完成的。但是,注意,当局部变量不再使用时,没有必要将其显式地设置为null。对这些变量的引

    用将随着方法的退出而自动清除。

    概括地说,这就是内存托管语言中的内存泄漏产生的主要原因:保留下来却永远不再使用的对象引用。

    典型泄漏

    既然我们知道了在Java中确实有可能发生内存泄漏,就让我们来看一些典型的内存泄漏及其原因。

    全局集合

    在大的应用程序中有某种全局的数据储存库是很常见的,例如一个JNDI树或一个会话表。在这些情

    况下,必须注意管理储存库的大小。必须有某种机制从储存库中移除不再需要的数据。

    这可能有多种方法,但是最常见的一种是周期性运行的某种清除任务。该任务将验证储存库中的数据,

    并移除任何不再需要的数据。

    另一种管理储存库的方法是使用反向链接(referrer)计数。然后集合负责统计集合中每个入

    口的反向链接的数目。这要求反向链接告诉集合何时会退出入口。当反向链接数目为零时,该元素就可以从集合中移除了。

    缓存

    缓存是一种数据结构,用于快速查找已经执行的操作的结果。因此,如果一个操作执行起来很慢,对于

    常用的输入数据,就可以将操作的结果缓存,并在下次调用该操作时使用缓存的数据。

    缓存通常都是以动态方式实现的,其中新的结果是在执行时添加到缓存中的。典型的算法是:

    检查结果是否在缓存中,如果在,就返回结果。

    如果结果不在缓存中,就进行计算。

    计算出来的结果添加到缓存中,以便以后对该操作的调用可以使用。

    该算法的问题(或者说是潜在的内存泄漏)出在最后一步。如果调用该操作时有

    相当多的不同输入,就将有相当多的结果存储

    在缓存中。很明显这不是正确的方法。

    为了预防这种具有潜在破坏性的设计,程序必须确保对于缓存所使用的内存容量有一个上限。因此,更

    好的算法是:

    检查结果是否在缓存中,如果在,就返回结果。

    如果结果不在缓存中,就进行计算。

    果缓存所占的空间过大,就移除缓存最久的结果。

    将计算出来的结果添加到缓存中,以便以后对该操作的调用可以使用。

    通过始终移除缓

    存最久的结果,我们实际上进行了这样的假设:在将来,比起缓存最久的数据,最近输入的数据更有可能用到。这通常是一个不错的假设。

    新算法将确保缓存的容量处于预定义的内存范围之内。确切的范围可能很难计算,因为缓存中的对象在

    不断变化,而且它们的引用包罗万象。为缓存设置正确的大小是一项非常复杂的任务,需要将所使用的内存容量与检索数据的速度加以平衡。

    解决这个问题的另一种方法是使用java.lang.ref.SoftReference类跟踪

    缓存中的对象。这种方法保证这些引用能够被移除,如果虚拟机的内存用尽而需要更多堆的话。

    ClassLoader

    Java

    ClassLoader结构的使用为内存泄漏提供了许多可乘之机。正是该结构本身的复杂性使ClassLoader在内存泄漏方面存在如此多的问题。

    ClassLoader的特别之处在于它不仅涉及“常规”的对象引用,还涉及元对象引用,比如:字段、方法和类。这意味着只要有对字段、方法、类或

    ClassLoader的对象的引用,ClassLoader就会驻留在JVM中。因为ClassLoader本身可以关联许多类及其静态字段,所以就有

    许多内存被泄漏了。

    确定泄漏的位置

    通常发生内存泄漏的第一个迹象是:在应用程序中出现了OutOfMemoryError。这通常

    发生在您最不愿意它发生的生产环境中,此时几乎不能进行调试。有可能是因为测试

    环境运行应用程序的方式与

    生产系统不完全相同,因而导致泄漏只出现在生产中。在这种情况下,需要使用一些开销较低的工具来监控和查找内存泄漏。还需要能够无需重启系统或修改代码就

    可以将这些工具连接到正在运行的系统上。可能最重要的是,当进行分析时,需要能够断开工具而保持系统不受干扰。

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,883
精华内容 3,953
关键字:

java内存泄漏

java 订阅