2019独角兽企业重金招聘Python工程师标准>>>
gc概念
Java堆中各代分布:
图1:Java堆中各代分布
Young:主要是用来存放新生的对象。
Old:主要存放应用程序中生命周期长的内存对象。
Permanent:是指内存的永久保存区域,主要存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域. 它和和存放Instance的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。
根节点:
java通过可达性分析来判断对象是否存活。基本思想是通过一系列称为“GC roots”的对象作为起始点,可以作为根节点的是:
- 虚拟机栈(栈帧中的本地变量表)中引用的对象
- 本地方法栈中JNI(即一般说的Native方法)引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
作为GC Roots的节点主要在全局性的引用(例如常量或类静态属性)与执行上下文(例如栈帧中的本地变量)中。
虚拟机、本地方法栈这都是局部变量,某个方法执行完,某些局部使用的对象可以被回收。
引用计数法
对于一个对象A,只要有任何一个对象引用了A,则A的引用计数器就+1,当引用失效,引用计数器就减1.对象A的引用计数器的值为0时,则对象就不可能再被使用。
使用者:com,actionScript3,python
引用计数法缺点:
1,引用和去引用伴随加法和减法,影响性能。
2,很难处理循环引用:
如上图:最后一张图的三个对象互相引用,虽然根对象无法达到这些对象,但是引用计数都是1,仍然无法被GC回收。
标记清除法
适用老年代
该算法有两个阶段:标记阶段、清除阶段。
标记阶段:从根节点开始搜索,但凡是根节点可以到达的对象,则标记为可达对象。
清除阶段:清除未被标记的对象。
标记压缩算法
该算法适用于存活对象较多的场合,如:老年代。
标记阶段:从根节点开始搜索,但凡是根节点可以到达的对象,则标记为可达对象。
清除阶段:将所有的存活对象压缩到内存的一端。然后清除边界外的所有空间。
优点
- 相对复制算法提高堆的利用率。
- 相对清除算法不会产生碎片。
复制算法
将原有的内存空间分为两块(两个绝对大小相等,实际有额外一块空间老年代做担保,用于存放大对象和老年对象),每次使用其中一块,在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存块中,之后,清除正在使用的内存中所有对象,交换两个内存角色,完成垃圾回收。
小的对象,年轻的对象复制到对面的空间中。大对象、老年对象复制到老年代中。
优缺点:
与标记-清除算法相比,复制算法是一种相对高效的回收算法
不适合存活对象较多的场合 如老年代
浪费内存空间
分代思想
根据对象的生命周期进行分类,短命对象归为新生代,长命对象归为老年代。
根据不通代的特点,选取合适的收集算法:
1,少量存活对象,适合用复制算法
2,大量存活对象,适合标记清除或者标记压缩算法。
可触性
1,可以触及的
从根节点可以触及到这个对象。
2,可以复活的
一旦所有引用被释放,就是可复活状态,因为在finalize()中可能复活该对象。finalize()方法调用后,该对象就不可以复活了。
3,不可以触及的
在finalize()后,可能会进入不可触及状态,不可以触及的对象不可能复活,但是可以回收。
stop-the-world
java中一种全局暂停的现象,全局停顿,所有java代码停止,native代码可以执行,但是不能与jvm交互。
被引起的原因:
GC,Dump线程,死锁检查,堆Dump