热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JVM垃圾回收器理论分析与详解【纯理论】

继续上次【https:www.cnblogs.comwebor2006p10740084.html】的理论继续。。有点吐血的感觉,都不知道学了这么一大堆理论有何实际意义,本身JVM就是个理论

继续上次【https://www.cnblogs.com/webor2006/p/10740084.html】的理论继续。。有点吐血的感觉,都不知道学了这么一大堆理论有何实际意义,本身JVM就是个理论体系比较多的东东,所以理论不得不去面对,继续硬着头皮往前进。

内存结构

这个在之前的学习中都已经学习过了,复习一下。

内存分配

  • 堆上分配
    大多数情况在eden【年轻代中的一个区域】上分配,偶尔会直接在old【老年代】上分配,细节取决于GC的实现。
  • 栈上分配
    原子类型的局部变量。

内存回收

1、GC要做的是将那些dead的对象所占用的内存回收掉。

  • Hotspot认为没有引用的对象是dead的。
  • Hotspot将引用分为四种:Strong【强引用】、Soft【软引用】、Weak【弱引用】、Phantom【虚引用】,这是大伙熟知的。
    1、Strong既默认通过Object o = new Object()这种方式赋值的引用。
    2、Soft、Weak、Phantom这三种则是继续Reference。

2、在Full GC时会对Reference类型的引用进行特殊处理。

  • Soft:内存不够时一定会被GC、长期不用也会被GC。
  • Weak:一定会被GC,当被mark为dead,会在ReferenceQueue中通知。
  • Phantom:本来就没引用,当从jvm heap中释放时会通知。

以上的概念会在未来举例进行代码说明的,先有个印象。

垃圾收集算法

以上是一些比较经典的垃圾收集算法,下面会逐个进行说明。

GC的时机

1、在分代模型的基础上,GC从时机上分为两种:Scavenge GC和Full GC。

2、Scavenge GC(Minor GC)

  • 触发时机:新对象生成时,Eden空间满了。
  • 理论上Eden区大多数对象会在Scavenge GC回收,复制算法的执行效率会很高,Scavenge GC时间比较短。

3、Full GC【这个在实际中一定得要避免】

  • 对整个JVM进行整理,包括Young、Old和Perm。
  • 主要的触发时机:1)Old满了;2)Perm满了;3)system.gc()
  • 效率很低,尽量减少Full GC

垃圾回收器(Garbage Collector)

  • 分代模型:GC的宏观愿景。
  • 垃圾回收器:GC的具体实现。
  • Hotspot JVM提供多种垃圾回收器,我们需要根据具体应用的需要采用不同的回收器。
  • 没有万能的垃圾回收器,每种垃圾回收器都有自己的适用场景。

垃圾收集器的“并行”和“并发”

  • 并行(Parallel):指多个收集器的线程同时工作,但是用户线程处于等待状态。
  • 并发(Concurrent):指收集器在工作时同时,可以允许用户线程工作。
    并发不代表解决了GC停顿的问题,在关键的步骤还是要停顿。比如在收集器标记垃圾的时候。但在清除垃圾的时候,用户线程可以和GC线程并发执行。 

Serial收集器

  • 单线程收集器,收集时会暂停所有工作线程(Stop The World,简单STW),使用复制收集算法,虚拟机运行在Client模式时的默认新生代会采用此收集器。
  • 最早的收集器,单线程进行GC。
  • New和Old Generation都可以使用。
  • 在新生代,采用复制算法:在老年代,采用Mark-Compact算法。
  • 因为是单线程GC,没有多线程切换的额外开销,简单实用。
  • Hotspot Client模式缺省的的收集器

    如图中出现了一个词:“Safepoint”,安全点,在之后会举具体的实例来说明安全点的作用。

ParNew收集器

  • ParNew收集器就是Serial的多线程版本,除了使用多个收集线程外,其余行为包括算法、STW、对象分配规则、回收策略等都与Serial收集器一模一样。
  • 对应的这种收集器是虚拟机运行在Server模式的默认新生代收集器,在单CPU的环境中,ParNew收集器并不会比Serial收集器有更好的效果。
  • Serial收集器在新生代的多线程版本。
  • 使用复制算法(因为针对新生代)。
  • 只有在多CPU的环境下,效率才会比Serial收集器高。
  • 可以通过-XX:ParallelGCThreads来控制GC线程数的多少。需要结合具体CPU的个数。
  • Server模式下新生代的缺省收集器。

