前言
之前咱们解说了 jvm
的组成构造
与垃圾回收算法
等知识点,明天咱们来讲讲 jvm 最重要的 堆内存
是如何应用 垃圾回收器
进行垃圾回收,并且如何应用 命令
去配置应用这些垃圾回收器。
堆内存详解
下面这个图大家应该曾经很明确了吧。大家就能够了解成一个 房子
被分成了几个 房间
,每个房间的作用不同而已,有的是婴儿住的,有的是父母住的,有的是爷爷奶奶住的
- 堆内存被划分为
两块
,一块的年老代
,另一块是老年代
。 - 年老代又分为
Eden
和survivor
。他俩空间大小比例默认为 8:2, - 幸存区又分为
s0
和s1
。这两个空间大小是截然不同的,就是一对双胞胎,他俩是 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 开发的程序猿,一路自学走到明天,关注 老哥,咱们一起来自学技术