JVM---对象存活判断、垃圾收集算法、垃圾收集器以及内存分配策略

一.对象是否存活判断

1.引用计数法

给对象添加引用计数器,一个地方引用它计时器值+1;当引用失效,计数器值-1;计数器为0的对象表示对象不可能引用。
缺陷:难以解决对象之间循环引用的情况

objA = objB;
objB = objA;

除此之外,这两个对象再无任何引用,但由于按照引用计数法他们的计数值都不为0,故不能被GC收集。

2.可达性分析算法

这个算法的基本思路是:通过一些系列"GC Roots“的对象作为起始点,从这些节点向下搜索,搜索走过的的路径称为”引用链"。当一个对象与GCRoots之间不存在一条引用链时,即它不可达GC_Roots,则它会被判定为可回收的对象。

根据图论理解:那些可以被回收的对象不存在一条路径到达GC_Roots。

GC_Roots对象可以是:

1.虚拟机栈(栈帧中的本地变量表)中引用的对象
2.方法区中类静态属性引用的对象
3.方法区中常量引用的对象
4.本地方法栈中JNI(即一般说的Native方法)引用的对象

关于引用

在JDK1.2之后,java对引用的概念进行扩充,将引用分为:强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Week Reference)、虚引用(Phantom Reference)。并提供相应的类用来实现我们的引用。

强引用:

指在程序代码中普遍存在的,类似“Object obj = new Object()”这样的引用,只要强引用还在,GC就不会回收该对象。

软引用:

用来描述一些有用但非必须的对象,对于软引用关联的对象,在系统将要发生内存溢出异常之前,将会把这些对象后列进回收范围之中进行第二次回收。如果这次回收还没有足够内存,才会抛出OOM。

弱引用:

用来描述非必须对象,但是它比软引用更弱一些,被弱引用关联的对象只能活到下一次GC发生之前。当GC时,无论内存是否足够,都会回收该对象。

虚引用:

也称为幽灵引用或幻影引用,它是最弱的一种引用关系。虚引用的存在,不会对对象的存活时间构成影响,但也不能通过虚引用实例化该对象。为该对象设置虚引用的唯一目的是:在该对象被GC回收时收到一个系统通知。

生存还是死亡

在可达性分析算法中那些不可达的对象,也并非是"非死不可",这时候它们处于"缓刑"阶段。真正宣告一个对象死亡,至少要经历两次标记过程:
在可达性分析过程中不可达的对象,会被标记一次,并且进行筛选,筛选条件:是此对象是否有必要执行finalize()方法。

当对象没有覆盖finalize()方法,或者finalize()方法被虚拟机调用过,则虚拟机会视为"没有必要执行"。

对于有必要执行finalize()方法的对象,将会把这个对象放入F-Queue队列中,并在稍后由一个虚拟机自动建立的、低优先级的Finalizer线程去触法它的finalize()方法,(但虚拟机并不承诺会等待这个方法执行结束,这样做的原因是由于一个对象的finalize()方法里面可能进行了耗时操作,从而导致F-Quene队列等待时间过长,甚至导致GC崩溃)在这个方法中对象可以进行自救,只要在该方法内把对象引用与GC_Roots上任意一个结点关联起来就会使它自救成功。它会在第二次标记时从"即将回收"的集合移除,如果此时自救失败,那对象基本上会被回收掉。

一个对象 finalize()方法只能调用一次,即第一次可以帮助对象逃离,但第二次就会失效。并且此方法的缺点是:使用需要高昂的运行代价,不确定性大,无法保证各个对象的调用顺序。
finalize()能做的工作,可以被try-finally或其他方式做的更好、更及时。

二.垃圾收集算法

1.标记-清除算法

分为
标记阶段:标记出所有需要回收的对象
清除阶段:在标记完成后,统一进行回收所有被标记的对象。
不足:效率慢,标记和清除两个过程的效率都不高;空间碎片化,标记-清除后会产生大量不连续的内存碎片,会导致以后程序运行过程中需要给分配一个比较大的对象时,找不到一块足够大的连续内存分配给它,从而不得不提前触发一次垃圾收集操作。

2.复制算法

复制算法的出现是为了解决上面存在的效率问题。
思想:将内存分为等大的两块,每次只用一块,当这一块用完时,就将还存活的对象复制到另一块上面,然后把满了的这块内存清理掉。
优点:实现简单,运行高效
不足:牺牲了一般的内存

发展:考虑到新生代的对象98%都死是"朝生夕死"的特性,将内存分为一个较大的Eden空间和两个较小的Survivor空间,每次使用Eden空间和其中一个Survivor,回收时将上述两部分内存上还存活的对象,复制到没使用的Survivor上,然后清理之前使用的那两块内存。
HotSpot虚拟机默认Eden和Survivor空间比例8:1。即每次可以使用80%+10%的内存,用10%的内存来存储最终存活的对象。但是,我们没有办法保证每次回收存活对象占用内存不多于10%,当Survivor内存不够用时,需要依赖

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值