垃圾收集的目的在于清除不再使用的对象。gc通过确定对象是否被活动对象引用来确定是否收集该对象。gc首先要判断该对象是否是时候可以收集。两种常用的方法是引用计数和对象引用遍历。
引用计数收集器
引用计数是垃圾收集器中的早期策略。在这种方法中,堆中每个对象(不是引用)都有一个引用计数。当一个对象被创建时,且将该对象分配给一个变量,该变量计数设置为1。当任何其它变量被赋值为这个对象的引用时,计数加1(a = b,则b引用的对象+1),但当一个对象的某个引用超过了生命周期或者被设置为一个新值时,对象的引用计数减1。任何引用计数为0的对象可以被当作垃圾收集。当一个对象被垃圾收集时,它引用的任何对象计数减1。
优点:引用计数收集器可以很快的执行,交织在程序运行中。对程序不被长时间打断的实时环境比较有利。
缺点: 无法检测出循环引用。如父对象有一个对子对象的引用,子对象反过来引用父对象。这样,他们的引用计数永远不可能为0
跟踪收集器
早期的jvm使用引用计数,现在大多数jvm采用对象引用遍历。对象引用遍历从一组对象开始,沿着整个对象图上的每条链接,递归确定可到达(reachable)的对象。如果某对象不能从这些根对象的一个(至少一个)到达,则将它作为垃圾收集。在对象遍历阶段,gc必须记住哪些对象可以到达,以便删除不可到达的对象,这称为标记(marking)对象。
下一步,gc要删除不可到达的对象。删除时,有些gc只是简单的扫描堆栈,删除未标记的未标记的对象,并释放它们的内存以生成新的对象,这叫做清除(sweeping)。这种方法的问题在于内存会分成好多小段,而它们不足以用于新的对象,但是组合起来却很大。因此,许多gc可以重新组织内存中的对象,并进行压缩(compact),形成可利用的空间。
为此,gc需要停止其他的活动活动。这种方法意味着所有与应用程序相关的工作停止,只有gc运行。结果,在响应期间增减了许多混杂请求。另外,更复杂的 gc不断增加或同时运行以减少或者清除应用程序的中断。有的gc使用单线程完成这项工作,有的则采用多线程以增加效率。
一些常用的垃圾收集器
标记-清除收集器
这种收集器首先遍历对象图并标记可到达的对象,然后扫描堆栈以寻找未标记对象并释放它们的内存。这种收集器一般使用单线程工作并停止其他操作。并且,由于它只是清除了那些未标记的对象,而并没有对标记对象进行压缩,导致会产生大量内存碎片,从而浪费内存。
标记-压缩收集器
有时也叫标记-清除-压缩收集器,与标记-清除收集器有相同的标记阶段。在第二阶段,则把标记对象复制到堆栈的新域中以便压缩堆栈。这种收集器也停止其他操作。
复制收集器
这种收集器将堆栈分为两个域,常称为半空间。每次仅使用一半的空间,jvm生成的新对象则放在另一半空间中。gc运行时,它把可到达对象复制到另一半空间,从而压缩了堆栈。这种方法适用于短生存期的对象,持续复制长生存期的对象则导致效率降低。并且对于指定大小堆来说,需要两倍大小的内存,因为任何时候都只使用其中的一半。
增量收集器
增量收集器把堆栈分为多个域,每次仅从一个域收集垃圾,也可理解为把堆栈分成一小块一小块,每次仅对某一个块进行垃圾收集。这会造成较小的应用程序中断时间,使得用户一般不能觉察到垃圾收集器正在工作。
分代收集器
复制收集器的缺点是:每次收集时,所有的标记对象都要被拷贝,从而导致一些生命周期很长的对象被来回拷贝多次,消耗大量的时间。而分代收集器则可解决这个问题,分代收集器把堆栈分为两个或多个域,用以存放不同寿命的对象。jvm生成的新对象一般放在其中的某个域中。过一段时间,继续存在的对象(非短命对象)将获得使用期并转入更长寿命的域中。分代收集器对不同的域使用不同的算法以优化性能。
并行收集器
并行收集器使用某种传统的算法并使用多线程并行的执行它们的工作。在多cpu机器上使用多线程技术可以显著的提高java应用程序的可扩展性。
最后,贴出一个非常简单的跟踪收集器的例图,以便大家加深对收集器的理解:
下章将描述有关垃圾收集器要注意的地方以及一些面试题的分析,感兴趣的朋友可以看看
- 大小: 5.7 KB
分享到:
相关推荐
“-XX:+UseConcMarkSweepGC”和“-XX:+UseParallelGC”选择不同的垃圾收集器策略,以适应不同应用场景的性能需求。还有像“-XX:MaxTenuringThreshold”用于设置对象晋升老年代的阈值,以及“-XX:...
它不仅向读者提供了JVM垃圾收集机制的理论知识,还提供了实操指导,比如如何选择和调优垃圾收集器以及使用哪些工具来评估垃圾收集器性能。对于开发人员来说,掌握这些知识可以帮助他们编写出性能更优、稳定性更高的...
书中可能涉及了各种垃圾收集器的工作原理,如Serial、Parallel、CMS、G1、ZGC等,并分析了不同场景下选择哪种GC策略更为合适。 3. **内存泄漏与溢出诊断**:通过对JVM日志的分析,书里可能会教授读者如何识别和处理...
本文将深入探讨两个重要的垃圾收集器——ParNew和Concurrent Mark Sweep (CMS) ——以及它们在JVM性能调优中的作用,特别是基于三色标记算法的实现。 首先,ParNew垃圾收集器是新生代(Young Generation)的默认...
《Java实现的JVM——深入理解与实践》 在计算机科学领域,Java虚拟机(JVM)是Java语言的关键组成部分,它使得Java程序能够在不同平台上运行而无需重新编译。本项目“jvmjava”是一个开源项目,由Java语言实现,...
- **JVM参数**:为了更好地控制JVM的行为,可以使用一系列命令行参数,如设置初始堆大小(-Xms)、最大堆大小(-Xmx)、启用特定的垃圾收集器(-XX:+UseG1GC)等。这些参数对于优化应用性能至关重要。 通过深入理解...
4. **G1(Garbage-First)**:新一代的垃圾收集器,目标是实现可预测的暂停时间模型,适用于大型应用。 五、GC调优 理解并优化GC是提升Java应用性能的关键。调优包括调整堆大小、设置新生代与老年代的比例、选择...
总结来说,解决Java应用中old GC耗时过长的问题,需要深入理解应用的内存使用模式,合理调整JVM参数,选择合适的垃圾收集器,并进行持续的性能监控和调优。在调整过程中,应遵循最小化停顿时间、最大化吞吐量和优化...
《深入JVM内核——原理、诊断与优化》是一份深度探讨Java虚拟机核心机制、问题诊断和性能优化的专业资料。这份资料涵盖了JVM的各个方面,对于Java开发者来说,理解和掌握这些知识至关重要。 首先,我们要了解JVM...
《实战Java虚拟机——JVM故障诊断与性能优化》是一本深入探讨Java开发人员和运维人员必备技能的书籍。本书作者葛一鸣以其丰富的实战经验,详细阐述了JVM(Java Virtual Machine)的工作原理,以及如何有效地进行故障...
JVM(Java虚拟机)是Java...通过对JVM内存模型和GC的深入理解,开发者可以更好地对Java应用程序进行性能调优,包括合理配置堆大小、选择适当的垃圾收集器,以及在编码时注意对象的创建和回收,避免不必要的内存泄漏。
jstat(JVM Statistics Monitoring Tool)是Oracle JDK提供的一款强大的命令行工具,用于实时监控Java虚拟机的各种运行状态,包括内存管理、类加载、垃圾收集以及JIT编译等关键指标。了解并熟练运用jstat,能帮助...
总结来说,JVM性能调优是多方面的工作,包括理解内存结构、选择合适的垃圾收集器、调整内存参数以及优化代码实现。通过细致入微的调优,可以显著提升Java应用的性能和稳定性。这份PDF资料将详细介绍这些关键点,帮助...
除了用户程序的线程,JVM实现还可能包含一些后台线程,如垃圾收集器,这些线程不需要直接对应执行引擎实例。 JVM的指令集是其操作的基础,字节码流由一系列指令组成,每个指令由一个操作码和可能的操作数构成。操作...
2. **垃圾收集器**:HotSpot支持多种垃圾回收算法,如Serial、Parallel、Concurrent Mark Sweep (CMS) 和 Garbage First (G1)。这些算法各有优缺点,适应不同的应用场景。 3. **运行时系统**:包括对象模型、内存...
Java虚拟机提供了多种垃圾收集器,如: - **Serial**:单线程的新生代收集器,使用复制算法,适用于简单应用。 - **ParNew**:Serial的多线程版本,同样使用复制算法,但可能导致`StopTheWorld`事件。 - **Parallel...
《JVM笔记(阳哥)》是一份深入探讨Java虚拟机(JVM)的资料,由阳哥精心整理。这份笔记涵盖了JVM的基础概念、内存管理、类加载机制、性能优化等多个方面,对于理解Java程序的运行机制以及提升开发效率具有重要的...
- **根搜索算法(GC Roots Tracing)**:这是现代垃圾收集器普遍采用的方法。它从一组被称为“GC Roots”的对象开始,递归地遍历可达对象。如果一个对象不可达,则认为它是不再使用的,从而可以被回收。 #### 四、GC ...
1. 根据应用类型选择合适的垃圾收集器,如低延迟应用推荐使用G1或ZGC,大内存应用可选择Parallel GC。 2. 优化对象分配,减少短生命周期对象进入老年代,降低GC频率。 3. 监控系统性能,如CPU使用率、内存占用、GC...