zoukankan      html  css  js  c++  java
  • JVM垃圾回收器理论分析与详解【纯理论】

    继续上次【https://www.cnblogs.com/webor2006/p/10740084.html】的理论继续。。有点吐血的感觉,都不知道学了这么一大堆理论有何实际意义,本身JVM就是个理论体系比较多的东东,所以理论不得不去面对,继续硬着头皮往前进。

    内存结构

    这个在之前的学习中都已经学习过了,复习一下。

    内存分配

    • 堆上分配
      大多数情况在eden【年轻代中的一个区域】上分配,偶尔会直接在old【老年代】上分配,细节取决于GC的实现。
    • 栈上分配
      原子类型的局部变量。

    内存回收

    1、GC要做的是将那些dead的对象所占用的内存回收掉。

    • Hotspot认为没有引用的对象是dead的。
    • Hotspot将引用分为四种:Strong【强引用】、Soft【软引用】、Weak【弱引用】、Phantom【虚引用】,这是大伙熟知的。
      1、Strong既默认通过Object o = new Object()这种方式赋值的引用。
      2、Soft、Weak、Phantom这三种则是继续Reference。

    2、在Full GC时会对Reference类型的引用进行特殊处理。

    • Soft:内存不够时一定会被GC、长期不用也会被GC。
    • Weak:一定会被GC,当被mark为dead,会在ReferenceQueue中通知。
    • Phantom:本来就没引用,当从jvm heap中释放时会通知。

    以上的概念会在未来举例进行代码说明的,先有个印象。

    垃圾收集算法

    以上是一些比较经典的垃圾收集算法,下面会逐个进行说明。

    GC的时机

    1、在分代模型的基础上,GC从时机上分为两种:Scavenge GC和Full GC。

    2、Scavenge GC(Minor GC)

    • 触发时机:新对象生成时,Eden空间满了。
    • 理论上Eden区大多数对象会在Scavenge GC回收,复制算法的执行效率会很高,Scavenge GC时间比较短。

    3、Full GC【这个在实际中一定得要避免】

    • 对整个JVM进行整理,包括Young、Old和Perm。
    • 主要的触发时机:1)Old满了;2)Perm满了;3)system.gc()
    • 效率很低,尽量减少Full GC

    垃圾回收器(Garbage Collector)

    • 分代模型:GC的宏观愿景。
    • 垃圾回收器:GC的具体实现。
    • Hotspot JVM提供多种垃圾回收器,我们需要根据具体应用的需要采用不同的回收器。
    • 没有万能的垃圾回收器,每种垃圾回收器都有自己的适用场景。

    垃圾收集器的“并行”和“并发”

    • 并行(Parallel):指多个收集器的线程同时工作,但是用户线程处于等待状态。
    • 并发(Concurrent):指收集器在工作时同时,可以允许用户线程工作。
      并发不代表解决了GC停顿的问题,在关键的步骤还是要停顿。比如在收集器标记垃圾的时候。但在清除垃圾的时候,用户线程可以和GC线程并发执行。 

    Serial收集器

    • 单线程收集器,收集时会暂停所有工作线程(Stop The World,简单STW),使用复制收集算法,虚拟机运行在Client模式时的默认新生代会采用此收集器。
    • 最早的收集器,单线程进行GC。
    • New和Old Generation都可以使用。
    • 在新生代,采用复制算法:在老年代,采用Mark-Compact算法。
    • 因为是单线程GC,没有多线程切换的额外开销,简单实用。
    • Hotspot Client模式缺省的的收集器

      如图中出现了一个词:“Safepoint”,安全点,在之后会举具体的实例来说明安全点的作用。

    ParNew收集器

    • ParNew收集器就是Serial的多线程版本,除了使用多个收集线程外,其余行为包括算法、STW、对象分配规则、回收策略等都与Serial收集器一模一样。
    • 对应的这种收集器是虚拟机运行在Server模式的默认新生代收集器,在单CPU的环境中,ParNew收集器并不会比Serial收集器有更好的效果。
    • Serial收集器在新生代的多线程版本。
    • 使用复制算法(因为针对新生代)。
    • 只有在多CPU的环境下,效率才会比Serial收集器高。
    • 可以通过-XX:ParallelGCThreads来控制GC线程数的多少。需要结合具体CPU的个数。
    • Server模式下新生代的缺省收集器。

    Parallel Scavenge收集器

    •  Parallel Scavenge收集器也是一个多线程收集器,也是使用复制算法,但它的对象分配规则与回收策略都与ParNew收集器有所不同,它是以吞吐量最大化(既GC时间占总运行时间最小)为目标的收集器实现,它允许较长时间的STW换取总吞吐量最大化。

    Serial Old收集器

    •  Serial Old是单线程收集器,使用标记-整理算法,是老年代的收集器。

    Parallel Old收集器

    • 老年代版本吞吐量优先收集器,使用多线程和标记一整理算法,JVM1.6提供,在此之前,新生代使用了PS收集器的话,老年代除Serial Old外别无选择,因为PS无法与CMS收集器配合工作。【了解既可】
    • Parallel Scavenge在老年代的实现
    • 在JVM1.6才出现Parallel Old
    • 采用多线程,Mark-Compact算法
    • 更注重吞吐量
    • Parallel Scavenge + Parallel Old = 高吞吐量,但GC停顿可能不理想

    CMS(Concurrent Mark Sweep)收集器【特别复杂的一种收集器】

    • CMS是一种以最短停顿时间为目标的收集器,使用CMS并不能达到GC效率最高(总体GC时间最小),但它能尽可能降低GC时服务的停顿时间,CMS收集器使用的是标记-清除算法。
    • 追求最短停顿时间,非常适合Web应用。
    • 只针对老年区,一般结合ParNew使用。
    • Concurrent,GC线程和用户线程并发工作(尽量并发)。
    • Mark-Sweep。
    • 只有在多CPU环境下才有意义 。
    • 使用-XX:+UseConcMarkSweepGC打开。
    • CMS以牺牲CPU资源的代价来减少用户线程的停顿。当CPU个数少于4的时候,有可能对吞吐量影响非常大。
    • CMS在并发清理的过程中,用户线程还在跑。这时候需要预留一部分空间给用户线程。
    • CMS用Mark-Sweep,会带来碎片问题。碎片过多的时候会容易频繁触发Full GC。

    GC垃圾收集器的JVM参数定义

    Java内存泄漏的经典原因

    1、对象定义在错误的范围(Wrong Scope)。

    • 如果Foo实例对象的生命较长,会导致临时性内存泄漏。(这里的names变量其实只是临时作用)
    • JVM喜欢生命周期短的对象,这样做已经足够高效【调整】

      这样一改之后,只要是doIt()方法一结束names的临时变量就立马会被回收。

    2、异常(Exception)处理不当。

    • 错误的做法

      对于有经验的程序员应该不会出现上面的问题,但是这里只是抛出泄漏的场景。
    • 正确的做法

    3、集合数据管理不当。

    • 当使用Array-based的数据结构(ArrayList,HashMap等)时,尽量减少resize:
      a、比如new ArrayList时,尽量估算size,在创建的时候把size确定。
      b、减少resize可以避免没有必要的array copying,gc碎片等问题。
    • 如果一个List只需要顺序访问,不需要随机访问(Random Access),用LinkedList代替ArrayList
      a、LInkedList本质是链表,不需要resize,但只适用于顺序访问。

    以上是对JVM垃圾回收相关理论的整体了解,说实话看完其实头晕晕的,没关系,接下来则会用实践来反证理论。

  • 相关阅读:
    springmvc log4j 配置
    intellij idea maven springmvc 环境搭建
    spring,property not found on type
    intellij idea maven 工程生成可执行的jar
    device eth0 does not seem to be present, delaying initialization
    macos ssh host配置及免密登陆
    centos7 搭建 docker 环境
    通过rest接口获取自增id (twitter snowflake算法)
    微信小程序开发体验
    gitbook 制作 beego 参考手册
  • 原文地址:https://www.cnblogs.com/webor2006/p/10982448.html
Copyright © 2011-2022 走看看