Java刷题知识点之垃圾回收算法过程、哪些内存需要回收、被标记需要清除对象的自我救赎、对象将根据存活的时间被分为:年轻代、年老代(Old Generation)、永久代、垃圾回收器的分类

简介:

哪些内存需要回收

  其实,一般是对堆内存而言的。

 

 

垃圾回收算法过程

  在Java语言中,GC(Garbage Collection)是一个非常重要的概念。它主要是回收程序中不再使用的内存。

  对对象而言,如果没有任何变量去引用它,那么该对象将不可能被程序访问,因此可以认为它是垃圾信息,可被回收。只要有一个以上的变量引用该对象,该对象就不会被垃圾回收。

复制代码
public class Test {
    public static void main(String a) {
    Integer i1 = new Integer (1);
    Integer i2 = new Integer (2);
    i2 = i1;
   }
}
复制代码

  资源i2所占的内存是不可达的。

 

 

(1)引用计数法

  原理:为每个对象配一个计数器,如果这个对象被引用,则计数器加1,计数器为0,则表示该对象没有任何引用指向它。

  缺点:不可达的对象出现循环引用,它的引用计数器均不为0。

 

 

(2)标记清除算法

  原理:先通过根节点标记所有可达对象,然后清除所有不可达对象,完成垃圾回收。

  缺点:会造成空间碎片。  

    ①  标记出所有需要回收的对象。

    ②  标记完成后,统一回收所有被标记的对象。

  缺点是:

    ①:标记和收集的两个过程效率都不高。

    ②:标记清除后会产生大量的不连续的内存空间,空间碎片多了以后就无法分配大块的内存空间给大的对象使用。

 

 

 

 

 

 

  (3)复制回收算法

  原理:将原有的内存空间分为两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存块中,之后,清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收。

  把堆内存分成两个大小相同的区域,在任何时刻,只有其中的一个区域被使用,直到这个区域的被消耗完为止,此时垃圾回收器会中断程序的执行,通过遍历的方式把所有活动的对象复制到另外一个区域中,在复制的过程中它们是紧挨着布置的,从而可以消耗内存碎片。当复制过程结束后程序会紧着运行,直到这块区域被使用完,然后采取上面的方法继续进行垃圾回收。

  优点:可确保回收后的内存空间是没有空间碎片的。同时,在进行垃圾回收的同时对对象的布置也进行了安排,从而消耗了内存碎片。

  缺点:将系统内存折半。对于指定大小的堆来说,需要两倍大小的内存空间,同时由于在内存调整的过程中要中断当前执行的程序,从而降低了程序的执行效率。

  复制算法适合用于新生代,因为新生代存活对象少,垃圾对象多。因为在新生代,垃圾对象通常会多于存活对象,复制算法的效果会比较好。

  

 

 

 

 

 

 

 

 

  (4)标记压缩回收算法

  标记压缩算法是一种老年代的回收算法,老年代大部分都是存活对象。

  它对所有可达对象做了一次标记,然后,将堆中所有的存活对象压缩到堆内存的一端,这样就会在堆中另外一端留出很大的一块空闲区域,之后,清理边界外所有的空间。这种方法既避免了碎片的产生,又不需要两块相同的内存空间。

 

 

 

  (5)增量算法

  如果一次性将所有的垃圾进行处理,需要造成系统长时间的停顿,那么就可以让垃圾收集线程和应用程序线程交替执行。每次垃圾收集线程只收集一小片区域的内存空间,接着切换到应用程序线程,依次反复,直到垃圾收集完成。

  优点:由于在垃圾回收的过程中,间断的执行了应用程序代码,所以能减少系统的停顿时间,但是,因为线程切换和上下文切换的消耗,会使得垃圾回收的总体成本上升,造成系统吞吐量的下降。

 

 

 

  (6)分代回收算法(非常重要)

  根据垃圾回收对象的特性,使用合适的算法回收。比如,新生代使用复制算法,老年代使用标记压缩回收算法。

 

 

 

 

 

 被标记需要清除对象的自我救赎

  标记清除算法是如何解决循环引用的问题呢?

  利用可达性分析。枚举根节点,看根节点与对象是否可达,不可达则判断其可被回收,即便有多个对象循环引用,如果不可达则一样要被回收,从此解决循环引用问题。

  可达性分析(Reachability Analysis),这个算法的思想是通过一系列的称为“GC Roots”的对象作为起点,从这些起点开始往下搜索,搜索走过的路径称为引用链,当一个对象到GC Roots没有任何的引用链,相连接时,则证明这个对象是不可引用的。

  可以作为GC ROOT的对象可以包括以下几种:

    1、虚拟机栈中引用的对象

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

    3、本地方法区中常量引用的变量

    4、本地方法栈中JNI(及一般说的Native方法)引用的对象。

   要注意的是,即使没有通过可达性分析的对象,也并非是“非死不可”。

    第一轮筛选:如果对象在可达性分析中没有于GcROOT链相连,那么就需要进行第二轮筛选

    第二轮筛选:对象有没有覆盖(override)过 finalize()函数,对象是否还没运行过finalize()函数。如果这连个条件都满足,

  那么对象就会判断为有必要执行finalize()函数,并把这个对象放入到一个叫做F-Queue的队列中,

  稍后GC会对这个队列中的对象进行第二次扫描,执行每个对象的finalize()函数,那么如果对象要在这里拯救自己——只要在finalize()函数中让自己重新与GcROOT的任何一个对象建立连接即可。

  譬如把自己(this关键字)赋值给某个类变量或者对象的成员变量,那么在这第二次筛选中就会将这个对象移出出“即将回收”的集合。

 

 

 

 

 

 

 

 

 

