yunshuipiao / Potato

Read the fucking source code for the Android interview
Apache License 2.0
80 stars 12 forks source link

GC And Algorithm #32

Open yunshuipiao opened 5 years ago

yunshuipiao commented 5 years ago

GC And Algorithm

Table of Contents GC And AlgorithmJVM 内存管理GC 机制查找算法四个引用内存分区GC 算法垃圾收集器串行收集器(Serial GC)ParNew GCParallel Scavenge GCCMS (Concurrent Mark Sweep)收集器….总结

这篇文章讲述 java 的垃圾回收机制,和之前的文章有密切的联系。 JMM, JVM, Java Class Model

在平常的开发中,如果不了解内存回收机制的原理,可能会引发内存泄漏,频繁 GC。导致应用卡顿,甚至崩溃等。

JVM 内存管理

这里在之前的基础上,详细介绍每一个区域的作用。

  1. 方法区:存放已被加载的类的信息,如(类名,修饰符),静态变量,构造函数,final定义的常量,类中的字段和方法等信息。全局共享。但方法区超过允许的大小时,会发生 OOM。 运行时常量是方法区的一部分,用于存储编译器生成的常量引用。
  2. 堆区:GC 最频繁的区域,也是理解 GC 机制最重要的区域。有所有线程共享,在虚拟机启动时创建。堆区主要用于存放对象实例及数组,所有 new 出来的对象都存储在该区域。
  3. 虚拟机栈:占用操作系统内存,每个线程对应一个虚拟机栈,线程私有,生命周期和线程一样,每个方法被执行时产生一个栈帧,用于存储局部变量表,动态链接,操作数和方法出口等信息。当方法被调用时,栈帧入栈,当方法调用结束,栈帧出战。 虚拟机栈定义了两种异常类型,StackOverFlowError 和 OOM。如果线程调用的深度大于虚拟机允许的最大深度,则抛出 StackOverFlowError;直到内存不足时,抛出 OOM。
  4. 本地方法栈:用于支持 native 的执行。
  5. 程序计数器:JVM在解释字节码(.class)文件时,存储当前线程执行的字节码行号,只是一种概念模型,各种JVM所采用的方式不一样。 此内存区是唯一不会抛出OutOfMemoryError的区域。

GC 机制

随着程序的运行,内存中的实例对像,变量占用的内存越来越多,如果不及时进行回收,就会降低程序运行效率,甚至引发系统异常。

在上面的区域中,有 3 个区域不需要进行垃圾回收,本地方法栈,虚拟方法栈和程序计数器。因为生命周期和线程同步,线程销毁和其占用内存也会销毁。因此,只有方法区和堆区需要进行垃圾回收,回收的对象就是那些不存在引用的对象。

查找算法

  1. 引用计数法:基本概念不做介绍。当存在相互引用时,无法回收。
  2. 根搜索算法(可达性分析):从一个称作 GC Roots 的根基点出发,向下搜索。如果一个对象不能达到 GC Roots 的时候,说明该对象不再被引用,可以回收。 可作为 GC Roots 的对象:
    • 虚拟机栈(栈帧中的本地变量表)中引用的对象
    • 方法区中类静态属性引用的对象
    • 方法区中常量引用的对象
    • 本地方法栈中的 JNI (Native)引用的方法

四个引用

在JDK1.2之后引入了四个概念:强引用、软引用、弱引用、虚引用

内存分区

内存主要被分为三代,新声代,旧生代和持久代。不同的特点造成了其回收算法的不同,新生代适合生命周期短,快速创建和销毁的对象;旧生代适合生命周期较长的对象,持久代在 Sun Hotpot 虚拟机中就是指方法区。

GC 算法

垃圾收集器

GC 是由垃圾回收器来执行。在实际场景中,需要选择合适的垃圾收集器。

串行收集器(Serial GC)

Serial GC是最古老也是最基本的收集器,但是现在依然广泛使用,JAVA SE5和JAVA SE6中客户端虚拟机采用的默认配置。比较适合于只有一个处理器的系统。

在串行处理器中,minor 和 major GC过程中都是用一个线程进行回收。最大特点是在进行垃圾收回是,需要对所有正在进行的线程暂停,对于有些应用难以接受。

ParNew GC

基本过程和串行收集器一样,但加入了多线程机制,提高了效率。

Parallel Scavenge GC

在整个扫描和复制过程采用多线程的方式进行,适用于多CPU、对暂停时间要求较短的应用,是server级别的默认GC方式。

CMS (Concurrent Mark Sweep)收集器

该收集器的目标是解决Serial GC停顿的问题,以达到最短回收时间。常见的B/S架构的应用就适合这种收集器,因为其高并发、高响应的特点,CMS是基于标记-清楚算法实现的。

CMS收集器的优点:并发收集、低停顿,但远没有达到完美;

….

总结

深入理解JVM的内存模型和GC机制有助于帮助我们编写高性能代码和提供代码优化的思路与方向。