jvm-GC
Sebastian Lv4

这一篇聊聊java虚拟机中的垃圾回收,梳理目前我所掌握的有关内容,当谈到此话题时应该从哪几个方面去深入交流,体现专业性,供查漏补缺,必要时再更新。

JVM的运行时数据区

从这个角度去理解GC的必要性以及发生的区域、重点关注区域

JVM中的运行时数据区主要有堆、栈、方法区、虚拟机栈以及程序计数器。其中会发生GC的区域为堆、栈和方法区。

堆:存放Java对象的地方,是GC的主要场所,当没有区域来存放对象时会抛出OutOfMemoryError

方法区:各个线程共享,用于存储被虚拟机加载的类型信息、常量、静态变量等信息。回收时主要针对常量池的回收和类型的卸载,对类型的卸载有严格的条件限制,一般不会发生。如果方法区没有足够的空间去存储新的内容,会抛出OutOfMemoryError

垃圾回收算法

虽然叫算法,也可以理解为垃圾回收方式,不同的算法都围绕的可用性来做,也以不影响用户程序为目标来改进,减少stop the world的影响。

标记清除

标记复制

标记整理

以上三种算法的原理都在字面意义上了,之所以会有这些不同的算法,主要是考虑到分代的思想以及内存的利用率,减少内存碎片。

垃圾回收器

GC时的主要参与者之一,有哪些回收器是可供选择的,各自的区别及特点是什么?

现代垃圾回收器都是基于分代收集理论设计的。对于新生代,对象存活时间短,对于老年代,存放大的且长时间存货的对象,各自的收集风格不同。

  • Serial

  • ParNew

  • Parallel Scavenge

  • Serial Old

  • Parallel Old

  • CMS

  • Garbage First

  • Shenandoah

  • ZGC

  • Epsilon

GC Root

GC时的另一个主要参与者,哪些对象是要回收的,如何判断

从GC Root开始去查相关引用,任何直接或非直接引用到的对象都不在GC的目标内。

系统类加载器加载的类,也包含其静态变量

存储在栈中的本地变量和方法参数

活跃的线程

native栈中的对象、参数

用于同步的对象

OOM

垃圾回收也无法保证JVM的正常使用,集体罢工了,这种情况怎么办(很无奈,至今没遇到过)

  1. 通过分析工具(目前为止我都是在客户端看的,运维同事提供dump日志,我用jdk自带的工具jvisualvm)对dump出来的快照进行分析,明确内存中导致OOM的对象是否是必要的, 以此区分是Memory Leak还是Memory Overflow

    • 如果是内存泄漏,可以进一步通过工具找到GC Root引用链,可以看到如何引用到,然后一步步定位到代码的具体位置。
  2. 检查JVM的参数设置”-Xmx, -Xms”,与机器内存做对比,看看是否还有向上调整的空间

  3. 从代码上检查是否某些对象的生存周期过长、持有状态时间过长、数据结构不合理等情况,减少程序运行周期的内存消耗。

Memory Leak

对象在业务中理应不再使用了,但无法通过GC回收。如果不加处理,堆中资源会被消耗殆尽,进造成OOM。