浅谈GC
关于Java中的GC,简单来说就是垃圾收集器自动回收生命周期结束的对象,释放内存。
那么怎样确定对象是否存活呢?
可达性分析算法
现在主流的Java虚拟机大多使用这种可达性分析算法来判断对象是否需要进行垃圾回收。具体也就是,从GC Roots出发,向下搜索,形成一个完整的对象引用链。当某个对象没有任何到达GC Roots的引用链时,便认为这个对象的生命周期结束,是可以被回收的。
GC Roots对象指的哪些呢?
- 虚拟机栈中引用的对象
- 元数据区中静态变量引用的对象
- 元数据区中常量引用的对象
- 本地方法栈中native方法引用的对象
分代回收算法
现在的JVM大多使用分代回收算法,将堆内存分为新生代和老年代。对这两部分分别使用不同的回收算法。
老年代中存放大对象和长期存活的对象,且对象较多,一般使用标记-清除算法或者标记-整理算法。新生代存活对象较少,一般使用复制算法。
标记-清除
以可达性分析算法遍历所有引用,给活着的对象打上标记。遍历结束后,统一清除需要回收的对象。
这种算法的缺点在于:
- 标记和清除的效率不高
- 进行清除以后,内存空间是不连续的。
使用这种算法的虚拟机,在进行对象内存分配时,会维护一个内存空闲列表,记录哪些内存空间可用,再进行分配。
标记-整理
与标记-清除类似,先进行标记,之后把活着的对象移动到一端,排在一起,最后清除需要回收的对象。这样的话,可以让内存地址是连续的。
如果虚拟机使用这种算法进行GC的话,在为对象分配内存时,只需要按对象的大小进行指针移动,分配足够的空间便可。
复制算法
一般在新生代中使用这种算法。将新生代内存分为一个Eden和两个Survivor区域,比例为8:1:1。
在初始时,先把对象分配到较大的Eden区域。Eden区满以后,触发Minor GC,将活着的对象复制到一个Survivor区(假如为Survivor0),并且把对象年龄加1,然后清空Eden区。当Eden再次放满以后,再把Eden区和Survivor0中活着的对象复制到另一个Survivor区,加对象年龄,清空Eden区和Survivor0区。如此循环往复。如果对象年龄达到界限(默认15),视对象为长生命周期对象,移动到老年代。大对象在内存分配时,直接放到老年代,因为大对象做复制操作费效率。值得注意的是,在复制算法的过程中,如果空闲的Survivor区内存大小无法满足需要,会依赖老年代的空间进行担保。
复制算法得到的内存空间同样是连续的。
最新文章
- MFC 工具栏隐藏与显示
- UI学习之常用方法(续)
- AESUtils.java
- php 判断复选框checkbox是否被选中
- 《统计推断(Statistical Inference)》读书笔记——第3章 统计分布族
- chown命令
- MySQL存储引擎总结
- centos 扩展root根分区的大小
- 基于TCP协议的网络通信
- JDK8新特性之接口
- 滑雪 (搜索)(dp)(贪心)
- Laravel控制器和视图
- java基础之类与对象2
- Code:Blocks中文输出乱码解决方法
- Django学习-8-模板渲染的一些特性
- SQL Server 创建跨库查詢、修改、增加、删除
- bootstrap动态添加Tab标签页
- python接口自动化测试(一)-request模块
- codevs 1200 同余方程 逆元
- ecshop报错”Deprecated: Assigning the return value of…”解决办法
热门文章
- PHP培训教程 PHP里10个鲜为人知但却非常有用的函数
- Oracle-存储过程实现更改用户密码
- Linux内核调试方法总结之内核通知链
- leetcode 36有效的数独
- 关于.NET Core的一些问题和疑惑
- AtomicIntegerArray 源码分析
- python twisted异步将数据导入到数据库中
- Jenkins简介&;邮箱配置
- python实现excel转换成pdf
- lazarus 2016 2月18 4:22:35 支持android开发了, 既ios,linux,macosx,window,web 后 囊括一切啦。 哈哈