说一下java的垃圾回收机制

     它使得java程序员在编写程序的时候可以不用考虑对内存的管理,垃圾回收器通常是作为一个单独的级别比较低的线程存在的,在不可预知的情况下对堆中的已经死亡的对象或者长时间没有引用的对象进行清除或回收。程序员是不可以手动调用垃圾回收器对某个对象进行回收的。程序员可以手动的调用System.gc(),通知GC来运行,但是java语言规范并不保证GC一定会运行。

垃圾回收机制可以从三方面来说,也就是Where(运行时的内存分布情况),when(对象何时被回收的),how(怎样进行回收的);

首先说一下jvm的内存的布局:在上篇博客中已经详细介绍(jdk1.7与1.8的区别)

然后就是 对象何时需要被回收的?也就是何时回收无效对象,已死对象的? 这里涉及到两种做法:引用计数法和可达性分析算法。这里还涉及到 java 中 4 种引用方式(上篇博客中已有说明)引用强度越弱,越容易被垃圾回收

引用计数法:给对象添加一个引用计数器,每当有一个对象引用他,计数器值加1。引用失效时,计数器的值就会减一,任何时刻计数器为0的对象就是不可能再次被使用的。但是它很难解决对象之间相互引用的问题。

可达性分析算法:通过一系列作为“GCROOTS”的对象作为起始点,从这些节点向下搜索,当一个对象GCROOT不可达的时候,就证明此对象是不可达的。可作为GCROOT的对象:

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

2.方法区中类静态属性引用的变量

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

4.本地方法栈中JNI(Native)方法引用的对象

最后就是对象是怎样被回收的?这里涉及四种垃圾回收算法

标记清除算法:首先标记出需要进行回收的对象,然后标记出需要回收的对象,标记完成后统一进行回收。这种算法有两个不足之处,一个是效率问题:标记和清除两个过程的效率都是非常低的。第二个就是造成了空间的碎片化,导致以后在程序运行过程中需要分配大对象的时候,无法找到足够的连续内存而提前触发垃圾回收动作

复制算法:原本是将内存按照容量分为大小相等的两块,每次只是使用其中的一块,当这一块内存用完之后,然后将存活的对象复制到另外一块内存上去,然后把已使用过的内存空间清理掉。但是由于新生代中的对象大多数生命周期段,因此并不需要按照1:1来进行内存空间的分配,而是将内存空间分成一块较大的Eden区和两块较小的survior区,每次只使用一块Eden区和一块survior区,回收时将其中还存活的对象一次性复制到另一块survior区,清理掉刚才的死去的对象。Hotspot虚拟机默认8:1,也就是新生代90%空间都是可用的。但是当10%不足以存放存活的对象时,就要依赖其他内存(老年代)进行分配担保。这种算法缺点是:对象存活率较高时,需要进行大量的复制操作。并且需要额外空间来分配担保

标记整理算法:根据老年代的特点提出的一种算法,和标记回收算法标记过程一样,但是在回收的过程中并不是直接对可回收对象进行清理,而是让所有存活的对象向一端移动,然后清理掉边界以外的内存。

分代收集算法:根据对象的存活周期不同将内存划分成几块,新生代每次都有大量的对象死去,因此采用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象的存活效率比较高,没有额外的空间对他进行分配担保,就必须使用标记整理或者标记清除算法。



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值