对于hotspot算法应该在解决这几个问题:
可达性分析是从根节点到最引用结尾吗?
不是的!
拿现在的方法区来说,一个应用有百兆之多,如果每个对象是从头找到尾,消耗的时间必然很长;
而且,可达性分析对GC的停顿很敏感。这句话的意思是可达性分析是要停留在一个时间点上的,如果不在一个时间点,引用必然发生变化,那么,可达性分析又有什么意义呢?
解决办法是,创建叫做oopmap的数据结构来解决该问题,就是说在完成类加载的时候,hotspot就把对象内什么偏移量的上是什么数据类型的数据计算出,存放到该结构中,那么在gc扫描中,就可以直接得到这些信息。
每一个对象都有oopmap结构?
也不是!
如果每个对象都有这样的对象,那么,对象太多了,这样,为了GC而消耗的内存也是巨大的。
为此,hotspot算法给出的解决方法是,创建一个安全点(safepoint),就是说,GC 不是在任何时候都可以进行,而是达到一个安全点之后才会进行,而安全点的产生是有方法调用,循环跳转,异常跳出等等产生。
程序会同时到达安全点吗?
不会!
对此,hotspot算法有俩中中断方式处理:
- 抢先式中断:当执行GC的时候,所有的程序都会中断,那么,当某些中短程序没有达到中断怎么办?让他恢复,继续执行到安全点。
- 主动式中断:这个方式中,程序主动去轮训中断标志,如果中断为true,那么久执行中断。这个中断标志的设置其实是和安全点重合的。
安全点能解决全部问题吗?
不能!
假设,一个线程进入了睡眠状态(执行Thread.sleep(),当前线程会立刻挂起),那么,当要执行GC的时候,这个线程如果一直在睡眠状态,永远达到不了安全点。怎么办嘞?
设置一个安全区域(safe region),当执行GC的时候,垃圾回收程序不会管有安全区域标志的线程。当该线程要离开方法区的时候,回去询问是否完成了GC,如果完成了,那么就继续执行;如果没有,等待指令离开