Java GC

GC简介

Java的内存管理实际上就是对象的管理,其中包括对象的分配和释放。

对于程序员来说,分配对象使用new关键字;释放对象时,只要将对象所有引用赋值为null,让程序不能够再访问到这个对象,我们称该对象为"不可达的".GC将负责回收所有"不可达"对象的内存空间。

对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是"可达的",哪些对象是"不可达的".当GC确定一些对象为"不可达"时,GC就有责任回收这些内存空间。但是,为了保证GC能够在不同平台实现的问题,Java规范对GC的很多行为都没有进行严格的规定。例如,对于采用什么类型的回收算法、什么时候进行回收等重要问题都没有明确的规定。因此,不同的JVM的实现者往往有不同的实现算法

Java堆分代/分区

我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能。你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我们要找到哪些对象没用,这样就会对堆的所有区域进行扫描。而我们的很多对象都是朝生夕死的,如果分代的话,我们把新创建的对象放到某一地方,当GC的时候先把这块存“朝生夕死”对象的区域进行回收,这样就会腾出很大的空间出来。
新生代有一个有一个Eden区和两个survivor区(默认比例为8:1,两个suivivor区,一个叫from ,一个叫to),首先将对象放入Eden区,如果空间不足就向其中一个survivor区上放,如果仍然放不下,就会引发一次在新生代的minor GC,将存活的对象放入另一个survivor去中,然后清空Eden和之前的那个survivor的内存,在某次GC过程中,如果发现仍然有放不下的对象,就将这些对象放入老年代内存中。

Paste_Image.png

(因为年轻代中的对象基本都是朝生夕死的(80%以上),所以在年轻代的垃圾回收算法使用的是复制算法,复制算法的基本思想就是将内存分为两块,每次只用其中一块,当这一块内存用完,就将还活着的对象复制到另外一块上面。复制算法不会产生内存碎片。)
2.大对象以及长期存活的对象直接进入老年区。
3.当每次执行minor GC的时候应该对要晋升到老年代的对象进行分析,如果这些马上要到老年区的老年对象的大小超过了老年区的剩余大小,那么执行一次Full GC以尽可能的获得老年区的空间。

什么是Minor gc、Full gc、Major gc

从年轻代空间(包括 Eden 和 Survivor 区域)回收内存被称为 Minor GC。
大家应该注意到,目前,这些术语无论是在 JVM 规范还是在垃圾收集研究论文中都没有正式的定义。但是我们一看就知道这些在我们已经知道的基础之上做出的定义是正确的,Minor GC 清理年轻代内存应该被设计得简单。
Major GC 是清理老年代。
Full GC 是清理整个堆空间—包括年轻代和老年代。

很不幸,实际上它还有点复杂且令人困惑。首先,许多 Major GC 是由 Minor GC 触发的,所以很多情况下将这两种 GC 分离是不太可能的。

清理的内容

从GC Roots搜索不到,而且经历过一次标记清理之后仍然没有复活的对象。
这里有一个问题,什么叫做经历过一次标记清理之后复活的对象,在《深入理解Java虚拟机》这本书中得到了解决。
java提供finalize()方法,垃圾回收器准备释放内存的时候,会先调用finalize()。
(1).对象不一定会被回收。
(2).垃圾回收不是析构函数。
(3).垃圾回收只与内存有关。
(4).垃圾回收和finalize()都是靠不住的,只要JVM还没有快到耗尽内存的地步,它是不会浪费时间进行垃圾回收的。

那么怎么复活?

重写finalized方法,在方法里给对象以引用,但只能复活一次。在垃圾回收过程中,不能对复活对象调用 Finalize。

GC Roots都有哪些:

1.虚拟机栈中的引用的对象
2.方法区中静态属性引用的对象
3.常量引用的对象
4.本地方法栈中JNI(即一般说的native方法引用的对象

堆分代/分区各自采用的GC算法

新生代:复制清理
老年代:标记-清除和标记-压缩算法
永久代:存放Java中的类和加载类的类加载器本身

详细介绍垃圾回收算法

引用计数法

对于对象设置一个引用计数器,只要任何对象引用了A,那么A的计数器就加1,每减少一个变量的引用, 引用计数器就会减1,只有当对象的引用计数器变成0时,该对象才会被回收。

存在两个问题:

1.每次在增加变量引用和减少引用时都要进行加法或减法操作,如果频繁操作对象的话,在一定程度上增加的系统的消耗。

2.假设有两个对象 A和B,A中引用了B对象,并且B中也引用了A对象,那么这时两个对象的引用计数器都不为0,但是由于存在相互引用导致无法垃圾回收A和 B,导致内存泄漏。

A a=new A();
B b=new B();
a.b1=b;
b.a1=a;
a=null;
b=null;

程序运行完后,计数器仍然是1,导致无法回收。

复制算法(Java中新生代采用)

原理:将内存空间分为两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存块中,之后,清除正在使用的内存中的所有对象,交换两个内存的角色。如果系统中垃圾对象多,需要复制的存活对象数量就会相对较少,因此,复制算法的效率是很高的,而且新的内存空间中可以保证是没有内存碎片的。

缺点:

复制算法的代价是将系统内存折半,一般情况下很难让人接受。
对于存活对象较多的情况,效率不能保证

标记清除法(Mark-Sweep)

笔记清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段。一种可行的方式是,在标记阶段,首先通过根节点,标记所有从根节点开始的可达对象,因此,未被标记的对象就是未被引用的垃圾对象。然后,在清除阶段,清除所有未被标记的对象。

缺点:

标记清除算法回收后的控件时不连续的,会产生空间碎片,在对象的堆空间分配过程中,尤其是大对象的分配,不连续内存空间的工作效率要低于连续的空间。

标记压缩清除法(Java中老年代采用)

在标记清除法的基础上做了一个改进,可以说这个算法分为三个阶段:标记阶段,压缩阶段,清除阶段。标记阶段和清除阶段不变,只不过增加了一个压缩阶段,就是在做完标记阶段后, 将这些标记过的对象集中放到一起,确定开始和结束地址,比如全部放到开始处,这样再去清除,将不会产生磁盘碎片。但是我们也要注意到几个问题,压缩阶段占用了系统的消耗,并且如果标记对象过多的话,损耗可能会很大,在标记对象相对较少的时候,效率较高。

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

推荐阅读更多精彩内容