文档章节

垃圾回收算法

s
 sen_ye
发布于 07/16 15:08
字数 1387
阅读 0
收藏 0

一 如何判断对象可以回收

1 引用计数法

思路大概为:给对象添加一个引用计数器,每当有一个地方引用它时,计数器值加1;当引用失效时,计数器减1;任何时刻计算器为0的对象就是不可能再被使用的。优点是,实现简单;但是如果两个引用之间相互引用,导致它们的引用计数都不为0的话,无法通知GC收集器回收它们。

2 可达性算法

思路大概为:从一系列可以作为"GC Roots"的对象作为起始点,从这些节点开始往下搜索,搜索走过的路径成为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。

可作为"GC Roots"的对象主要包括以下几种:

    1虚拟机栈(栈帧中的本地变量表)中引用的对象

    2方法区中类静态属性引用的对象

    3方法区中常量引用的对象

    4本地方法中JNI(即一般说的Native方法)引用的对象

特别提醒,方法区(或者说HotSpot虚拟机中的永久代)也是需要垃圾回收的,虽然java虚拟机规范中确实说过可以不要求虚拟机在方法区中实现垃圾回收,而且在方法区中进行垃圾收集的性价比比较低。永久代的垃圾回收主要包括两部分内容:废弃常量和无用的类。废弃常量回收的一个例子为常量池的字符串的回收。判断一个类是否无用的类比较复杂,必须具备以下三个条件:

1该类的所有实例已被回收,也就是java堆中不存在该类的实例

2加载该类的ClassLoader已经被回收

3该类的java.lang.Class对象没有在任何地方被引用到,无法在任何地方通过反射访问该类的方法

二 垃圾收集算法

1标记清除算法(Mark-Sweep)

核心内容分为标记和清除两个阶段: 首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。它的不足主要有两个:一个是效率问题,标记和清除两个过程的效率都不高;另一个是标记清除后会产生大量不连续的内存碎片,空间碎片太多在以后程序需要分配大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾回收动作。
 

2标记整理(标记压缩 Mark-Compact)算法

标记整理算法的标记阶段和标记清除算法基本一致,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象向一端移动,然后直接清理掉端边界以外的内存
 

3复制算法

复制算法将内存按照容量划分为大小相等的两块,每次只使用其中的一块,当这一块的内存用完了,就将还存活的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这样可以使得每次都是针对整个半区进行内存回收,内存分配时也不需要考虑内存碎片的问题。不足之处就是讲内存缩小为原来的一半,代价比较高。而且在对象存活率较高时要进行较多的复制操作,效率比较低。

商用的虚拟机一般不是按照1:1的比例划分内存空间,而是将内存划分为一块较大的eden空间和两块较小的Survivor空间,每次使用eden和其中一块survivor。当回收时,把eden和survivor中存活的对象一次性复制到另外一块survivor空间上,最后清理掉eden和刚才使用过的survivor空间。HotSpot默认eden和Survivor的比例为8:1,也就是每次新生代可用内存空间为90%,只有10%会被浪费。需要注意的是我们没有办法保证每次回收都只有不多于10%的对象存活,所以当Survivor空间不足时,需要依赖其他内存(这里指老年代)进行分配分担。虚拟机参数-XX:Surviorratio : 设置Eden和一个Suivior的比例,比如值为5,代表eden占年轻代的空间为5/(5+1+1)=5/7。

总结:

分代收集算法其实是基于上面三个算法,分代收集根据对象存活周期的不同将内存划分为几块。新生代每次垃圾回收都有大批对象死去,所以一般采用复制算法,老年代则因为对象存活率高,没有额外空间为它进行分配担保,就必须采用标记-清理或者标记-整理算法来进行回收。

 

© 著作权归作者所有

共有 人打赏支持
s
粉丝 0
博文 9
码字总数 6292
作品 0
广州
javascript 垃圾回收算法了解一下

我们通常理解的 javascript 垃圾回收机制都停留在表面,"会释放不被引用变量内存",最近在读《深入浅出node.js》的书,详细了解了下 v8 垃圾回收的算法,记录了一些学习笔记。 敲黑板:v8引擎...

程序员解决师
06/12
0
0
GC垃圾回收算法

什么是GC垃圾回收呢。日常生活中我们去餐厅吃饭吃完饭,吃完饭走了餐具不用管,服务员在把餐具拿走,这是一种方式,服务员怎么知道他要来把餐具拿走呢,因为你走了,这个位置空了。服务员什么...

分享达人
2016/04/10
0
0
JVM调优总结(2):基本垃圾回收算法

可以从不同的的角度去划分垃圾回收算法: 按照基本回收策略分 引用计数(Reference Counting): 比较古老的回收算法。原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数。...

serenity
2016/04/05
3
0
技术晨读_20160217

技术导读 Build a RESTful API with Martini 使用martini搭建一个Restful API,使用的是简易的内存database,搭建了一套支持json和xml的RESTFUL的API http://0value.com/build-a-restful-API...

王二狗子11
01/07
0
0
JVM调优总结(2):基本垃圾回收算法

来源: pengjiaheng 链接:http://pengjiaheng.iteye.com/blog/520228 可以从不同的的角度去划分垃圾回收算法: 按照基本回收策略分 引用计数(Reference Counting): 比较古老的回收算法。原...

Alson清
2016/09/29
3
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

nginx模块学习六 add_header 跨域访问

语法 Syntax: add_header name value [always];Default: --Context:http,server,location,if in location 例:/etc/nginx/conf.d/default.conf server {    listen       80; ......

Romanceling
今天
0
0
SpringBoot初探

#SpringBoot初探 三种创建SpringBoot项目的方式: 第一种:使用IDEA创建maven项目,选择maven-archetype-quickstart; 第二种:使用IDEA创建Spring Initializer,选择web组件; 第三种:使用...

向码而生
今天
2
0
IO

JAVA中IO技术:BIO、NIO、AIO 1、同步异步、阻塞非阻塞概念 同步和异步是针对应用程序和内核的交互而言的。 阻塞和非阻塞是针对于进程在访问数据的时候,根据IO操作的就绪状态来采取的不同方...

DemonsI
今天
0
0
org.apache.commons 常用工具类

一. org.apache.commons.io.IOUtils closeQuietly 关闭一个IO流、socket、或者selector且不抛出异常。通常放在finally块。 toString 转换IO流、 Uri、 byte[]为String。 copy IO流数据复制,...

sprouting
今天
0
0
linux使用Inotify监控目录或者文件状态变更

基本概念: Inotify 是一个 Linux特性,它监控文件系统操作,比如读取、写入和创建。Inotify 反应灵敏,用法非常简单,并且比 cron 任务的繁忙轮询高效得多。 需求: 1.有一个文件采集进程,...

mickelfeng
今天
0
1

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部