java垃圾回收(GC)

java和c++最大的不同点之一即中无需程序员去关注程序的内存管理,因为jvm提供了垃圾回收机制来保证内存的管理和回收。

 

jvm如何确定回收对象

引用计数法:

该方法当前jvm并未采用,仅作简单介绍,类似于c++智能指针,提供对象的引用计数器判断对象是否活跃,但是无法解决两个对象循环引用问题。

可达性分析算法:

通过判断对象的引用链是否可达来决定对象是否可以被回收。可达性分析算法是从离散数学中的图论引入的,程序把所有的引用关系看作一张图,通过一系列的名为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连(就是从 GC Roots 到这个对象不可达)时,则证明此对象是不可用的,然后对此对象进行标记。
 注:注意的是被判定为不可达的对象不一定就会成为可回收对象。被判定为不可达的对象要成为可回收对象必须至少经历两次标记过程,如果在这两次标记过程中仍然没有逃脱成为可回收对象的可能性,则基本上就真的成为可回收对象了。

 

jvm会在什么时候进行垃圾回收的动作

  1.  会在cpu空闲的时候自动进行回收
  2.  在堆内存存储满了之后
  3.  主动调用System.gc()后尝试进行回收 

 

jvm如何进行垃圾回收

常见垃圾回收算法有四个:标记-清除算法,复制算法,标记-整理算法,分代收集算法.。当前主流使用的是分代收集。

标记-清除算法:标记存活的对象,把未标记的回收。回收后内存不是连续的,会产生大量的不连续的碎片,标记对象的时候效率低。

复制算法:会把内存分为相同的2个部分,每次回收,会把存活的对象移动到另一边,回收当前使用的空间。分配的内存被分成2份,实际使用空间变成正常的一半。但是不会出现垃圾碎片。

标记-整理算法:会把存活的对象移动到一起,清除边间外的垃圾对象,效率低

分代收集算法

java中,堆区分为老年代和新生代,新生代又分为Eden区、Survivor0区和Survivor1区(分配比例8:1:1)

当对象去堆区申请资源时:

  1. 若Eden区空间足够,则对象在Eden区中生成
  2. 若Eden区满,则触发Young GC,进行垃圾回收,此时将Eden区存活对象复制到Survivor0区,然后清空Eden区,为后续新的对象分配内存。
  3. 当Survivor0区也满了时,则将Eden区和Survivor0区存活对象复制到Survivor1区,然后清空Eden区和Survivor0区。此时Survivor0区为空,交换S0区和S1区身份,即让S1区为空。
  4. 若Survivor01区也不足以存放Eden区和Survivor0区的存活对象时,就将存活对象直接存放到老年代。如果老年代也满了,就会触发一次FullGC,即新生代、老年代都进行回收。

注意新生代发生的GC也叫做MinorGC,MinorGC发生频率比较高,不一定等 Eden区满了才触发。而新生代触发Young GC是当Eden区满了才触发。

关于老年代:老年代存放的都是一些生命周期较长的对象,就像上面所叙述的那样,在新生代中经历了N次垃圾回收后仍然存活的对象就会被放到老年代中。此外,老年代的内存也比新生代大很多(大概比例是1:2),当老年代满时会触发Major GC(Full GC),老年代对象存活时间比较长,因此FullGC发生的频率比较低。  

 

 

转载文章:https://blog.csdn.net/qq_41946216/article/details/131201057

 

posted @ 2023-08-16 20:31  _Explosion!  阅读(27)  评论(0编辑  收藏  举报