垃圾收集器和内存分配策略

可达性分析算法

可达性算法图解

当一个对象到GC Roots没有任何引用链(用图论的话说,就是从GC Roots节点触发到某个节点不可达)时,则证明此对象是不可用的。也就是说该对象是可回收的。

什么是GC Roots?

在Java语言中,可作为GC Roots的对象包括下面几种。

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI(即一般所说的Native方法)引用的对象

对象何时宣告死亡

要真正宣告一个对象死亡,至少需要经历两次标记过程:

  1. 如果对象在经历一次可达性分析之后发现没有与 GC Roots 相连接的引用链,那么他将会被第一次标记。

  2. 如果这个对象被判定有必要执行 finalize() 方法,那么这个方法将会被放置在一个叫做 F-Queue 的队列中,并在稍后由一个虚拟机建立的,低优先级的 Finalizer 线程去执行它。稍后GC将对 F-Queue 中的对象进行第二次小规模标记。

两次标记成功之后,GC便会将这个对象收回,对象宣告死亡。

那么第一次被标记之后有没有办法逃脱GC回收呢?

答案是有的,在进入 F-Queue 中时或者已经在队列中的这一段时间内,只要重新与引用链上的任何一个对象建立联系即可。

回收方法区(永久代)

在堆中,尤其是在新生代中,常规应用进行一次垃圾收集一般可以回收70%-90%的空间,但是在永久代垃圾回收率却远低于此。

永久代垃圾回收主要负责两部分内容:

  1. 废弃常量
    没人用则进行回收

  2. 回收无用类
    判断一个常量是否需要回收比较简单,但是回收一个类需要满足下面三个条件。

    • 该类所有的实例已经被回收,也就是Java堆中不存在该类的任何实例
    • 加载该类的类加载器已经被回收
    • 该类对应的java.lang.Class对象没有在任何地方被使用,无法在任何地方通过反射调用该类的方法。

回收永久代的常用场景:

在大量使用反射,动态代理,CGLib等框架,动态生成JSP以及OSGi这类频繁自定义ClassLoader的场景都需要虚拟机具备类卸载功能,以保证永久代不会发生内存溢出。

垃圾收集算法

  1. 标记--清楚算法

标记过程前面已经介绍过,一个对象需要经历两次标记的过程才能被确定为可回收的对象,清除时直接释放原对象所占的内存空间即可。

这样做的问题也随之而来,会带来内存碎片,这将导致如果突然加载一个大的对象将会导致内存溢出的问题。

另外该算法还存在效率问题,标记和清除两个过程的效率都不够高。

  1. 复制算法

复制算法为解决效率问题而生,它将内存划分为两块相等的空间,每次只使用其中一块,当这一块内存用完之后,就将这块内存中还存活的对象复制到另外一块内存中,再把该内存块中的内存全部释放掉。

该算法顺手也把内存碎片的问题给解决了,但是该算法付出的代价也很大--将内存缩小了一半。

然而,很多商业虚拟机采用该算法回收新生代的对象,他们在使用该算法的时候,并不会按照一比一的比例去划分内存,而是按照8:1:1的比例将内存划分为3个部分,这三个部分分别对应新生代的Eden,From Survivor,To Survivor区。

每次使用时,只使用其中的Eden和From Survivor区,也就是说每次只使用内存的90%的容量。当GC时,将Eden和From Survivor中还存活的对象存放在To Survivor区中,当To Survivor区中内存不足以存放下所有新生代存活的对象时,需要依赖其他内存进行分配担保(这里指老年代)。

分配担保--即新生代发生GC时,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象总空间。

  1. 标记--整理算法

该算法是标记过程与前两种无异,但是后续步骤是让所用存活对象都向一端移动,然后将存活的对象按地址大小进行排列,最后将大于队列末端的地址全部释放掉。

该算法很适合对老年代进行GC。

  1. 分代收集算法
    对新生代采用复制算法,对老年代采用标记--整理算法。

HptSpot算法实现

  1. 枚举根节点

从可达性分析中从GC Roots节点找引用链这个操作为例,可作为GC Roots的节点主要是全局性的引用(例如常量和静态属性)与执行上下文(例如栈帧中的变量表),现在很多应用仅仅方法区就有数百兆,如果逐个检查这里面的引用,必然耗费很多时间。

枚举根节点就是解决如何找到GC Roots的问题。

使用一组称为OopMap的数据结构来达到这个目的。

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

推荐阅读更多精彩内容