Java3:垃圾回收

垃圾回收

什么是堆内存?

什么是垃圾?

有哪些方法回收这些垃圾?

什么是分代回收机制?

回收算法主要做 2 件事情:

       (1)发现无用的对象

          (2)  回收被无用对象占用的内存空间

所谓“垃圾”,就是指所有不再存活的对象。常见的判断是否存活有两种方法:引用计数法和可达性分析。

1.如何发现无用的对象

引用计数算法: 
      教科书中判断一个对象是否存活的办法:给每一个对象添加一个引用计数器,每当有一个地方引用他的时候,计数器的值就加1,当引用失效的时候,计数器的值就减1;任何时候计数器都为0的对象就是不可能再被使用的,但是它没有办法解决对象之间互相引用的问题,这样引用计数法就没有办法通过GC收集器回收他们 
可达性分析(根搜索算法)
通过一系列的名为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索所有的路径称为引用链,当一个对象到 GC roots没有任何引用链相连(也就是GC Roots到这个独享不可达的时候),就证明此对象是不可用的,所以他们会被判定为可以回收的对象 
可以作为GC Roots的对象包括下面的几种: 
虚拟机栈(栈帧中本地变量表中引用的对象)、方法区中类静态属性引用的对象、方法区中常量引用的对象、类的静态属性引用的对象

 

2.常见的垃圾收集算法 
 

1.标记-清除算法 
      标记 - 清除算法是从根集进行扫描,对存活的对象进行标记,标记完毕后,再扫描整个空间中未被标记的对象,进行回收。该方法不移动对象,仅仅回收未标记的对象,在存活对象较多的情况下效率极高。但是这个算法也容易产生内存碎片,过多的内存碎片会导致为大对象分配空间时无法找到足够的空间,而触发新一次的垃圾收集动作。
      缺点;   效率低 、会产生大量的不连续的内存碎片 导致以后的程序运行过程中需要分配较大的对象的时候无法找到足够的内存而不得不提前触发另一次的垃圾收集动作。 
2.复制算法 
      将内存按大小容量划分为可以使用的两块,每次只使用其中的一块,当一块的内存用完了,就将还存活着的对象复制到另一部分,直接清除掉之前的那部分。 
缺点:将内存缩小为了原来的一半

现在的商业模式都采用复制算法来回收新生代,新生代中98%的对象都是朝生夕死的,所以不需要按照1:1的比例来划分空间,而是将内存分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden的其中的一块Survivor,当回收的时候将Eden中和Survivor中还存活着的对象一次性的拷贝到另外一块Survivor上(当Survivor不够用的时候,需要依赖老年代进行担保分配内存),最后清理掉原来的两块空间。 
3.标记整理算法 
       标记 - 整理算法在标记阶段与标记 - 清除算法一致,但是为了解决内存碎片的问题,在完成标记后,并不直接清理未标记的对象,而是将存活的对象都向一端移动,然后清理掉存活对象端边界以外的内存。一般在这种算法的实现中,都增加了句柄和句柄表,也造成了一定的开销。
4.分代收集算法 
将java 堆分为新生代和老年代,新生代采用复制算法 老年代采用 标记清除或者标记整理算法

(3)内存分配与回收策略 
对象的内存分配:就是在堆上分配 
大多数情况下,对象在新生代的Eden分配,如果没有足够的内存,将进行一次minor GC(从新生代空间(包括 Eden 和 Survivor 区域)回收内存被称为 Minor GC) 
大对象直接进入老年代 
长期存活的对象将进入老年代(可以通过对象年龄计数器判断对象的年龄)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值