如果说垃圾收集算法是内存回收的方法论,那么垃圾收集器则内存回收的具体实现。Java虚拟机规范中对垃圾收集应该如何实现并没有任何规定,因此不同的厂商、不同版本的虚拟机所提供的垃圾收集器都可能会有很大的差别,并且一般都会提供参数供用户根据自己的应用特点和要求组合出各个年代所使用的垃圾收集器。这里讨论的收集器基于Sun HotSpot虚拟机1.6版本Update 22,这个虚拟机包含的所有收集器如图: 图中展示了7种不同分代的收集器,如果这两个收集器之间存在连线,就说明他们可以搭配使用。
Serial收集器
新生代收集器,采用复制算法,是最基本、历史最悠久的收集器,Jdk1.3.1之前虚拟机新生代收集的唯一选择。单线程收集器,在进行垃圾收集时,必须暂停其他所有工作线程(Stop The World),直到它收集结束。虚拟机运行在Client模式下的默认新生代收集器。单CPU的情况下由于没有线程交互开销,可以获得最高的单线程收集效率。
ParNew收集器
新生代收集器,采用复制算法,Serial收集器的多线程版本,除了使用多线程,其余行为与Serial完全一致(包括所有控制参数[-XX:SurvivorRatio、-XX:PretenureSizeThreshold、-XX:HandlePromotionFailure等]、收集算法、Stop The World、对象分配规则、回收策略) ,是除了Serial之外唯一能与CMS配合使用的新生代收集器。ParNew也是使用-XX:UseConcMarkSweepGC选项后的默认新生代收集器,也可通过使用-XX:+UseParNewGC选项强制使用它。使用该收集器时默认开启收集线程数量与CPU个数相同,可使用-XX:ParallelGCThread参数限制线程数。
Parallel Scavenge收集器
新生代收集器,使用复制算法、并行的多线程收集器。其他收集器关注点是尽可能缩短垃圾收集时间,Parallel Scavenge的目标却是:达到一个可控的吞吐量。
吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)
停顿时间短适合与用户交互的程序,良好的响应速度能提升用户的体验;而高吞吐量则可以最高效率地利用CPU时间,尽快地完成运算任务,主要适合在后台运算而不需要太多交互的任务。
Parallel Scavenge提供了两个参数用于精确控制吞吐量:
- -XX:MaxGCPauseMillis:控制最大垃圾收集停顿时间,参数允许的是一个大于0的毫秒数,收集器将尽力保证内存回收花费的时间不超过设定值。
- -XX:GCTimeRatio:直接设置吞吐量大小,参数的值应当是一个大于0小于100的整数。也就是垃圾收集时间占总时间的比率,相当于是吞吐量的倒数。
另外还有一个参数值得关注:-XX:+UseAdaptiveSizePolicy,这是一个开关参数,当参数打开后不需要手工指定新生代大小、Eden与Surivor区的比例等参数细节了,虚拟机会根据当前系统的运行情况动态调整这些参数以提供最合适的停顿时间或最大吞吐量。
Serial Old收集器
Serial的老年代版本,单线程收集器,使用“标记-整理”算法。Client模式运行的虚拟机的默认老年代收集器。主要有两大用途:
- Jdk1.5及之前版本与Parallel Scavenge搭配使用。
- 作为CMS收集器的后备预案,在并发收集发生Concurrent Mode Failure的时候使用。
Parallel Old收集器
Parallel Scavenge的老年代版本,使用多线程和“标记-整理”算法。Parallel Scavenge加Parallel Old的组合终于成为“吞吐量优先”收集名副其实的组合。
CMS收集器
Concurrent Mark Sweep,是一种以获得最短回收停顿时间为目标的收集器。基于“标记-清除”算法实现。整个收集过程分为4个步骤:
- 初始标记(CMS initial mark):仍然需要“Stop The World”。初始标记仅仅只是标记一下GC Roots能直接关联到的对象,速度很快。
- 并发标记(CMS Concurrent mark):进行GC Roots Tracing的过程
- 重新标记(CMS remark):为了修正并发标期间,因用户程序继续运行导致标记产生变动的那一部分对象的标记记录,停顿时间一般会比标记阶段稍长一些,但远比并发标记的时间短
- 并发清除(CMS concurrent sweep)
由于整个过程中耗时最长的并发标记和并发清除过程中,收集器线程都可以与用户线程一起工作,所以总体上来说,CMS收集器的内存回收过程是与用户线程一起并发地执行的。
CMS收集器主要有以下三个缺点:
- CMS对于CPU资源敏感,CMS默认启动的回收线程数是(CPU数量+3)/4。
- 无法处理浮动垃圾(并行过程中新产生的垃圾):CMS需预留空间提供并发收集时程序运作使用,默认设置下为老年代达使用率达到68%时触发,可通过参数(-XX:CMSInitiatingOccupancyFraction)调整,不建议设置太高,因为太高会产生ConcurrentModeFailure而导致Serial Old收集而拉长停顿时间。
- 由于采用“标记-清除”算法会产生内存碎片,碎片过多时将给大对象带来很大机率的分配失败,而不得不提前触发一次Full GC。可通过-XX:+UseCMSCompactAtFullCollection用于“享受”完Full GC后额外免费附送一次碎片整理,但会增长停顿时间。-XX:CMSFullGCsBeforeCompaction设置执行完多少次不压缩Full GC之后紧跟着来一次带压缩的。
G1收集器
基于“标记-整理”算法实现,可非常精确的控制停顿时间,极力避免完全区域垃圾收集,划分多个独立区域(固定大小),并跟踪这些区域垃圾段义和程序,在后台维护一个优先列表,每次根据允许的时间收集垃圾最多的区域。
垃圾收集器参数
参数 | 描述 |
UseSerialGC | 虚拟机运行在Client模式下的默认值,打开此开关后,使用Serial+Serial Old的收集器组合进行内存回收。 |
UseParNewGC | 打开此开关后,使用ParNew+Serial Old的收集器组合进行内存回收。 |
UseConcMarkSweepGC | 打开此开关后,使用ParNew+CMS+Serial Old的收集器组合进行内存回收。Serial Old收集器将作为CMS收集器出现Concurrent Mode Failure失败后的后备收集器使用。 |
UseParallelGC | 虚拟机运行在Server模式下的默认值,打开此开关后,使用Parallel Scavenge+Serial Old(PS MarkSweep)的收集器器组合进行内存回收。 |
UseParallelOldGC | 打开此开关后使用Parallel Scavenge+Parallel Old的收集器组合进行内存回收 |
SurvivorRatio | 新生代中Eden区域与Survivor区域的容量比值,默认为8,代表Eden:Survivor=8:1 |
PretenureSizeThreshold | 直接晋升到老年代的对象大小,设置这个参数后,大于这个参数的对象将直接在老年代分配 |
MaxTenuringThreshold | 晋升到老年代的对象年龄。每个对象在坚持过一次Minor GC之后,年龄就加1,当超过这个参数值时就进入老年代 |
UseAdaptiveSizePolicy | 动态调整Java堆中各个区域的大小以及进行老个代的年龄。 |
HandlePromotionFailure | 是否允许分配担保失败,即老年代的剩余空间不足以应付新生代的整个Eden和Survivor区的所有对象都存活的极端情况。 |
ParallelGCThreads | 设置并行GC进行内存回收的线程数 |
GCTimeRatio | GC时间占总时间的比率,默认值为99,即允许1%r GC收集时间。仅在使用Parallel Scavenge收集器时生效 |
MaxGCPauseMillis | 设置GC的最大停顿时间。仅在使用Parallel Scavenge收集器时生效 |
CMSInitiatingOccupancyFration | 设置CMS收集器在老年代空间被使用多少后触发垃圾收集。默认值为68%,仅在CMS收集器时生效 |
UseCMSCompactAtFullCollection | 设置CMS收集器在完成垃圾收集后是否要进行一次内存碎片整理。仅在使用CMS收集器时生效 |
CMSFullGCsBeforeCompaction | 设置CMS收集器在进行若干次垃圾收集后再启动一次内存碎片整理。仅在使用CMS收集器时生效 |
相关推荐
JVM内在结构的图解文档,visio格式 1.编译过程 2.内存结构 3.对象与类的结构 4.类结构信息 5.对象建立过程 6.收集器 7.方法调用 8.垃圾回收 9.JIT 10.指令 11.线程
及时将不再使用的对象设置为null,使其可以被垃圾收集器回收。 3. **处理对象生命周期** - Item7:Java中的finalizers用于清理对象资源,但不应依赖其执行,因为它们可能不会被调用,而且会影响垃圾收集性能。 4...
当我们不再使用某些对象时,Java会自动调用垃圾收集器来释放这些对象所占的内存空间。可以通过调用`System.gc()`来请求进行垃圾回收,但实际上何时执行由JVM决定。 2. **Java程序的运行流程** - 类加载器(Class ...
15. **避免在析构函数中抛出异常**:析构函数( finalize() 方法)不应该抛出异常,因为这可能导致对象无法正确地被垃圾收集。 以上仅是《Effective Java》一书中部分核心知识点的概述,实际的读书笔记中会更详细地...
C#具有自动内存管理机制,即垃圾收集器(Garbage Collector)。它负责跟踪并回收不再使用的内存,使得开发者无需手动管理内存,降低了内存泄漏的风险。 九、Lambda表达式和表达式树 Lambda表达式是匿名函数的简洁...
* 堆的空间由垃圾收集器管理,它是一个独立的线程。 四、垃圾回收机制 * 分代复制 GC 收集器超过 95% 的对象的生存期都非常短,分代复制算法根据对象的生存期将对象分为两代。 * 所有的新创建的对象都在一个类假栈...
4. **垃圾收集**:内核使用垃圾收集器回收不再使用的内存,可以是异步的(通过定时器触发)或同步的(达到特定阈值时启动)。 5. **函数指针和虚拟函数表(VFTS)**:内核中使用函数指针实现面向对象特性,允许在...
理解不同类型的垃圾收集器,如Serial、Parallel、CMS、G1等,以及它们的工作机制,可以帮助我们选择适合应用的GC策略,减少内存瓶颈。 3. **对象生命周期**:了解对象从创建到消亡的过程,包括新生代、老年代的划分...
垃圾回收算法包括标记-清除、复制、标记-整理和分代收集。分代收集是现代JVM常用的策略,将堆分为新生代和老年代,针对不同年龄段的对象使用不同的收集策略。 5. **《Inside Java Virtual Machine》**:这本书是...
Java对象的生命周期超出了作用域,即使引用消失,对象依然存在于堆中,直到垃圾收集器回收。 Java会为类的成员变量赋予默认值,但不会为局部变量自动初始化。方法参数列表中必须指定参数的类型和名称,传递对象时...
JVM内在结构的图解文档,visio格式 1.编译过程 2.内存结构 3.对象与类的结构 4.类结构信息 5.对象建立过程 6.收集器 7.方法调用 8.垃圾回收 9.JIT 10.指令 11.线程
- **内存管理**:OpenJDK7的垃圾收集器有Parallel GC、Serial GC、CMS(Concurrent Mark Sweep)和G1(Garbage-First)。它们各有优缺点,适用于不同场景。 - **编译器**:C1编译器主要针对方法的早期优化,而C2...
避免浪费了很多时间收集的资料,实际上只是活在硬盘空间中的垃圾。 并且多数的其它软件以网页以主,但网页的知识载体量约为20%而于; 而针式PKM则以Word、PDF、PPT、网页等为主。覆盖全面文档格式。 针式PKM ...
避免浪费了很多时间收集的资料,实际上只是活在硬盘空间中的垃圾。 并且多数的其它软件以网页以主,但网页的知识载体量约为20%而于; 而针式PKM则以Word、PDF、PPT、网页等为主。覆盖全面文档格式。 针式PKM ...
避免浪费了很多时间收集的资料,实际上只是活在硬盘空间中的垃圾。 并且多数的其它软件以网页以主,但网页的知识载体量约为20%而于; 而针式PKM则以Word、PDF、PPT、网页等为主。覆盖全面文档格式。 针式PKM ...