Parallel Scavenge收集器

  •  Parallel Scavenge收集器也是一个多线程收集器,也是使用复制算法,但它的对象分配规则与回收策略都与ParNew收集器有所不同,它是以吞吐量最大化(既GC时间占总运行时间最小)为目标的收集器实现,它允许较长时间的STW换取总吞吐量最大化。

Serial Old收集器

  •  Serial Old是单线程收集器,使用标记-整理算法,是老年代的收集器。

Parallel Old收集器

  • 老年代版本吞吐量优先收集器,使用多线程和标记一整理算法,JVM1.6提供,在此之前,新生代使用了PS收集器的话,老年代除Serial Old外别无选择,因为PS无法与CMS收集器配合工作。【了解既可】
  • Parallel Scavenge在老年代的实现
  • 在JVM1.6才出现Parallel Old
  • 采用多线程,Mark-Compact算法
  • 更注重吞吐量
  • Parallel Scavenge + Parallel Old = 高吞吐量,但GC停顿可能不理想

CMS(Concurrent Mark Sweep)收集器【特别复杂的一种收集器】

  • CMS是一种以最短停顿时间为目标的收集器,使用CMS并不能达到GC效率最高(总体GC时间最小),但它能尽可能降低GC时服务的停顿时间,CMS收集器使用的是标记-清除算法。
  • 追求最短停顿时间,非常适合Web应用。
  • 只针对老年区,一般结合ParNew使用。
  • Concurrent,GC线程和用户线程并发工作(尽量并发)。
  • Mark-Sweep。
  • 只有在多CPU环境下才有意义 。
  • 使用-XX:+UseConcMarkSweepGC打开。
  • CMS以牺牲CPU资源的代价来减少用户线程的停顿。当CPU个数少于4的时候,有可能对吞吐量影响非常大。
  • CMS在并发清理的过程中,用户线程还在跑。这时候需要预留一部分空间给用户线程。
  • CMS用Mark-Sweep,会带来碎片问题。碎片过多的时候会容易频繁触发Full GC。

GC垃圾收集器的JVM参数定义

Java内存泄漏的经典原因

1、对象定义在错误的范围(Wrong Scope)。

  • 如果Foo实例对象的生命较长,会导致临时性内存泄漏。(这里的names变量其实只是临时作用)
  • JVM喜欢生命周期短的对象,这样做已经足够高效【调整】

    这样一改之后,只要是doIt()方法一结束names的临时变量就立马会被回收。

2、异常(Exception)处理不当。

  • 错误的做法

    对于有经验的程序员应该不会出现上面的问题,但是这里只是抛出泄漏的场景。
  • 正确的做法

3、集合数据管理不当。

  • 当使用Array-based的数据结构(ArrayList,HashMap等)时,尽量减少resize:
    a、比如new ArrayList时,尽量估算size,在创建的时候把size确定。
    b、减少resize可以避免没有必要的array copying,gc碎片等问题。
  • 如果一个List只需要顺序访问,不需要随机访问(Random Access),用LinkedList代替ArrayList
    a、LInkedList本质是链表,不需要resize,但只适用于顺序访问。

 

以上是对JVM垃圾回收相关理论的整体了解,说实话看完其实头晕晕的,没关系,接下来则会用实践来反证理论。


