Java垃圾回收机制——从JVM、JMM讲起,包含FullGC及其解决方案

1.JVM、JMM

1.什么是JVM

JVM是1个规范,它包括:

  • 方法区
  • 堆区
  • 虚拟机栈
  • 本地方法栈
  • 程序计数器
    加粗样式
2.什么是JMM

JMM:它规定了线程和内存之间的一些关系。

  • 根据JMM的设计,系统存在1个主内存,java中所有的变量都存在主内存中,对于所有线程都是共享的。
  • 每个线程都有自己的工作内存,该工作内存中保存的是主存中某些变量的copy,线程中的所有操作都是在工作内存中进行的,线程之间无法直接相互访问,变量传递需要通过主内存完成。

volitail关键字:

  • 它可以保证线程之间工作内存中变量的可见性。

线程i++的操作分3步:

  • 1.栈中取出i;
  • 2.i+1;
  • 3.i存回栈。

在这里插入图片描述

2. 运行时数据区域

Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分成若干个不同的数据区域。

1.程序计数器(线程私有)
  • 1.字节码解释器工作时,通过改变程序计数器的值选取下一条需要执行的指令;
  • 2.分支、循环、跳转、异常处理、线程恢复等功能都依赖它。

程序计数器是唯一不会出现 OutOfMemoryError 的内存区域。

2.Java虚拟机栈(线程私有)

1.Java 虚拟机栈也是线程私有的,它的生命周期与线程相同。
2.java方法在被调用时,会在虚拟机栈分配空间,每个方法被执行时会创建1个栈帧。

1.可存:
  • 基本数据类型
  • 对象引用类型
  • 返回地址类型
2.存在2种异常

1.栈溢出(StackOverflowError):

  • 如果虚拟机栈不可以动态扩展,当线程请求的栈深度大于虚拟机所允许的深度时,将抛出StackOverflowError异常;

2.内存溢出(OutOfMemoryError):

  • 如果虚拟机栈可以动态扩展,当无法申请到足够的内存时。
3.本地方法栈(线程私有)
1.也是线程私有的,它的生命周期与线程相同。
2.与虚拟机栈的区别在于:
  • 它是为本地方法服务的,不是用java语言写的方法,(比如native关键字修饰的方法)。
3.存在2种异常:
  • 栈溢出
  • 内存溢出
4.Java堆区(线程共享)

1.他是被所有线程共享的区域,是GC主要管理的区域
2.用途:

  • 存放对象实例
3.存在异常

内存溢出:在申请内存时,没有足够的内存空间供其使用

  • 申请了Integer,但是给他存了Long才能存下的数。

内存泄漏: 程序在申请内存后,无法释放已申请的内存

  • 一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。导致内存溢出
5.方法区(线程共享)

1.他是被所有线程共享的区域,也是GC管理的区域
2.存放数据类型:

  • 加载的类文件
  • 常量
  • 静态变量
  • 编译后的代码
3.存在异常
  • 内存溢出。

JDK 1.8 将方法区彻底移除,取而代之的是元空间,元空间使用的是直接内存

4.运行时常量池

用于存放编译生成的字面量和符号引用

  • String str = “abcdefg”; //符号引用
  • static int n = 100; //-128-127范围的常量
2.5.直接内存

它不是JVM运行时数据区的一部分,也不是虚拟机规范中定义的内存区域。

存在异常
  • 内存溢出

本机直接内存的分配不受到 Java 堆大小的限制,受到本机总内存地大小及处理器寻址空间的限制。如果各个内存区域的总和大于物理内存限制,就会导致动态扩展时出现 OutOfMemoryError 异常。

3.垃圾回收

1.什么是垃圾回收?

它是释放垃圾占用的空间,提升程序性能,防止内存泄露。当一个对象不再被需要时,该对象就要被回收以释放空间。

2.调用垃圾回收的方法

调用垃圾回收器的方法是gc,该方法在System类和Runtime类中存在

  • 在System类中,gc是静态方法,该方法会调用Runtime类中的gc方法;
  • 在Runtime类中,gc是实例方法,借助System.gc是调用该方法的便捷方式。
    其实,java.lang.System.gc 等价于 java.lang.Runtime.getRuntime.gc 的简写,都是调用垃圾回收器。

该方法由系统自动调用,不需要人为调用。该方法被调用之后,由 Java 虚拟机决定是立即回收还是延迟回收

finalize方法

一般在该方法中,释放对象所持有的资源。

3.判定垃圾的方法
1.引用计数法(存在循环引用的问题)

给每个对象添加引用计数器,用于记录对象被引用次数,计数为0代表它是可回收对象

优点:

  • 实现简单,判定效率高

