如何理解Java的垃圾回收机制

Android性能调优之垃圾回收机制

本篇文章大概按照以下逻辑来讲述

1.什么是垃圾回收(GC)

2.垃圾回收机制对于我们来说有什么好处?又有什么缺点?

3.什么时候会发生垃圾回收

4.垃圾回收它是如何工作的?

5.具体的回收方式和回收算法

6.OOM时如何调整

7.JVM 的内存划分

技术详情

1.什么是垃圾回收(GC)

垃圾回收或GC(Garbage Collection),是一种自动的存储管理机制,它是Java语言的一大特性,方便了我们这些程序员编码,把内存释放工作的压力都转让到了系统,故而是以消耗系统性能为代价的。

2.垃圾回收机制对于我们来说有什么好处?又会带来哪些坑?

以下我列举一下系统自动垃圾回收给我们带来的一些好处:

1.让作为程序员的我们专注于逻辑实现,提高了我们的编码效率
2.能够保护程序的完整性,垃圾回收是Java语言的安全策略的一个重要部分

但是随之的,也会到来一些缺点:
1.系统层面负责垃圾回收,明显会加大系统资源的开销,从而影响程序的性能
2.垃圾回收机制也存在不完备性,并不能百分百保证回收所有的垃圾内存

3.什么时候会发生垃圾回收

1.应用进程空闲的时候,GC会回收空闲进程的内存资源。
2.应用进程繁忙的时候,当需要的内存资源不足时,GC会强制执行回收优先级较低的进程资源,如果还是不足,再回收两次,还是不足,就会报OOM。

4.垃圾回收它是如何工作的?

主要流程:根据一定的算法判断某个对象是否存活,然后把判定是垃圾的对象进行回收。

GC的流程主要分为以下几种:
1.可回收对象的判定
2.通过某些算法垃圾回收

1.可回收对象的判定

可通过以下两种方法判定对象是否可以回收:

1.1 引用计数算法
这种算法的工作原理是:
首先给每一个对象添加一个计数器
当程序的某一个地方引用了这个对象,计数器的值就加1
当引用失效时,计数器的值就减1
当某一个对象的计数器值为0,则判定这个对象不可能被引用
这种算法对于系统来说比较简单,高效,垃圾回收器运行较快,不需要长时间中断我们程序的运行,缺点是很难处理循环引用,这就导致互相引用的对象无法被回收。

 OC(Objective-C)中的垃圾判定就是用的引用计数方法

1.2 GC Root可达性分析算法
这种算法的工作原理是:
以称作“”GC Root”对象作为起点向下搜索
每走过一个对象,就生成一条引用链
当GC Root不可到达对象时,这个对象就是不可用的,可回收

程序中能够被用来当做GC Root对象的有:

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

2.方法区中静态属性引用的对象

3.方法区中常量引用的对象

4.本地方法栈中JNI引用的对象

2.通过某些算法垃圾回收

以上内容讲述了系统如何去判定某一个对象是否是垃圾,是否应该被回收。接着,当判定了某一个对象为垃圾对象后,系统就要开始进行回收了,那么系统的垃圾回收算法以下几种:

  1. 标记清除算法
  2. 复制算法
  3. 标记整理算法
  4. 分代回收算法

2.1标记清除算法

先进行标记,然后进行清除
这个算法优点易于理解,容易实现,只需将特定地址的空间进行处理。
缺点,把整个区域弄得非常不完整,形成很多碎片化的内存,对于分配大内存的对象,
无法申请足够的空间,再次触发GC。

2.2复制算法

复制算法是对标记清除算法导致内存的碎片化的一个优化方案。原理如下:
1.复制算法将内存分为A和B两个区域
2.将A中存活的对象复制到B区域中
3.将A区域的所有对象都清除,这样A区域就是一个完整的内存块了,避免内存碎片化。
缺点是内存减半

2.3标记整理算法

是对于标记清楚的一个优化,原理如下:
1. 需要进行存活对象的标记
2. 存活的对象向一端移动,
3. 然后把另一端的内存进行清理
这个也能避免内存碎片化问题,但效率不怎样,毕竟相对于复制算法,多了一步效率同样较低的标记过程,而与标记清除算法相比,多了一步内存整理过程,效率上明显更低。
适用于存活对象多,回收对象少的情况。

2.4分代回收算法

根据不同对象的不同特性,使用不同的算法进行处理,所以严格来讲并不是一个新的算法,而是属于一种算法整合方案,我们知道:
1. 复制算法适用于存活对象少,回收对象多的情况。
2. 标记整理算法适用于存活对象多,回收对象少的情况。

具体使用方式:
根据jvm特性:年轻代每次gc回收大部分对象,存活量较少,故用复制算法
年老代存活对象较多,且没有其他内存为年老代分配担保,推荐标记整理算法

之前说的复制算法是将内存均分为二,但是在分代回收中,并不是这样,而是根据Eden:Survivor A:Survivor B= 8:1:1,具体的过程是:

1.新创建一个对象,默认是分在Eden区域,当Eden区域内存不够的时候,会触发一次Min
or GC(新生代回收),这次回收将存活的对象放到Survivor A区域,然后新的对象继续放在Eden区域

2.再创建一个新的对象,要是Eden区域又不够了,再次触发Minor GC,这个时候会把Eden区域的存活对象以及
Survivor A区域的存活的对象移动到Survivor B区域,然后清空Eden区域以及Survivor A区域

3.如果继续有新的对象创建,不断触发Minor GC,有些对象就会不断在Survivor A区域以及Survivor B区域
来回移动,但移动次数超过15次后,这些对象就会被移动到老年代区域

4.如果新的对象在Minor GC后还是放不下,就直接放到老年代

5.如果Survivor区域放不下该对象,这直接放到老年代

6.如果老年代也满了,就会触发一次Full GC(major gc)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章