JVM垃圾回收

回顾JVM的内存分配包括程序计数器,虚拟机栈,本地方法栈,JAVA堆和方法区5部分,其中前三是属于线程私有的,内存分配和回收有确定性,不多考虑回收的问题,因为线程或者方法结束时,内存自然回收。相对的,在JAVA堆和方法区里,需要注意内存回收的问题。

  1. 对象存活判断方法
    1.1 引用计数法,非Java
    给对象添加一个引用计数器,当有引用时,给之加一,引用减少,给之减一,当计数器为0代表不再存在引用。
    ️无法解决循环引用
    1.2 可达性分析
    通过定义GC Roots作为起始点,从这些节点往下搜索,路径称为引用链,当一个GC roots没有任何引用链相连,则证明对象不可用。如下o5,o6和GC roots是不可达的,如图:


    GC roots

    可以作为GC Roots的对象:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI引用的对象,即Native方法
  1. java引用类型
    2.1 强引用
    普遍存在的类似Object o = new Object()的引用
    2.2 软引用
    描述一些还有用但是非必需的对象,系统在发生内存溢出之前,会把这些对象列入回收范围做第二次回收,如果还是没有足够内存,才会抛出异常。提供SoftReference类实现软引用。
    2.3 弱引用
    只能生存到下一次垃圾回收之前,即处在回收边缘。当垃圾回收时,无论当前内存是否足够,都会回收只被弱引用关联的对象。提供WeakReference类实现弱引用。
    2.4 虚引用
    对象的虚引用关系不会对其生存时间构成影响,也无法通过虚引用取得一个实例,设置虚引用的唯一目的是能在这个对象被回收内存时收到一个系统通知。提供一个PhantomReference来实现虚引用。

  2. 方法区回收
    3.1 回收废弃常量
    常量没有被引用,或不存在对应字面值
    3.2 无用的类
    ️是否回收通过参数控制,可以进行回收的条件如下:

  • 类所有实例已经被回收,java堆中不存在该类的任何实例。
  • 加载类的ClassLoader被回收
  • 类对应的java.lang.class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
  1. 垃圾回收算法
    4.1 标记-清除
    基于之前的可达性分析,标记出所有需要回收的对象,在标记完成后统一回收。存在两个问题:1,效率,2,空间,会产生很多内存碎片。如果之后再分配大对象时,无法找到足够内存,而触发另一次新的垃圾收集动作。
    4.2 复制-算法
    将内存按容量分为大小相等的两块,每次只使用其中一块,当用完以后将还存活的对象复制到另一块上面,再把已经使用过的内存空间一次性清掉。每次只堆半个区进行回收,分配时也不用考虑内存碎片的问题,只要移动堆顶指针,按顺序分配内存即可。缺点是将内存分为两块,缩小了一半。
    细节是将堆分为eden区和两个survivor区,一般比例是8:1,在survivor空间之间进行复制清理,也就只有10%的内存浪费。
    ️如果另一个survivor区没有足够空间存放上一次新生代收集下来的存活对象,这些对象通过分配担保机制进入老年代。
    4.3 标记-整理
    复制算法在对象存活率较高时,需要很多的复制操作,效率较低。如果不想类似分配survivor区,需要额外的内存担保,所以老年代不能直接选用复制算法。根据其特性,使用标记-整理方法。先进行内存标记,标记可回收对象,和标记清除不同,标记-整理让这些所有存活对象都向一端移动,然后直接清理掉端边界以外的内存。
    4.4 分代收集
    分为新生代和老年代。新生代每次垃圾回收都有大批对象死去,选用复制算法。老年代对象存活率高,没有额外空间进行分配担保,必需使用标记-清除或者标记-整理进行回收。

  2. 垃圾收集器
    5.1 Serial串行收集器
    单独一个线程,新生代复制算法,老年代标记整理,都暂停所有用户线程,有很高的但线程效率,常用在client模式的服务上。
    5.2 ParNew收集器
    多个GC线程,并行多线程版本的Serial收集器,server模式下,首选的新生代收集器,与老年代收集器CMS配合。
    5.3 Parallel Scavenge收集器
    新生代收集器,采用复制算法,并行多线程,与ParNew不同在于通过参数设置吞吐量,GCTimeRatio-收集时间占比和MaxGCPauseMillis-最大GC时间。补充:通过UseAdaptiveSizePolicy设置根据监控数据自适应提供最大吞吐量。
    5.4 Serial Old收集器
    Serial收集器的老年代版本,单线程,主要用在client模式下。server模式主要和Parallel Scavenge配合,以及作为CMS的后备方案。
    5.5 Parallel Old收集器
    Parallel Scavenge的老年代版本,多线程,与Parallel Scavenge配合,保证吞吐量。
    5.6 CMS收集器
    低停顿,并发,最常用的收集器。收集过程有:初始标记,并发标记,重新标记,并发清除。缺点有以下3个:

  • 并发的缘故,CPU资源敏感
  • 无法清理浮动垃圾,垃圾不断新产生。如果导致CMS预留的内存无法满足需要,出现一次“Concurrent Model Failure” , 临时会启动Serial Old 收集器,关联参数,设置触发阈值,CMSInitiatingOccupancyFraction
  • 标记-清除,导致内存碎片,分配大对象没有连续空间,导致提前FGC。关联参数:
    UseCMSCompactAtFullCollection 在CMSfull GC时开启内存碎片整理过程。
    CMSFullGCsBeforeCompaction 执行参数设置的次数FGC后,进行压缩的碎片整理。
    5.7 G1
    以下4个特性:
  • 并行和并发:利用多CPU,多核优势,缩短停顿时间。
  • 分代收集:保留分代收集,但不再隔离。
  • 空间整合:分成region区域,整体看类似标记-整理,region间类似复制,不会产生内存碎片,收集后有规整的可用内存。
  • 可预测的停顿:有可预测的时间模型,指定停顿时间。因为可以有计划的进行全区域的垃圾收集。跟踪Region里的垃圾堆积的价值大小(回收后的空间和垃圾收集所需的时间经验值),后台维护一个优先列表,优先回收价值最大的Region,也是其名称G1(Garbage First)的由来。

️可能的问题:region区域之间对象的引用,是否需要扫描整个堆?
引申阅读:remember Set 在创建引用时,先检查引用关系,写入对应的region的remember set中,之后GC过程方便取到,避免全堆扫描。(个人理解)


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

推荐阅读更多精彩内容