缺点:

  • 无法解决循环引用的问题
2.根搜索法

从若干被称为GC Roots的对象开始搜索,不可达的对象就是可回收对象

2.1.GC Roots的4种引用变量
  • 1.虚拟机:中引用的对象
  • 2.本地方法:的本地方法引用的对象
  • 3.方法区中:类静态属性引用的对象
    string是堆区中的实例对象
public static String str = string; 
  • 4.方法区中:常量引用的对象。
2.2.引用的4种分类

1.强引用:GC永远不会回收的引用对象
2.软引用:还有用,但非必需的对象。

  • 只有在将要发生内存溢出时,才会被回收

3.弱引用:非必需的对象

  • 他只能活到,下一次GC之前

4.虚引用:一个对象是否有虚引用,完全不对其生存空间构成影响,也无法通过虚引用取得1个对象实例。

  • 它存在的唯一目的:能在这个对象被回收时,收到1个系统通知
4.回收垃圾的方法
1.标记清除

分为标记清除两个阶段

  • 1、标记出所有需要回收的对象
  • 2、清除所有被标记的对象
优点:
  • 实现简单
缺点:
  • 1.效率问题:标记、清除效率都不高
  • 2.空间问题:标记清除后会产生大量不连续的内存碎片,导致程序无法为大对象分配足够连续内存。
    在这里插入图片描述
2.复制算法

把内存分为大小相等的2块,每次只使用其中1块,用完后,将存活的对象复制到另1块内存,把原来的1块,一次性清除。

优点:
  • 实现简单,运行高效
缺点:
  • 内存缩小为原来的一半
  • 在对象存活率高时,复制次数较多,会拖慢效率。

在这里插入图片描述

3.标记整理

根据老年代的特点提出的,标记过程和标记清除一样,但后续步骤不同
它是让所有存活对象往一端移动,然后清理边界外的内存

在这里插入图片描述

4.分代收集

根据对象的存活周期不同,将其划分为多个区域,对每个区域使用不同的垃圾回收算法

回收策略:
  • 新生代:大多数对象存活时间短,选用复制算法
  • 老年代:对象存活率高,因此一般选用标记清除标记整理
    在这里插入图片描述
5.分配内存与回收策略

Java堆可以分成,新生代、老年代,新生代又可以细分成,Eden区,From Survivor区,To Survivor区。
对于不同的区有不同的对象,有相应的内存分配规则。

1.MinorGC和FullGC
Minor GC

它是发生在新生代的垃圾回收操作。因为大多数对象的生命周期都很短,因此Minor GC会频繁的执行,一般回收速度很快

Full GC (或称Major GC)

他是发生在老年代的垃圾回收操作。出现了Full GC 一般伴随至少1次的Minor GC。老年代对象的存活时间长,因此Full GC很少执行,而且执行速度比Minor GC慢很多

2.对象优先在Eden区分配

大多数情况下,对象在新生代Eden区分配,当Eden区空间不够时,发起Minor GC。

3.大对象直接进入老年区

大对象是指需要连续分配内存空间的对象,

  • 最典型的大对象是那种很长的字符串、数组。

大对象对于虚拟机的内存分配是个坏消息,经常出现大对象导致内存在还有不少空间时就触发垃圾回收以获取足够的连续空间分配给大对象。

大对象直接放在老年代中,是为了避免在Eden区、Survivor区之间出现大量的内存复制

4.长期存活的进入老年区

虚拟机采用分代收集的方式进行垃圾收集,因此需要识别每个对象应该放在老年区还是新生区。

虚拟机给每个对象定义了年龄计数器

  • 对象在Eden区出生后,如果金经过第1次Minor GC 还存活,将进入Survivor区,同时年龄变为1;
  • 对象在Survivor区每经过1 次MinorGC 且存活,年龄+1,增加到一定阈值进入老年区。(默认为15)
5.动态对象年龄判定

为了更好地适应不同程序的内存状况,虚拟机并不总要求对象的年龄必须达到阈值才会进入老年代。

  • Survivor区相同年龄的对象 > Survivor空间一半 ???

Survivor区中相同年龄的所有对象的空间总和大于Survivor区空间的一半,则年龄大于等于该年龄的对象直接进入老年区。

6.空间分配担保——Full GC触发的条件?
  • 老年代最大可用连续空间 > 新生代所有对象空间总和 ???

在发生Minor GC之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象的空间总和,如果这个条件成立,则进行Minor GC是安全的。

只要老年代的连续空间大于新生代的对象总大小 或者历次晋升的平均大小,就会进行Minor GC,否则将会进行Full GC.

4.FullGC及其解决方案、CMS垃圾收集器介绍

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值