1、进行垃圾回收的区域
(1)堆
(2)方法区
栈是线程的私有数据,所以不进行垃圾回收
2、垃圾回收的时间
对这个对象不再引用的时候
public class ReferenceCountingGC { private static final int MB=1024*1024; public Object instance=null; private byte[] size=new byte[2*MB]; public static void main(String[] args) { ReferenceCountingGC referenceCountingGC1=new ReferenceCountingGC(); ReferenceCountingGC referenceCountingGC2=new ReferenceCountingGC(); //循环引用 referenceCountingGC1.instance=referenceCountingGC2; referenceCountingGC2.instance=referenceCountingGC1; referenceCountingGC1=null; referenceCountingGC2=null; System.gc();; } }
[Full GC (System.gc()) [Tenured: 0K->640K(86016K), 0.0045506 secs] 6862K->640K(124736K),
[Metaspace: 3223K->3223K(1056768K)], 0.0046551 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
Heap def new generation total 38784K, used 345K [0x0000000082200000, 0x0000000084c10000, 0x00000000ac150000) eden space 34496K, 1% used [0x0000000082200000, 0x0000000082256548, 0x00000000843b0000) from space 4288K, 0% used [0x00000000843b0000, 0x00000000843b0000, 0x00000000847e0000) to space 4288K, 0% used [0x00000000847e0000, 0x00000000847e0000, 0x0000000084c10000) tenured generation total 86016K, used 640K [0x00000000ac150000, 0x00000000b1550000, 0x0000000100000000) the space 86016K, 0% used [0x00000000ac150000, 0x00000000ac1f0040, 0x00000000ac1f0200, 0x00000000b1550000) Metaspace used 3230K, capacity 4496K, committed 4864K, reserved 1056768K class space used 350K, capacity 388K, committed 512K, reserved 1048576K
(1)引用计数
给对象添加一个引用计数器,每当这个对象进行一次引用,计数器就加1;每当引用失效的时候,计数器就减1。当这个计数器等于0的时候,表示这个对象不会再被引用了。
3、java的引用类型
(1)强引用
Object obj=new Object();这样的常规引用,只要引用还在就永远不会回收对象,在代码中有明显的new Object()这类引用,只要这种引用还在,垃圾回收器就不会回收它。就算内存不够,抛出OutOfMrmory异常也不会回收对象。
(2)弱引用
生存到下一次垃圾回收之前,无论当前内存是否够用,都回收掉被弱引用关联的对象
(3)软引用
在发生内存溢出之前,进行回收,如果这次回收之后还没有足够的内存,则报OOM。如果内存够用的情况下,不会回收,如果内存不够的话进行
(4)虚引用
不会对对象的生命周期有任何影响,也无法通过它得到对象的实例,唯一的作用也就是在垃圾回收之前收到一个系统通知
4、可达性分析算法
(1)可达与不可达
可达:
不可达:
此时对象已经不再被引用了,也就是说可以被回收了。
(2)在java语言中,可以作为GC Roots的对象包括下面几种:
虚拟机栈(栈帧中的本地变量表)中引用的对象
方法区中类静态属性引用的对象
方法区中常量引用的对象
本地方法栈中JNI(即一般说的Native方法)引用的对象
5、标记、清除算法
(1)概念:
该算法包括“标记”和“清除”两个阶段:首先标记出所有要回收的对象,在标记完成后统一回收所有被标记的对象。
(2)缺点:
效率问题,标记和清除的效率都不高
空间问题,标记和清除之后会产生大量不连续的内存碎片
6、复制算法
(1)概念
将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块内存用完了,就将还存活的对象复制到另外一块上面,然后再把已经使用过的内存空间一次清理掉
(2)缺点
内存缩小为原来的一半,内存利用率太低(还要留出另外一半等着复制的时候使用)
7、标记整理算法
(1)概念
标记过程依旧和“标记清除算法”一样,但是后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后把其他的内存区域清理掉。
8、分代算法
(1)概念
根据对象存活周期的不同将内存划分为几块
(2)回收原则
一般是把java堆分为新生代和老年代,这样可以根据各个年代的特点采用最适合的收集算法。在新生代中,每次垃圾回收的时候都会回收掉大量的对象,只有少量的对象存活,此时,选用复制算法,只需要付出少量存活对象的复制成本即可完成对象的收集,而老年代中因为对象的存活率高,没有额外空间进行分配担保,就必须使用“标记清理”算法进行回收。
堆:
经过几次回收之后会进入老年代
9、GC类型
(1)保守式GC
在回收的时候,不对数据进行记录,而是扫描内存,效率低
(2)半保守式GC
在类里面记录信息,然后扫描
(3)精确式GC
OopMap存放运行信息(类型、地址等),回收的时候只需查询Map即可
10、安全点:safepoint
(1)概念
在OopMap的协助下,HotSpot可以快速且准确地完成GC Roots的枚举,但如果每一条指令都生成对应的OopMap那将会需要大量的额外空间,这样GC的空间成本将会变得很高
(2)抢占式中断
在GC发生时,首先把所有的线程全部中断,如果发现有中断的地方不在安全点上,就恢复线程,让它跑到安全点上。
缺点:处于sleep或wait的时候不能到达安全点
(3)主动式中断
当GC需要中断线程的时候,不直接对线程进行操作,仅仅简单地设置一个标志,发现中断标志为真的时候就自己中断挂起
原文:https://www.cnblogs.com/zhai1997/p/12606874.html