破茧(一)GC回收机制

转眼已是而立之年,随波逐流若干年并无太大成就,目前在某信集团安安稳稳做一个PM混日子

某日,突然顿悟,不愿再混吃等死,决定从新开始认识和学习陪伴自己多年的好伙伴“Android”

记录下重新渡劫的点点滴滴!


一、前言

一直都没有深入去了解GC回收机制,对于软件开发者来说还是有必要好好研究一下的,对APP的优化起到很好的帮助。
以下是参考过的文章,非常感谢各位作者!

Android小知识-内存回收机制

Android内存优化5 了解java GC 垃圾回收机制3

Java gc(垃圾回收机制)小结,以及Android优化建议

android 垃圾回收机制

Android GC机制介绍

两个互相引用对象的垃圾回收

二、GC机制

1. 什么是GC

GC是Garbage Collection [ˈɡɑːrbɪdʒ kəˈlekʃn]或Garbage Collector [ˈɡɑːrbɪdʒ kəˈlektər]的缩写,也叫垃圾回收器。为了避免出现内存问题,JAVA引入了自动内存管理机制,确保所有被引用的对象保留在内存中,把没有引用的对象内存进行回收。

2. 检测垃圾的方式

  • 引用计数法:给一个对象添加引用计数器,每当有一个地方引用它,计数器就加1,引用失效就减1。
    缺陷:如果有两个对象互相引用,除此之外没有其他任何对象引用他们,实际上这两个对象已经无法访问、但他们互相引用,计数不为0,所以无法回收。

  • 可达性分析算法 :通过一系列的被称为“gc roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到“gc roots”没有任何引用链相连时,则证明此对象是不可用的。
    可以作为“gc roots”的对象:
    (1)虚拟机栈(栈针中的局部变量表)中引用的对象
    (2)方法区中类静态属性引用的对象。
    (3)方法区中常量引用的对象
    (4)本地方法栈中JNI引用的对象。

    image.png

    JVM在做垃圾回收的时候,会检查堆中的所有对象是否被这些“gc roots”的对象所引用,不能够被引用的对象就会被垃圾回收器回收。

3. 回收垃圾的方式

  • 标记&清除(mark&sweep)
    此算法分为两个阶段:标记和清除。标记所有需要回收的对象,之后统一回收。
    缺陷:效率低,标记清除之后会产生大量碎片。效果图如下:
    image
  • 复制(copying)
    此算法把内存空间划分为两个相等的区域,每次只使用其中的一个区域。垃圾回收时,遍历当前使用区域的所有对象,将有引用的对象复制到另一个区域。此算法每次只处理有引用的对象,因此复制成本比较小,同时复制过去之后还能进行相应的内存整理,所以不会出现碎片问题。
    缺陷:需要两倍的内存空间。效果图如下:
    image
  • 标记&整理(mark&compact):
    此算法结合了以上两个算法的优点,也分两个阶段,第一阶段是从根节点遍历所有对象标记所有能被引用的对象,第二阶段遍历整个堆中的对象,清除所有未被标记的对象,并把所有存活对象“压缩”到堆的其中一块,按顺序排放。避免了“标记--清除”的碎片问题,也没有“复制”的空间问题。效果图如下:
    image
  • 分代收集算法
    image

内存分为三个部分:
(1)Young Generation [dʒenəˈreɪʃn]:新生代,分成Eden [ˈiːdn],Survivor [sərˈvaɪvər] 0 和 Survivor [sərˈvaɪvər] 1 三个部分。所有new 的对象都都在Eden区,当Eden区满时,可引用的对象将被复制到其中一个Survivor [sərˈvaɪvər]区,当此Survivor [sərˈvaɪvər]区的对象占用空间满时,此区可引用的对象又被复制到另一个Survivor [sərˈvaɪvər]区,反复多次后依旧可引用的对象将被复制到老年代。
(2)Old Generation [ˌdʒenəˈreɪʃn]:老年代,在这个区域存储的都是从新生代中转过来的长期可引用的对象;当可引用的对象在老年代存在时间达到一定程度时,将会被复制到持久代。
(3)Permanent Generation [ˈpɜːrmənənt ˌdʒenəˈreɪʃn]:持久代,用于存放静态的类和方法,以及JRE库的类和方法信息,持久代对垃圾回收没有显著的影响。

三、GC对APP的影响

GC在运行时,会停止其他所有线程,在GC开始运行和结束时均会发生,对象越多,停止的时间越长,会造成APP卡顿,因此需要尽量减少GC的运行时间,避免发生卡顿;为了达到这个目的,我们需要先了解一下GC的执行条件。

四、GC的触发条件

  1. GC所在线程的优先级最低,当程序空闲时,GC会被执行;
  2. 当内存不足的时候,JVM会强制执行GC,当一次运行过后,内存仍然不足,将再次运行GC,若还是不足,将发生内存泄漏(OOM)。

五、优化

  1. 少用静态对象,静态对象从新建的时候就存在于Permanent Generation [ˈpɜːrmənənt ˌdʒenəˈreɪʃn]持久代中,不会被GC回收;
  2. 对象使用完后,尽快释放,设置对象为null,空对象会加快GC的执行速度;
  3. 分散创建或删除对象时间,集中短时间内创建或删除大量对象,会导致内存紧张,JVM会增加执行GC的次数;
  4. 能用基本类型如int、long,就不用Integer、Long对象;基本类型变量占用的内存资源比引用类型变量占用的少得多;
  5. 尽量使用StringBuffer,而不用String来累加字符串;String每赋值一次,就会重新分配一次内存,String str = str1+str2+str3+str4+str5,每多一个“+”,就会多创建一个对象;
  6. 根据不同的场景使用不同的对象引用方式:

强引用:通过new出来的对象,即使内存不足,GC进行垃圾收集的时候也不会主动回收。

Object obj=newObject();

软引用:在内存不足的时候,GC进行垃圾收集的时候会被GC回收。

Object obj=newObject();SoftReference<Object> softReference = new SoftReference<>(obj);

弱引用:无论内存是否充足,GC进行垃圾收集的时候都会回收。

Object obj=newObject();WeakReference<Object> weakReference = new WeakReference<>(obj);

虚引用:和弱引用类似,主要区别在于虚引用必须和引用队列一起使用。

Object obj=newObject();ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
PhantomReference<Object> phantomReference = new PhantomReference<>(obj, referenceQueue);

引用队列:如果软引用和弱引用被GC回收,JVM就会把这个引用加到引用队列里,如果是虚引用,在回收前就会被加到引用队列里。

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

推荐阅读更多精彩内容

  • 来自: Android梦想特工队作者: Aaron主页: http://www.wxtlife.com/原...
    技术特工队阅读 4,395评论 0 28
  • JVM架构 当一个程序启动之前,它的class会被类装载器装入方法区(Permanent区),执行引擎读取方法区的...
    cocohaifang阅读 1,688评论 0 7
  • 1、什么是垃圾回收? 程序的运行必然需要申请内存资源,无效的对象资源如果不及时处理就会一直占有内存资源,最终将导致...
    JavaLover阅读 887评论 0 1
  • Java虚拟机整体篇幅如下: Java虚拟机基础——1Java的内存模型Java虚拟机基础——2JVM运行时数据区...
    隔壁老李头阅读 5,613评论 8 25
  • 如果你想要从太空观察地球,卫星技术就能够做到这一点。图中的海洋流是卫星地图展现的,紫色和粉红色的漩涡代表更暖的洋流...
    allever阅读 1,413评论 0 8