一、垃圾回收
1.如何判断对象可以回收
(1)引用计数法
存在循环引用问题, Java未使用这种算法
在引用计数法中,每个对象都有一个引用计数器,记录着指向该对象的引用数量。当引用计数器为零时,表示没有任何引用指向该对象,该对象可以被释放,回收其占用的内存。
(2)可达性分析法
根对象:肯定不能被垃圾回收的对象
2.Java引用类型
1.强引用
被GC-Root引用
2.软引用
没有被强引用, 垃圾回收时内存不够,软引用被回收
3.弱引用
没有强引用,只要发生垃圾回收,弱引用会被回收掉
软引用 弱引用也占用一定的内存,对 它两进行释放,通过引用队列
4. 虚引用
必须配合引用队列使用,虚引用对象被垃圾回收时,虚引用 自己放入引用队列,由一个线程释放内存
5.终结器引用
Object中有finallize方法,对象重写finallize方法 ,并且没有强引用 引用它,可以被当作垃圾回收
软引用实例
弱引用实例
垃圾回收算法
1.标记清除算法
标记清除算法(Mark-Sweep Algorithm)是一种常见的垃圾回收算法,用于自动管理动态分配的内存空间。其原理如下:
标记阶段(Mark):从根对象开始,通过引用链追踪,标记所有的活动对象。标记过程中,将活动对象的标记位设置为有效状态,表示这些对象是可达的,不会被回收。
清除阶段(Sweep):在标记阶段完成后,遍历整个内存空间,将未被标记的对象视为垃圾对象,将其所占用的内存空间释放,以便下次分配给新的对象使用。
优点:速度快
缺点:容易造成内存碎片
标记清除算法通过标记和清除的过程,将不再被使用的内存空间回收,以避免内存泄漏和内存碎片的问题。
然而,标记清除算法也存在一些缺点,如清除阶段会产生内存碎片,可能会导致内存分配的效率降低。
2.标记整理算法
- 标记阶段:
与其他垃圾回收算法一样,标记-整理算法从根对象开始遍历整个对象图,标记所有与根对象可达的对象,即被引用的对象。 - 整理阶段:
在整理阶段,标记-整理算法会对内存空间进行整理,将所有存活的对象移动到一端,而未标记的对象则被认为是垃圾对象。
移动存活对象的过程中,标记-整理算法会保持存活对象之间的相对位置关系,从而确保所有存活对象在整理后仍然是连续的。 - 回收阶段:
在整理阶段完成后,标记-整理算法会回收并释放未标记的垃圾对象所占用的内存空间,从而实现垃圾回收。
优点:没有内存碎片
缺点:速度慢
3.复制算法
复制算法的基本思想是将内存空间划分为两个大小相等的区域,通常称为"From"空间和"To"空间。在垃圾回收过程中,首先将所有存活的对象从"From"空间复制到"To"空间中,然后对整个"From"空间进行垃圾回收,将未复制的垃圾对象清理掉。在下次垃圾回收时,交换"From"空间和"To"空间的角色,继续进行复制和回收操作。这样,"From"空间和"To"空间的角色不断交替,实现了垃圾对象的回收和内存空间的复用。
优点:不会产生碎片
缺点:需要占用双倍内存
分代回收
新生代空间不足,触发MinorGC,先标记
eden(伊甸园)满了,采用复制算法将存活的对象复制到TO中,幸存的对象寿命+1
交换From和To
第二次垃圾回收
当对象寿命超过阈值(15),晋升到老年代
FullGC
老年代空间不足,先尝试进行一次MinorGC ,之后空间任然不足,触发FullGC