深入探索JVM垃圾回收:ARM服务器垃圾回收的挑战和优化
上QQ阅读APP看书,第一时间看更新

2.4.4 JVM中根的构成

JVM中根的构成非常复杂,根据程序执行的语义、语言特性的支持及JVM内部优化实现,可以将根划分为Java根、JVM根和其他根。

Java根用于找到Java程序执行时产生的对象,包括两类,分别为:

  • 类元数据对象,主要利用类加载器来跟踪Java程序运行时加载的类元数据对象。
  • Java对象,主要通过线程栈帧跟踪Java程序的活跃对象。

JVM根主要指JVM为了运行Java程序所产生的一些对象,这些对象可以简单地被认为是全局对象。主要有:

  • Universe,Java程序运行时需要一些全局对象,比如Java支持8种基本类型,这些基本类型的信息需要对象来描述(基本类型的描述信息作为全局对象是为了性能考虑),这些对象就存放在Universe中。
  • Monitor,全局监视器对象,对于Monitor对象主要是用于锁相关,可能存在只有Monitor对象引用到内存空间的对象,所以Monitor是JVM的根之一。
  • JNI,JVM执行本地代码时使用API产生的对象,例如通过JNI API在堆中创建对象,这些对象只在JNI API中使用,所以需要单独管理这些对象。
  • JVMTI,使用JVM提供的接口用于调试、分析Java程序。使用JVMTI API时也会分配新的对象。
  • System Dictionary,JVM在设计类加载时,对于基本的类,比如Java中经常使用的基础类,会通过系统加载器加载这些类,而这些类在运行Java程序一直都需要,所以这些类被单独加载,单独标记。
  • Management,是JVM提供的内存管理API,用于JVM内存的统计信息,在使用这些API时需要创建Java对象,所以需要标记。
  • AOT,在JDK 9之后引入了提前编译。在AOT的编译过程中会把全局对象和编译优化的代码对象放在可执行文件中,当执行时会用到这些对象,所以在回收时需要标记。

其他根主要有:

  • 语言特性的弱引用。
  • JVM弱根,例如管理Java中String中intern产生的对象、编译后代码等。

这些根共同构成了GC根集合,实际上根的确定和虚拟机运行时密切相关,而运行时又非常复杂,限于篇幅,本书无法对根详细介绍,有兴趣的读者可以参考其他文献。

需要注意的是,对于弱根的处理在不同的GC实现中有所不同,主要原因是弱根通常涉及内部资源的释放,整个流程耗时较多,在一些回收中会把弱根当作强根对待(即不释放弱根相关的内部资源),以加快GC的执行。