垃圾收集器与内存分配策略

上面时候对象才叫做死去了?
两个最主要的方法:引用计数算法和根搜索法。 引用分为强引用,软引用,弱引用,虚引用,这四种引用强度一次逐渐减弱。

实际操作中是怎么处理的呢?
首先使用根搜索法对堆中对象进行第一次标记,如果没有与根对象相连,那么就把他们进行标记出来,并进行一次筛选,帅选的条件是此对象是否有必要执行finalize()方法。当对象没有覆盖finalize方法,或者finalize()方法已经被虚拟机调用过,虚拟机将这两种情况都视为“没有必要执行”。
如果这个对象被判定为有必要执行finalize方法,那么这个对象就会被放置在一个名为F-Queue队列之中,并在稍后有一条虚拟机自动建立的,低优先级的Finilize线程去执行。这里所谓的执行是指虚拟机会触发这个方法,但并不承诺会等待它执行结束。这样做的原因是,如果一个对象在finalize方法中执行缓慢,或者发生了死循环,将很可能会导致F-Queue队列中的其他对象永久处于等待状态,甚至导致整个内存回收系统崩溃。finalize方法是对象逃脱死亡命运的最后一次机会,稍后GC将对F-Queue中的对象进行第二次小规模的标记,如果对象要在finalize中成功的拯救自己,只要重新与引用链上的任何一个对象建立关联即可,譬如把自己赋值给某个变量或对象的成员变量,那么第二次标记时它将被移除出“即将回收”的集合;如果对象这时候还没有逃脱,那它就真的离死不远了。

回收方法区,类需要同时满足3个条件才能算是无用的类:
1类所有的实例都已经被回收;2加载该类的classloader已经被回收;3该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

垃圾回收的三个方法:
1标记清除算法
2复制算法
3标记整理算法

垃圾收集器,对应新生代和永久代使用不同的垃圾回收方法。

内存分配与回收策略:
1对象优先在Eden分配;
2大对象直接进入老年代,大对象是指,需要大量连续内存空间的java对象。最典型的就是很长的字符串及数组。
3长期存活的对象将进入老年代。VM给每个对象一个Age计数器,经过一次Minor GC仍活着就+1,达到某个阈值就进去;
4动态对象年龄判定。为了能更好的适应不同程序的内存状况,虚拟机并不总是要求对象的年龄必须达到MaxTenuringThreshold才能晋升老年代,如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无需等到MaxTenuringThreshold中要求的年龄。
5空间分配担保。在发生Minor GC时,虚拟机会检测之前每次晋升到老年代的平均大小是否大于老年大的剩余空间大小,如果大于,则改为直接进行一次Full GC,如果小于,则查看HandlePromotionFailue设置是否允许担保失败;如果允许,那只会进行Minor GC;如果不允许,则也要改为进行一次Full GC。

最后大致讲述一下整体流程

我们首先要明确,根据分代收集算法,我们的java堆被分为新生代和老年代(他们的特点不同,一个朝生夕死,一个相对稳定)。新生代又被进一步的细分,分为一个eden区和2个survivor区。一般情况下,我们制定他们的内存大小比例为8:1:1。根据survivor这个英文单词的含义,我们就大致可以猜出他们主要用来存放幸存者。

垃圾收集器与内存分配策略_第1张图片
1.png

你可能感兴趣的:(垃圾收集器与内存分配策略)