推荐阅读
  • HBase在金融大数据迁移中的应用与挑战
    随着最后一台设备的下线,标志着超过10PB的HBase数据迁移项目顺利完成。目前,新的集群已在新机房稳定运行超过两个月,监控数据显示,新集群的查询响应时间显著降低,系统稳定性大幅提升。此外,数据消费的波动也变得更加平滑,整体性能得到了显著优化。 ... [详细]
  • 如何在Java中高效构建WebService
    本文介绍了如何利用XFire框架在Java中高效构建WebService。XFire是一个轻量级、高性能的Java SOAP框架,能够简化WebService的开发流程。通过结合MyEclipse集成开发环境,开发者可以更便捷地进行项目配置和代码编写,从而提高开发效率。此外,文章还详细探讨了XFire的关键特性和最佳实践,为读者提供了实用的参考。 ... [详细]
  • Java集合框架特性详解与开发实践笔记
    Java集合框架特性详解与开发实践笔记 ... [详细]
  • 在Python编程中,探讨了并发与并行的概念及其区别。并发指的是系统同时处理多个任务的能力,而并行则指在同一时间点上并行执行多个任务。文章详细解析了阻塞与非阻塞操作、同步与异步编程模型,以及IO多路复用技术的应用。通过模拟socket发送HTTP请求的过程,展示了如何创建连接、发送数据和接收响应,并强调了默认情况下socket的阻塞特性。此外,还介绍了如何利用这些技术优化网络通信性能和提高程序效率。 ... [详细]
  • Node.js 教程第五讲:深入解析 EventEmitter(事件监听与发射机制)
    本文将深入探讨 Node.js 中的 EventEmitter 模块,详细介绍其在事件监听与发射机制中的应用。内容涵盖事件驱动的基本概念、如何在 Node.js 中注册和触发自定义事件,以及 EventEmitter 的核心 API 和使用方法。通过本教程,读者将能够全面理解并熟练运用 EventEmitter 进行高效的事件处理。 ... [详细]
  • 通过整合JavaFX与Swing,我们成功地将现有的Swing应用程序组件进行了现代化改造。此次升级不仅提升了用户界面的美观性和交互性,还确保了与原有Swing应用程序的无缝集成,为开发高质量的Java桌面应用提供了坚实的基础。 ... [详细]
  • 本文详细探讨了Java集合框架的使用方法及其性能特点。首先,通过关系图展示了集合接口之间的层次结构,如`Collection`接口作为对象集合的基础,其下分为`List`、`Set`和`Queue`等子接口。其中,`List`接口支持按插入顺序保存元素且允许重复,而`Set`接口则确保元素唯一性。此外,文章还深入分析了不同集合类在实际应用中的性能表现,为开发者选择合适的集合类型提供了参考依据。 ... [详细]
  • 深入解析Gradle中的Project核心组件
    在Gradle构建系统中,`Project` 是一个核心组件,扮演着至关重要的角色。通过使用 `./gradlew projects` 命令,可以清晰地列出当前项目结构中包含的所有子项目,这有助于开发者更好地理解和管理复杂的多模块项目。此外,`Project` 对象还提供了丰富的配置选项和生命周期管理功能,使得构建过程更加灵活高效。 ... [详细]
  • HTTP协议作为互联网通信的基础,其重要性不言而喻。相比JDK自带的URLConnection,HttpClient不仅提升了易用性和灵活性,还在性能、稳定性和安全性方面进行了显著优化。本文将深入解析HttpClient的使用方法与技巧,帮助开发者更好地掌握这一强大的工具。 ... [详细]
  • 通过菜单项触发Activity启动过程详解
    本文详细解析了通过菜单项触发Activity启动的过程。在Android开发中,菜单项是用户与应用交互的重要途径之一。文章从技术角度深入探讨了如何通过菜单项触发特定Activity的启动,并提供了具体的代码示例和实现步骤。通过对菜单项的响应处理、Intent的创建与传递等关键环节的分析,帮助开发者更好地理解和掌握这一机制。 ... [详细]
  • RxJava 中 Observable.singleElement() 方法详解与实例代码分析 ... [详细]
  • 本文深入探讨了 iOS 开发中 `int`、`NSInteger`、`NSUInteger` 和 `NSNumber` 的应用与区别。首先,我们将详细介绍 `NSNumber` 类型,该类用于封装基本数据类型,如整数、浮点数等,使其能够在 Objective-C 的集合类中使用。通过分析这些类型的特性和应用场景,帮助开发者更好地理解和选择合适的数据类型,提高代码的健壮性和可维护性。苹果官方文档提供了更多详细信息,可供进一步参考。 ... [详细]
  • 本题库精选了Java核心知识点的练习题,旨在帮助学习者巩固和检验对Java理论基础的掌握。其中,选择题部分涵盖了访问控制权限等关键概念,例如,Java语言中仅允许子类或同一包内的类访问的访问权限为protected。此外,题库还包括其他重要知识点,如异常处理、多线程、集合框架等,全面覆盖Java编程的核心内容。 ... [详细]
  • 进程(Process)是指计算机中程序对特定数据集的一次运行活动,是系统资源分配与调度的核心单元,构成了操作系统架构的基础。在早期以进程为中心的计算机体系结构中,进程被视为程序的执行实例,其状态和控制信息通过任务描述符(task_struct)进行管理和维护。本文将深入探讨进程的概念及其关键数据结构task_struct,解析其在操作系统中的作用和实现机制。 ... [详细]
  • 全面解析Java虚拟机:内存模型深度剖析 ... [详细]
author-avatar
ZZDXP
学 無
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有