• 如何判断对象可以被回收


    jvm是如何判断对象可以被回收的?

    方法一:引用计数法

      jvm给对象中添加一个引用计数器,每当有一个地方引用它,计数器加1,当引用失效,计数器减1,任何时候计数器为0的对象就是不可能再被使用的。

      此方法存在的局限性:不能解决对象之间相互引用的问题。例如:

      

       

      如上图所示,栈中引用了堆中对象objA和objB,此时objA和objB的引用计数器都加1;而且把objA赋值给objB的成员变量,objB赋值给objA的成员变量,也就是说objA和objB之间存在引用,此时objA和objB的引用计数器都再加1变成2。而当栈中对objA和objB的引用失效了之后,此时objA和objB实际上已经是无用对象了,但是objA和objB的引用计数器也都只是减1尚且不为0,因此objA和objB两个对象都不会被回收。任然占用堆的内存。这样的情况多了就可能出现内存泄漏问题。

    方法二:可达性分析算法

      通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连(用图论的话来说,就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的。

      

       

      在Java语言中,可作为GC Roots的对象包括下面几种:

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

        方法区中类静态属性引用的对象。

        方法区中常量引用的对象。

        本地方法栈中JNI(即一般说的Native方法)引用的对象

    方法三:

      常见引用类型:

        强引用:普通的变量引用

        软引用:将对象用SoftReference软引用类型的对象包裹,正常情况不会被回收,但是GC做完后发现释不出空间存放新的对象,则会把这些软引用的对象回收掉。软引用可用来实现对内存敏感度不高的高速缓存。public static SoftReference<User> user = new SoftReference<User>(new User());

        弱引用:将对象用WeakReference弱引用类型的对象包裹,弱引用跟没有引用差不多,GC会直接回收掉,很少用。

        public static WeakReference<User> user = new WeakReference<User>(new User());

        虚引用:虚引用也成为幽灵引用或幻影引用,它是最弱的一种引用,几乎不用。

    方法四:finalize()方法最终判定对象是否存活

      即使在可达性分析算法中不可达的对象,也并非是“非死不可”de ,这时候它们暂时处于“缓刑”阶段,要真正宣告一个对象死亡,至少要经历再次标记过程。

      标记的前提是对象在进行可达性分析后发现没有与GC Roots相连接的引用链。

      1、第一次标记并进行一次筛选:

        对象没有覆盖finalize()方法,对象将直接被回收。

      2、第二次标记:

        如果这个对象覆盖了finalize()方法,只要重新与引用链上的任何一个对象建立关联即可。

    PS:如何判断一个类是无用的类

      类需要同时满足下面3个条件才能算是无用的类:

      1、该类所有的实例都已经被回收,也就是堆中不存在该类的任何实例。

      2、加载该类的ClassLoader已经被回收。

      3、该类对应的java.lang.Class对象没有任何地方呗引用,无法在任何地方通过反射访问该类的方法。

    学习没有一蹴而就,放下急躁,一步一步扎实前进
  • 相关阅读:
    深度优先和广度优先
    ajax<转>
    display:inline-block后会有间隙
    css样式多了个分号
    回答
    return false作用
    824. Goat Latin
    7. Reverse Integer
    48. Rotate Image
    9. Palindrome Number
  • 原文地址:https://www.cnblogs.com/jpxjx/p/12552790.html
Copyright © 2020-2023  润新知