Java的GC的内部原理

来源:互联网 发布:兄弟连it教育地址 编辑:程序博客网 时间:2024/06/05 12:05

程序运行过程中每次分配的对象 语言的runtime都会记录谁和谁的引用关系,当内存不够用或者特定的时机就会触发GC,这个时候 首先会暂定所有的线程,也就是stop the world,这个时候整个语言的执行权交给了GC程序,GC会收集当前 全部的 【全局变量】【每一个线程的运行栈中的对象】等等,这些对象都是当前直接可以访问的对象,这些对象的合集称之为【根集】。然后GC会从这个根集出发遍历整个程序分配的对象,【由于对象的相互引用关系GC是知道的,所以这个问题就简化成了一个图论的问题,】。这个过程中如果出现 GC扫描不到的对象,但是runtime中有分配这个对象。这种对象就是垃圾对象。【仔细想想 GC的根集扫描就是判断当前代码那些变量是可以访问到的,那些变量存在内存中但是对象的 句柄已经丢失,程序代码已经访问不到的】。至于这些对象是立马回收还是标记后回收,这个就看内存回收的策略了。有各种针对这个做优化的算法,有的会内存释放后整理内存,有的会做颜色标记。

其他的GC算法  也都是从这个基础,出发优化的, 有个根据程序的28原理。 有的先用引用计数保证一部分删除,删除不掉的用GC算法干掉。不管怎么优化,GC的算法斗都不是很快。

其中Golang的GC算法 在大内存的情况下,会出现卡顿达到2s以上的情况,Golang1.4 版本之后又改善

其实 Java的内存回收看起来很玄妙。但是其实原理就是学过的图论的基础算法。比如3色标记算法,他查询到一个对象已经没有可能被访问到了,  他不是立马回收。程序有 28原理,就是可以假设这些对象在之后的时候可能再被分配。28原理就是 当前访问的对象或者分配的对象,在稍后的时间也可能被访问到。所以当这个对象被标记可能要回收的时候,首先不回收,因为之后的时间段可能还会分配。所以先暂存起来,等下次分配的时候直接从池里返回,但是接下来一段时间还是没有被分配,就说明确实没必要留了, 那就干掉了。

这过程中  对象有几个 生命过程,比如 存活态,被标记态,死亡态 等等   对象被标记各种状态。

这里面讲的 有些语言先用引用计数释放,释放不掉的时候在用GC算法。  典型的代表就是 php。

Java的GC判断一个对象是否是垃圾,是通过图来判断该对象是否可达,启动垃圾回收的频率和算法则根据内存分区不同而不同,old代对象一般活的比较久,回收频率没那么高,new代对象大部分是刚产生的对象,回收频率比较高,经过几轮new代GC的对象有可能会进入lod代,内存分配的策略以及回收算法可以在启动Java虚拟机时候指定

0 0
原创粉丝点击