关于java:7种jvm垃圾回收器这次全部搞懂

6次阅读

共计 3967 个字符,预计需要花费 10 分钟才能阅读完成。

前言

之前咱们解说了 jvm组成构造 垃圾回收算法 等知识点,明天咱们来讲讲 jvm 最重要的 堆内存 是如何应用 垃圾回收器 进行垃圾回收,并且如何应用 命令 去配置应用这些垃圾回收器。

堆内存详解

下面这个图大家应该曾经很明确了吧。大家就能够了解成一个 房子 被分成了几个 房间,每个房间的作用不同而已,有的是婴儿住的,有的是父母住的,有的是爷爷奶奶住的

  • 堆内存被划分为 两块 ,一块的 年老代 ,另一块是 老年代
  • 年老代又分为 Edensurvivor。他俩空间大小比例默认为 8:2,
  • 幸存区又分为 s0s1。这两个空间大小是截然不同的,就是一对双胞胎,他俩是 1:1 的比例

堆内存垃圾回收过程

第一步

新生成 的对象首先放到 Eden 区,当 Eden 区 满了 会触发Minor GC

第二步

第一步 GC 活下来的对象,会被挪动到 survivor 区中的 S0 区,S0 区满了之后会触发Minor GC,S0 区存活下来的对象会被挪动到 S1 区,S0 区闲暇。

S1 满了之后在 GC,存活下来的再次挪动到 S0 区,S1 区闲暇,这样反反复复 GC,每 GC 一次,对象的年龄就 涨一岁 ,达到某个值后(15),就会进入 老年代

第三步

在产生一次 Minor GC 后(前提条件),老年代可能会呈现Major GC,这个视垃圾回收器而定。

Full GC 触发条件

  • 手动调用 System.gc,会一直的执行 Full GC
  • 老年代空间有余 / 满了
  • 办法区空间有余 / 满了

留神

们须要记住一个单词:stop-the-world。它会在任何一种 GC 算法中产生。stop-the-world 意味着 JVM 因为须要执行 GC 而 进行 应用程序的执行。

当 stop-the-world 产生时,除 GC 所需的线程外,所有的 线程 都进入 期待 状态,直到 GC 工作实现。GC 优化很多时候就是缩小 stop-the-world 的产生。

回收哪些区域的对象

须要留神的是,JVM GC 只回收 堆内存 办法区内 的对象。而 栈内存 的数据,在超出作用域后会被 JVM 主动开释掉,所以其不在 JVM GC 的治理范畴内。

堆内存常见参数配置

参数 形容
-Xms 堆内存初始大小,单位 m、g
-Xmx 堆内存最大容许大小,个别不要大于物理内存的 80%
-XX:PermSize 非堆内存初始大小,个别利用设置初始化 200m,最大 1024m 就够了
-XX:MaxPermSize 非堆内存最大容许大小
-XX:NewSize(-Xns) 年老代内存初始大小
-XX:MaxNewSize(-Xmn) 年老代内存最大容许大小
-XX:SurvivorRatio=8 年老代中 Eden 区与 Survivor 区的容量比例值,默认为 8,即 8:1
-Xss 堆栈内存大小
-XX:NewRatio= 老年代 / 新生代 设置老年代和新生代的大小比例
-XX:+PrintGC jvm 启动后,只有遇到 GC 就会打印日志
-XX:+PrintGCDetails 查看 GC 详细信息,包含各个区的状况
-XX:MaxDirectMemorySize 在 NIO 中能够间接拜访 间接内存,这个就是设置它的大小,不设置默认就是最大堆空间的值 -Xmx
-XX:+DisableExplicitGC 敞开 System.gc()
-XX:MaxTenuringThreshold 垃圾能够进入老年代的年龄
-Xnoclassgc 禁用垃圾回收
-XX:TLABWasteTargetPercent TLAB 占 eden 区的百分比,默认是 1%
-XX:+CollectGen0First FullGC 时是否先 YGC,默认 false

TLAB 内存

TLAB 全称是 Thread Local Allocation Buffer 即 线程本地调配缓存,从名字上看是一个线程专用的内存调配区域,是为了减速对象调配而生的。

每一个线程都会产生一个 TLAB,该线程独享的工作区域,java 虚拟机应用这种 TLAB 区来防止多线程抵触问题,进步了对象调配的效率。

TLAB 空间个别不会太大,当大对象无奈在 TLAB 调配时,则会间接调配到堆上。

参数 形容
-Xx:+UseTLAB 应用 TLAB
-XX:+TLABSize 设置 TLAB 大小
-XX:TLABRefillWasteFraction 设置保护进入 TLAB 空间的单个对象大小,他是一个比例值,默认为 64,即如果对象大于整个空间的 1 /64,则在堆创立
-XX:+PrintTLAB 查看 TLAB 信息
-Xx:ResizeTLAB 自调整 TLABRefillWasteFraction 阀值。

垃圾回收器总览

新生代可配置的回收器:Serial、ParNew、Parallel Scavenge

老年代配置的回收器:CMS、Serial Old、Parallel Old

新生代和老年代区域的回收器之间进行连线,阐明他们之间能够搭配应用。

新生代垃圾回收器

Serial 垃圾回收器

