GC垃圾回收

一、垃圾

在c或c++中垃圾是要手动进行回收的

Java:new对象申请内存

      自动回收内存,若手动释放内存,容易出现两种类型问题:

    1、忘记回收,导致内存溢出

    2、多次回收

二、什么是垃圾

1、如果一个对象没有任何引用指向他

2、存在多个对象,互相之间引用,没有其他对象指向这个循环引用的对象(多个)

三、如何定位垃圾

1、引用计数法:一个对象有几个引用,这个对象中的计数器为相应的数,当计数器为0时,为垃圾(不能解决循环引用的问题)

但是,当三个对象循环引用,每个对象的计数器都为1,此时没有对象引用该整体时,会发生内存泄漏

 2、根可达算法:程序会找到一些根对象,与根对象有关联的都不是垃圾,其余都是垃圾

 四、垃圾回收算法

1、标记清除:找到垃圾后清除,相应区域标记为非垃圾区域

存在问题:位置不连续、产生碎片

 黑色为垃圾,绿色为未使用

2、拷贝:将内存区域非为两半,在上半区找到正在使用的内存,拷贝到下半区。拷贝完成后将上半区清空,标记为未使用区域,需要内存时往下半区分配

存在问题:浪费空间,需要准备两份。项目中需要5G,你要准备10G内存

3、标记压缩:从头开始按照顺序,将存活对象拷贝到可回收区域,形成连续空间

好处:没有碎片,内存连续。但是效率偏低

效率偏低原因:若单线程操作,效率本身就低

       若多线程操作,需要线程同步

 五、JVM内存分代模型

1、部分垃圾回收器使用的模型

2、新生代+老年代+永久代(1.7)/元数据区(1.8)

  永久代、元数据都是装Class对象中

  永久代必须指定大小限制,元数据区可以设置也可以不设置

3、堆内存逻辑分区

新生代=伊甸+2个survivor区 

  ①YGC回收之后,大多数内存会被回收,存活的对象进入S0,伊甸园区清空

  ②伊甸+S0中存活的对象拷贝到S1中,其余两个区域清空

  ③再次YGC,伊甸+S1中存活对象放到S0中

  ④当对象年龄足够大或S区装不下后,放到老年代中

老年代满之后会触发FGC(Full GC)

4、调优目标:尽量减少FGC

 默认新生代:老年代=1:3

新生代中伊甸:survivor:survivor = 8:1:1

六、常见的垃圾回收器

 Serial(年轻代,串行回收,单线程):从左到右,空间满了,触发GC,所有程序线程停止,垃圾回收线程进行垃圾回收,回收后程序继续运行

 蓝色的线表示程序正常运行

Paraller Scavenge(年轻代,并行回收)

 ParNew(年轻代):配合CMS的并行回收

SerialOld:将Serial放到old区

ParallelOld:将Parallel放到old区

CMS(老年代):在进行垃圾回收的时候程序也可以运行,效率较高,降低STW的时间(200ms)

G1(10ms)

ZGC(1ms)

作者:http://cnblogs.com/lyc-code/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权力。

原文地址:https://www.cnblogs.com/lyc-code/p/14748119.html