专业的JAVA编程教程与资源

网站首页 > java教程 正文

一文理解Java垃圾回收机制(java垃圾回收机制优缺点)

temp10 2024-10-22 17:06:40 java教程 13 ℃ 0 评论

前言

Java的垃圾回收机制让开发者可以把更多的精力投入到业务和逻辑中,少关注内存的管理(JVM会自动将垃圾内存进行回收),降低了程序员的工作难度。但是在当今互联网的环境下,高并发,高可用的需求下,充分理解垃圾回收机制才能更好的完成工作。

这就需要我们对于虚拟机对内存的管理方式,方法,垃圾回收的方法,策略有很好的了解。下面我们可以带着问题去阅读:

一文理解Java垃圾回收机制(java垃圾回收机制优缺点)

  1. JVM如何管理内存

  2. JVM如何确定某些内存为垃圾需要回收

  3. JVM如何在不影响正在运行程序的同时进行垃圾回收

JVM运行区域

JVM在管理内存的时候会将内存划分为不同的数据区域,这些数据区域各有各的用途。

JVM运行时数据区域

  1. 程序计数器

    比较小的内存空间,可以看成当前程序所执行的字节码的行号指示器。在我们进行JVM优化的时候基本上不用考虑它。

  2. 虚拟机栈

    描述了Java方法执行的内存模型,每个方法执行的时候会创建栈帧,存储局部变量表、操作数、动态连接、返回地址等。调用方法的过程是一个进栈和出栈的过程。

  3. 本地方法栈

    为虚拟机使用到的Native方法提供服务,与虚拟机栈有点类似

  4. 虚拟机所管理的内存中最大的一块。被所有的线程所共享,虚拟机启动的时候创建。用于存放对象的实例。也是垃圾收集器的主要工作区域。

  5. 方法区

    各个线程共享的内存区域,存储被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。运行时常量池是方法区的一部分,存放编译期间生产的各种字面量和符号引用。

Java对象的前世今生

为了更好的理解垃圾回收,让我们先看看对象的整个生命周期,从诞生到消亡的过程。

产生过程:

  1. new 指令创建对象

  2. 检查常量池中是否有创建类的符号引用,并检查此引用是否被加载,解析和初始化过

  3. 虚拟机为对象分配空间(此时对象的大小以及确定)

  4. 分配的空间初始化为0

  5. 对对象进行必要的设置:那个类的实例,类的元数据,对象的Hash值等。存放在对象头中。

  6. 至此对象JVM中对象已经产生,可以开始执行Java的代码

生存状态:

  1. 对象在内存中有3块区域:对象头,实例数据,对其填充

  2. 当我们建立对象的时候,会在栈上有一个对象的引用来访问对象

对象的消亡:

  1. 对象不在被引用会被JVM标记为垃圾

  2. 通过JVM的垃圾回收机制(本文描述的重点)将对象销毁内存释放

什么是垃圾

我们把JVM的内存回收叫做垃圾回收机制。到底什么是垃圾,通过字面理解,既然是垃圾就是不再使用的对象啦,JVM如何去判断那?

答案:JVM通过一种可达性分析算法来确定对象是否为垃圾。简单的说,就好像树林中,对象是叶子,如果叶子不能可以沿着枝条(引用关系)找到任何一颗树根,则这个叶子是垃圾(应该已经掉落在地上了)。树根==GC Root;枝条==引用关系;叶子==对象

下面的问题来了,JVM中的GC Root都有什么??

  1. 虚拟机栈中引用的对象

  2. 方法区中静态属性引用的对象

  3. 方法区中常量引用的对象

  4. 方法区栈JNI中引用的对象

垃圾回收算法

通过之前的阅读,我们大体可以得到如下的结论:

  1. 垃圾回收主要集中在堆上

  2. 方法区中有大量的常量和类(如果使用反射和动态代理等框架,产生大量的动态类的情况下,需要考虑类卸载的问题)

  3. 知道了那些类会被定义为垃圾

现在的问题是,什么时间,如何进行垃圾回收?

我们先看看垃圾回收的主要算法

  1. 标记-清除

    灰色表示需要释放的内存

    经历2个步骤,第一步进行标记(找出垃圾),第二步进行清理(释放内存)。会产生很多内存碎片


  2. 复制

    两个区域相互拷贝


    使用一半的内存,交替使用。内存没有碎片,但是会浪费一半的资源

  3. 标记-整理

    和标记清除类似,但是没有内存碎片

垃圾回收实现

现代的JVM都使用分代收集算法,主要是根据对象存活的周期不同将内存分为几个块。一般分为:新生代,老年代。

  1. 新生代:存储的对象都是很快会被回收的对象,只有少量存活,由于存活的比较少,使用复制算法将比较合适。新生代中还可以细分3个区:Eden,S1,S2。

  2. 老年代:对象存活率比较高,可以使用标记清除或者标记整理来实现垃圾回收

GC有2种:

  1. Minor GC

    又称新生代GC,指发生在新生代的垃圾收集动作;

    因为Java对象大多是朝生夕灭,所以Minor GC非常频繁,一般回收速度也比较快;

    触发条件:当Eden区满时,触发Minor GC。

  2. Full GC

    又称Major GC或老年代GC,指发生在老年代的GC;

    出现Full GC经常会伴随至少一次的Minor GC(不是绝对,Parallel Sacvenge收集器就可以选择设置Major GC策略);

    Major GC速度一般比Minor GC慢10倍以上;

Full GC触发条件:

(1)调用System.gc时,系统建议执行Full GC,但是不必然执行

(2)老年代空间不足

(3)方法区空间不足

(4)通过Minor GC后进入老年代的平均大小大于老年代的可用内存

(5)由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小

垃圾回收器

HotSpot虚拟机提供了如下几种垃圾回收器

垃圾回收器示意图

连线表示可以搭配使用

  1. Serial收集器:

    单线程,会暂停所有的工作进行垃圾回收,默认用于Java client中。设置参数:-XX:+UseSerialGC

  2. ParNew:

    Serial的多线程版本

  3. Parallel Scavenge:

    新生代的收集器,使用复制算法,并行的多线程收集器。主要的特点是控制吞吐量。

  4. CMS:

    是一种以最小停顿为目标的设计方案,是基于标记-清除的算法

  5. Serial Old:

    Serial收集器的老年代版本,可以作为CMS收集器的后备预案,在并发收集发生Concurrent Mode Failure时使用

  6. Parallel Old:

    Parallel Scavenge收集器的老年代版本

  7. G1:

    面向服务端应用的收集器,并行与并发;分代收集;空间整合;可预期的停顿

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表