在运行程序中没有任何指针指向的对象称为垃圾
标记阶段:发现垃圾
- 引用计数算法:
- 对象自身开启空间记录被引用次数
- 缺点是无法解决循环引用问题
- python中使用此算法,通过手动解除引用和采用弱引用来解决循环信用问题
- 可达性分析算法:
- 从gc root开始,在引用链上的对象是可达的,否则不是可达,可以被回收
- 缺点是效率低会存在STW,原因是必须保证在一个保证一致性的内存快照中进行,此时需要暂停用户线程
- GC Root有哪些?
- 虚拟机栈中引用的对象
- 本地方法栈中引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量池中的引用
- 所有被同步锁持有的对象
- 虚拟机内部的引用:基本数据类型对应的类对象,异常对象,系统类加载器
- 分代回收的影响:例如只收集年轻代时,老年代中的对象对新生代有引用时也可以作为根节点
- 如何查看GC Root:通过工具MAT
- 如何进行对象引用的溯源#通过工具JProfiler
对象的finalization机制
在对一个对象进行垃圾回收之前虚拟机会去调用对象的finalize方法
- 用于释放资源:关闭文件,套接字,数据库连接等
- 不建议主动调用:有可能导致对象复活或执行性能差
- 由于finalize的存在对象会有三种状态:可触达,可复活(还未执行finalize),不可触及(已经执行finalize)
清除阶段:处理垃圾
标记清除算法
- 从根节点标记可达对象(非垃圾对象),标记过程产生STW,是否存活标记放在对象头中,对未被标记对象进行清除
- 缺点是什么?
- 效率不高,两次遍历,第一次是可达分析,第二次是全量遍历回收
- 会产生STW
- 会产生空间碎片,并需要维护空闲列表
- 如何清除?
- 并不是真的置空,而是将地址维护到空闲列表
复制算法
- 对内存区域进行分区,每次将存活对象从回收区复制到另一个区域,例如年轻代的回收机制
- 优点
- 执行高效
- 内存空间连续
- 缺点
- 浪费内存,需要两倍内存空间
- 适合存活对象少的年轻代
标记整理算法
- 标记存活对象然后让所有存活的对象都向一端移动,直接清理掉端边界以外的内存。适合年老代。注意其不需要维护空闲列表,直接清除垃圾对象
- 优点
- 没有内存碎片化问题
- 不用占用两倍内存空间
- 缺点
- 效率相对低于复制算法
- 移动对象时如果对象被其它对象引用,要整体调整引用地址
- 需要STW
分代回收算法
不同年龄代的对象采用不同的回收算法。
新生代对象存活率低,就采用复制算法;
老年代存活率高,就用标记清除算法或者标记整理算法
增量收集算法
每次垃圾收集线程只收集一部分区域,接着切换到应用线程,以此往复,直到垃圾收集完成。
底层依然是标记清除和复制算法。
优点:减少STW
缺点:频繁线程切换导致系统吞吐量降低
分区收集算法
把一块大的内存空间划分为若干区域的小空间,每一个小空间的分代年龄不同(新生代,老年代,永久代,大对象),每次只对需要收集的部分区域进行收集。
垃圾回收的基本概念
- system.gc()手动触发full gc,但是不能保证能够被立即执行。一般用不到。
- 内存溢出oom:没有空闲内存可用,垃圾收集后也无法提供足够空间
- 内存泄漏memory leak:对象不会被使用但是gc又无法回收。公摊
- 单例模式中如果引用了外部对象有可能造成内存泄漏
- 有些需要close的资源未关闭导致内存泄漏。数据库连接,网络连接
- stop the word:gc发生时用户线程会被暂停,gc线程执行,完成应用程序的卡顿。
- 程序中的并行:多个cpu分别各自处理不同的程序进程。即多个事情在同一时间点发生
- 程序中的并发:一个cpu不断切换不同的程序进程来执行,同一时刻只能执行一个,但看起来像是都在执行。即多个事情在同一时间段发生
- 垃圾回收的并行与并发
- 并行:指多条垃圾回收线程同时执行回收工作
- 串行:指单线程执行回收工作
- 并发:用户线程和垃圾回收线程同时执行(但并不一定同时,还是会有stw)
- 安全点
- 只有在安全点才可以进行垃圾回收
- 通常将耗时较长的指令作为安全点,例如方法调用,循环跳转,异常跳转
- 如何确保所有线程在安全点暂停?
- 抢先式终端:首先中断所有线程,然后检查将未达到安全点的线程执行到安全点
- 主动式中断:首先设定一个中断标志,然后各线程轮训,如果为真则自行中断挂起
- 安全区域
- 指在一段代码片段中对象的引用不会发生变化,这个区域的任何位置gc都是安全的
- 例如线程的sleep和blocked状态都是安全区域
什么时候发生GC
Minor GC(新生代GC):当jvm无法为新的对象分配空间的时候就会发生Minor gc,所以分配对象的频率越高,也就越容易发生Minor gc
Full GC/Major GC(年老代GC):①当老年代无法分配内存的时候,②当发生Minor GC的时候可能触发Full GC
版权声明:本文为博主原创文章,欢迎转载,转载请注明作者、原文超链接,感谢各位看官!!!
本文出自:monkeyGeek
座右铭:生于忧患,死于安乐
欢迎志同道合的朋友一起交流、探讨!
