java--GC原理分析与内存泄漏

 java使用的垃圾回收算法是根路径搜索算法,在介绍改算法前先说说引用计数算法:

   1 引用计数算法原理:给一个对象添加一个引用计数器,每当有一个地方引用他时,计数器加1;当引用失效时,计数器减1;任何时刻引用计数为0的对象就是不可能再被使用的,就会被回收。但是它的缺点就是很难解决对象之间相互循环引用的问题。所有java并没有采用该算法。

  2 根路径搜索算法原理:通过一系列的名为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连(用图论的话说就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的,被判定为可回收对象。

       可用作为GC Roots的对象有下面几种:

        (1)虚拟机栈中引用的对象(栈的本地变量表);

        (2)方法区中的类静态属性引用对象;

       (3)方法区中常量应用对象;

       (4)本地方法中JNI引用的对象;

内存泄漏:

  1 含义:对象不可达,即在有向图中,存在通路与之相连;对象是无用的,即程序不会再使用这些对象。如果满足上面的两个条件,就会出现内存泄漏。

2 原因有几种:

(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/parryyang/p/5748711.html

                   https://www.cnblogs.com/yl-saber/p/6907517.html

猜你喜欢

转载自blog.csdn.net/u010098159/article/details/81287716