成神之路4 Java的垃圾回收机制

参考资料:

《深入理解Java虚拟机》

《Hotspot实战》

理解Java垃圾回收机制

一个面试官对GC问题的分析

理解Java垃圾回收机制

Jvm内存模型

图解Java 垃圾回收机制

0. 序

Java 垃圾回收机制要考虑的问题很复杂,本文将阐述其三个核心问题,包括:

  • What 哪些内存需要回收?

    判断对象是否可以被回收的两种经典算法:

    1. 引用计数法
    2. 可达性分析算法
  • When 什么时候回收?(堆的新生代、老年代、永久代的垃圾回收时机,MinorGC 和 FullGC)

  • How 如何回收?(三种经典垃圾回收算法(标记清除算法、复制算法、标记整理算法)及分代收集算法 和 七种垃圾收集器)

1. 首先回顾Java内存模型

运行时内存模型,分为线程私有和共享数据区两大类,其中线程私有的数据区包含程序计数器、虚拟机栈、本地方法栈,所有线程共享的数据区包含Java堆、方法区,在方法区内有一个常量池。

运行时数据区域

(1)线程私有区:

  • 程序计数器:记录正在执行的虚拟机字节码的地址;
  • 虚拟机栈:方法执行的内存区,每个方法执行时会在虚拟机栈中创建栈帧;
  • 本地方法栈:虚拟机的Native方法执行的内存区;

(2)线程共享区:

  • Java堆:对象分配内存的区域;
  • 方法区:存放类信息、常量、静态变量、编译器编译后的代码等数据;
    • 常量池:存放编译器生成的各种字面量和符号引用,是方法区的一部分。

2. 问题一:What 哪些内存需要回收

可以通过两种算法来判断对象是否可以被回收

  1. 引用计数算法:判断对象的引用数量
  2. 可达性分析算法:判断对象的引用链是否可达

引用计数算法

堆中的每个对象实例都有一个引用计数。当一个对象被创建时,且将该对象实例分配给一个引用变量,该对象实例的引用计数设置为 1。当任何其它变量被赋值为这个对象的引用时,对象实例的引用计数加 1(a = b,则b引用的对象实例的计数器加 1),但当一个对象实例的某个引用超过了生命周期或者被设置为一个新值时,对象实例的引用计数减 1。特别地,当一个对象实例被垃圾收集时,它引用的任何对象实例的引用计数器均减 1。任何引用计数为0的对象实例可以被当作垃圾收集。

缺点:很难解决对象之间的相互循环引用的问题。

可达性分析算法

可达性分析算法是通过判断对象的引用链是否可达来决定对象是否可以被回收。

程序把所有的引用关系看作一张图,通过一系列的名为 “GC Roots” 的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain)。当一个对象到 GC Roots 没有任何引用链相连(用图论的话来说就是从 GC Roots 到这个对象不可达)时,则证明此对象是不可用的,如下图所示。在Java中,可作为 GC Root 的对象包括以下几种:

  • 虚拟机栈(栈帧中的局部变量表)中引用的对象;
  • 方法区中类静态属性引用的对象;
  • 方法区中常量引用的对象;
  • 本地方法栈中Native方法引用的对象;

可达性分析算法示意图.jpg-101.8kB

。。。。待写。

打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2015-2023 高行行
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信