JVM | JVM内存分代模型及垃圾回收算法

自我要求,超越自我.jpg

如何定位垃圾?

  • 引用计数算法
    在Java领域,主流的Java虚拟机里面都没有选用引用计数算法来管理内存,主要原因是单纯的引用计数很难解决对象之间相互循环引用的问题;例如:objA.instance = objB 及objB.instance = objA,导致objA与objB互相引用着对方,导致被引用计数都不为0,引用计数算法就无法回收它们。

算法的基本思路:在对象中添加一个引用计数器,每当有一个地方引用它时,计数器就加一;当引用失效时,计数器值就减一;任何时刻计数器为0的对象就是不可能再被使用的。

  • 可达性分析算法
    当前主流的商用程序语言(Java、C#)的内存管理子系统,都是通过可达性分析算法来判定对象是否存活。
利用可达性分析判断对象是否可回收.jpg

算法的基本思路:通过“GC Roots”的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程所走过的路径称为“引用链”,如果某对象到GC Roots间没有任何引用链相连,或者说从GC Roots到这个对象不可达,则证明这个对象不可能再被使用。

非可达对象也不是“非死不可”:被判断为非可达对象暂时处于“缓刑”阶段,要想死亡,至少要经历两次标记过程:当对象进行可达性分析发现没有与GC Roots相连接的引用链,就会第一次标记,随后进行筛选,如果对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,那么虚拟机将这两种情况视为“没必要执行”;如果对象被判断有必要执行finalize()方法,那么该对象会放置在F-Queue的队列之中,然后会去执行finalize()方法,在这次方法执行之前,若重新与引用链上的任何对象建立了关联,那么就“逃脱了回收”,否则就会第二次标记并回收。

在Java体系中可作为GC Roots的对象包括以下几种:
1、虚拟机栈中引用的对象
2、方法区中类静态属性引用的对象
3、方法区中常量引用的对象
4、本地方法栈中引用的对象
5、Java虚拟机内部的引用
6、所有被同步锁(synchronize关键字)持有的对象

Java四种引用类型

  • 1、强引用
    在 Java 中最常见的就是强引用,把一个对象赋给一个引用变量,这个引用变量就是一个强引用,例如:Object obj = new Object()。
    当一个对象被强引用变量引用时,它处于可达状态,它是不可能被垃圾回收机制回收的,即使该对象以后永远都不会被用到 JVM 也不会回收。因此强引用是造成 Java 内存泄漏的主要原因之一。

  • 2、软引用
    软引用需要用 SoftReference 类来实现,对于只有软引用的对象来说,当系统内存足够时它不会被回收,当系统内存空间不足时它会被回收。软引用通常用在对内存敏感的程序中。

  • 3、弱引用
    弱引用需要用 WeakReference 类来实现,它比软引用的生存期更短,对于只有弱引用的对象来说,只要垃圾回收机制一运行,不管 JVM 的内存空间是否足够,总会回收该对象占用的内存。

  • 4、虚引用
    虚引用需要 PhantomReference 类来实现,它不能单独使用,必须和引用队列联合使用。
    虚引用的主要作用是跟踪对象被垃圾回收的状态。

常见的垃圾回收算法

1、分代收集理论

    当代商业虚拟机的垃圾收集器,大多数都遵循“分代收集”的理论进行设计,它建立在两个假说上之上:

  • 弱分代假说:绝大多数对象都是朝生夕死。
  • 强分代假说:熬过多次垃圾收集过程的对象就越难以消亡。
  • 跨代引用假说:跨代引用相对于同代引用来说仅占极少数。

    这两个分代假说共同奠定了常用垃圾收集器的一致的设计原则:收集器应该将Java堆划分为不同的区域,然后将回收的对象依据年龄(对象熬过垃圾收集过程的次数)分配到不同的区域之中存储。

    显而易见,如果一个区域中大多数对象都是朝生夕死,难以熬过垃圾收集器收集的过程,把它们放到一起,每次回收只关注如何保留少量存活而不是去标记那些大量将被回收的对象,就能以最小的代价回收到大量的空间;如果剩下的是难以消亡的对象,把它们放到一起,就使用较低的频率来回收这个区域;这样就兼顾了垃圾收集的时间开销和内存的空间有效利用。

    在Java堆划分不同区域之后,垃圾收集器就可以每次回收其中某些部分的区域——因此,就有了“Minor GC”、“Major GC”、“Full GC”这样的回收类型的划分——才能针对这些不同区域与里面存储对象存亡的特征相匹配的垃圾收集算法——因此,发展出“标记——复制算法”“标记——清除算法”、“标记——整理算法”等针对性的垃圾收集算法。

    这一切的出现都始于分代收集理论。

    很容易发现分代收集并非只是简单的划分一下内存区域那么容易,它至少存在一个明显的困境:对象不是孤立的,对象之间会存在跨代引用,存在相互引用关系的两个对象,是应该倾向于同时生存或者同时消亡的,依据这条假说,我们不应该再为少量的跨代引用去扫描整个老年代,也不必浪费空间专门记录每个对象是否存在跨代引用,只需在新生代建立一个全集的数据结构(该结构为“记忆集”,Remembered Set),标识出老年代哪块内存会存在跨代引用,当发生Minor GC时,只有包含跨代引用的小块内存里的对象才会被加入到GC Roots进行扫描。

分代收集名称定义:

  • 部分收集(Partial GC):指目标是部分收集整个Java堆的垃圾收集,其中又分为:
    1、新生代收集(Minor GC/Young GC):只是新生代的垃圾收集。
    2、老年代收集(Major GC/Old GC):只是老年代的垃圾收集。目前只有CMS收集器会有单独收集老年代的行为。
    3、混合收集(Mixed GC):收集整个新生代以及部分老年代的垃圾收集。目前只有G1收集器会有这种行为。
  • 整堆收集(Full GC):收集整个Java堆和方法区的垃圾收集。

2、标记——清除算法

最基础的收集算法,后续的收集算法大多以标记——清除算法为基础,对其缺点进行改进而得到的。

标记-清除算法.png

算法的基本思路:标记出所有需要回收的对象,在标记完成后,统一回收掉所有被标记的对象。

主要的缺点有两个:
1、执行效率不稳定,当大部分数据需要被回收时,就需要进行大量标记和清除的动作。
2、内存空间碎片化问题,标记、清除之后会产生大量不连续的内存碎片。

3、标记——复制算法【新生代】

标记——复制算法简称复制算法,为了解决标记——清除算法面对大量可回收对象时的执行效率问题。


标记——复制算法.png

把新生代分为一块较大的Eden空间和两块较小的Survivor空间,每次分配内存只使用Eden和其中一块Survivor。当发生垃圾搜索时,将Eden和Survivor中仍存活的对象一次性复制到另一个Survivor上,然后直接清除掉Edon和已用过的那块Survivor空间。

HotSpot虚拟机默认Eden和Survivor的大小比例是8:1,即10%的新生代是会被浪费掉的。当Survivor空间不足以容纳一次Minor GC之后存活的对象时,就需要以来其他内存区域进行分配担保。

4、标记——整理算法【老年代】

标记——整理算法.png

和标记—清除算法一样,从根节点递归标记所有可达的对象,让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。

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