GC回收机制,GC算法。GC垃圾回收

对于java对象,什么是垃圾状态呢?就是不再被任何对象所引用.他就是垃圾.

在java中,GC的主要对象是堆空间和永久区。而我们更多讨论的是堆空间这部分。

                   堆的内存分配图

jdk8之前有永久代 jdk8之后被取消了,不再有永久代

GC的工作目的很明确:新生成的对象,都放在Eden中;当Eden充满时(小孩太多 了),GC将开始工作,首先停止应用程序的运行,开始收集垃圾。在堆中,找到已经无用的对象,并把这些对象占用的空间收回使其可以重新利用.大多数垃圾回收的 算法思路都是一致的:把所有对象组成一个集合,或可以理解为树状结构,从树根开始找,只要可以找到的都是活动对象,如果找不到,这个对象就是凋零的昨日黄 花,应该被回收了。

垃圾标记算法

我们如何标记一个对象是垃圾呢?主要有几种方法:引用计数法和可达性分析算法  这两种属于垃圾标记算法 并没有垃圾回收的功能

一.引用计数法的原理:对于一个对象A,只要有任何一个对象引用了A,则A的引用计数器就加1,当引用失效时,引用计数器就减1。只要对象A的引用计数器的值为0,则对象A就不可能再被使用。

缺陷:引用和去引用伴随加法和减法,影响性能很难处理循环引用。所以主流java中并没有使用引用计数法。

二:可达性分析算法:通过判断对象的引用链,来判断对象是否可以被回收,他是整个程序中 对象所有的引用关系进行搜索记录,当GC根连接不到的对象,即标记为垃圾对象,如图灰色即为不可达对象.

什么对象可以称为根对象呢,主要有五种

虚拟机栈中引用的对象 方法区中常量引用的对象 方法区中类静态属性引用的对象 活跃线程引用的对象,本地方法栈jni(native方法)引用的对象(不熟悉)

垃圾回收算法

我们把对象标记为垃圾对象,接下来就是回收了

一.标记-清除算法是现代垃圾回收算法的思想基础。标记-清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段。一种可行的实现是,在标记阶段,首先通过根节点,标记所有从根节点开始的可达对象,可达对象可理解为被引用的对象,因此,未被标记的对象就是未被引用的垃圾对象。然后,在清除阶段,清除所有未被标记的对象。如图中,标记阶段先标记,清除阶段,清除未标记为引用的对象。

简单说就是标记阶段:从跟对象开始扫描,标记存活的对象,清除阶段,从堆内存进行线性扫描,清除垃圾对象

                           图1

标记清除算法的缺点:只清除了不引用的对象,会使那部分对象的空间不连续,造成空间碎片化.

二。复制算法:与标记-清除算法相比,复制算法是一种相对高效的回收方法,不适用于存活对象较多的场合 如老年代。复制算法一般使用在新生代,对新生代进行垃圾回收又叫做MinorGC(他和老年代不冲突)。

复制算法原理:将原有的内存空间分为两块,分为对象面和空闲面,每次只使用其中一块,对象创建在对象面,在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的空闲面中,之后,清除对象块中的所有对象,交换两个内存的角色,完成垃圾回收.

                     图3

 

如上图3,复制算法执行后,先把存活对象复制到另一块区域,然后对之前区域进行一次清理,第一张图所画的A,B空间,把存活的对象由A复制到B,然后清理A区域,再把B区域存活对象复制到A,来回复制,每被复制一次,就会加一计数,当到达十五次(,默认应该是十五次,可以设置)之后,就进入了老年代,如下图4,还有一部分对象就是大对象,因为占得空间比较大,复制比较占空间,会直接进入老年代。

所以:少量对象存活,适合复制算法。大量对象存活,适合标记清理或者标记整理。

三.标记-压缩算法(也有的叫标记整理算法)适合用于存活对象较多的场合,如老年代一般使用这种算法,对老年代垃圾回收又叫MajorGC。它在标记-清除算法的基础上做了一些优化。和标记-清除算法基本思想一样,标记-压缩算法也首先需要从根节点开始,对所有可达对象做一次标记。但之后,它并不简单的清理未标记的对象,而是将所有的存活对象压缩到内存的一端,就是移到一边。之后,清理边界外所有的空间。如图2

                                                              图二

标记压缩算法的优点:使用存活率较高的场景,避免内存不连续,不用设置两块内存,造成内存浪费

四:分代收集算法(比较主流的垃圾回收算法)

他是按照对象生命周期不同进行划分,划分到不同区域,进行不同的算法,是上面算法的一种组合算法

我们经常说哦full GC是其中的一种分类,还有一种是Minor GC

Minor 采用的就是复制算法 

如上图在新生代中,新创建的对象一般都放在 Eden ,第一次复制 把里面存活的对象 放进S0 第二次复制,将Eden中&S0中对象,复制到S1,每次对象年龄加1.(S0个S1是新生代两块不同于Eden的区域)

什么时候对象从新生代进入老年代呢?主要有三种

1.默认是15岁之后,2新生代存不下,3超大对象 超过一定size的对象  这三种对象会进入老年代

老年代一般采用标记清理算法和标记整理算法  一般full GC就发生在老年代

full GC通常是堆垃圾回收 触发点主要有:

1.system.GC  2.老年代空间不足3MInor 去到老年代的对象大小 大于老年代的剩余空间 4.CMS GC出现异常

补充名词:

1.Stop-The-World:多半由于GC引起的,Java中一种全局暂停的现象,全局停顿,所有Java代码停止。native代码可以执行(但不能和JVM交互)。Jvm处于挂机状态,当然Dump,线程死锁检查,堆Dump,也是有可能引起全局暂停的现象,但多数还是GC引起,原因是GC的时候 ,只有这个线程执行,其他线程都是等待状态

2.可触及的对象:从根节点可以触及到这个对象。

3.不可触及的对象:在finalize()调用后,可能会进入不可触及状态,不可触及的对象不可能复活,可以回收。

4.可复活的对象:一旦所有引用被释放,就是可复活状态,因为在finalize()中可能复活该对象。

GC时为什么会有全局停顿?

类比在聚会时打扫房间,聚会时很乱,又有新的垃圾产生,房间永远打扫不干净,只有让大家停止活动了,才能将房间打扫干净。

JVM运行模式 server client 两者区别是:client启动快,运行慢.server启动慢 运行快 ,server启动是重量级的虚拟机,运行要快

注意事项:

 

1.当eden满了,触发young GC;

2.young GC做2件事:一,去掉一部分没用的object;二,把老的还被引用的object发到survior里面,等下几次GC以后,survivor再放到old里面。

3.当老年代满了,触发full GC。full GC很消耗内存,把old,young里面大部分垃圾回收掉。这个时候用户线程都会被block。

4.young generation比例越大,不一定最好。将young的大小设置为大于总堆大小的一半时会造成效率低下。如果设置得过小,又会因为young generation收集程序不得不频繁运行而造成瓶颈。

5.在sun 的文档说明中,对JVM堆的新域,是采用coping算法,该算法的提出是为了克服句柄的开销和解决堆碎片的垃圾回收。

看完算法,并不能学会如何优化jvm参数,感觉只是入门尝试

http://www.importnew.com/3146.html

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值