java内存泄漏

一、什么是内存泄漏

  开发中,都能遇到或者听过两种关于java内存的异常情况:内存溢出(out of memory)和内存泄漏(memory leak)。

  内存溢出指的是程序需要申请新的内存时,没有足够大小的内存空间供其使用。常见类型:

    1、java.lang.OutOfMemoryError: Java heap space  堆内存溢出   解决办法:通过-Xmn(最小值)–Xms(初始值) -Xmx(最大值)参数手动设置 Heap(堆)的大小

    2、 java.lang.StackOverflowError 栈溢出  解决办法:通过Xss参数调整大小

    3、 java.lang.OutOfMemoryError: PermGen space  解决办法:通过MaxPermSize参数设置PermGen space大小

  内存泄漏指的是程序申请内存后,当不再使用时,本该被回收却始终无法释放或是不能及时的释放已申请的内存空间。内存泄漏,如果数量庞大,最终是会导致内存溢出的。

  对用户来说,内存泄漏并不会产生什么危害。程序代码、运行对用户是完全透明的,真正的危害性在于内存泄漏可能导致的最终的内存溢出,程序崩溃终止。

  这里,java开发人员一般会有疑问:既然java存在GC,为什么还会发生内存泄漏?

  简单说说GC的回收:

    java GC会监控所有堆中创建的对象的运行状况,监控对象是否可达(从GC Roots根开始向下搜索),如果对象不可达,则其就可以被GC回收。GC由jvm自动执行,不可人为干预(System.gc()方法只是建议jvm去执行回收动作,并不能确定一定会即时的去执行)

  内存泄漏为什么发生:

    实际的开发过程中,可能会存在着无用但可达的对象,这些对象不能被GC回收,所以就导致了内存泄漏的产生。

二、java中案例

  1、静态集合类中存储对象

    static List<Object> list = new ArrayList<>();
    
    public static void main(String[] args) {
        for(int i =0; i<10; i++){
            Object object = new Object();
            list.add(object);
            object = null;
        }
        
    }

  静态集合类中,循环申请对象放入集合中。后面仅仅是对新申请的对象置null,并不能引起GC对于这个对象的回收,因为集合类仍然对其保持着引用,

  也就是可达的(list引用指向的内存空间中存在指向 Object 对象的引用)。如果后面的程序中,不再使用集合list,则这就产生了内存溢出。一般好的习惯,不使用的集合clear,然后置为null。

  2、单例模式

    单例的生命周期和应用程序是一样长的,所以单例程序中,如果持有对外部对象的引用的话,那么这个外部对象是不能被回收的,则会导致内存泄漏的产生。

  3、一些提供close的资源未关闭导致内存泄漏

    数据库连接(dataSourse.getConnection()),网络连接(socket)和io连接必须手动close,否则是不能被回收的。

  

原文地址:https://www.cnblogs.com/eric-fang/p/10270218.html