`
fly_ever
  • 浏览: 153123 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JVM垃圾回收

    博客分类:
  • java
阅读更多

JVM垃圾回收算法和垃圾收集器

 

一: JVM 垃圾回收算法

         

     根搜索算法:

     程序把所有的引用节点看做一张图,从一个节点GC Root开始,寻找对应的引用节点,直到所有的引用节点寻找完毕,剩下的即被没有引用的节点,可以被回收。

      可以当做GC Root的对象有如下四种:

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

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

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

      4,本地方法栈(Native栈)中引用的对象

 

根据根搜索算法,找出内存中存在的垃圾并进行回收,JVM提供了四种垃圾回收算法:

         

1,复制算法

          把内存分为大小相等的From和To两块,每次只使用其中一块From,当From被占满,则把From中的存活对象复制到To,同时释放From中的所有内存。

          由于在实际程序运行时,有98%的对象生命周期非常短暂,创建之后很快就被回收了,因此用于存储可存活对象的空间可以小一些。现在的JVM是把新生代内存分为一个较大的Eden和两个大小相等的较小的Survivor内存区,每次只使用Eden和其中一个Survivor区。

         复制算法不产生碎片,但是浪费空间,始终有一个区域是空余的。

 

2,标记-清除算法

         算法有两个阶段:标记和清除。

         容易产生大量碎片,会出现即时内存足够的情况下,因为没有够大的连续内存空间,导致会触发一次垃圾回收动作。

 

3,标记-整理算法

         算法有两个阶段:标记和整理。

         在每次标记出需回收的内存后,把存活的对象都移动到内存的一端。解决了标记-清除算法产生大量碎片的问题。

 

4,分代收集算法

          根据对象的存活周期不同,把Java堆内存分为新生代和年老代两个部分。新生代由于只有少量对象能存活下来,复制成本低,可以使用复制算法。年老代由于对象的生命周期长,因此采用标记-整理或标记-清除算法。

 

 

二: JVM垃圾收集器

 

       Java堆内存划分了新生代和老年代两部分,Java虚拟机也提供了几种不同的垃圾收集器,这些垃圾收集器在堆内存中搭配使用。


 

1,串行垃圾收集器(Serial Collector)

      串行收集器组合(Serial + Serial Old);

      Serial 收集器使用复制算法,单线程执行收集任务,在执行垃圾收集任务时,必须暂停当前的所有工作线程,适合于单核处理器平台。是目前JVM在Client模式下新生代默认的垃圾收集器。

      Serial Old收集器是Serial收集器在老年代的版本,也是单线程收集器,使用标记-整理算法。是目前JVM在Client模式下老年代默认的垃圾收集器。

      可通过参数设置:-XX:+UseSerialGC  使用串行垃圾收集器

 

2,ParNew垃圾收集器

      串行垃圾收集器的多线程版本。JVM在Server模式下新生代默认的垃圾收集器

 

3,Parallel Scavenge 垃圾收集器

      使用复制算法,也是一个多线程垃圾收集器,致力于达到高吞吐量的目的,是高吞吐量优先的垃圾收集器。自适应调整策略是ParNew和Parallel Scavenge的最大区别。

       可通过参数设置:

       -XX:-UseParallelGC  新生代使用并行清除的垃圾收集器

       -XX:MaxGCPauseMillis=n   设置垃圾收集最大暂停时间
       -XX:GCTimeRation=n   大于0小于100的整数,程序运行时间占总时间的比例。公式为1/(1+n),默认值为99,即垃圾收集运行最大1%的时间

       -XX:+UseAdaptiveSizePolicy 打开该开关,则自动指定新生代内存大小,以及其中Eden区和Survivor区的比例,虚拟机会根据当前系统性能监测情况,动态调整这些参数,以达到最大的吞吐量。这种方式叫做GC自适应调整策略。

 

 

4,Parallel Old垃圾收集器

      是Parallel Scavenge收集器的老年代版本,使用标记-整理算法。

      -XX:-UseParallelOldGC 新生代和老年代使用并行清除的垃圾收集器(与该参数-XX:-UseParallelGC同步启用)

 

5, CMS(Concurrent Mark Sweep)垃圾收集器

     CMS致力于获取最短的垃圾收集停顿时间,在多处理器平台上,能使垃圾收集工作和用户线程同时工作。是一种老年代垃圾收集器,使用多线程的标记-清除算法。官方强烈建议使用G1收集器来代替CMS收集器。

     CMS工作过程分为四个阶段:初始标记,并发标记,重新标记,并发清除。其中初始标记和重新标记需要暂停所有的工作线程。

     初始标记:这个阶段,虚拟机需要停顿所有正在执行的任务,STW(Stop the World)。从GC Root对象开始,只扫描跟GC Root对象直接关联的对象,并做标记,这个过程虽然STW,但是很快就能完成。

     并发标记:这个阶段,是在初始标记之后关联的对象上继续向下追溯标记。与应用程序并发执行,不会STW。

     重新标记:这个阶段,虚拟机会STW,为了修正并发标记期间因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录。

     并发清除:清理垃圾对象,并发执行。

     CMS收集器有以下三个不足:

     a, 对CPU资源非常敏感,默认启动的垃圾收集线程数:(CPU个数+3)/4。

     b, 无法处理浮动垃圾,可能导致Concurrent ModeFailure而导致另一次GC,浮动垃圾是指即在并发清除过程中工作线程产生的垃圾,需要等到下一次GC才能清除掉。

            Concurrent ModeFailure 是指CMS在GC时,需要在老年代预留一部分空间供并发工作时使用,如果在GC时,预留的空间不够分配,则会出现Concurrent ModeFailure,此时虚拟机会启用预备方案,使用Serial Old收集器进行垃圾回收。

      c, CMS是基于标记-清除算法,因此会产生大量的垃圾碎片。当无法找到一个足够大的连续区域存放对象时,会触发一次Full GC。

 

     可通过参数设置:

      -XX: +UseConcMarkSweepGC   使用CMS垃圾收集器。

      -XX:CMSInitiatingOccupancyFraction=70  是指内存占用达到该比例70%时启动CMS进行垃圾回收。

      -XX:+UseCMSCompactAfFullCollection  默认启用,在每次Full GC后,进行内存压缩整理。

      -XX:CMSFullGCBeforeCompaction 默认值为0,是指在CMS Full GC多少次后,进行内存压缩整理。与参数UseCMSCompactAfFullCollection  配合使用。

 

6,G1(Garbage-First)垃圾收集器

       G1致力于在高吞吐量和短的停顿时间这两者取得一个最好的平衡。G1全面支持JDK7 Update4及后续版本,主要用于内存大,多处理器的机器。

       在Java 9之后,G1已经取代CMS成为默认的垃圾收集器。

       G1有两个最突出的改进:

       a,基于标记-整理算法,不产生碎片

       b,可以非常精确的控制停顿时间,可以在不牺牲吞吐量的前提下,实现短的停顿时间进行垃圾回收。

 

        G1收集器避免全区的垃圾回收,它把堆内存划分为几个大小固定的独立区域,并且跟踪这几个区域的垃圾收集进度,同时在后台维护一个优先级列表,每次根据所允许的垃圾收集时间,优先回收垃圾最多的区域。

       可通过参数设置:

       -XX:+UseG1GC  使用G1垃圾收集器

 

三: Java四种应用类型的垃圾回收方式

1,强引用:

       强引用不会被GC回收。

2,软应用:

       如果内存空间不足了,就会回收这些对象的内存软引用可用来实现内存敏感的高速缓存

3,弱引用:

       弱引用与软引用的区别在于:垃圾回收器一旦发现了弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些弱引用的对象

方法isEnQueued(); // 返回是否被垃圾回收器标记为即将回收的装状态
弱引用主要用于监控对象是否已经被垃圾回收器标记为即将回收的垃圾,可以通过弱引用的isEnqueued方法返回对象是否被垃圾回收器标记。
4,虚引用:
      虚引用必须和引用队列(ReferenceQueue)联合使用,虚引用可以用来做一些精细的内存控制操作。
你声明虚引用的时候是要传入一个queue的。当你的虚引用所引用的对象已经执行完finalize函数的时候,就会把对象加到queue里面。你可以通过判断queue里面是不是有对象来判断你的对象是不是要被回收了。
虚引用主要用来跟踪对象被垃圾回收的活动。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。程序如果发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动
关于PhantomReference有以下几点需要注意:
1 the PhantomReference.get() method always returns null
2 another difference is that the PhantomReference is enqueueed only after the finalize() method has been called.
If you want the reference to be added to the reference queue, you have to keep a strong reference to the Phantom reference.(这一点很重要,为了保持phantom reference被回收后,添加到reference queue中,必须有一个strong reference 引用到这些phantom reference)
当phantom reference 被enqueue到队列时,phantom reference引用的referent已经在内存中删除
 
关注finalize方法
finalize函数最多运行一次

当对象不可达,但是调用finalize之后又变得可达的情况存在,在finalize函数中通过this指针让其他句柄执行本身即可,但是再下次回收时不会再调用finalize,因为只能调用一次。

protected void finalize()

{

     main.ref=this;  // 恢复本对象,让本对象可达

}

finalize函数的调用具有很大的不确定性:
      调用时间不确定——有资源浪费的风险

      可能不被调用——有资源泄漏的风险

在某些情况下,finalize()压根儿不被调用。比如在JVM退出的当口,内存中那些对象的finalize函数可能就不会被调用了。

因此一些清理工作如文件的关闭,连接的关闭等不要放到finalize函数中,要在程序中单独进行管理,一般finalize只做C/C++内存的回收

很多时候,我们认为一个对象的finalize()方法执行过以后,如果对象没有自救,这个对象马上就被垃圾回收了。但是实际不然,有个时间差,要到下次垃圾回收时才会真正回收掉这个对象。

 

四, FullGC的触发条件

 

1,直接调用System.gc();

2,老年代空间不足:

      在新生代的对象转入,以及创建大对象,大数组时可能出现空间不足的情况。

3,永久代空间不足:

      永久代不属于堆空间,也就是方法区。存放的是虚拟机加载的类的元数据信息:如常量,静态变量,即时编译器编译后的代码。

      系统要加载的类,反射的类和调用的方法较多时,会出现空间不足的情况。

4,CMS GC时出现promotion failed和concurrent mode failed:

      promotion failed 是在Min GC时,有对象在survivor放不下而只能放到老年代,而此时老年代的空间不足引起的。

      concurrent mode failed是在CMS GC时,有对象要放入老年代,而此时老年代的空间不足引起的。

5,统计得到MinGC后晋升到老年代的平均大小大于老年代的剩余空间大小。

 

       

 

分享到:
评论

相关推荐

    JVM垃圾回收机制.xmind

    自己学习总结JVM垃圾回收机制的结构图,一起分享!!!

    JVM垃圾回收机制

    我们通过深入探讨以下几个关键点来理解JVM垃圾回收机制的工作原理: 1. 如何确定某个对象是“垃圾”? JVM垃圾回收机制通过两种主要算法来确定对象是否成为垃圾,即“可达性分析算法”和“引用计数法”。 - 可达性...

    深入探索JVM垃圾回收:ARM服务器垃圾回收的挑战和优化.docx

    深入探索 JVM 垃圾回收:ARM 服务器垃圾回收的挑战和优化 JVM 垃圾回收是 Java 内存管理的重要组成部分,其主要职责是自动释放不再被应用程序使用的内存。在现代计算机系统中,内存是一种宝贵的资源,其有效管理...

    JVM垃圾回收器和内存分配策略.zip

    Java虚拟机(JVM)是Java程序运行的基础,它的核心组成部分之一就是垃圾回收器(Garbage Collector, GC),以及内存分配策略。理解这些概念对于优化Java应用性能至关重要。本篇文章将深入探讨JVM的垃圾回收机制以及...

    JVM垃圾回收器工作原理及使用实例介绍Java开发Java

    本文将深入探讨JVM垃圾回收器的工作原理,并通过实例来帮助开发者理解和应用。 1. 垃圾回收概述 - 内存管理:Java中的内存分为堆内存和栈内存,垃圾回收主要针对堆内存。 - 对象生命周期:创建、使用、不再引用...

    JVM垃圾回收艺术

    《JVM垃圾回收艺术——探索Tenured Generation的内涵》 在深入探讨JVM垃圾回收机制的艺术之前,我们先来理解一下“天才”的定义——一种对事业、对工作的极度热爱。JAVA垃圾回收(GC)同样展现出这种对效率和优化的...

    JVM垃圾回收原理

    ### JVM垃圾回收原理详解 #### 一、相关概念与基本回收算法 在深入探讨JVM垃圾回收机制之前,我们先了解几个重要的概念及其工作原理。 ##### 1. 引用计数(Reference Counting) 引用计数是一种较为古老且简单的...

    JVM 垃圾回收(GC)

    理解JVM垃圾回收机制对于优化Java应用性能至关重要。 1. **垃圾回收的基本概念** - **对象生命周期**:在Java中,对象的生命周期包括创建、使用和销毁。当对象不再被引用时,就被认为是“垃圾”。 - **垃圾回收器...

    java jvm垃圾回收

    Java JVM 垃圾回收机制 Java 语言中一个显著的特点就是引入了垃圾回收机制,使 c++ 程序员最头疼的内存管理的问题迎刃而解,它使得 Java 程序员在编写程序的时候不再需要考虑内存管理。垃圾回收机制的意义是防止...

    垃圾回收系列(3):CLR与JVM垃圾回收器的比较宣贯.pdf

    《垃圾回收系列(3):CLR与JVM垃圾回收器的比较》 本文主要探讨了.NET框架中的CLR(公共语言运行库)与Java平台中的JVM(Java虚拟机)在垃圾回收机制上的异同。垃圾回收是现代编程环境中管理内存的重要机制,它可以...

    JVM垃圾回收与调优详解1

    《JVM垃圾回收与调优详解1》 Java虚拟机(JVM)的内存管理和垃圾回收是其性能优化的关键环节。本文主要探讨JVM内存分配、对象回收的判断标准以及垃圾收集算法。 1. JVM内存分配与回收 在JVM中,内存分为新生代、...

    jvm垃圾回收调整.pdf

    在调整JVM垃圾回收参数时,需考虑到应用的特性,如对象生命周期、内存分配模式等。过多的垃圾回收会导致应用暂停,因此合理配置堆大小和GC策略是提升系统响应速度和稳定性的关键。同时,监控JVM的垃圾回收行为,通过...

    JVM垃圾回收,参数,强软弱虚,常见错误OOM,与微服务结合.docx

    "JVM垃圾回收、参数、强软弱虚、常见错误OOM、与微服务结合" JVM垃圾回收是Java虚拟机(JVM)中的一种机制,用于自动回收无效对象所占用的内存资源。垃圾回收机制可以防止内存溢出、提高系统性能和可靠性。 在C/...

    JVM垃圾回收分享(文字在博客)

    【JVM垃圾回收分享】 Java语言的一大亮点是其自动内存管理机制,这使得开发者无需手动管理内存,从而避免了常见的内存泄漏和指针越界问题。这种机制通过垃圾回收(Garbage Collection,简称GC)来实现,确保了程序...

    09 Java基础-JVM垃圾回收-玉峰1

    JVM垃圾回收是其核心功能之一,旨在自动管理内存,避免程序出现内存泄漏或过度消耗导致的性能问题。本节将深入探讨JVM垃圾回收机制以及与之相关的工具和概念。 1. **JVM内存模型** JVM内存分为堆内存和栈内存,...

    jvm垃圾回收机制:.md

    全面概述jvm垃圾回收机制的功能、各部分组成及各部分算法实现

    JVM垃圾回收机制与GC性能调优

    Java虚拟机(JVM)的垃圾回收(GC)机制是Java程序高效运行的关键部分,它自动管理内存,释放不再使用的对象以避免内存泄漏。本文主要探讨JVM堆内存的结构和GC的工作原理,以及如何进行性能调优。 JVM堆是Java应用...

    JVM垃圾回收.jpg

    jvm 垃圾回收思维导图,总结了现有的垃圾回收器的有点以及使用场景、垃圾回收算法以及回收的判断依据。

Global site tag (gtag.js) - Google Analytics