1.首先关于HotSpot中根节点的选择
首先在现在开发过程中,因为不断增加的内存引用,往往光方法区就超过了数百兆,如果要逐个检查,必然浪费很长时间
而且在可达性的分析过程中,必须保证在分析的时候,不可以出现在分析过程中对象的引用关系在不断的变化
为了保证这点,就必须在GC的过程中,停顿所有的Java执行线程,称为Stop The World,
而且为了确保在GC过程中的高效性,并非在停顿检查的时间,检查所有的对象,是使用了OopMap数据结构实现了这个目的,在类加载完成后,将对象什么偏移量上什么类型的数据计算下来,在GC的时候直接进行扫描.
2.为了可以保证分析过程中对象的引用关系不进行变化
虽然说引入了OopMap机制,导致了快速的GCRoots枚举,但是对于Cpu指令来说,能进行修改的代码太多了,所以在前面也介绍了,在某些特定的地方进行了记录,这些位置称为安全点,也就是在程序执行的时候并非所有的地方都能GC,必须在某一个安全点进行GC,常见的安全点的位置要符合指令的复用
例如
方法调用,循环跳转,异常跳转,
在这些点上,我们将其设置为安全点
而在某些解释的时候,就将其比较为安全词,一旦垃圾回收线程喊出了安全词,其他的线程就会停下工作
3.如何让所有的线程都可以在安全点处停下来进行GC呢?
基本策略分为:抢先式中断和主动式中断
抢先式中断:在GC发生时候,首先将所有的线程中断下来,如果有中断的地方不在安全点上,就恢复线程,让其重新跑到安全点,在进行GC回收,在现在已经没有虚拟机使用这种方式进行GC事件了
主动式中断,这是在GC需要中断线程的时候,不进行直接操作,简简单单的设置一个标志,让各个线程去主动轮询这个标志,在标志为真的时候就进行挂起,在何处轮训的地方和安全点是重合的
在安全点机制上,我们还补充了Safe Region安全区域来进行补充,也就是在线程处于Sleep或者Bolcked状态的时候,线程无法响应JVM中断的请求,这时候就引入了安全区域的概念,在这个区域内,引用关系不会被改变,在此区域内进行GC都是安全的,所以通常将Safe Region看作是扩展了的Safepoint
在安全区域的时候,线程表示自己进入了Safe Region.这样,在JVM进行GC的时候,就自动pass为Safe Region状态的线程了,而线程在离开Safe Region的时候,就需要检测是否已经完成了根节点枚举,如果完成了,就需要继续执行,不然就持续等待可以离开的信号