您的位置:首页 > 其它

JVM学习笔记

2015-08-27 09:20 148 查看
我们知道,虚拟机在判断对象是否应该被回收的依据是该对象是否处于可达状态,如果不可达,就会进行回收。

那么虚拟机是怎么判断对象是否可达呢?

答案是通过一系列GC Roots的对象作为搜索起点,从这些节点从下到上开始搜索,走过的路径成为引用链,当一个对象不再被任何引用链所引用,及判断该对象处于不可达,可回收状态。如下图所示,图片摘自《深入理解JAVA虚拟机》



可作为GC Roots的对象:帧栈中的本地变量表引用的有效对象、方法区中的静态属性引用的对象和常量引用的对象、本地方法栈中引用的对象。

每次进行垃圾回收的时候,回收线程就会找到这些对象,筛选出不可达的对象,进行回收,然而现在的程序方法动辄达到上百兆,回收线程要从栈和方法区中的引用中一个一个寻找识别出哪些是GC Roots的引用无疑是比很大的开销,实际上,虚拟机并不需要检查完所有的执行的上下文和全局的引用变量,而是通过使用一组OopMap的数据结构来实现。

简单来说,OopMap里面记录的就是(执行的上下文和全局的引用变量中)GC Roots对象的引用,这些引用指向的就是GC Roots对象,在类加载完成的时候,HotSpot就把对象偏移量上是什么类型的数据计算出来,在JIT编译过程中,也会在特定的位置下记录在栈和寄存器中哪些位置是引用,每当虚拟机要进行垃圾回收的时候,扫描很快的得到这些信息,只需要通过OopMap即可很快的确定不可达对象,从而省去了从所有变量中寻找GC
Roots对象的时间。

在OopMap的协助下,GC可以很快的寻找和完成GC Roots枚举,但是一个现实的问题随之而来,如果OopMap中引用的变化的指令非常多,如果为每一条指令都生成对应的OopMap,那么就会需要大量的额外空间,GC的空间成本就会变高。

实际上,OopMap的选取指令位置一般为:方法结束前,call方法执行后,循环结束时,异常开始前。这些位置也成为安全点(safepoint),这样之前的问题就解决了。程序执行时并非在所有的位置都能停下来开始GC,而是到达安全点才能开始执行GC。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: