来自JVM的灵魂拷问:你是什么垃圾?

写在前面

魔都才开始垃圾分类,有些人还是傻傻分不清垃圾应该怎么分类,Java真是伟大的语言(傲娇脸)早就实现垃圾分类回收了! 还不懂就out了!

什么?你说现实里的垃圾分类有图文说明,看看就明白?Java里的垃圾回收是算法写的,看不懂? 拜托!要是看看就明白,怎么还会流传“猪能吃的是湿垃圾,猪不吃的是有害垃圾……”

但是Java世界的回收划分很简单,只分可回收还是不可回收~

所以计算机的世界其实更简单。

Java开发需要熟悉GC吗?

虽然Java开发同学不用像C和C++的同学,自己申请了内存,要惦记着不用的时候释放掉,申请了就不管了,但是不用关心不代表它不重要,有些看不见的不代表不会影响你。

回收哪些对象 —— To be or not to be

马路上很常见的垃圾桶分为:干垃圾和可回收垃圾,像纸箱、金属、塑料瓶,都是属于可回收的。

在0-1的世界里,所谓“垃圾回收”,就是指收回那些不可能再被任何途径使用的对象所占的内存空间,释放了这些内存可以给需要的对象使用。

那么JVM里是怎么来分的?或者说哪些对象是需要被回收的?

哪些对象可回收?

主要有两种算法来判断:引用计数法和可达性分析法。

算法 思想 优点 缺点
引用计数法 给对象中添加一个引用计数器,每当一个地方引用这个对象时,计数器值+1;当引用失效时,计数器值-1。 判定效率很高 很难解决对象之间相互引用的情况; 开销较大、频繁且大量的引用变化,带来大量的额外运算
可达性分析法 通过一系列称为“GC Roots”的对象作为起始点,从这些节点向下搜索,当GC Roots到某个对象不可达时,这个对象就是可回收的。 更加精确和严谨,可以分析出循环数据结构相互引用的情况 实现比较复杂;需要分析大量数据,消耗大量时间

引用计数法,最大的问题是很难解决对象之间互相引用的情况。

  • 1

这是两个对象互相引用的情况,除此之外,这两个对象再无引用,但因为它们的引用计数不为0,所以引用计数器无法通知GC收集器回收它们。

  • 2

这是循环引用的情况,没有外部引用指向它们,但它们的引用计数不为0,就无法进行回收了。

所以主流的jvm都不使用引用计数法来管理内存,而是采用下面的可达性分析法,下图是它的基本思路示意图。

由图可知,object5、object6和object7都没有到GCRoots对象的引用链,它们都会被回收。

可以做为GC Roots的包含以下几种:

四种引用类型

类型 描述对象 使用情况
强引用 StrongReference 类似"Object obj = new Object()"这类的引用 如果一个对象具有强引用,那垃圾回收器绝不会回收它。
软引用 SoftReference 用来描述还有用但并非必需的对象 内存空间不够时(抛出OutOfMemoryError之前),才会被垃圾回收
弱引用 WeakReference 非必需对象 只能生存到下一次垃圾回收之前,无论内存是否足够 (只能活到下一集)
虚引用 PhantomReference 幽灵引用或幻影引用 唯一目的就是能在这个对象被回收时收到一个系统通知

几种类型的继承关系:

// Todo

怎么回收?

回收算法

ref

  1. 图解 Java 垃圾回收机制
  2. 简述Java垃圾回收
  3. 【深入理解JVM】GC
  4. Java垃圾回收(GC)机制详解

猜你喜欢

转载自juejin.im/post/5d25aa94f265da1b8f1aea57
今日推荐