JVM 内存回收与内存的分配

我们从下面的三件事情开始今天的探讨 

1、哪些内存需要回收

2、什么时候进行回收

3、如何进行回收

我们对内存进行回收,我们就要先知道哪些东西可以被我们进行回收,那就是要回收那些已经死去的对象。

 

如何判断对象已经死去

1、采用 引用计数法

我们对我们在一个地方对对象进行引用的时候,计数器的值就 +1 ,当引用失效的时候进行减一,当计数器为0的时候默认他是可以被回收的对象。

缺点:如果两个都失去引用的对象之间存在互相引用,即他们已经不存在任何引用,但是他们的计数器依旧不为0;

如下

A a = new A();   B  b = new B();   a.conf = b;   b.conf = a;  a= null;  b= null;

2、采用 可达分析法(根搜索算法)

我们判断一个对象是否为存活对象就判断他是否有跟 GC Roots 存在引用链,如果有就是存活,没有就凉凉。

 

什么是GCRoots呢

1、虚拟机栈即栈帧中的本地变量表中的引用的对象。

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

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

4、本地方法栈中的引用对象。

 

在我们判断对象为不可达对象的时候,是否就代表该对象为死亡对象呢

不是的,他会进行如下的步骤。

步骤:

1、被判断为不可达对象。

2、判断该对象有没有执行 finalize 的机会。(判断条件:1、查看该对象是否执行过 finalize方法。2、查看该对象有没有覆盖finalize方法)

3、被判断为有机会的对象,就会进如 队列当中

4、在排队进行 finalize的对象,在过不久的时间会在一次进行一次 Gc 。

 

我们上面默认讲的都是堆中的内存回收,那么方法区是否会进行回收呢

会的,只是方法区的回收率相对较为低下。

回收内容

1、废弃的常量

回收条件:

如我们定义了 “abc” 这个常量,并且该常量在其他地方没有引用了这个字面量,这个时候就会发生内存回收。

2、无用的类

回收条件:

(1)该类的所有实例都被回收了,也就是在堆中不存在该类的任何实例。

(2)加载该类的ClassLoader 已经被进行回收。

(3)该类对应的 Class 对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。 

 

在知道了,何种对象可以被进行回收,那么我们通过何种方式来进行回收的呢

1、标记清除算法

(1)对那些被我们判定为可回收的对象进行标记

(2)进行回收 

缺点:(1)效率问题,标记和清除的过程效率不高。(2)清除后会出现大量的内存碎片,导致大对象无法存储,而导致Gc。

2、复制算法

将我们的内存划分为三块区域,默认为 一块 Eden 区域 两块 survivor 区域。这两块也被成为 from 和 to 这两个名字。

过程: 我们将我们新出生的对象存放到 Eden 区 和 一块 survivor 区域,每当进行一个 Gc 的时候,就会把 这两块区域的存活对象移到一块 survivor 区域当中,在将原本的两块的内存清空。如果最后一个survivor内存不足,这时候会出现两种情况:

(1)判断是否有设置分配担保,如果有就把内存移到老年代,没有的情况下 FullGC 

(2)如果设置了内存担保就会进入老年代,在进行判断老年代的大小是否满足,如果不满足就会进行一次 FullGC,相反就是为 MinorGC

3、标记整理算法

出现的原因:

复制算法就是使用浪费一部分的内存来进行使用的,但是有一个问题是,当我们想要清理的内存中,该内存的存放区域的存活率较高。所以复制算法并不合适,如老年代就类似该内存。

过程:将存活的对象都向一端进行移动,然后直接清理掉端边界以外的内存。

4、分代收集算法

如上面标志整理算法我们可以得知,所有内存使用相同的方法并不合适,所以建议在 新生代采用复制算法,在老年代使用标志整理算法。

 

在上面出现的 Full GC 与 MinorGc 的区别

MinorGc:指发生在新生代的垃圾收集动作,因为java 对象大多都具备朝生夕灭的特征,所以这种回收发生得非常频繁,一般回收速度也比较快。

MajorGc/FullGc: 指发生在老年代的Gc,出现这种垃圾回收,经常伴随着出现至少一次的 Minor Gc。

 

对象优先分配在Eden区域

在大多数情况下,对象在新生代 Eden 区中分配。当没有足够的空间进行分配时,虚拟机将发起一次 Minor Gc。

-XX:+PrintGCDetails   打印垃圾回收日志。

 

大对象直接进入老年代

 -XX:PretenureSizeThreshold  设置当对象大于或等于某个数值的时候直接进入老年代当中。

 

长期存活的对象进入老年代

-XX:MaxTenuringThreshold  设置经过多少次Gc 该对象如果还存活就会进入老年代当中。

 

动态对象年龄判定

如果在survivor 空间当中相同年龄所有对象大小的总和大于survivor的一半,就会直接进入 老年代当中

 

空间分配担保

-XX:HandlePromotionFailure 设置是否进行老年代担保。

如果最后一个内存不足,这时候会出现两种情况:

(1)判断是否有设置分配担保,如果有就把内存移到老年代,没有的情况下 FullGC 

(2)如果设置了内存担保就会进入老年代,在进行判断老年代的大小是否满足,如果不满足就会进行一次 FullGC,相反就是为 MinorGC

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值