1.当前对象是否为垃圾(垃圾确认机制)
运行时区域中的程序计数器. 虚拟机栈, 本地方法栈都是随着线程而灭, 不需要过多考虑回收问题, 而且基本上内存大小的分配也都是编译器就已知的(暂不考虑JIT的优化)
堆和方法区是线程共享的区域, 这部分区域在内存的分配和回收都是动态的, 垃圾回收器回收的就是这部分的内存
那么在堆中如何确认一个对象是否已经是垃圾即需要被回收了呢?
有两种思路即算法
(1)引用计数
实现简单, 效率高, 在对象上添加一个引用计数器, 每当一个有效引用到此对象时候, 计数器+1, 反之-1
主流的Java虚拟机实现都基本没有选择此算法, 因为不好解决循环引用的问题
(2)可达性分析
通过一系列GC Roots的对象作为起始点, 从此对象向下搜索走过的路径称为引用链, 当一个对象到GC Roots没有任何引用链时, 即被判定为可回收对象
以上两种算法都是通过引用来实现, 为了使引用更加灵活, 而不是非生即死的状态, Java对引用的概念进行了扩充, 能够描述一些'食之无味, 弃之可惜'的对象, 即当内存空间还足够时, 则能够保留在内存中, 进行回收之后还是很紧张, 则可以抛弃这些对象, 很多系统的缓存都符合这样的应用场景
强引用, 软引用, 弱引用, 虚引用 四种引用类型强度逐渐减弱, JDK中都有对应的class来实现各种类型引用, ThreadLocalMap就是弱引用的实现
方法区的回收
1.此区域主要回收两部分内容, 废弃常量和无用的类
虚拟机规范说过不要求虚拟机实现方法区的垃圾收集, 而且此区域の垃圾收集一般性价比比较低(以下都是HotSpot的实现)
常量池中的字符串常量和类. 接口, 方法和字段的符号引用回收较简单, 主要取决于是否有引用指向
而无用的类就比较不好判断, 需满足三个条件才有回收的可能, 分别是:
(1).该;类的所有对象都已经被回收
(2).加载该类的ClassLoader已经被回收
(3).该类对应的java.lang.Class对象没有在任何地方被引用, 无法在任何地方通过反射访问此类的方法
在大量使用反射, 动态代理, CGLib等ByteCode框架, 动态生成JSP以及OSGI这类频繁自定义ClassLoader的场景都需要虚拟机具备类卸载的功能, 以避免永久带溢出
2.回收垃圾的算法概述
标记-清除
最容易想到的方法, 后面各个算法都是在此基础上的改进, 两个阶段: 标记所有需要回收的对象, 回收
缺点: 效率不高, 标记和清除两个过程的效率都不高, 而且会造成内存碎片, 使内存不连续无法容纳需要连续空间的大对象, 从而造成FullGC
复制
效率高, 一定程度的内存浪费(HotSpot对新生代的收集实现, 这里的程度可以配置调整)
标记-压缩
解决了标记清除的内存碎片化问题
3.回收垃圾的各收集器
JVM发起内存回收前, 需要保证线程执行到Safe Region中, 线程离开Safe Region前, 需保证JVM已经完成了根节点枚举或者整个GC
上图为现有的垃圾收集器的分代组合使用情况
新生代:
Serail收集器: 单线程收集, 有STW, 无线程切换开销, 单CPU环境下比较适合, client模式下的默认选择
ParNew收集器: Serial的多线程版本, 通常使用CMS清理老年代时, 与ParNew这使用, 也是CMS模式下的默认选择
Parallel Scavenge收集器: 其他收集器主要关注垃圾收集时工作线程的停顿时间, Parallel Scavenge更关注CPU吞吐量(运行代码时间/虚拟机总运行时间), 主要适合在后台运算而不需要太多交互的任务, Parallel Scavenge还提供了自适应调节策略
老年代:
Serial Old收集器: 单线程, 标记-整理
Parallel Old收集器: '多线程, 标记-整理 吞吐量优先', 注重吞吐量的场合, 可以优先考虑Parallel Scavenge+Parallel Old
CMS: 标记-清除 四个阶段: 初始标记, 并发标记, 重新标记, 并发清除, 初始标记为了找到GC Roots,速度很快, 并发标记时间较长即标记线程与用户线程并行工作(吞吐量会降低), 重新标记也比较快, 把上一步骤过程中遗漏的(少)再次收集, 然后并发清除
JDK7下的常用参数
参数
|
描述
|
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% 的GC 时间。仅在
使用Parallel Scavenge 收集器时生效
|
MaxGCPauseMillis
|
设置GC 的最大停顿时间。仅在使用Parallel Scavenge 收集器时生效
|
CMSInitiatingOccupancyFraction
|
设置CMS 收集器在老年代空间被使用多少后触发垃圾收集。默认值为
68%,仅在使用CMS 收集器时生效
|
UseCMSCompactAtFullCollection
|
设置CMS 收集器在完成垃圾收集后是否要进行一次内存碎片整理。仅
在使用CMS 收集器时生效
|
CMSFullGCsBeforeCompaction
|
设置CMS 收集器在进行若干次垃圾收集后再启动一次内存碎片整理。
仅在使用CMS 收集器时生效
|
相关推荐
引用计数法是一种简单的垃圾收集算法,它为每个对象维护一个引用计数器,每当有新的引用指向该对象时,计数器加一;当引用失效时,计数器减一。当对象的引用计数器为零时,表示该对象不再被任何引用,可以被回收。...
此外,算法还允许用户指定一个时间段内垃圾收集导致应用程序暂停的最长时间,这为实时应用提供了灵活性和可配置性,使其能够根据具体的应用场景调整GC策略,以达到最佳的实时性能。 #### 结论 基于实时性的Java...
垃圾收集算法主要涉及两个关键步骤:识别垃圾对象与活动对象(即仍在使用中的对象),以及回收垃圾对象占用的内存空间,使其可供再次使用。 #### 垃圾收集算法分类 垃圾收集算法大致可以分为两大类:基于引用计数...
第三节:定位垃圾对象的依据 1.1 引用计数法 1.2 可达性算法 第四节:垃圾回收算法 1.1标记清除算法 1.2复制算法 1.3 标记整理(标记压缩)算法 第五节:垃圾回收器 1.1Serial/Serial Old收集器 1.2 ParNew收集...
* 降低暂停时间:CMS垃圾收集器可以在不停止应用程序的情况下进行垃圾收集。 * 提高系统性能:CMS垃圾收集器可以提高系统的整体性能。 Java垃圾收集器的其他知识点包括: * GC Roots:垃圾收集器的根对象,包括...
对于像Java这样的自动管理内存的语言而言,理解其内部的对象释放与垃圾收集机制显得尤为重要。 #### 二、对象的释放 在程序运行过程中,会不断地创建和销毁对象。当一个对象不再被引用时,它就成为了一个无用的...
引用跟踪是垃圾收集算法中的一个重要步骤,它可以跟踪对象之间的引用关系,从而确定哪些对象可以被垃圾收集。 知识点7:实时性环境 实时性环境是指需要实时响应的应用场景,如工业控制、新兴的实时网络游戏等领域...
本文将详细探讨GC算法、判断对象回收条件、垃圾收集器的工作原理及其调优步骤和常用参数。 首先,GC需要判断哪些对象可以被回收。在JVM中,主要有两种算法用来判断对象的生死:引用计数法和可达性分析算法。引用...
2. **垃圾收集算法** - **跟踪收集器**:从GC Roots开始遍历对象,如果对象无法从GC Roots到达,视为可回收。常见的跟踪收集器有串行收集器、并行收集器和并发收集器。 3. **类加载机制** - 类加载过程包括加载、...
JVM内存管理是Java虚拟机的核心机制之一,其主要包含对象的创建、内存分配、...通过对内存分配策略、对象生死判定、垃圾收集算法和垃圾收集器的理解与应用,可以更好地掌握JVM的内存管理,从而提升应用性能和稳定性。
引用计数算法是最直观的垃圾回收策略,它为每个对象分配一个引用计数器,每当有对象引用它时,计数器加1;当引用失效时,计数器减1。当计数器为0时,表明对象不再被使用,可以进行回收。虽然简单易懂,但这种方法...
4. **多样的回收策略**:不同版本的JVM提供了多种GC算法,包括但不限于串行收集器、并行收集器、并发标记扫描收集器以及G1收集器等。每种算法都有其适用场景和优劣,开发者可以根据应用需求选择最适合的GC策略。 ##...
增量式收集器在堆空间的划分、对象跟踪等方面进行了优化,以减少垃圾收集的不确定性暂停,并允许用户指定应用程序在特定时间段内因垃圾收集导致的最长暂停时间。 改进的垃圾收集算法主要集中在以下几个方面: 1. ...
在这篇手册中,我们将深入探究 Java 垃圾收集的基础知识,包括垃圾收集的定义、垃圾收集算法、垃圾收集器的实现、垃圾收集优化等内容。 垃圾收集的定义 垃圾收集(Garbage Collection,简称 GC)是指在 Java 语言中...
垃圾回收器的任务就是找到这些无用的对象并释放它们占用的内存空间,以便重新利用。 在Java中,垃圾回收主要分为以下几个阶段: 1. **标记阶段**:GC首先从根对象(如栈中的引用、静态变量等)开始,遍历所有可达...
CMS垃圾收集器是一种Java虚拟机(JVM)的老年代垃圾收集器,它的主要目标是减少垃圾收集时的停顿时间,以提供更优秀的响应速度,适合于需要低延迟且CPU资源充足的服务器应用。CMS基于“标记-清除”算法,这意味着它...
2. 垃圾收集机制:垃圾收集是JVM用来自动管理内存的一种机制,其主要目标是识别并处理不再被程序使用的对象,回收它们占用的内存空间。垃圾收集机制通过各种算法来优化内存使用,减少程序运行时的内存泄漏。 3. 分...
Java垃圾回收之分代收集算法是Java虚拟机中的一种垃圾回收机制,它根据对象的存活周期的不同将内存划分成几块,新生代和老年代,以便于采用最适当的收集算法提高垃圾收集的效率。 新生代(Young Generation) ...
在Java世界中,JVM垃圾收集器是内存管理的重要组成部分,负责自动回收不再使用的对象,以释放内存空间。垃圾收集器的选取并非一成不变,而是需要根据具体应用的需求和环境来定制。本文将详细解析几种常见的JVM垃圾...