垃圾回收主要回收的是堆中的实例、数组。
STW(stop the world)暂停所有应用程序的线程,等待垃圾回收完成
1.对象什么时候可以被垃圾回收器回收
一个对象如果没有任何的引用指向他了,那么他现在就是不可达对象(垃圾),如果定位了垃圾,那么垃圾回收器就可能会将他回收。(比如这个对象被显式的设置为null,可以让垃圾回收器更好的识别他并回收)
定位垃圾有两种办法:
- 引用计数法(不常用,循环引用会导致内存泄漏问题),
- 可达性分析算法(常用,扫描堆内的对象,如果沿着GC root对象为起点的引用链找不到该对象,则表示该对象可以回收)
- 可达性分析法有哪些可以作为GC root的对象
- 虚拟机栈帧中的对象
- metaspace中类静态属性引用的对象、常量引用的对象
- native修饰的方法
- 可达性分析法有哪些可以作为GC root的对象
2.JVM中的垃圾回收算法都有哪些
标记清除算法
- 标记:根据可达性算法将得出的垃圾进行标记
- 清除:对这些标记为可回收的对象进行垃圾回收
- 清除和回收速度相对较快,但是会导致内存不完整,碎片化比较严重
标记整理算法(老年代常用算法)
- 在标记清除算法的基础上,再将对象位置进行移动,虽然解决了碎片化问题,但是在性能上会有一定影响
复制算法(年轻代常用算法)
需要开辟两个大小完全相同的内存空间;
同样是通过gc root标志垃圾;在垃圾回收后,会将存活的对象复制到另一个区域,该区域全部清空。
在垃圾对象较多的情况下效率较高,而且无碎片化;但是需要分配两块内存空间,并且有一块在同一时间内是无法使用的
3.JVM中的分代回收
堆会进行区域划分:新生代(eden,幸存者区to,幸存者区from):老年代比例为1:2
对象分代回收策略:
- 新创建的对象都先分配到eden区;
- eden区内存不足时,会标记eden区与from区的存活对象
- 采用复制算法将存活对象复制到to中,复制完毕后释放eden和from区内存
- eden区内存再次不足时,标记eden区和to区存活对象,再次进行复制算法将其移动到from区,回到2
- 当幸存区对象经历多次回收(至多15次),会从新生代晋升为老年代。(幸存区内存不足或者大对象也会提前晋升)
4.MinorGC、MixedGC、fullGC的区别是什么
MinorGC(youngGC)发生在新生代的垃圾回收,暂停时间短(STW)
MixedGC发生在新生代+老年代部分区域的垃圾回收,由G1收集器持有
fullGC新生代+老年代完整的垃圾回收,STW时间很长,应极力避免
5.JVM都有哪些垃圾回收器
串行垃圾回收器:分为serial和serial old串行垃圾收集器,使用单线程进行垃圾回收,堆内存较小,适合个人电脑
- serial作用于新生代,使用复制算法;serial old作用于老年代,使用标记-整理算法。垃圾回收时,只有一个线程在工作,其他线程都要STW,等待垃圾回收完成
并行垃圾回收器:分为parallel new和parallel old,JDK8默认使用该回收器
- parallel new作用于新生代,使用复制算法;parallel old作用于老年代,使用标记-整理算法。与串行不同的是,并行回收是多个线程在工作,其他没什么不同....
CMS(并发)垃圾回收器concurrent mark sweep:主要针对老年代的垃圾回收器。停顿时间短,用户体验好;在进行垃圾回收时应用可以正常运行。有以下四个工作阶段
- 初始标记:短暂的STW,标记一下GCroot关联的对象
- 并发标记:标记出所有科可达对象
- 重新标记:修正并发标记期间的变动,需要STW
- 并发清楚:采用标记-清除法,会有内存碎片
G1垃圾回收器
G1和其他垃圾回收器的区别就是不再按默认的将堆分为新生代与老年代,而是将堆划分为多个大小相同的region,每一个region可以按需要来充当eden、survivor、old。也因此G1可以预测STW
JDK9之后默认垃圾回收器都是采用的G1。G1应用于老年代与新生代
划分了多个区域,每个区域都可以作为eden,survivor,old,humongous(专门存储大对象,如果一个存储空间不够的话他是会连续存储来实现humongous);采用复制算法。
如果垃圾回收速度赶不上新建对象速度会导致fullGC
有三个工作阶段:
- 年轻代垃圾回收
- 初始时,所有区域都处于空闲状态
- 刚刚创建对象时,会随机选择一些空间作为eden区
- 当eden区需要进行垃圾回收时,挑选一个空闲区作为survivor区,用复制算法复制存活对象,需暂停用户线程(这里的STW很短)
- eden区会和新的survivor通过复制算法合并成新的survivor区,其中较老的对象晋升至老年代
- 并发标记
- 当老年代占用内存超过阈值(默认45%)后,触发并发标记,无STW
- 混合垃圾回收
- 回收存活对象较少的老年代,和survivor区中的合并为新的old
6.强引用,软引用,弱引用,虚引用的区别
强引用:只有所有的GCroot都不通过强引用引用该对象,该对象才能被垃圾回收
软引用:SoftReference当触发一次垃圾回收时,下一次垃圾回收就会回收该对象
弱引用:WeakReference垃圾回收时,无论内存是否充足都会回收弱引用对象。ThreadLocal内存泄漏问题就是因为Entry extend WeakReference
虚引用:需配合引用队列使用,被引用对象回收时,会将虚引用入队,由Reference Handler线程调用相关方法释放内存。该引用主要用于跟踪对象被垃圾回收的状态