zwz的学习之路

成长的路途还长

JVM——对象已死吗?(Java对象引用分析)

对象已死?

谈到JVM,就不得不提到他的自动内存管理,那么就离不开垃圾回收,那么,作为Java中,占据首要位置的对象,JVM如何确定它已经死亡? 或者说,何时GC将其回收?

现在主流的两个方式是:1.引用计数法 2.可达性分析算法

引用计数法

顾名思义,就是在对象每被引用一次,就将其自身用于计数的变量加一,当GC进行时,通过判断该变量是否等于0,从而决定是否回收。目前使用该方式的有Python等。
优点:简单明了,实现容易。
缺点:对于这种情况: 对象A中存在B的引用,对象B中存在A的引用,当两个对象除了对方之外,没有其他引用,且已经无用之后,计数却仍然不为零,这就造成了内存泄露。

可达性分析算法

通过确定GCroots,然后Gcroot向下寻找引用关系,能够找到引用关系的对象就不会被回收,否则回收。GC Roots一般选择有四种:
1.方法区的常量对于对象的引用。
2.方法区中类静态属性对于对象的引用.
3.虚拟机栈中本地变量中对于对象的引用。
4.本地方法区中对于对象的引用。

再谈引用

引用分为四种:

  • 强引用
  • 软引用
  • 弱引用
  • 虚引用

其中,强引用为 new出来的,只要引用关系还在,就永远不会被回收。
软引用次于强引用,当虚拟机将要发生OutOfMemory时,会触发GC回收这部分,如果回收后依旧不足,才会发生OutOfMemory异常。
弱引用更次于软引用,只要发生GC,将直接回收这部分,不管它是否在使用。
虚引用是最弱的引用,他的存在不会对对象有任何影响,唯一作用就是在对象被GC时,发出一个系统通知。

生存还是死亡?

当可达性分析过后,是否所有的不可达对象就一定会被回收?答案是否定的。
对于不可达对象,虚拟机还是要给他们一些机会的。此时,虚拟机会对这些对象进行二次标记,具体做法是:

第一次标记时,判断对象是否 覆盖了 finalized()方法,如果没有,它就死定了。如果覆盖了,虚拟机会判断是否有必要执行它的finalized方法,判断条件是这个方法是否被执行过。执行过就不再执行(只会执行一次)。

然后在第二次标记之前,如果对象的finalized方法中,重新将自己与可达对象引用上了 如 xxx=this。那么它就逃出生天。否则,GG。

回收方法区

方法区主要回收:废弃的常量、无用的类
废弃的常量很好理解,但是对于无用的类,怎么判断它无用呢?

虚拟机有一下条件:
1.该类的不存在任何实例
2.该类的类加载器被回收
3.该类对应的Java.lang.Class实例没有在任何地方被引用,即不能通过反射访问该类的方法。


多复习多看书。。。

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zwzsdy/article/details/79945835
个人分类: jvm知识学习
上一篇CentOs7 安装mysql5.6(源码安装)
下一篇剑指offer-旋转数组的最小数字
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