gc原理以及gc日志java
一.概述算法
学习Java的咱们都知道垃圾收集(gc),大部分人把这项技术看成是java语言的伴生产物。事实上,gc的历史比Java久远,1960年诞生于MIT的Lisp是第一门真正使用内存动态分配和垃圾收集技术的语言。那咱们今天就研究下垃圾收集原理。安全
二.对象已死吗?数据结构
Java的垃圾回收主要是对推内存的回收,里面存放着Java几乎全部的对象实例,垃圾回收以前是要肯定哪些还“存活”哪些已经“死去”。学习
1.引用计数器法spa
给对象添加一个引用计数器,每当有地方对他进行引用时计数器值➕1;当引用失效时,计数器值就➖1,任什么时候候计数器值为0的时候表示对象不可能在使用的。线程
2.可达性分析算法3d
经过一系列称为“GC Roots”的对象做为起点,从这些节点往下搜索,搜索所走过的路径称为“引用链”,当一个对象到“GC Roots”没有任何引用链相连时,则证实对象不可用的日志
代码示例:对象
gc日志以下:
咱们很明显的看到gc日志中6092K->456K,意味着虚拟机并无由于这两个对象互相引用而不回收他们,因此java虚拟机使用的是可达性分析算法标记的。
其实即便被可达性分析算法标记的不可达对象也不是必定会被回收的,虚拟机会对这些对象进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法。当对象没有覆盖finalize()方法或者finalize()已经被虚拟机调用过,虚拟机将这两种状况视为“没有必要执行”。若是对象被断定有必要执行finalize()方法是并在finalize()中与“GC Roots”创建关联则次对象不会被回收了。
三.垃圾回收算法
咱们知道了虚拟机怎么标记一个对象是否可用,那他怎么进行回收的呢?其实堆内存能够分为新生代和老年代,新生代又被划分为一个Eden和两个Survivor区域他们的比例为8:1:1,不一样的垃圾收集器厂商给对这两个区域给出了不一样的算法。
1.新生代——复制算法
新生代对象的特色就是,大部门对象在一次GC中会被回收掉,因此使用的是复制算法:新生代每次建立对象的时候只会使用一个Eden和其中的一块Survivor,在垃圾回收时将存活的对象复制到另一块Survivor区域,最后清理掉Eden和刚才的Survivor区域。
1.老年代——标记-整理算法
老年代通常保存的是一些大对象,或者不被常常回收的对象,根据特色使用的标记-整理算法:如同名字同样,算法分为"标记"和“整理”两个阶段:首先先标记出全部须要回收的对象,在标记完成后统一回收因此被标记的对象进行整理,将被标记的对象都向一端移动,而后直接清理掉边界之外的内存。
四.HotSpot算法实现
上面说了咱们怎么标记对象“死亡”和怎么进行垃圾回收的,但在HotSpot虚拟机在实现这些算法上是必须对算法的执行效率进行考量的。
1.安全点
在可达性分析中对执行的时间的敏感体如今GC停顿上,其意思是在整个分析的过程当中看起来就像被冻结在某一个时间点上的,不能够出现分析的过程当中引用关系在不断变化,若是这点得不到保证则分析的结果的准确性就得不到保障。这点是致使在GC进行时须要停顿全部的java执行线程。当执行系统停顿下来后,虚拟机并不须要所有上小文和全局全部的位置,虚拟机经过一个OopMap的数据结构在类加载的时候将对象的偏移量数据信息记录下来,因此GC扫描是就直接获得这些信息的。其实这些经过指令被加入进行记载对象信息的OopMap位置也叫作安全点,程序执行时并不是全部点均可以停下来开始GC的,只有在到达安全点才能停顿。安全点机制程序执行中,在不太长的时间内会遇到可进入GC的安全点。在实际中会遇到在GC时有线程再也不执行,例如线程被挂起了。这是咱们须要安全区域去解决。
2.安全区域
安全区域是指在一段代码片断中,引用关心不会发生变化。在这个区域中的任意地方开始GC都是安全的。在代码执行到安全区域是,首先表示这直接进去安全区域,这样虚拟机在这段时间GC时就不用管那些标记为安全区域的线程了。当离开安全区域时首先得判断是GC分析是否完成,没完成则须要等待。
五.理解GC日志
这是上图打印的gc日志
[GC (System.gc()) [PSYoungGen: 6092K->448K(38400K)] 6092K->456K(125952K), 0.0051702 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
PSYoungGen表示的是新生代gc不一样垃圾收集器新生代名称不同,6092K->448K(38400K)表示新生代大小的变化,6092K->456K(125952K)表示推内存的大小变化 后面表示用时。
[Full GC (System.gc()) [PSYoungGen: 448K->0K(38400K)] [ParOldGen: 8K->378K(87552K)] 456K->378K(125952K), [Metaspace: 3050K->3050K(1056768K)], 0.0056045 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
表示发生在老年代的gc(Major GC/Full GC) 他知识为伴随一次的新生代的gc(Minor GC),448K->0K(38400K)表示新生代内存变化,8K->378K(87552K) 老年代gc变化,456K->378K(125952K)表示gc先后堆内存的变化。