java垃圾收集器与内存分配策略
1. 根搜索算法(GC Roots Tracing)
java语言中判定一个对象是否存活,用的是根搜索算法。
算法思路:从一系列名为“GC Roots”的对象作为起始点,开始向下搜索,搜索经过的路线称为引用链。当一个对象到GC Roots没有任何应用链相连,则证明此对象是不可用的。
可以作为GC Roots的对象包括:
(1)虚拟机栈(栈帧中的本地变量表)中的引用的对象。
(2)方法区中的类静态属性引用的对象。
(3)方法区中常量引用对象。
(4)本地方法栈中JNI(native方法)的引用对象。
对象不可用并不是代表一个对象已经死亡,可以进行回收,在这之前至少要经历两次标记过程:如果对象被宣告为不可用,那它将会被第一次标记并进行第一次筛选,筛选条件是此对象是否有必要执行finalize()方法。当对象没有覆盖该方法,或者该方法已经被虚拟机执行,则这两种情况都被视为“没有必要执行”。
如果这个对象被判定为有必要执行finalize()方法,那么这个对象将被放置在一个名为F-Queue的队列中,并在稍后由一条由虚拟机自动创建的、低优先级的Finalizer线程去执行,但是虚拟机不会阻塞在该方法上,这是为了避免由于finalize()方法执行时间过长或者死循环造成的内存回收系统崩溃。finalize()是对象逃逸的最后一次机会。如果对象在finalize()方法成功的将自己和引用链连接上,那么在F-Queue上的第二次标记时,它将被移出即将回收的集合。还有一点要注意的是finalize()方法对于一个对象而言只会执行一次。
2. 引用的类型
jdk1.2以后java对引用的概念进行了扩充:
(1)强引用(Strong Reference):在程序代码中普遍存在的。类似“Object obj = new Object()”,这类引用只要存在垃圾收集器永远不会回收。
(2)软引用(Soft Reference):一些还有用,但并非必须的对象。系统将在发生内存溢出异常之前,将这些对象列进回收范围之中并进行第二次回收。如果回收后还没有足够内存,才抛出异常。
(3)弱引用(Weak Reference):也是描述非必须对象,被弱引用关联的对象只能生存到下一次垃圾收集之前。
(4)虚引用(Phabntom Reference):最弱的引用关系。为一个对象设置虚引用的唯一目的就是希望能在这个对象被回收时收到一个通知。
3.垃圾收集算法
3.1 标记-清除算法(Mark-Sweep)
首先标记出要回收的对象,在标记完成后统一回收掉被标记的对象。
缺点:效率问题,标记和清除效率都不高。导致产生大量不连续的内存碎片。
3.2 复制算法
将空间容量等量的划分成两块,每次使用其中一块。当当前块用完时,将存活对象复制到另外一块,然后将前面一块清理掉。
优点:实现简单、运行高效。
缺点:内存缩小了一半,空间代价高昂。
现在的商业虚拟机都采用这种方法来回收新生代。新生代的对象一般都是朝生夕死,所以不需要1:1的划分空间。而是将分为较大的一块为Eden,两块较小为Survivor空间,每次使用一块Survivor,回收时将Eden和Survivor中存活对象复制到另外一块Survivor空间。HotSpot默认Eden:Survivor=8:1。但是也有可能会出现Survivor大小不足以满足一次复制的需求,这就需要依赖其他内存(这里指老年代)进行分配担保(Handle Promotion),一旦出现这种Survivor空间不够的情况,这些对象将直接进入老年代。
3.3 标记-整理算法
复制算法在对象存活率较高时就要执行较多的复制操作,效率就变低。如果Survivor空间不足还需要额外的空间分配担保。所以根据老年代的特点,运用“标记-整理”算法。标记过程和前面提到的标记算法一致,后面将存活对象都移动到空间的一段,然后清理另一端。
4.垃圾收集器
(1)Serial收集器:用户线程将暂停,GC为单个线程。
(2)ParNew收集器:Serial收集器的多线程版本。用户线程将暂停,在新生代收集时GC为多个线程。
(3)Parallel Scavenge收集器:并行的多线程收集器。其他收集器关注缩短收集时用户线程暂停时间,而此收集器的目标是到达一个可控的吞吐量(Throughput),就是cpu用于用户的时间与CPU总消耗时间的比值。
(4)Serial Old收集器:Serial收集器的老年代版本。单线程。
(5)Parallel Old收集器:Parallel Scavenge收集器的老年代版本。多线程。
(6)CMS(concurrent Mark Sweep)收集器:最短回收时间为目标的收集器。垃圾收集过程分为4个过程:
- 初始标记:标记GC Roots能直接关联到的对象,速度快。单线程。不可以与用户线程一起工作。
- 并发标记:进行GC Roots Tracing的过程。单线程。可以与用户线程一起工作。
- 重新标记:修正并发标记期间,因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段停顿时间一般比初始标记稍长,但是远比并发标记时间段。多线程。不可以与用户线程一起工作。
- 并发清除:时间最长,收集器线程可以与用户线程一起工作。单线程。
并发标记和并发清除耗时最长。Serial和ParNew能够和它配合使用。
(7)G1收集器:不牺牲吞吐量的前提下完成低停顿的的内存回收。G!将整个堆划分为多个大小固定的区域,根据垃圾堆积程度,在后台维护一个优先列表,每次在允许的收集时间,优先回收垃圾最多的区域。
5.内存分配与回收策略
(1)在新生代进行Minor GC。发生频繁,回收速度也比较快。老年代进行Full GC,经常会伴随一次Minor GC,也叫Major GC一般比Minor GC慢10倍。
(2)多数情况下,对象直接在新生代Eden区中分配。当Eden区没有足够的空间进行分配时,虚拟机将发起一次Minor GC。当Survivor区空间不足时,Minor GC将对象存入老年代。
(3)大对象直接进入老年代。虚拟机提供参数-XX:PretenureSizeThreshold参数设定,如果大于这个参数,怎对象直接进入老年代。
(4)长期存活的对象将进入老年代。如果对象在Eden出生并经过第一次Minor GC后仍然能存活,并被Survivor容纳,将被移动到Survivor区,并将年龄增加1,对象每熬过一次Minor GC年龄就加1。当年龄增加到一定程度时,将被晋升到老年代。这个阀值可以通过设置参数-XX:MaxTenuringThreshold来设置。但是也存在动态的年龄判定,如果Survivor空间中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象直接进入老年代,无须等到满足该参数。
(5)空间分配担保:发生Minor GC时,虚拟机会检测之前每次晋升到老年代的平均大小是否大于老年代的剩余空间大小,如果大于,则直接进行一次Full GC。如果小于,则查看HandlePromotionFailure设置是否允许担保失败。如果允许,只进行Minor GC。如果不允许,则也要改为一次Full GC。前面提到,当Survivor空间不足时,就要在老年代中分配担保。这样也会经历刚刚分析的过程。
分享到:
相关推荐
主要整理内容为:分析了垃圾收集的算法和JDK1.7中提供的7款垃圾收集器的特点以及运作原理。以及内存分配策略
JAVA 垃圾收集器与内存分配策略.rar
介绍了JAVA垃圾收集器与内存分配策略,需要了解的朋友可以参考下
1. JVM调优 1.1 JVM调优总结(一)-一些概念 1.2 JVM调优总结(二)-一些概念 1.3 JVM调优总结(三)-基本垃圾回收算法 1.4 JVM调优总结(四)-垃圾...4.2 JVM内存管理:深入垃圾收集器与内存分配策略 4.3 深入理解JVM
JVM(Java虚拟机)的整个流程:发展,运行区域,垃圾回收器,内存分配策略,垃圾收集,JVM分析工具,JVM优化
/ 41 2.5 本章小结 / 42 第3章 垃圾收集器与内存分配策略 / 43 3.1 概述 / 43 3.2 对象已死? / 44 3.2.1 引用计数算法 / 44 3.2.2 根搜索算法 / 46 3.2.3 再谈引用 / 47 3.2.4 生存还是死亡? / 48 3.2.5 ...
本书以极其精练的语句诠释了 HotSpot VM的方方面面,比如:字节码的编译原理、字节码的内部组成结构、通过源码的方式剖析 HotSpot VM 的启动过程和初始化过程、Java 虚拟机的运行时内存、垃圾收集算法、垃圾收集器...
第3章 垃圾收集器与内存分配策略 3.1 概述 3.2 对象已死吗 3.2.1 引用计数算法 3.2.2 可达性分析算法 3.2.3 再谈引用 3.2.4 生存还是死亡 3.2.5 回收方法区 3.3 垃圾收集算法 3.3.1 标记-清除算法 3.3.2 ...
很久之前就一直在学习JVM,但是一直也没有好好的总结,最近终于有了空闲,将之前学习的内容整理成了一个PPT。 也希望大神们可以批评指正。 ppt中主要包含下面几部分: Java内存模型 ... 垃圾收集器
当前JVM对于堆的垃圾回收,采用分代收集的策略。根据堆中对象的存活周期将堆内存分为新生代和老年代。在新生代中,每次垃圾回收都有大批对象死去,只有少量存活。而老年代中存放的对象存活率高。 这样划分的目的是...
文中将为您提供如何管理内存的细节,然后将进一步展示如何手工管理内存,如何使用引用计数或者内存池来半手工地管理内存,以及如何使用垃圾收集自动管理内存。 为什么必须管理内存 内存管理是计算机编程最为基本的...
在Java中,程序员不需要去关心内存动态分配和垃圾回收的问题,这一切都交给了JVM来处理。顾名思义,垃圾回收是释放垃圾占用的空间,那么在Java中,什么样的对象会被认定为“垃圾”?那么当一些对象被确定为垃圾之后...
理解了应用程序的工作负荷和jvm支持的垃圾收集算法,便可以进行优化配置垃圾收集器。 垃圾收集的目的在于清除不再使用的对象。gc通过确定对象是否被活动对象引用来确定是否收集该对象。gc首先要判断该对象是否是...
JVM,JVM内存结构、HotSpot 虚拟机对象探秘、垃圾收集策略与算法、HotSpot 垃圾收集器、内存分配与回收策略、JVM 性能调优、类文件结构。。
包括JVM执行过程、虚拟机类加载机制、运行时数据区、GC、类加载器、内存分配与回收策略等,全套视频加资料高清无密码 第1讲 说在前面的话 免费 00:05:07 第2讲 整个部分要讲的内容说明 免费 00:06:58 第3讲...
java8 集合源码分析 AboutJava ==java 相关知识(理论,代码)相关知识均是看书,博客等地方获取再由自己整理,如存在侵权,请告诉我== Java基础 ...垃圾收集器和内存分配策略 虚拟机性能监控工具 编程规范
垃圾收集器与内存分配策略 2.3 类加载机制 2.4 JVM 内存模型 2.5 JVM 性能监控工具与调优 2.5.1 jps 2.5.2 jstat 2.5.3 jinfo 2.5.4 jmap 2.5.5 jhat 2.5.6 jstack 2.5.7 jConsole 3. 多线程 3.1 线程的通信与状态...
内存分配与回收策略 类加载 参数优化 进程与线程的区别 进程通信 创建线程的方式 线程的状态转换 线程安全 上下文切换 死锁 同步 异步 阻塞 非阻塞 synchronized & Lock volatile ThreadLocal sleep & wait 线程通信...
finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。 13、sleep() 和 wait() 有什么区别? sleep是线程类(Thread)的...
很久之前就一直在学习JVM,但是一直也没有好好的总结,最近终于有了空闲,将之前学习的内容整理成了一个PPT。PPT也可以在这里下载: ... 也希望大神们可以批评指正。 ppt中主要包含下面几部分: ...垃圾收集器