对象将根据存活的时间被分为:年轻代、年老代(Old Generation)、永久代

  以下是Java堆内存分配:

 

    (1)年轻代

        对象被创建时,内存的分配首先发生在年轻代(大对象可以直接被创建在年老代),大部分的对象在创建后很快就不再使用,因此很快就变得不可达,于是被年轻代的GC机制清理掉,这个GC机制被称为Young GC。

         注意:Young GC并不代表年轻代内存不足,事实上只表示在Eden区上的GC                      

        年轻代可以分为3个区:Eden(伊甸园,亚当和夏娃偷吃禁果生娃娃的地方,用来表示内存首次分配的区域,再贴切不过了)和2个survivor区。

 

       (2)年老代

        对象如果在年轻代存活了足够长的时间而没有被清理掉(即在几次Young GC后存活了下来),则会被复制到年老代,年老代的空间一般比年轻代要大,能存放更多的对象,在年老代上发生GC的次数也比年轻代少。当老年代内存不足时,将执行Full GC

       如果对象比较大(如大数组),Young空间不足,则大对象会直接分配到年老代上。

 

      (3)永久代

      也就是方法区,主要存储Class信息,和存放对象的堆区不同,GC不会再主程序运行期间对永久代进行清理。如果load很多class,就会有可能出现Permanent Generation space错误。

 

 

 

 

 

  以下是GC机制:

  (1)年轻代

           收集算法:

           1)绝大多数刚创建的对象会被分配在Eden区,其中的大多数对象很快就会消亡

           2)当Eden区满的时候,执行Young GC,将消亡的对象清理掉,并将剩余的对象复制到一个存货区survivor0中(此时survivor1是空白的,两个survivor区总是有一个是空白的)

          3)此后,每次Eden区满了,就执行一次Young GC,并将剩余存活的对象都添加到survivor0中

         4)当survivor0也满的时候,会将其中仍然存活的对象放入survivor1中,如果survivor1放不下,会将多出来的放入年老区中。以后Eden区执行Young GC之后,就将剩余的对象添加到survivor1中(此时survivor0是空的)

         5)当两个存货区切换了若干次(默认为15次)之后,仍然存活的对象将被复制到年老代。

 

        (2)老年代

         老年代存储的对象比年轻代多的多,而且不乏大对象,对老年代进行内存清理时,一般采用标记-整理方法,即标记出仍然存活的对象,将存活对象向一端移动,以保证内存的连续。

         在发生Young GC的时候,虚拟机会检查每次进入老年代的大小是否大于老年代的剩余空间大小,如果大于,则触发一次Full GC。

 

         (3)永久代

         包括常量池中的常量回收、无用的类信息回收。

 

  注意:

          1)Young  GC只收集年轻代的对象,Full GC收集所有堆上的对象,包括年轻代、年老代、永久代的对象

          2)总而言之,就是分代分配、分代回收

          3)System.gc()调用的是Full GC

 

 

 

 

 

 

 

垃圾回收器的分类(非常重要)

   如下

 

 

 

