- 1.如何判断对象已死?(判断算法)
- (1)引用计数算法
- (2)可达性分析算法
- 2.GCRoots包含哪些对象?
- 3.方法区回收内容?
- (1)废弃常量
- (2)不再使用的类型(如何判断?)
- 3.分带假说?
- 4.垃圾收集算法?
- (1)标记清除算法
- (2)标记复制算法
- (3)标记整理算法--更适合老年代
- 5.Hotspot算法细节?
- (1)根节点枚举
- (2)安全点(抢先式中断、主动式中断)
- (3)安全区域
- (4)记忆集与卡表
- (5)并发时可达性分析-三色标记
缺点:无法解决循环依赖
(2)可达性分析算法标记不可达后并不一定死亡,之前还有一次判断finalize()是否有必要执行的自救机会。
①覆盖了finalize②未执行过finalize
保证这两点后对象将被加入一个等待执行finalize的队列,但并不一定保证自救成功,也就是不一定真的会执行finalize
1.虚拟机栈中的引用对象(参数,局部变量,临时变量) 2.方法区中静态属性对象(static) 3.方法区中常量对象(finall) 4.本地方法引用对象 5.虚拟机内部引用(如基本数据类型对象,异常对象,类加载器) 6.同步锁持有对象(synchronized) 7.反应虚拟机内部情况的JMXBean、JVMT1中注册的回调、本地代码缓存等3.方法区回收内容? (1)废弃常量
不再被使用的字面量等常量池中的内容
(2)不再使用的类型(如何判断?) 3.分带假说?1.弱分代假说:绝大多数对象是朝生夕灭的 2.强分代假说:越是熬过多次垃圾收集的对象越难以消亡 3.跨代引用假说:存在相互引用关系的两个对象应该是倾向于同生共死的4.垃圾收集算法? (1)标记清除算法
效率低,碎片化内存
(2)标记复制算法空间浪费高,无碎片
解决:提出“Appel”式回收–新生代分为Eden、From Survivor、To Survivor 8:1:1。前两区可分配内存。eden快满时发生minor gc->将eden存活对象放到ts,fs中存活对象,一部分放入老年代,一部分放入ts->清空eden,fs->交换ts、fs
无需标记复制一样的“分配担保(ts不足容纳)”,但是需要暂停用户线程
5.Hotspot算法细节? (1)根节点枚举由于根节点枚举过程必须stop the world,为保证效率,使用OopMap(普通对象指针图)来保证准确式垃圾收集,类加载完成时和即时编译过程中,将记录下哪些位置是引用。详见深入理解java虚拟机第3版,123页
为每条指令都生成oopmap过于浪费空间,所以只在特定位置(安全点)记录oopmap并且只在这些位置才能开始垃圾收集。安全点选取标准是:是否具有让程序长时间执行的特征,例如方法调用、循环跳转、异常跳转。
主动式中断,采用 内存保护陷阱 方式保证轮询操作高效性;何为内存保护陷阱?如用一条test指令检测一个地址是否为真,如果为真产生异常,转去异常处理程序处理。(3)安全区域
安全点保证程序执行时进入垃圾收集状态,安全区域解决不执行时进入。
①安全区域保证这片代码中引用关系不发生变化
②安全区域内的线程不会被收集,线程离开时检查虚拟机是否完成根节点枚举,未完成则等待
记忆集用于记录非收集区指向收集区的指针结合,卡表是记忆集定义了记录精度(卡)、与堆内存映射关系的实现。卡表可用字节数组实现。
采用写屏障更新卡表,在每个引用对象赋值操作时产生环形通知,但是会导致伪共享问题。
1.浮动垃圾问题
2.对象消失问题
产生条件:①赋值器插入了从黑色到白色的新引用
②赋值器删除了全部从灰色到白色的引用
解决:①增量更新:破坏条件①,并发扫描结束后,以记录过的有变动的黑色对象为根再扫描一遍
②原始快照:破坏条件②,并发扫描结束后,以记录过的变化之前的灰色对象为根再扫描一遍