Serial 收集器是最根本的、倒退历史最悠久的收集器。俗称为:串行回收器 ,采纳 复制算法 进行垃圾回收

特点

串行回收器是指应用单线程进行垃圾回收的回收器。每次回收时,串行回收器只有一个工作线程。

对于并行能力较弱的单 CPU 计算机来说,串行回收器的专一性和独占性往往有更好的性能体现。

它存在 Stop The World 问题,及垃圾回收时,要进行程序的运行。

应用 -XX:+UseSerialGC 参数能够设置新生代应用这个串行回收器

ParNew 垃圾回收器

ParNew 其实就是 Serial 的 多线程 版本,除了应用多线程之外,其余参数和 Serial 截然不同。俗称:并行垃圾回收器 ,采纳 复制算法 进行垃圾回收

特点

ParNew 默认开启的线程数与 CPU 数量雷同,在 CPU 核数很多的机器上,能够通过参数 -XX:ParallelGCThreads 来设置线程数。

它是目前新生代首选的垃圾回收器,因为除了 ParNew 之外,它是惟一一个能与老年代 CMS 配合工作的。

它同样存在 Stop The World 问题

应用 -XX:+UseParNewGC 参数能够设置新生代应用这个并行回收器

ParallelGC 回收器

ParallelGC 应用复制算法回收垃圾,也是多线程的。

特点

就是十分关注零碎的吞吐量,吞吐量 = 代码运行工夫 /( 代码运行工夫 + 垃圾收集工夫)

-XX:MaxGCPauseMillis:设置最大垃圾收集进展工夫,可用把虚拟机在 GC 进展的工夫管制在 MaxGCPauseMillis 范畴内,如果心愿缩小 GC 进展工夫能够将 MaxGCPauseMillis 设置的很小,然而会导致 GC 频繁,从而减少了 GC 的 总工夫 升高 吞吐量。所以须要依据理论状况设置该值。

-Xx:GCTimeRatio:设置吞吐量大小,它是一个 0 到 100 之间的整数,默认状况下他的取值是 99,那么零碎将破费不超过1/(1+n) 的工夫用于垃圾回收,也就是 1/(1+99)=1% 的工夫。

另外还能够指定 -XX:+UseAdaptiveSizePolicy 关上自适应模式,在这种模式下,新生代的大小、eden、from/to 的比例,以及降职老年代的对象年龄参数会被主动调整,以达到在堆大小、吞吐量和进展工夫之间的平衡点。

应用 -XX:+UseParallelGC 参数能够设置新生代应用这个并行回收器

老年代垃圾回收器

SerialOld 垃圾回收器

SerialOld 是 Serial 回收器的 老年代 回收器版本,它同样是一个 单线程 回收器。

用处

  • 一个是在 JDK1.5 及之前的版本中与 Parallel Scavenge 收集器搭配应用,
  • 另一个就是作为 CMS 收集器的后备预案,如果 CMS 呈现 Concurrent Mode Failure,则 SerialOld 将作为后备收集器。

应用算法:标记 – 整顿算法

ParallelOldGC 回收器

老年代 ParallelOldGC 回收器也是一种多线程的回收器,和新生代的 ParallelGC 回收器一样,也是一种关注吞吐量的回收器,他应用了 标记压缩算法 进行实现。

-XX:+UseParallelOldGc进行设置老年代应用该回收器

-XX:+ParallelGCThreads也能够设置垃圾收集时的线程数量。

CMS 回收器

CMS 全称为:Concurrent Mark Sweep 意为并发标记革除,他应用的是 标记革除法。次要关注零碎进展工夫。

应用 -XX:+UseConcMarkSweepGC 进行设置老年代应用该回收器。

应用 -XX:ConcGCThreads 设置并发线程数量。

特点

CMS 并不是独占的回收器,也就说 CMS 回收的过程中,应用程序依然在不停的工作,又会有新的垃圾一直的产生,所以在应用 CMS 的过程中应该确保应用程序的内存足够可用。

CMS 不会等到应用程序 饱和 的时候才去回收垃圾,而是在某一阀值的时候开始回收,回收阀值可用指定的参数进行配置:-XX:CMSInitiatingoccupancyFraction来指定,默认为 68,也就是说当老年代的空间 使用率 达到 68% 的时候,会 执行CMS 回收。

如果内存使用率增长的很快,在 CMS 执行的过程中,曾经呈现了内存不足的状况,此时 CMS 回收就会失败,虚拟机将启动老年代 串行 回收器;SerialOldGC进行垃圾回收,这会导致应用程序中断,直到垃圾回收实现后才会失常工作。

这个过程 GC 的进展工夫可能较长,所以 -XX:CMSInitiatingoccupancyFraction 的设置要依据理论的状况。

之前咱们在学习算法的时候说过,标记革除法有个毛病就是存在 内存碎片 的问题,那么 CMS 有个参数设置 -XX:+UseCMSCompactAtFullCollecion 能够使 CMS 回收实现之后进行一次 碎片整顿

-XX:CMSFullGCsBeforeCompaction参数能够设置进行多少次 CMS 回收之后,对内存进行一次 压缩

G1 回收器

篇幅太长,咱们下篇文章解说!!!

IT 老哥

一个在大厂做高级 Java 开发的程序猿,一路自学走到明天,关注 老哥,咱们一起来自学技术

正文完
 0