【JVM】垃圾回收算法与内存分配策略
来源:互联网 发布:交友约会软件 编辑:程序博客网 时间:2024/05/17 23:14
垃圾回收算法与内存分配策略
一、判断对象是否已死
1、引用计数算法
根据引用计数器判断对象存活,给每个对象创建一个引用计数器。对象有被引用时 引用计数器加1,不引用引用计数器减1,当引用计数器为0时表示该对象不存活可回收。
特殊情况:在两个对象相互引用时,实际情况对象是可回收状态,但这种情况会被认为是对象存活,不可回收。
2、可达性分析算法
现在一些通用虚拟器都是通过可达性分析算法判断对象是否存活,基本思想是:在java堆中,会有一系列叫做 “GC ROOT" 作为起点向下延伸,延伸的每个节点叫做引用链,
如果延伸的引用链(对象引用)到根节点不可达,认为这个对象可回收,如下图:
3、生死还是死亡
对象通过可达性分析算法标记后,并不是“非死不可”,此时对象处于“缓刑”状态,还要经过两次标记过程,确定对象真正死亡。
如果对象覆盖了finalize()方法,GC认为是“有必要执行“的,就是可以进行二次缓刑,此时,对象会被放到F queu 对象中,会有的优先级的 Finalize 线程进行执行,在 finalize()方法中可以进行自我拯救(对象被任意对象重新引用即可),如果引用成功,第一次逃脱成功,对象进行二次标记,不被回收。GC再次回收时,二次标记对象会被回收,因为finalize 只能执行一次,对象不能再次逃脱。
二、垃圾回收算法
1、标记-清除 算法
如名称所讲,GC将要回收的对象先进行标记,然后再进行回收。
缺点:
效率低:标记和清除两个阶段效率都不高
内存问题:地址不连续,如果遇到大对象,内存不够会触发再次回收,增加回收次数,浪费资源
2、复制算法
复制算法将可用内存分为相等两部分,Eden(回收对象),Survivor(存活对象),GC将Enden可用对象复制到Survior空间内,然后回收Eden空间。
优点:只对一半区域进行回收,不用考虑空间不了连续问题;实现建单,只要移动栈顶指针即可,效率高
缺点:对象存活率较高时,会进行频繁的复制
现在虚拟机用复制算法机制进行新生代的回收,新生代的对象大多是”朝生夕死“,比较科学的Eden 和 Survior比例是8:1,HotSpot 会划分一块较大的(80%)Eden空间和两块叫小的Survior空间,将Eden 和 一个Survior 存活对象复制到另一个 Survior空间上,然后回收Eden 和 其中一个Survior死亡对象。
如上所说,新生代回收只会有10%的空间会浪费,但在一些情况下,存活的对象>10%的内存,此时,就需要老年代做担保,通过担保机制进入老年代。
3、整理-清除 算法
与标记-清除 算法比较,标记清除会造成空间不连续,整理-清除 算法先将存活对象像一端移动,然后清除掉存活对象边界以外的死亡对象。
4、分代回收算法
分代回收没有特殊的技术,只是根据新生代和老年代的特点进行选择适合的回收算法:
新生代:大多数对象”朝生夕死“,死亡对象多,存活对象少,复制回收算法可以减少回收次数,提高效率
老年代:存活对象多,存活几率高,用复制回收算法,没有额外的内存做担保,适合使用”标记-清除“或”标记-整理“回收算法。
三、内存分配策略
1、对象优先分配Eden内存区域下
对象优先分配到Eden下,当内存不够是,Eden会进行一次Minor GC,如Eden和Survior空间不够时,按照担保机制进入老年代。
2、大对象直接进入老年代
所谓的大对象是指具有大量连续内存空间的java对象,大对象对内存来说是一个坏消息,一堆“朝生夕死”的短命大对象对内存来说简直是恶梦,遇到短命大对象,导致还有空间就需要Minor GC 来清理出足够大的空间来安置大对象。
虚拟机提供了-xx:PretenureThreshold参数配置大对象内存,大对象超过配置参数内存,就直接分配到老年代,减少复制内存造成的资源消耗(新生代采用复制算法)。
3、长期存活对象进入老年代
既然虚拟机采用分代管理,那么在分配内存时就应该识别是新生代和老年代,为了识别虚拟机给每个对象定义一个年龄计数器(age),对象每次被Minor GC 一次,年龄计数器加1,当年龄计数器超过配置值(可通过-XX:MaxTenuringThreshold=15,默认是15)时,被认定为长期存活对象,会被分配到老年代。
4、动态对象年龄判定
如上长期对象进入老年代所说,长期对象根据判定达到年龄进入老年代。实际上,虚拟机对应于对象年龄的判定不是一定要求达到配置年龄,如果Survior中的相等年龄对象中和超过Surivor一半时就会直接进入老年代。
5、空间分配担保
在新生代发生Minor GC之前,先会检查老年代空闲空间是否大于新生代对象总大小:
a.如果成立,则Minor GC可确保是安全的;
b.如果不成立,则虚拟机会查看HandlePromotionfailure设置是否允许担保失败:a.如果允许,会继续检查老年代的空闲空间是否大于历次回收对象的平均大小,如大于,会进行一次Minor GC,尽管这次Minor GC有风险;b.如大于或HandlePromotionfailure设置不允许担保失败,则会进行一次Full GC。
备注:
Minor GC:Minor GC 指新生代的非存活对象的回收动作,新生代大多存储“朝生夕死”对象,回收频繁,回收速度快。
Full GC/Major GC:值老年代大对象及存活时间长的对象的回收对象,出现了Full GC 通常伴随至少一次的Minor GC,Full GC 一般比Minor GC 慢10倍。
- 【JVM】垃圾回收算法与内存分配策略
- JVM垃圾回收算法和内存分配策略
- JVM垃圾回收及内存分配策略
- JVM垃圾回收和内存分配策略
- JVM内存分配和垃圾回收策略
- JVM垃圾回收算法与内存管理策略
- 垃圾回收机制与内存分配策略
- 垃圾回收器与内存分配策略
- JVM的垃圾回收与内存分配
- jvm 内存分配与垃圾回收
- Java内存区域分配、存储、垃圾回收策略与回收机制(深入JVM虚拟机)
- JVM内存分配与回收策略
- JVM-内存分配与回收策略
- JVM虚拟机-内存分配与回收策略
- JVM-内存分配与回收策略
- JVM内存分配与回收策略
- JVM:内存分配与回收策略
- JVM堆内存分配与回收策略
- android studio2.2 导入eclipse项目所遇到的坑
- caffe中的matlab读取均值文件imagenet_mean.binaryproto
- nginx模块
- 建造者模式-Builder Pattern 复杂对象的组装与创建——建造者模式(二):游戏角色设计的建造者模式解决方案
- golang time 包 常用函数
- 【JVM】垃圾回收算法与内存分配策略
- 多线程----生产者消费者
- Unity 获取摄像机的视口区域
- PHP7 和 ECMAScript 新特性
- centos 6.6 yum安装mysql 5.7.16
- xcode编译出现AFNetworking.framework did not have a CFBundleIdentifier in its Info.plist
- 从0开始学习 GITHUB 系列之「GIT 速成」
- AAC家族命名
- 最全面的Xcode 8 带来的新特性。