什么是垃圾
系统没有被使用的无用对象或者一组循环引用对象
如何找到垃圾
引用计数
对引用进行计数,无法解决循环引用问题(java里已经抛弃了这种算法,python现在垃圾回收用的还是引用计数)
根可达算法
根对象有哪些?
线程栈变量
静态变量
常量池
JNI指针等
垃圾回收算法
mark-sweep:标记清除
copying:拷贝
mark-compact:标记压缩
标记清除:不适合伊甸区
先标记后清除,两遍扫描,容易产生碎片,适合存活对象比较多的情况
拷贝算法:适合伊甸区
容易造成空间浪费,移动复制对象,需要调整对象引用,适用于存活对象较少的情况,只扫描一次,效率提高,不会造成内存碎片
标记压缩
每次清除垃圾,都把不是垃圾的对象填充到垃圾的坑里,这样就不会产生碎片,但需要扫描两次,需要移动对象,效率低一些
JVM组成
主流的hostspot的JVM是分代模型
由伊甸区 suvisor1 suvisor2 old区组成
对象出生到消亡过程;如下图
s1 最大年龄是4位,最大数是15,所以有个对象在s1里 被扫描了15次就会被放入到 老年代
动态年龄
s1 -> s2 超过50%(超过s1+s2的总和的50%)
把年龄最大的放入O
分配担保
YGC期间,suvivor区的空间不够了,空间担保直接进入老年代
垃圾回收器
1.8 默认用的yong是Parallel+ old Parallel (PS+PO)
下图凡是Yong+Old 红线可以连在一起的都可以组合。
Serial:串行工作,会导致STW。(stop the word),意思是serial垃圾回收的时候,别的都没有工作了。已经过时了。
Parallel:多个线程并行处理GC,也会导致STW,但是比Serial效率高
ParNew: 由Parallel的增强版:ParNew 响应时间优先,配合CMS,线程数一般是cpu核心数
CMS(重点): concurrent Mark sweep,多个线程并行处理,解决(缓解)了STW问题。但是cms问题特别多,例如最严重的内存碎片化,如果管理大内存,碎片化问题严重失衡,会导致使用Serial Old去对老年代的gc顺序做标记进行压缩,导致更严重的STW问题。
并发标记算法:三色标记
三色扫描算法
三色标记法是传统 Mark-Sweep 的一个改进,它是一个并发的 GC 算法。原理如下,
首先创建三个集合:白、灰、黑。
将所有对象放入白色集合中。
然后从根节点开始遍历所有对象(注意这里并不递归遍历),把遍历到的对象从白色集合放入灰色集合。
之后遍历灰色集合,将灰色对象引用的对象从白色集合放入灰色集合,之后将此灰色对象放入黑色集合
重复 4 直到灰色中无任何对象
通过write-barrier检测对象有变化,重复以上操作
收集所有白色对象(垃圾)
这个算法可以实现 “on-the-fly”,也就是在程序执行的同时进行收集,并不需要暂停整个程序。
但是也会有一个缺陷,可能程序中的垃圾产生的速度会大于垃圾收集的速度,这样会导致程序中的垃圾越来越多无法被收集掉。