深入理解java虚拟机(二)

二、垃圾收集器与内存分配策略

Jvm启动GC日志:-Xloggc:/your/log/path/gc.log,笔者测试使用的是JDK17,启动时会提示参数过时:-Xloggc is deprecated. Will use -Xlog:gc:/your/log/path/gc.log instead.

2.1 对象已死?

2.1.1 引用计数算法

在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加一;当引用失效时,计数器值就减一;任何时刻计数器为零的对象就是不可能再被使用的。

在Java领域,主流的虚拟机没有选用引用计数算法来管理内存的,很难解决对象之间相互循环引用的问题。

2.1.2 可达性分析算法

当前主流的商用程序语言(Java、C#等)的内存管理子系统,都是通过可达性分析(Reachability Analysis)算法来判定对象是否存活的。将“GC Roots”作为根对象,如果对象到根对象之间没有“引用链”(Reference Chain),也就是从GC Roots到对象不可达,则证明此对象不再被使用。

在Java技术体系里,固定可作为GC Roots的对象包括以下几种:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象,比如:各个线程被调用方法堆栈中使用的参数、局部变量、临时变量等;
  • 在方法区中类静态属性引用的对象,比如Java类的引用类型静态变量;
  • 在方法区中常量引用的对象,比如字符串常量池(String Table)里的引用;
  • 在本地方法栈中JNI(Native方法)引用的对象;
  • JVM内部的引用,如基本数据类型对应的Class对象,一些常驻的异常对象(NPE,OOM)等,还有系统类加载器;
  • 所有被同步锁(synchronized 关键字)持有的对象;
  • 反应JVM内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等。

除了这些固定的集合外,根据用户使用的垃圾收集器和当前回收的内存区域不同,还有一些对象可以“临时”加入,比如分代收集和局部回收(Partial GC)要考虑到不同代或者其他区域时候存在对象的引用,需要把这些有关联的区域都一起加入到GC Roots集合中。


深入理解java虚拟机(二)
https://wttch96.github.io/post/java/jvm/深入理解java虚拟机/深入理解java虚拟机(二).html
作者
Wttch
发布于
2022年5月13日
许可协议