1.GC介绍
垃圾回收器(Garbage Collection,GC),顾名思义,垃圾回收就是释放垃圾占用的空间, Java中,程序员不需要去关心内存动态分配和垃圾回收的问题,这一切都交给了JVM来处理。
我们需要考虑一下JVM处理垃圾回收三个问题:
1).哪些内存需要回收?
2).GC什么时候开始回收?
3).如何回收
2.垃圾收集方式
2.1 引用计数
2.2 对象遍历引用
3.垃圾收集算法
1).复制copying:
找到活动对象拷贝到新的空间
适合存活对象较少情况,增加内存成本高 (使用于年轻代回收)
2).标记清除
从跟开始将活动对象标记,然后再扫描未标记的一次回收
不需要移动对象,仅对不存活对象处理,适合存活对象较多情况,会造成内存碎片(适合老年代回收)
3).标记压缩
在标记清除基础上,往左移动存活对象
成本高,好处是没有碎片
4.三种基本算法简要对比:
时间开销:
mark-sweep:mark阶段与活对象的数量成正比,sweep阶段与整堆大小成正比
mark-compact:mark阶段与活对象的数量成正比,compact阶段与活对象的大小成正比
copying:与活对象大小成正比
如果把mark、sweep、compact、copying这几种动作的耗时放在一起看,大致关系:
compaction > copying > marking > sweeping
还有 marking + sweeping > copying
虽然compactiont与copying都涉及移动对象,但算法实现存在不同,
compact可能要先计算一次对象的目标地址,然后修正指针,然后再移动对象;
copying则可以把这几件事情合为一体来做,所以可以快一些。
年轻代:
在分代式垃圾中,年轻代中的对象在minor GC时的存活率应该很低,这样用copying算法就是最合算的,因为其时间开销与活对象的大小成正比,如果没多少活对象,它就非常快;而且young gen本身应该比较小,就算需要2倍空间也只会浪费不太多的空间.那么影响新生代GC的主要因素排序:存活对象数 > 新生代大小 > 老年代算法
在分代式垃圾中,年轻代中的对象在minor GC时的存活率应该很低,这样用copying算法就是最合算的,因为其时间开销与活对象的大小成正比,如果没多少活对象,它就非常快;而且young gen本身应该比较小,就算需要2倍空间也只会浪费不太多的空间.那么影响新生代GC的主要因素排序:存活对象数 > 新生代大小 > 老年代算法
老年代:
分代式GC里,老年代CMS常用mark-sweep或者是mark-sweep + mark-compact的混合方式,一般情况是用mark-sweep,统计估算碎片量达到一定程度时用mark-compact。老年代被GC时对象存活率可能会很高,而且假定可用剩余空间不太多,这样copying算法就不太合适,于是有另两种算法:mark-sweep,mark-compact.
HotSpot VM中老年代除了CMS之外的其它收集器都是会移动对象的,也就是要么是copying、要么是mark-compact的变种。
CMS为什么用mark-sweep基本算法将其并发化,而不使用移动对象的算法?(ps:原理出自淘宝沙迦)
主要原因分析:GC之外的代码(应用代码)和 GC的代码(collector),两者之间需要保持同步,这样才可以保证两者所观察到的对象图是一致的。
如果是一个串行、不并发、不分代、不增量式的collector,那么它在工作的时候总是能观察到整个对象图。因而它跟应用代码之间的同步方式非常简单:应用代码一侧不用做任何特殊的事情,只要在需要GC时同步调用collector即可。
如果有一个分代式的,或者增量式的collector,那它在工作的时候就只会观察到整个对象图的一部分;它观察不到的部分就有可能与应用代码产生不一致,于是需要应用代码配合:它与应用代码之间需要额外的同步。应用代码在改变对象图中的引用关系时必须执行一些额外代码,让collector记录下这些变化。有两种做法,一种是write barrier,一种是read barrier。
如果是一个串行、不并发、不分代、不增量式的collector,那么它在工作的时候总是能观察到整个对象图。因而它跟应用代码之间的同步方式非常简单:应用代码一侧不用做任何特殊的事情,只要在需要GC时同步调用collector即可。
如果有一个分代式的,或者增量式的collector,那它在工作的时候就只会观察到整个对象图的一部分;它观察不到的部分就有可能与应用代码产生不一致,于是需要应用代码配合:它与应用代码之间需要额外的同步。应用代码在改变对象图中的引用关系时必须执行一些额外代码,让collector记录下这些变化。有两种做法,一种是write barrier,一种是read barrier。
通常一个程序里对引用的读远比对引用的写要更频繁,所以通常认为read barrier的开销远大于write barrier,所以很少有GC使用read barrier。
如果只用write barrier,那么“移动对象”这个动作就必须要完全暂停应用代码,让collector把对象都移动好,然后把指针都修正好,接下来才可以恢复应用代码的执行。也就是说collector“移动对象”这个动作无法与应用代码并发进行。
如果用read barrier,那移动对象就可以单个单个的进行,而且不需要立即修正所有的指针,所以可以看作整个过程collector都与应用代码是并发的。
CMS 没有使用read barrier,只用了write barrier。这样,如果它要选用mark-compact为基本算法的话,就只有mark阶段可以并发执行(其中root scanning阶段仍然需要暂停应用代码,这是initial marking;后面的concurrent marking才可以跟应用代码并发执行),然后整个compact阶段都要暂停应用代码。回想最初提到的:compact阶段的时间开销与活对象的大小成正比,这对年老代来说就不划算了。
于是选用mark-sweep为基本算法就是很合理的选择:mark与sweep阶段都可以与应用代码并发执行。Sweep阶段由于不移动对象所以不用修正指针,所以不用暂停应用代码。
那 碎片堆积起来了怎么办呢?HotSpot VM里CMS只负责并发收集年老代(而不是整个GC堆)。如果并发收集所回收到的空间赶不上分配的需求,就会回退到使用serial GC的mark-compact算法做full GC。也就是mark-sweep为主,mark-compact为备份的经典配置。但这种配置方式也埋下了隐患:使用CMS时必须非常小心的调优,尽量 推迟由碎片化引致的full GC的发生。一旦发生full GC,暂停时间可能又会很长,这样原本为低延迟而选择CMS的优势就没了。
新的Garbage-First(G1)GC就是以copying为基础的算法上,把整个GC堆划分为许多小区域(regions),通过每次GC只选择收集很少量region来控制移动对象带来的暂停时间。这样既能实现低延迟也不会受碎片化的影响。 (注意:G1虽然有concurrent global marking,但是可选的,真正带来暂停时间的工作仍然是基于copying算法)
因此在HotSpot VM 只要涉及到对象的移动(copying,compact),就会暂定应用代码(stop-the-world).
相关文章:
- JAVA虚拟机-JMM内存模型(六)
-
JAVA虚拟机-JVM性能调优(五) -
JAVA虚拟机-G1 Heap Structure(四) -
JAVA虚拟机-CMS Heap Structure(三) -
JAVA虚拟机-GC介绍和垃圾算法理解(二) -
JAVA虚拟机-Java体系结构及hotspot介绍(一)
相关推荐
Java虚拟机详解04----GC算法和种类【重要】,有助于更深入理解记忆,文字配图片,10分钟让你记住gc工作机制。
它采用分代收集算法,包括新生代、老年代和永久代,以及各种GC策略如Stop-the-world、并发标记等。 6. **异常处理**:JVM支持异常处理框架,通过异常表来确定异常发生时的处理流程。 7. **多线程**:JVM内置对多...
在深入理解JVM内存管理和垃圾收集器之前,我们需要先了解JVM内存模型的基本结构。 内存模型主要包括以下几个部分: 1. **Java堆**:这是JVM管理的最大的内存区域,所有线程共享,主要用于存储类实例和数组。堆内存...
本文详细探讨了JVM中的垃圾收集器和垃圾收集算法,以帮助开发者深入理解Java虚拟机的内部运作机制。 垃圾收集(GC,Garbage Collection)是JVM的一个重要功能,用于自动释放不再使用的对象所占用的内存空间,以防止...
GC算法主要包括标记-清除算法、复制算法、标记-整理算法和分代收集算法。其中,分代收集算法是基于对象存活周期的不同将堆空间划分为新生代和老年代,分别采用不同的收集策略,以达到高效的内存管理。 ### 性能优化...
除了上述提到的基础知识点外,《深入理解Java虚拟机——JVM高级特性与最佳实践(第2版)》这本书籍还深入探讨了JVM的性能调优、并发编程、以及各种高级特性的具体应用。比如,对于性能调优,书中讲解了如何根据不同的...
基于实时性的Java虚拟机垃圾收集算法通过对堆空间划分、引用追踪等方面的改进,成功地减少了GC带来的不确定暂停,降低了暂停的频率和时长,极大地提升了Java在实时性环境下的适用性。这对于工业控制、实时网络游戏等...
Java虚拟机(JVM)是Java平台的核心组件之一,它提供了一个运行Java字节码的环境,并且负责管理Java程序的内存分配和垃圾回收。在本文中,我们将深入探讨Java虚拟机的体系结构、垃圾回收机制、Java对象的生命周期和...
### Java虚拟机中的垃圾收集(GC)运行机制及种类 #### 概述 垃圾收集(Garbage Collection,简称GC)是Java虚拟机(JVM)自动管理内存的重要功能之一。通过自动识别并回收不再使用的对象所占用的内存空间,GC极大地...
通过学习《深入JAVA虚拟机第二版》,开发者可以提升对JVM的深入理解,从而更好地设计和优化Java程序,解决性能问题,提升应用程序的稳定性和效率。对于任何想要成为Java技术专家的人来说,这本书无疑是一本不可多得...
《实战Java虚拟机——JVM故障诊断与性能优化》是一本深入探讨Java开发人员和运维人员必备技能的书籍。本书作者葛一鸣以其丰富的实战经验,详细阐述了JVM(Java Virtual Machine)的工作原理,以及如何有效地进行故障...
这里我们使用举例来说明为什么要学习Java虚拟机,其实这个问题就和为什么要学习数据结构和算法是一个道理,工欲善其事,必先利其器。曾经的我经常害怕处理内存溢出的问题,因为不知道他为什么会出现这个问题,当我在...
通过阅读《深入JAVA虚拟机》和《JVM规范》,结合实际的代码分析,可以让我们更好地理解和掌握这个强大的虚拟机。无论是初级开发者还是经验丰富的专家,都应该对JVM有深入的理解,这将极大地提升我们的编程实践能力。
Java虚拟机的内存区域分为几个部分,其中包括线程私有的区域(程序计数器、Java虚拟机栈、本地方法栈)和线程共享的区域(Java堆、方法区、运行时常量池)。对象的访问是通过句柄或直接指针的方式来进行的。 在了解...
这些算法可能包括改进标记-清除(Mark-Sweep)、复制(Copying)、标记-压缩(Mark-Compact)等基本垃圾收集算法,或者引入新的策略,例如并发标记清除(Concurrent Mark Sweep, CMS)和垃圾优先(Garbage-First, G1...
Java 7 GC(垃圾回收)参数配置是Java虚拟机(JVM)调优的关键组成部分,它决定了垃圾回收的行为和性能表现。本文将详细介绍Java 7中常见的垃圾回收器和相应的JVM参数,帮助读者更好地理解和使用这些参数进行性能...
第二版可能会详细介绍各种垃圾收集算法,如标记-清除、复制、标记-整理和分代收集等,以及如何调整GC参数以优化内存使用和减少停顿时间。此外,新生代、老年代、持久代的概念也会被详细解析。 此外,JVM的性能优化...