JVM之垃圾收集策略

背景:看完《深入理解Java虚拟机》和相关博客,对JVM还是没有一个条理清晰的认识,遂提取了书中相关知识点和参考相关优秀博客并整理成JVM专题博文系列,帮助自己巩固并理清有关JVM的知识重点,也分享出来给有需要的童鞋,如有差错,欢迎拍砖!

在之前,我总结了JVM之内存结构中提到各种垃圾回收器,今天就来聊聊它们的回收策略

我们知道JAVA最大的优点就是可以实现自动内存管理,这极大的便利了JAVA程序员,降低了使用成本。但这也使得平时我们在使用JAVA编程时不太关注JVM到底是怎样进行内存回收的,只有在需要实际对JVM进行系统性能调优,这里的场景可能是在系统面临极致性能优化要求时,我们才发现需要对JAVA的整体内存结构以及内存回收机制要有一定的认识和了解才行。

JVM垃圾回收

GC (Garbage Collection)的基本原理:将内存中不再被使用的对象进行回收,GC中用于回收的方法称为收集器,由于GC需要消耗一些资源和时间,Java在对对象的生命周期特征进行分析后,按照新生代、旧生代的方式来对对象进行收集,以尽可能的缩短GC对应用造成的暂停

对新生代的对象的收集称为minor GC;
对旧生代的对象的收集称为Full GC;
程序中主动调用System.gc()强制执行的GC为Full GC。

不同的对象引用类型, GC会采用不同的方法进行回收,JVM对象的引用分为了四种类型:

强引用:默认情况下,对象采用的均为强引用(这个对象的实例没有其他对象引用,GC时才会被回收)
软引用:软引用是Java中提供的一种比较适合于缓存场景的应用(只有在内存不够用的情况下才会被GC)
弱引用:在GC时一定会被GC回收
虚引用:由于虚引用只是用来得知对象是否被GC

在图中,我们也大致对整个垃圾回收系统进行了标注,这里主要涉及回收策略、回收算法、垃圾回收器这几个部分。形象一点表述,就是JVM需要知道那些内存可以被回收,要有一套识别机制,在知道那些内存可以回收以后具体采用什么样的回收方式,这就需要设计一些回收算法,而具体的垃圾回收器就是根据不同内存区域的使用特点,采用相应地回收策略和算法的具体实现了。

我们也标注了不同垃圾回收器所适用的特定内存区域,对于JVM垃圾回收这块的优化,就是我们需要在了解这些垃圾回收算法、垃圾回收器特点后能够根据自己应用的场景选择合适的垃圾收集器,以及各区域垃圾收集器的搭配关系。

回收策略

我们知道,JVM进行内存回收的主要目的是为了回收不再使用的内存,因为在进行JAVA程序编写时,我们只有new的操作,而不需要收工释放不再使用的空间,如果这些空闲内存不能及时被回收,很快我们的JVM内存空间就会泄露(新申请内存空间的操作失败,导致程序报错),所以回收不再使用的内存的目的则是为了及时释放空间,腾笼换鸟,以防止内存泄漏。

那么问题来了,JAVA程序申请了那么多的内存空间,那些内存才能被认定是不再使用的内存呢?搞错了,如果把正在被程序使用的内存给释放了,程序逻辑就空指针异常了!

由于程序计数器、Java虚拟机栈、本地方法栈都是线程独享,其占用的内存也是随线程生而生、随线程结束而回收。而Java堆和方法区则不同,线程共享,是GC的所关注的部分。
在堆中几乎存在着所有对象,GC之前需要考虑哪些对象还活着不能回收,哪些对象已经死去可以回收,所以回收对象所占用的内存是JAVA垃圾回收的主要目标。

有两种算法可以判定对象是否存活:

引用计数算法:给对象中添加一个引用计数器,每当一个地方应用了对象,计数器加1;当引用失效,计数器减1;当计数器为0表示该对象已死、可回收。但是它很难解决两个对象之间相互循环引用的情况。

可达性分析算法:通过一系列称为“GC Roots”的对象作为起点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连(即对象到GC Roots不可达),则证明此对象已死、可回收。Java中可以作为GC Roots的对象包括:虚拟机栈中引用的对象、本地方法栈中Native方法引用的对象、方法区静态属性引用的对象、方法区常量引用的对象。

那么如何判断对象是处于可回收状态的呢?在主流的JVM中是采用“可达性分析算法”来进行判断的。

这个算法的基本思路就是通过一系列的称为“GC Roots”的对象作为起始点,并从这些节点开始往下进行搜索,搜索走过的路径我们称之为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,我们就称之为对象引用不可达,则证明这个对象是不可用的,就可以暂时判定这个对象为可回收对象。示意图如下:

可达性分析算法

在图中虽然Obj F与Obj J之间互相有关联但是它们到GC Roots是不可达的,所以将会被判定为可回收对象。既然如此,什么样的对象可以作为GC Roots对象呢?
在JAVA中可以被作为GC Roots的对象主要是:虚拟机栈-栈帧中的本地变量表所引用的对象、方法区(<JDK1.8)中类静态属性所引用的对象/常量属性所引用的对象、本地方法栈中引用的对象。

这里还需要注意一个小的细节,就是被判定为对象不可达的对象也并非会被立刻回收,在学习JAVA语法是我们应该学习过finalize()方法,如果对象重写了finalize方法,并重新把this关键字赋值给了某个类变量或对象的成员变量的话,该对象就会被"救活",具体过程可参考上图所示,只是这种方式并不鼓励大家使用,了解下就行。

在关于如何判定对象是否属于不再使用的内存时,还有个通常会被大家错误认为是JVM使用的方式-“引用计数法”,事实上引用计数法的实现比较简单,判定效率也比较高,在Python语言中就使用了这种算法进行内存管理,但是它有一个比较难解决的对象之间循环引用的问题,所以在JAVA虚拟机里并没有选用“引用计数法”来管理内存,需要大家注意下!

参考

面试必问之JVM原理
一张图看懂JVM之垃圾回收算法详解


技术讨论 & 疑问建议 & 个人博客

版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议,转载请注明出处!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容