为什么要了解GC
对于Java程序猿来说,内存分配与释放都交给JVM处理,而更多的精力能够投入到业务开发中去,这也是Java能够受广大开发者欢迎的重要原因之一。但问题来了,万一程序出现内存泄漏和内存溢出问题怎么排查,如何定位问题,所以防患于未然,了解JVM的GC原理是每位Java开发者的职业素养。
对象实例收集算法
1.引用计数算法
顾名思义,就是为对象添加一个引用计数,用于记录对象被引用的次数,对象引用计算为0,则表示对象可回收。Java并没有选择引用计数机制,因为它不可解决循环引用的问题。
2.可达性分析
Java选择的是可达性分析算法。其原理是将对象及其引用看作一个关系图,选定对象作为GC Roots,然后跟踪引用链条,如果一个对象和GC Roots之间不可达,也就是说不存在引用链条,那么即可认为是可回收对象。JVM会把虚拟机栈和本地方法栈中引用的对象、静态属性引用的对象和常量,作为GC Roots。
如图,GC Roots作为实例对象,obj1、obj2、obj3、obj4与GC Roots存在引用链条,而obj5、obj6、obj7与GC Roots不存在引用链条,呢么obj5、obj6、obj7则被视为可回收对象。
![](https://img.haomeiwen.com/i1933808/b63a578305ea1506.png)
GC算法
1.标记清除算法(Mark-Swap)
分为两个阶段:标记和清除。标记阶段的工作是标记可回收对象的内存。清除阶段的工作是清除已标记的内存。
优点:效率高。
缺点:多次清除后,会产生大量的内存碎片
![](https://img.haomeiwen.com/i1933808/36616cb5759c5294.jpg)
2.复制算法(Copying)
按内存容量分为两部分:已使用和未使用。把已使用部分的存活对象复制到未使用部分,统一回收已使用部分的全部空间,那么就不会出现Mark-Swap算法的内存碎片问题。
优点:效率高、保持内存的最大可用性。
缺点:当存活数量较多的时候,效率会骤降。
![](https://img.haomeiwen.com/i1933808/d883214cab0bcc66.jpg)
3.标记整理算法(Mark-Compact)
分为两个阶段:标记和整理。标记阶段和Mark-Swap阶段一样。整理阶段工作是把存活对象移向一端,统一处理可回收内存,解决了Copying算法和Mark-Compact算法的结构弊端。
优点:保持内存的最大可用性。
缺点:效率低。
![](https://img.haomeiwen.com/i1933808/cf6dba92c73c8c48.jpg)
垃圾收集器
Serial:串行--新生代--复制算法--响应速度优先--单CPU环境下的Client模式。
ParNew:并行--新生代--复制算法--响应速度优先--多CPU环境Server模式下与CMS配合使用。
Parallel Scavenge:并行--新生代--复制算法--吞吐量优先--适用于后台运算而且不需要太多交互的场景。
Serial Old:串行--老年代--标记-整理算法--响应速度优先--单CPU环境下的Client模式。
Parallel Old:并行--老年代--标记-整理算法--吞吐量优先--适用于后台运算而不需要太多交互的场景。
CMS:并行--老年代--标记-清除--响应速度优先--适用于互联网或者B/S业务。
G1:并行--新生代老年代都可--标记-整理算法+复制算法--响应速度优先--面向服务器端应用。
GC调优
从性能角度看,关注三个方面:内存占用、延时、吞吐量。
网友评论