JVM_02_垃圾收集器

4 篇文章 0 订阅


JVM垃圾收集器

了解JVM虚拟机是为了具有排查各种内存溢出内存泄漏问题的能力,在产生性能瓶颈时,我们也需要相关知识对垃圾回收过程进行必要的监控和调节。

对于程序计数器、虚拟机栈、本地方法栈来说,它们的内存分配和回收都具备确定性。而方法区中的内存的分配和回收都是动态的,因此只讨论对于这些区域的垃圾收集。


一、对象死亡的判断

对象死亡即是该对象再也无法由任何途径使用,垃圾收集器只能对已经死亡的对象进行垃圾收集。判断对象死亡的算法主要有两种:引用计数算法可达性分析算法

1. 引用计数算法(Reference Counting)

  • 有一个地方引用,计数器就加1
  • 有一个地方引用失效,计数器就减1
  • Python中使用了这种算法

缺点:无法解决对象间的。循环引用问题

2. 可达性分析算法(Reachability Analysis)

  • 设定一系列“GC Roots”作为起点,若任何一个GC Roots都无法到达某个对象,则该对象被判定为死亡
  • GC Roots包括
    1. 虚拟机栈中引用的对象
    2. 方法区中类的静态属性引用的对象
    3. 方法区中常量引用的对象
    4. 本地方法栈中引用的对象,

3. 引用类型

JDK1.2之后,Java扩充了引用的概念,将引用类型分为强引用、软引用、弱引用和虚引用

  • 强引用的对象无论如何都不会被回收
  • 软引用在发生OOM之前会被列入回收范围进行第二次回收,若回收后还是没有足够内存,则就会抛出异常
  • 弱引用比软引用更弱一些,不论当前内存是否足够,下次GC的时候一定会被回收
  • 虚引用是否存在不会影响一个对象的生存时间。唯一的目的是在对象被GC的时候收到一个系统通知

4. 最终死亡

  • 一个对象的最终死亡需要经过两次标记
  • 第一次标记:由可达性算法进行分析,若不可达,则进行一次标记
  • 第二次标记:判断是否有必要执行finalize()方法,若有必要执行,则暂时不标记

5. 回收方法区

方法区中主要有两个部分需要回收,即:废弃变量和无用的类

  • 废弃常量的回收和堆中对象的回收非常类似
  • 判断一个类是否需要回收需要满足三个条件
    1. 该类的所有实例都已经被回收
    2. 该类的ClassLoader已经被回收
    3. 该类的java.lang.Class对象在任何地方都没有被引用,无法在任何地方通过反射访问该类的方法

频繁自定义ClassLoader的场景都需要虚拟机具备类卸载的功能,以保证方法区不会溢出


二、垃圾收集算法

1. 标记-清除算法(Mark-Sweep)

  • 首先标记需要清除的对象,标记完成后统一进行回收
  • 存在两个问题:
    1. 效率问题
    2. 内存碎片问题

2. 复制算法(Copying)

  • 分为两块,在清除时,先将存活的对象复制到另外一块上面,再对原有的内存空间进行整体清除
  • 实际上并不需要1:1地划分两个区域,比如HotSpot虚拟机
    1. HotSpot中将新生代内存分为较大的Eden空间和两个较小的Survivor空间(8:1)
    2. 每次回收内存时,将Eden空间和其中一块Survivor空间中还存活的对象一次性复制到另一块Survivor空间中
    3. 若目标Survivor空间的内存不足,则采用老年代的内存进行分配担保(Handle Promotion)

3. 标记-整理算法(Mark-Compact)

  • 标记需要清除的对象
  • 所有不需要清除的对象向被标记的对象方向移动
  • 最后清除掉边界外的内存

4. 分代收集算法(Generational Collection)

  • 根据对象的存活周期将内存分为几个部分
  • 一般是分为新生代老年代,不同代内采用不同的垃圾收集算法
  • 新生代中对象存活率低,并且有分配担保,可以采用复制算法
  • 老年代中对象存活率高,没有分配担保,必须采用标记-清除或者标记-整理算法

三、HotSpot垃圾收集实现要点

1. 枚举根节点

用于可达性分析,需要"Stop The World",可以采用OopMap进行优化

2. 安全点

只在特定的位置设置了OopMap,有了OopMap才可以GC。这些位置称为安全点(SafePoint)

3. 安全区域

在安全区域(Safe Region)中,引用关系不会发生变化,在其中任何地方开始GC都是安全的。

四、垃圾收集器

1. Serial收集器

  • JDK1.3.1之前唯一选择
  • 单线程完成收集
  • 在收集过程中,必须停止其他线程
  • 新生代采用复制算法,老年代采用标记-整理算法

2. ParNew收集器

  • Serial收集器的多线程版本
  • 只有Serial和ParNew可以和CMS收集器配合使用

3. Parallel Scavenge收集器

  • 用于新生代,采用复制算法
  • 特点在于可以精准地控制吞吐量(运行用户代码时间/CPU总消耗时间)
  • 适用于在后台运算而不需要太多交互的任务

4. Serial Old收集器

  • Serial的老年代版本
  • 单线程
  • 主要用于Client模式

5. Parallel Old收集器

  • Parallel Scavenge 的老年代版本
  • JDK1.6之后提供
  • 与 Parallel Scavenge 配合,更好地控制吞吐量

6. CMS (Concurrent Mark Sweep)收集器

  • 最短回收停顿时间为目标的收集器
  • 用于重视服务响应速度的场景上
  • 基于标记-清除算法
  • 分为四个步骤
    1. 初始标记,耗时短,不可并发
    2. 并发标记,耗时长,可以并发
    3. 重新标记,耗时稍短,不可并发
    4. 并发清除,耗时长,可以并发