垃圾回收器按分代划分

  新生代串行收集器:

    1.复制算法    2.单线程垃圾回收      3.独占式的垃圾回收(也就是,在串行收集器运行时,应用程序中的所有线程都停止工作,进行等待。Stop the world现象。)

  老年代串行收集器:

    1.标记压缩算法 2.单线程垃圾回收 3.独占式的垃圾回收

并行收集器:

  并行收集器是工作在新生代的垃圾收集器,它只是简单的将串行回收器多想线程化。同时,它也是独占式的收集器。

  新生代并行回收收集器:

    1.复制算法     2.多线程     3.独占式

  老年代并行回收收集器:

    1.标记压缩算法     2.多线程    3.独占式

 

  CMS收集器:它关注系统挺停顿时间。并发标记清除。它可以与用户同时运行,从而降低应用程序的停顿时间。

 

  G1收集器:

  G1收集器是目前最新的垃圾回收器,G1收集器的目标是作为一款服务端的垃圾收集器,它在吞吐量和停顿控制上,预期要优于CMS收集器。

  与CMS收集器相比,G1收集器是基于标记-压缩算法的,因此,它不会产生空间碎片,也没有必要在收集之后,进行一次独占式的碎片整理工作。G1收集器还可以进行非常精确的停顿控制,它可以在开发人员在指定长度为M的时间段中,垃圾回收时间不超过N。


本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/7623016.html,如需转载请自行联系原作者

相关文章
|
9月前
|
存储 Java
课时4:对象内存分析
接下来对对象实例化操作展开初步分析。在整个课程学习中,对象使用环节往往是最棘手的问题所在。
|
缓存 监控 算法
Python内存管理:掌握对象的生命周期与垃圾回收机制####
本文深入探讨了Python中的内存管理机制,特别是对象的生命周期和垃圾回收过程。通过理解引用计数、标记-清除及分代收集等核心概念,帮助开发者优化程序性能,避免内存泄漏。 ####
291 3
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
735 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
算法 Java
JVM进阶调优系列(4)年轻代和老年代采用什么GC算法回收?
本文详细介绍了JVM中的GC算法,包括年轻代的复制算法和老年代的标记-整理算法。复制算法适用于年轻代,因其高效且能避免内存碎片;标记-整理算法则用于老年代,虽然效率较低,但能有效解决内存碎片问题。文章还解释了这两种算法的具体过程及其优缺点,并简要提及了其他GC算法。
 JVM进阶调优系列(4)年轻代和老年代采用什么GC算法回收?
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
631 4
|
Java 测试技术 Android开发
让星星⭐月亮告诉你,强软弱虚引用类型对象在内存足够和内存不足的情况下,面对System.gc()时,被回收情况如何?
本文介绍了Java中四种引用类型(强引用、软引用、弱引用、虚引用)的特点及行为,并通过示例代码展示了在内存充足和不足情况下这些引用类型的不同表现。文中提供了详细的测试方法和步骤,帮助理解不同引用类型在垃圾回收机制中的作用。测试环境为Eclipse + JDK1.8,需配置JVM运行参数以限制内存使用。
143 2
|
存储 Java
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
这篇文章详细地介绍了Java对象的创建过程、内存布局、对象头的MarkWord、对象的定位方式以及对象的分配策略,并深入探讨了happens-before原则以确保多线程环境下的正确同步。
221 0
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
|
算法 Java
JVM进阶调优系列(3)堆内存的对象什么时候被回收?
堆对象的生命周期是咋样的?什么时候被回收,回收前又如何流转?具体又是被如何回收?今天重点讲对象GC,看完这篇就全都明白了。
|
存储 算法 Java
【JVM】垃圾释放方式:标记-清除、复制算法、标记-整理、分代回收
【JVM】垃圾释放方式:标记-清除、复制算法、标记-整理、分代回收
389 2
|
算法 Java
JVM有哪些垃圾回收算法?
(1)标记清除算法: 标记不需要回收的对象,然后清除没有标记的对象,会造成许多内存碎片。 (2)复制算法: 将内存分为两块,只使用一块,进行垃圾回收时,先将存活的对象复制到另一块区域,然后清空之前的区域。用在新生代 (3)标记整理算法: 与标记清除算法类似,但是在标记之后,将存活对象向一端移动,然后清除边界外的垃圾对象。用在老年代
147 0

热门文章

最新文章