垃圾回收基础知识
内容纲要
垃圾回收概述
- 什么是垃圾:简单说就是内存中已经不再被使用到的内存空间就是垃圾
引用计数法
给对象添加一个引用计数器,有访问就加1,引用失效就减1 (优点:实现简单、效率高;缺点:不能解决对象之间循环引用的问题)
根搜索算法
从根( GC Roots )节点向下搜索对象节点,搜索走过的路经称为引用链,当一-个对象到根之间没有连通的话,则该对象不可用
- 根搜索算法示意图
- 可作为GC Roots的对象包括:虚拟机栈(栈帧局部变量)中引用的对象、方法区类静态属性引用的对象、方法区中常量引|用的对象、本地方法栈中JNI引|用的对象、同步锁 synchronized持有的对象
HotSpot使用了一组叫做OopMap的数据结构达到准确式GC的目的,OopMap:用来描述对象与引用关系的数据结构,在类加载完成的时候,虚拟机就会计算出当前对象在那个偏移位置上会有什么样的引用,然后把这些信息都记录在OopMap里面,GC扫描的时候就可以直接扫描OopMap,不用再从根节点再一个一个的查找了,这样就可以大大加快GC Roots 算法的速度了- 在OopMap的协助下,JVM可以很快的做完GC Roots枚举。但是JVM并没有为每一条指令生成一个OopMap
- 记录OopMap的这些"特定位置"被称为安全点,即当前线程执行到安全点后才允许暂停进行GC
- 如果一段代码中,对象弓|用关系不会发生变化,这个区域中任何地方开始GC都是安全的,那么这个区域称为安全区域
引用分类算法
- 强引用:类似于Object a = new A()这样,不会被回收
- 软引用:还有用但并不必须的对象。用SoftReference来实现软引用
- 弱引用:非必须对象,比软引用还要弱,垃圾回收时会回收掉。用WeakReference来实现弱引用
- 虚引用:也称为幽灵弓|用或幻影引用,是最弱的引用。垃圾回收时会回收掉。用PhantomReference来实现虚引用
跨代引用
- 跨代引用:也就是一一个代中的对象引用另-一个代中的对象
- 跨代弓|用假说:跨代引用相对于同代引用来说只是极少数
- 隐含推论:存在互相引用关系的两个对象,是应该倾向于同时生存或同时消亡的
记忆集
- 记忆集( Remembered Set) : 一种用于记录从非收集区域指向收集区域的指针集合的抽象数据结构(建立一个全局数据结构,把老年代或新生代划分为若干个小块,标识出来那块内存会出现跨代引用)
- 字长精度:每个记录精确到一个机器字长,该字包含跨代指针
- 对象精度:每个记录精确到一个对象,该对象里面有字段含有跨代指针
- 卡精度:每个记录精确到一块内存区域,该区域内有对象含有跨代指针
- 卡表( Card Table ) : 是记忆集的一-种具体实现,定义了记忆集的记录精度和与堆内存的映射关系等
- 表的每个元素都对应着其标识的内存区域中-块特定大小的内存块,这个内存块称为卡页( Card Page )
写屏障(维护卡表数据)
- 写屏障可以看成是JVM对“引用类型字段赋值”这个动作的AOP
- 通过写屏障来实现当对象状态改变后,维护卡表状态
判断是否垃圾的步骤
- 根搜索算法判断不可用
- 看是否有必要执行finalize方法(一般不调用)
3.两个步骤走完后对象仍然没有人使用 ,那就属于垃圾
GC类型
- MinorGC/YoungGC :发生在新生代的收集动作
- MajorGC / OldGC :发生在老年代的GC,目前只有CMS收集器会有单独收集老年代的行为
- MixedGC :收集整个新生代以及部分老年代,目前只有G1收集器会有这种行为
- FullGC :收集整个Java堆和方法区的GC
Stop-The-World
- STW是Java中一种全局暂停的现象,多半由于GC引起。所谓全局停顿,就是所有Java代码停止运行,native代码可以执行,但不能和JVM交互
- 其危害是长时间服务停止,没有响应;对于HA系统,可能引起主备切换,严重危害生产环境
垃圾收集类型
- 串行收集: GC单线程内存回收、会暂停所有的用户线程,如: Serial
- 并行收集:多个GC线程并发工作,此时用户线程是暂停的如: Parallel
- 并发收集:用户线程和GC线程同时执行(不一定是并行可能交替执行) , 不需要停顿用户线程,如: CMS
判断类无用的条件
- JVM中该类的所有实例都已经被回收
- 加载该类的ClassLoader已经被回收
- 没有任何地方弓|用该类的Class对象
- 无法在任何地方通过反射访问这个类
共有 0 条评论