7. G1(Gabage-First)收集器

  • JDK1.7中可以正式商用
  • 特点有:
    1. 并行与并发
    2. 分代收集
    3. 空间整合
    4. 可预测的停顿
  • JDK9之后成为默认收集器

参考

  • 深入理解Java虚拟机
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: JVM是一种虚拟机(Java Virtual Machine),能够在不同操作系统和硬件平台上运行Java程序。而G1垃圾收集器JVM中的一种垃圾收集算法,可以处理大型Java堆。 使用G1垃圾收集器能够提高应用程序性能,因为它采用分区技术和优先级调度算法,可以根据应用程序的使用情况,动态地分配堆空间分区,从而减少垃圾收集时间和暂停时间。 下面是使用G1垃圾收集器来优化JVM的步骤: 第一步,设置JVM参数,例如开启G1垃圾收集器,设置堆空间大小等。 第二步,使用JVisualVM或其他工具,对应用程序进行分析,确定是否存在内存泄漏或内存过度消耗的现象。如果有问题,则需要对应用程序进行修改,以降低内存使用率。 第三步,对应用程序进行压测,确定最大并发并适当调整G1垃圾收集器参数,例如设置初始停顿时间、最大停顿时间、空闲时间等。 但需要注意的是,使用G1垃圾收集器时需要事先评估应用程序的运行环境和特性,例如硬件配置、每秒请求计数、响应时间等。只有在合适的环境下,G1垃圾收集器才能发挥最佳效果。同时,应用程序也需要符合一些条件,例如堆空间不能太小,内存消耗不能太大等。 总之,通过优化JVM,使用G1垃圾收集器能够提高Java应用程序的性能和可靠性,减少停顿时间。但使用时需要仔细评估和测试,确保最佳效果。 ### 回答2: JVMJava虚拟机的缩写,是Java运行环境的核心部分。垃圾收集器JVM的一个重要组成部分,负责回收程序的无用对象和内存。G1垃圾收集器JVM中的一种,是目前比较流行的一种。下面介绍G1垃圾收集器的优化使用方法。 首先,G1垃圾收集器最大的优点是能够充分利用多核处理器和大内存的优势。因此,在使用G1垃圾收集器时,需要配置合适的垃圾回收线程数和堆内存大小。通常情况下,推荐将垃圾回收线程数设置为CPU核心数的一半左右,而堆内存大小则应根据应用程序的实际情况设定。 其次,G1垃圾收集器还支持增量垃圾回收和并发标记。这意味着垃圾收集器可以在应用程序执行的同时,进行部分的垃圾回收和标记操作。这有利于减少垃圾回收对应用程序执行的影响。 再次,G1垃圾收集器还支持混合模式。这种模式下,垃圾收集器会将堆内存分为多个区域,并按照各个区域的使用情况决定垃圾回收的策略。一些非常重要的区域可以在短时间内进行Full GC,而其它区域则可以使用增量式垃圾回收策略。这一功能可以进一步提高垃圾回收的效率。 最后,在使用G1垃圾收集器时,还需要注意一些细节问题。例如,需要选择合适的回收阈值、合理配置回收周期等等。此外,一些调试工具如JConsole、JVisualVM等也可以帮助开发者监控和调整G1垃圾收集器的性能。 总之,G1垃圾收集器是目前JVM中性能较优异的垃圾收集器之一。在使用G1垃圾收集器时,需要根据实际情况合理配置线程数、堆内存大小和一些参数,同时关注混合模式、增量垃圾回收和并发标记等特点,才能充分发挥其性能优势。 ### 回答3: JVMJava虚拟机的缩写,它是Java程序运行的环境,它提供了一个平台无关的执行环境,能够提高Java应用程序的效率和安全性。Java应用程序的性能优化是一个复杂的过程,其中之一的重要方面是垃圾收集器的优化。 G1是JVM中的一种垃圾收集器,它主要用于大堆内存应用程序,它在处理垃圾回收时可以实现高吞吐量和低延迟,而且它可以管理大容量的内存,能够处理高并发情况下的大量垃圾回收。 G1垃圾收集器具有以下优点: 1.低延迟:G1垃圾收集器能够有效地降低应用程序的延迟,因为它是一个分区式的垃圾收集器,它会将内存分成多个区域,每个区域都有自己的垃圾回收时间,这样可以最大程度的减少垃圾回收的时间。 2.高吞吐量:G1垃圾收集器能够管理大容量的内存,能够处理大量的垃圾回收,因此它的吞吐量很高。 3.可预测性:G1垃圾收集器能够实现可预测性垃圾回收,这意味着它可以为每个应用程序分配一个确定的垃圾回收时间,从而避免出现系统性能波动的情况。 4.自适应:G1垃圾收集器能够根据内存的使用情况来自动调整垃圾回收的策略,从而最大程度地优化垃圾回收的效率和性能。 在使用G1垃圾收集器时,需要注意以下几点: 1.适当配置参数:需要根据应用程序的实际情况,适当配置G1的参数,以提高垃圾回收的效率和性能。 2.避免频繁Full GC:G1垃圾收集器能够尽量避免Full GC,但是在一些场景下,还是会出现Full GC的情况,因此需要尽量避免频繁Full GC的情况出现。 3.避免内存泄漏:G1垃圾收集器虽然能够处理大量垃圾,但是它无法处理内存泄漏的情况,因此需要及时发现和解决内存泄漏的问题。 总之,G1垃圾收集器是一个高性能、高效率的垃圾回收器,能够满足大堆内存应用程序的垃圾回收需求。在使用过程中,需要根据实际情况适当配置参数,避免频繁Full GC和内存泄漏的发生。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值